<!-- SOLID CITY · part 3181 -->
yId('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>'+s.gens+' / 4</b><span class="label">Generators</span></div><div class="stat"><span class="label">Phase 3</span><b>'+s.core+' / 1</b><span class="label">Core</span></div><div class="stat"><span class="label">Current</span><b>'+s.phase+' / 3</b><span class="label">Assault phase</span></div></div><p style="line-height:1.6;color:var(--muted);font-size:12px">Claiming one command never interrupts the others. AI admirals continue their work, while the claimed station rejects every command from its previous ownership epoch. Advisories remain visible but can never actuate your station.</p>';}
    if(which==='stats'){title.textContent='Event-Derived STATS';c.innerHTML='<div class="stats-grid"><div class="stat"><span class="label">Human destroys</span><b>'+s.humanKills+'</b></div><div class="stat"><span class="label">AI destroys</span><b>'+s.aiKills+'</b></div><div class="stat"><span class="label">Bombard hits</span><b>'+s.hits+'</b></div><div class="stat"><span class="label">Wing losses</span><b>'+s.losses+'</b></div><div class="stat"><span class="label">Handoffs</span><b>'+s.handoffs+'</b></div><div class="stat"><span class="label">Mean handoff</span><b>'+s.avgLatency.toFixed(2)+'</b><span class="label">milliseconds</span></div><div class="stat"><span class="label">Stale rejected</span><b>'+s.rejected+'</b></div><div class="stat"><span class="label">PD intercepts</span><b>'+s.intercepts+'</b></div><div class="stat"><span class="label">Measured render</span><b>'+(state?state.fps.toF