<!-- SOLID CITY · part 2908 -->
ata.epoch); updateStations();
    }
    if(type==='rescue') showToast(data.pod+' is safe inside the rescue gate.');
    if(type==='lost') showToast('Pod '+data.pod+' was lost.');
    renderLog(); updateStats();
  }
  function pretty(s){return s.charAt(0).toUpperCase()+s.slice(1)}
  function showToast(text){const el=$('#toast');el.textContent=text;el.classList.add('show');clearTimeout(toastTimer);toastTimer=setTimeout(()=>el.classList.remove('show'),1800)}
  function setAdvice(text){state.advisory=text;$('#advisory').innerHTML='<strong>AI crew</strong> '+text}

  function updateStations(){
    if(!coordination)return;
    let humans=0;
    $$('.station').forEach(btn=>{
      const task=btn.dataset.task,t=coordination.tasks[task];btn.dataset.owner=t.owner;
      btn.querySelector('.epoch').textContent='E'+t.epoch;
      btn.querySelector('.owner').textContent=t.owner==='human'?'You hold':'AI '+({navigation:'pilot',extraction:'operator',protection:'gunner',support:'engineer'}[task]);
      if(t.owner==='human')humans++;
    });
    $('#crewSplit').textContent=humans+' human · '+(4-humans)+' AI';
    const claimed=$$('.station[data-owner="human"]').map(x=>x.dataset.task);
    $$('.control-group').forEach(g=>g.classList.toggle('active',claimed.includes(g.dataset.controls)));
    $('#controlEmpty').style.display=claimed.length?'none':'block';
  }

  $$('.station').forEach(btn=>btn.addEventListener('click',()=>{
    const task=btn.dataset.task,t=coordination.tasks[task];
    if(t.owner==='ai')coordination.claim(task,'human');else coordination.release(task);
  }));

  function issue(task,owner,action,fn){
    const t=coordination.tasks[task];
    if(coordination.command(task,owner,t.epoch,action+':'+Math.floor(elapsed*10))){fn();return true}return false;
  }
  function humanAction(task,action,fn){if(coordination.owner(task)!=='human'){showToast('Claim '+pretty(task)+' first.');return}issue(task,'human',action,fn)}

  function dist(a,b){return Math.hypot(a.x-b.x,a.y-b.y)}
  function nearestPod(){return state.pods.filter(p=>p.status==='adrift').sort((a,b)=>dist(state.ship,a)-dist(state.ship,b))[0]||null}
  function nearestEnemy(){return state.enemies.filter(e=>e.hp>0).sort((a,b)=>dist(state.ship,a)-dist(state.ship,b))[0]||null}

  function update(dt){
    if(!running||state.missionEnd)return;
    elapsed+=dt; adviceTimer-=dt; spawnTimer-=dt;
    const s=state.ship;
    Object.keys(s).forEach(()=>{});
    updateNavigation(dt); updateExtraction(dt); updateProtection(dt); updateSupport(dt);
    s.x=Math.max(38,Math.min(W-34,s.x+s.vx*dt));s.y=Math.max(55,Math.min(H-35,s.y+s.vy*dt));
    s.vx*=Math.pow(.1,dt);s.vy*=Math.pow(.1,dt);if(Math.hypot(s.vx,s.vy)>3)s.angle=Math.atan2(s.vy,s.vx);
    s.fireCd=Math.max(0,s.fireCd-dt);s.repairCd=Math.max(0,s.repairCd-dt);s.pulse=Math.max(0,s.pulse-dt);
    s.shield=Math.min(100,s.shield+dt*(coordination.owner('protection')==='ai'?3.6:1.5));
    updateWorld(dt); updateRisk(dt); checkEnd(); updateUI();
  }

  function updateNavigation(dt){
    const s=state.ship;
    if(coordination.owner('navigation')==='human'){
      let ax=0,ay=0;const k=state.keys;if(k.left||k.a)ax--;if(k.right||k.d)ax++;if(k.up||k.w)ay--;if(k.down||k.s)ay++;const power=k.boost?155:105;s.vx+=ax*power*dt;s.vy+=ay*power*dt;
    } else {
      let target;
      if(s.cargo)target=state.gate;else target=nearestPod()||state.gate;
      const dx=target.x-s.x,dy=target.y-s.y,d=Math.max(1,Math.hypot(dx,dy));
      const stop=d<75?0.25:1;s.vx+=dx/d*72*dt*stop;s.vy+=dy/d*72*dt*stop;
      state.hazards.forEach(h=>{const hd=dist(s,h);if(hd<h.r+70){s.vx+=(s.x-h.x)/hd*145*dt;s.vy+=(s.y-h.y)/hd*145*dt}});
    }
  }

  function updateExtraction(dt){
    const p=nearestPod();if(!p||state.ship.cargo)return;
    const d=dist(state.ship,p),owner=coordination.owner('extraction');
    let stabilizing=false,tractoring=false;
    if(owner==='ai'&&d<92){stabilizing=true;if(p.stabilize>=100)tractoring=true}
    if(owner==='human'){stabilizing=state.stabilizeHeld;tractoring=state.extractHeld}
    if(stabilizing&&d<105){p.stabilize=Math.min(100,p.stabilize+dt*(owner==='ai'?29:38));if(adviceTimer<=0){setAdvice('Holding '+p.id+' steady — stabilization '+Math.floor(p.stabilize)+'%.');adviceTimer=2.5}}
    else p.stabilize=Math.max(0,p.stabilize-dt*5);
    if(tractoring&&d<92&&p.stabilize>=100){
      p.status='cargo';state.ship.cargo=p;recordEvent('extraction',{pod:p.id,owner});setAdvice(p.id+' is aboard. Protect the pod and make for the blue gate.');
    }
  }

  function fireAt(target,owner){
    const s=state.ship;if(s.fireCd>0||!target)return;s.fireCd=.28;
    state.shots.push({x:s.x,y:s.y,target,vx:0,vy:0,owner});
    recordEvent('shot',{owner});
  }
  function updateProtection(dt){
    const e=nearestEnemy();
    if(coordination.owner('protection')==='ai'&&e&&dist(state.ship,e)<270)fireAt(e,'ai');
  }
  function repair(owner){
    const s=state.ship;if(s.repairCd>0)return;s.repairCd=3.2;s.hp=Math.min(100,