<!-- SOLID CITY · part 3196 -->
urst-dt);state.targetPulse+=dt;lastSignal=performance.now();
    if(state.phaseDelay>0){state.phaseDelay=Math.max(0,state.phaseDelay-dt);if(state.phaseDelay===0)spawnPhase();}
    if(state.enemyCooldown<=0){enemyFire();state.enemyCooldown=Math.max(.38,1.65-state.phase*.34-Math.min(.35,state.time/240));}
    ai(dt);
    for(var i=state.shots.length-1;i>=0;i--){var s=state.shots[i];s.t+=dt;var q=Math.min(1,s.t/s.d);s.x=s.x+(s.tx-s.x)*Math.min(1,dt*8);s.y=s.y+(s.ty-s.y)*Math.min(1,dt*8);if(q>=1){hitTarget(s);state.shots.splice(i,1);}}
    for(var j=state.enemyShots.length-1;j>=0;j--){var e=state.enemyShots[j];e.t+=dt;e.x=e.x+(e.tx-e.x)*Math.min(1,dt*4.5);e.y=e.y+(e.ty-e.y)*Math.min(1,dt*4.5);if(e.t>=e.d){enemyHit(e);state.enemyShots.splice(j,1);}}
    for(var k=state.particles.length-1;k>=0;k--){var p=state.particles[k];p.t+=dt;p.x+=p.vx*dt;p.y+=p.vy*dt;if(p.t>p.d)state.particles.splice(k,1);}
    if(state.time%10<dt&&state.wings<state.maxWings&&state.phase>0&&Math.random()<.23){state.wings++;record('WING_REINFORCED',{phase:state.phase+1});}
    state.frameSamples.push(1/Math.max(dt,.001));if(state.frameSamples.length>40)state.frameSamples.shift();state.fps=state.frameSamples.reduce(function(a,b){return a+b},0)/state.frameSamples.length;
    updateHud();
  }
  function draw(){
    ctx.clearRect(0,0,W,H);var g=ctx.createRadialGradient(W*.72,H*.5,0,W*.72,H*.5,W*.7);g.addColorStop(0,'#142029');g.addColorStop(.38,'#080d12');g.addColorStop(1,'#020406');ctx.fillStyle=g;ctx.fillRect(0,0,W,H);
    stars.forEach(function(s){ctx.globalAlpha=s.a;ctx.fillStyle='#d9ffff';ctx.fillRect(s.x*W,s.y*H,s.s,s.s)});ctx.globalAlpha=1;
    // fortress asteroid
    var fx=.73*W,fy=.5*H,fr=Math.min(W,H)*.13;ctx.save();ctx.translate(fx,fy);ctx.rotate(state?state.time*.025:0);ctx.beginPath();for(var i=0;i<14;i++){var a=i/14*Math.PI*2,r=fr*(.78+((i*17)%7)/24);ctx.lineTo(Math.cos(a)*r,Math.sin(a)*r)}ctx.closePath();var ag=ctx.createRadialGradient(-fr*.3,-fr*.3,2,0,0,fr);ag.addColorStop(0,'#46515a');ag.addColorStop(.55,'#222b31');ag.addColorStop(1,'#0d1317');ctx.fillStyle=ag;ctx.fill();ctx.strokeStyle='#60717a';ctx.lineWidth=1;ctx.stroke();ctx.restore();
    if(!state)return;
    // orbit rings per phase
    ctx.strokeStyle=state.phase===0?'rgba(255,76,50,.3)':state.phase===1?'rgba(42,214,201,.28)':'rgba(255,181,52,.35)';ctx.lineWidth=1;ctx.setLineDash([4,7]);ctx.beginPath();ctx.arc(fx,fy,(state.phase===0?.23:state.phase===1?.15:.08)*Math.min(W,H)*1.4,0,Math.PI*2);ctx.stroke();ctx.setLineDash([]);
    state.targets.forEach(drawTarget);
    // wings
    for(var wi=0;wi<state.wings;wi++){var wa=state.time*(state.formation==='SCREEN'?.8:1.2)+wi/state.wings*Math.PI*2;var wr=state.formation==='SCREEN'?22+wi%3*4:14+wi%4*7;var wx=state.ship.x*W+Math.cos(wa)*wr,wy=state.ship.y*H+Math.sin(wa)*wr*.55;ctx.fillStyle='#35d5cb';ctx.beginPath();ctx.moveTo(wx+5,wy);ctx.lineTo(wx-3,wy-2.5);ctx.lineTo(wx-1,wy);ctx.lineTo(wx-3,wy+2.5);ctx.closePath();ctx.fill();}
    // capital ship
    var sx=state.ship.x*W,sy=state.ship.y*H;ctx.save();ctx.translate(sx,sy);ctx.fillStyle='#d8e9ea';ctx.strokeStyle='#0b1216';ctx.lineWidth=2;ctx.beginPath();ctx.moveTo(34,0);ctx.lineTo(-22,-12);ctx.lineTo(-10,0);ctx.lineTo(-22,12);ctx.closePath();ctx.fill();ctx.stroke();ctx.fillStyle='#f0ad31';ctx.fillRect(-24,-7,5,4);ctx.fillRect(-24,3,5,4);if(state.aegisBurst>0){ctx.strokeStyle='rgba(56,225,211,.8)';ctx.lineWidth=3;ctx.beginPath();ctx.ellipse(0,0,50,28,0,0,Math.PI*2);ctx.stroke()}ctx.restore();
    // projectiles
    state.shots.forEach(function(s){ctx.strokeStyle=s.kind==='bombard'?'#ffb43b':'#4bf1e5';ctx.lineWidth=s.kind==='bombard'?4:2;ctx.beginPath();ctx.moveTo((s.x-.018)*W,s.y*H);ctx.lineTo(s.x*W,s.y*H);ctx.stroke()});
    state.enemyShots.forEach(function(s){ctx.strokeStyle='#ff5038';ctx.lineWidth=2;ctx.beginPath();ctx.moveTo((s.x+.012)*W,s.y*H);ctx.lineTo(s.x*W,s.y*H);ctx.stroke()});
    state.particles.forEach(function(p){ctx.globalAlpha=Math.max(0,1-p.t/p.d);ctx.fillStyle=p.c;ctx.fillRect(p.x*W,p.y*H,3,3)});ctx.globalAlpha=1;
    // fleet bars
    bar(12,H-12,Math.min(180,W*.25),5,state.ship.hp/state.ship.max,'#ff5a43');bar(12,H-20,Math.min(180,W*.25),4,state.ship.shield/state.ship.maxShield,'#35d5cb');
  }
  function drawTarget(t){if(!t.alive)return;var x=t.x*W,y=t.y*H,isSel=t===selectedTarget,r=t.type==='core'?18:t.type==='generator'?11:8;ctx.save();ctx.translate(x,y);if(isSel){ctx.strokeStyle='#fff';ctx.lineWidth=1;ctx.beginPath();ctx.arc(0,0,r+7+Math.sin(state.targetPulse*5)*2,0,Math.PI*2);ctx.stroke()}
    if(t.type==='turret'){ctx.rotate(t.angle);ctx.fillStyle='#d84b36';ctx.fillRect(-6,-6,12,12);ctx.fillStyle='#ffb33b';ctx.fillRect(3,-2,10,4)}
    else if(t.type==='generator'){ctx.rotate(state.time);ctx.strokeStyle='#36d9cc';ctx.lineWidth=3;ctx.strokeRect(-8,-8,16,16);ctx.fillStyle='#b8fff8';ctx.fillRect(-3,-3,6,6)}
    else{ctx.fillStyle='#e6a62d';ctx.beginPath();ctx.arc(0,0,r,0,Math.PI*2);ctx.fill();ctx.strokeStyle='#fff2bf';ctx