<!-- SOLID CITY · part 3197 -->
.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){if(!state||!state.running||state.paused)return;var dt=Math.min(.05,(ts-last)/1000||.016);last=ts;resize();update(dt);draw();if(state&&state.running&&!state.paused)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':'LINK DEGRADED';document.getElementById('signalDot').style.background=ok?'var(--good)':'var(--hot)';
  }
  function updateStations(){Object.keys(tasks).forEach(function(k){var t=tasks[k],el=document.getElementById('station-'+k),owner=el.querySelector('.owner'),btn=el.querySelector('.claim'),c=el.querySelector('[data-controls]');el.classList.toggle('human',t.owner==='HUMAN');owner.textContent=t.owner==='HUMAN'?'HUMAN · EPOCH '+t.epoch:'AI · '+t.admiral;btn.textContent=t.owner==='HUMAN'?'RELEASE TO AI':'TAKE CONTROL';c.innerHTML='';if(t.owner!=='HUMAN'){c.innerHTML='<span class="label">AUTO</span>';return;}if(k==='fleet')c.innerHTML='<div class="dpad"><button class="control up" data-move="0,-.035">▲</button><button class="control left" data-move="-.035,0">◀</button><button class="control down" data-move="0,.035">▼</button><button class="control right" data-move=".035,0">▶</button></div>';if(k==='bombard')c.innerHTML='<button class="control fire" data-action="fire">FIRE</button>';if(k==='wings')c.innerHTML='<button class="control" data-action="formation">'+state.formation+'</button><button class="control fire" data-action="strike">STRIKE</button>';if(k==='aegis')c.innerHTML='<button class="control fire" data-action="aegis">FOCUS</button>';});}
  function advise(msg,warn){var el=document.getElementById('advisory');el.classList.toggle('warn',!!warn);el.innerHTML='<strong>ADVISORY:</strong> '+msg;record('ADVISORY',{message:msg,severity:warn?'warning':'info'});}
  function updateTicker(type,d){var label=type.replaceAll('_',' ');if(type==='OWNERSHIP_TRANSFER')label=d.task.toUpperCase()+' transferred to '+d.to+' · '+d.latencyMs.toFixed(2)+' ms';if(type==='TARGET_DESTROYED')label=d.owner+' destroyed '+d.target;document.getElementById('ticker').textContent=label;}
  function derived(){
    var count=function(type,filter){return events.filter(function(e){return e.type===type&&(!filter||filter(e))}).length};var hand=events.filter(function(e){return e.type==='OWNERSHIP_TRANSFER'});var lats=hand.map(function(e){return e.latencyMs});return {phase:state?state.phase+1:0,turrets:count('TARGET_DESTROYED',function(e){return e.target==='turret'}),gens:count('TARGET_DESTROYED',function(e){return e.target==='generator'}),core:count('TARGET_DESTROYED',function(e){return e.target==='core'}),humanKills:count('TARGET_DESTROYED',function(e){return e.owner==='HUMAN'}),aiKills:count('TARGET_DESTROYED',function(e){return e.owner==='AI'}),hits:count('BOMBARDMENT_HIT'),losses:count('WING_LOST'),handoffs:hand.length,avgLatency:lats.length?lats.reduce(function(a,b){return a+b},0)/lats.length:0,rejected:count('STALE_COMMAND_REJECTED'),intercepts:count('POINT_DEFENSE_INTERCEPT'),events:events.length};
  }
  function openDrawer(which){var d=document.getElementById('drawer'),title=document.getElementById('drawerTitle'),c=document.getElementById('drawerContent');d.classList.add('open');document.querySelectorAll('.tab').forEach(function(b){b.classList.toggle('active',b.dataset.drawer===which)});var s=derived();if(which==='mission'){title.textContent='Assault Plan';c.innerHTML='<div class="stats-grid"><div class="stat"><span class="label">Phase 1</span><b>'+s.turrets+' / 8</b><span class="label">Turrets</span></div><div class="stat"><span class="label">Phase 2</span><b>