<!-- SOLID CITY · part 3188 -->
.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.lineWidth=3;ctx.beginPath();ctx.arc(0,0,r+5+Math.sin(state.time*3)*3,0,Math.PI*2);ctx.stroke()}
    ctx.restore();bar(x-r,y+r+7,r*2,3,t.hp/t.max,t.type==='generator'?'#36d9cc':'#ff5a43');}
  function bar(x,y,w,h,p,c){ctx.fillStyle='rgba(255,255,255,.15)';ctx.fillRect(x,y,w,h);ctx.fillStyle=c;ctx.fillRect(x,y,Math.max(0,w*p),h);}
  function loop(ts){var dt=Math.min(.05,(ts-last)/1000||.016);last=ts;resize();update(dt);draw();if(state&&state.running)raf=requestAnimationFrame(loop);}
  function updateHud(){
    var p=phaseData[state.phase],alive=state.targets.filter(function(t){return t.alive}).length,total=p.count,progress=(total-alive)/total*100;document.getElementById('objective').textContent=p.objective;document.getElementById('objectiveMeter').style.width=progress+'%';document.getElementById('targetCount').innerHTML=alive+' / '+total+' <small>ACTIVE</small>';var strength=Math.max(0,Math.round(((state.ship.hp/state.ship.max)*.75+(state.wings/state.maxWings)*.25)*100));document.getElementById('fleetStrength').textContent=strength+'%';document.getElementById('fleetMeter').style.width=strength+'%';document.getElementById('siegeClock').textContent=fmt(state.time);document.getElementById('phaseLabel').textContent='PHASE '+(state.phase+1)+' · '+p.name;document.getElementById('phaseText').textContent=p.text;var maxEpoch=Math.max.apply(null,Object.keys(tasks).map(function(k){return tasks[k].epoch}));document.getElementById('epochReadout').textContent='4 TASKS · EPOCH '+maxEpoch;
    var lag=performance.now()-lastSignal,ok=lag<500;document.getElementById('signalText').textContent=ok?'LINK NOMINAL':'LI