<!-- SOLID CITY · part 3705 -->
ip',{task:name,owner:'ai',epoch});this.emit('handoff',{task:name,to:'ai',latency:+activeElapsed.toFixed(2),epoch});updateStations();};setTimeout(complete,16);}
  command(name,owner,epoch,fn,id){if(paused||ended)return false;const t=this.tasks[name];id=id||name+'-'+owner+'-'+epoch+'-'+Math.random();if(!this.connected){this.emit('command_rejected',{task:name,reason:'operator disconnected',epoch});return false;}if(this.seen.has(id)){this.emit('command_rejected',{task:name,reason:'duplicate command',epoch});return false;}this.seen.add(id);if(this.queue.length>48){this.emit('command_rejected',{task:name,reason:'queue overloaded',epoch});return false;}if(!t||t.owner!==owner||t.epoch!==epoch){this.emit('command_rejected',{task:name,reason:'stale ownership epoch',epoch,current:t?t.epoch:null});return false;}this.queue.push(id);try{fn();this.emit('command_accepted',{task:name,owner,epoch});}finally{this.queue.shift();}return true;}
  advisory(task,text){this.emit('advisory',{task,text});}
}

const canvas=document.getElementById('game'),ctx=canvas.getContext('2d');
const $=id=>document.getElementById(id);let dpr=1,W=800,H=560,last=0,raf=0,running=false,paused=false,ended=false,gameClock=0;
let ship,enemies=[],shells=[],enemyShots=[],particles=[],stars=[],events=[],eventSeq=0,wave=1,nextSpawn=0,aiTick=0,adviceTick=0,missionStart=0;
let rngSeed=92811;
function rand(){rngSeed=(rngSeed*1664525+1013904223)>>>0;return rngSeed/4294967296;}
function emit(type,data){events.push({id:++eventSeq,type,time:performance.now(),mission:missionStart?performance.now()-missionStart:0,...(data||{})});if(events.length>1000)events.shift();if(type==='advisory')$('advisoryText').textContent=data.text;if(type==='command_rejected')showWarning('SIGNAL GUARD · '+data.reason.toUpperCase());renderOwnership();}
let coordination=new ControlCoordination(['nav','batteryA','batteryB','defense'],emit);
/* ================= THE MERIDIAN MIRROR — summit =================
   The Gate is a mirror. The last enemy is your own warship reflected:
   it holds your x, copies your shield facing, and returns every
   single-battery salvo shell-for-shell. Only a symmetric dual salvo —
   both batteries striking as one — can crack it. Three rings, phi-paced.
   The last ring is a shield: it falls only when both ships stand bare.
   The AI crew learns the law but will never give the vulnerable order;
   that touch belongs to the human hand. Minimal words; the form teaches. */
const PHI=1.6180339887;
let summit=null;
function beginSummit(){
  if(summit||ended)return;
  enemies=[];shells=[];enemyShots=[];
  summit={phase:'reveal',rings:3,x:ship.x,y:-.28,revealT:0,counterT:2.2,syncT:2.1,finalT:1,nudgeT:0,stillT:0,ascentT:0,
    aiSync:false,returned:0,shieldsDown:false,mirrorGone:false,
    advisedReturn:false,advisedSync:false,advisedCrack:false,advisedShield:false,advisedOrder:false,advisedReflect:false};
  emit('summit_begin',{rings:3});
  emit('advisory',{task:'crew',text:'THE GATE IS A MIRROR.'});
  const ot=$('objectiveTitle');if(ot)ot.textContent='Face the Meridian Mirror';
  updateHUD();
}
function summitMirrorFire(){
  const s=summit,dx=ship.x-s.x,dy=ship.y-s.y,l=Math.hypot(dx,dy)||1;
  for(let i=0;i<4;i++){const ox=[-.03,-.01,.01,.03][i];
    enemyShots.push({id:'M'+Math.floor(rand()*99999),x:s.x+ox,y:s.y+.04,vx:dx/l*.19+ox*.4,vy:dy/l*.19,life:4,mirror:true});}
  emit('mirror_fire',{rings:s.rings});
}
function summitShellStrike(s){
  const sm=summit;
  const others=shells.filter(o=>o!==s&&!o.hit&&o.mirror&&o.battery!==s.battery);
  if(!others.length||sm.phase==='ascent'||sm.mirrorGone){
    /* asymmetric: the mirror catches the salvo and returns it shell for shell */
    s.hit=true;
    const dx=ship.x-sm.x,dy=ship.y-sm.y,l=Math.hypot(dx,dy)||1;
    enemyShots.push({id:'R'+Math.floor(rand()*99999),x:sm.x,y:sm.y,vx:dx/l*.19,vy:dy/l*.19,life:4,mirror:true});
    sm.returned++;
    emit('salvo_returned',{battery:s.battery,owner:s.owner});
    if(!sm.advisedReturn){sm.advisedReturn=true;emit('advisory',{task:'crew',text:'ONE BATTERY · IT RETURNS.'});}
    if(!sm.aiSync){sm.aiSync=true;if(!sm.advisedSync){sm.advisedSync=true;emit('advisory',{task:'crew',text:'TWO AS ONE · IT BREAKS.'});}}
    return;
  }
  /* symmetric strike: both batteries as one — consume every inbound shell */
  const consumed=shells.filter(o=>!o.hit&&o.mirror);consumed.forEach(o=>{o.hit=true;});
  const owners=[...new Set(consumed.map(o=>o.owner))];
  if(sm.phase==='stillness'&&!sm.shieldsDown){
    /* the last ring is a shield: it reflects everything while shields hold */
    for(let i=0;i<14;i++)particle(sm.x+(rand()-.5)*.12,sm.y+(rand()-.5)*.12,'muzzle');
    emit('shield_ring_ripple',{owners});
    if(!sm.advisedReflect){sm.advisedReflect=true;emit('advisory',{task:'crew',text:'IT REFLECTS EVERYTHING.'});}
    return;
  }
  for(let i=0;i<26;i++)particle(sm.x+(rand()-.5)*.09,sm.y+(rand()-.5)*.09,'boom');
  emit('symmetric_strike',{owners,ringsBefore:sm.rings}