<!-- SOLID CITY · part 3738 -->
t(win?'mission_arrival':'mission_failed',{progress:+(ship.progress*100).toFixed(1),hull:+Math.max(0,ship.hull).toFixed(1)});const stats=deriveStats();$('resultKicker').textContent=win?'MISSION COMPLETE':'WARSHIP LOST';$('resultTitle').textContent=win?'Meridian Gate reached.':'The blockade held.';$('resultText').textContent=win?'The ship arrived under combined human–AI command. Every station contribution below comes from the mission ledger.':'The route remains open for another attempt. Your station ownership and combat contributions were preserved in the mission ledger.';$('resultStats').innerHTML=statCards(stats,true);$('debrief').hidden=false;}
function deriveStats(){const shots=events.filter(e=>e.type==='shot'),hits=events.filter(e=>e.type==='hit'),hands=events.filter(e=>e.type==='handoff'),destroyed=events.filter(e=>e.type==='threat_destroyed'),damage=events.filter(e=>e.type==='damage_taken').reduce((a,e)=>a+e.amount,0),reject=events.filter(e=>e.type==='command_rejected');const handAvg=hands.length?hands.reduce((a,e)=>a+e.latency,0)/hands.length:0;return {shots:shots.length,hits:hits.length,destroyed:destroyed.length,damage:+damage.toFixed(1),handoffs:hands.length,handAvg:+handAvg.toFixed(2),rejected:reject.length,events:events.length,shotsA:shots.filter(e=>e.battery==='batteryA').length,hitsA:hits.filter(e=>e.battery==='batteryA').length,shotsB:shots.filter(e=>e.battery==='batteryB').length,hitsB:hits.filter(e=>e.battery==='batteryB').length,humanHits:hits.filter(e=>e.owner==='human').length,aiHits:hits.filter(e=>e.owner==='ai').length};}
function statCards(s,small){const arr=[['THREATS',s.destroyed],['HITS',s.hits],['HANDOFFS',s.handoffs],['HULL DAMAGE',s.damage+'%']];if(!small)arr.push(['LEDGER EVENTS',s.events],['STALE / JAM REJECTS',s.rejected],['AVG HANDOFF',s.handAvg+' ms'],['HUMAN / AI HITS',s.humanHits+' / '+s.aiHits]);return arr.map(x=>'<div class="stat"><b>'+x[1]+'</b><span>'+x[0]+'</span></div>').join('');}
function renderStats(){const s=deriveStats();$('statsGrid').innerHTML=statCards(s,false);$('batteryStats').innerHTML='<div class="log-row"><time>BATTERY A</time><b>'+s.hitsA+' hits / '+s.shotsA+' shells · '+(s.shotsA?Math.round(s.hitsA/s.shotsA*100):0)+'%</b></div><div class="log-row"><time>BATTERY B</time><b>'+s.hitsB+' hits / '+s.shotsB+' shells · '+(s.shotsB?Math.round(s.hitsB/s.shotsB*100):0)+'%</b></div>';$('statsLog').innerHTML=eventRows(events.slice(-28).reverse());}
function eventRows(rows){if(!rows.length)return '<div class="log-row"><time>—</time><b>No events recorded yet.</b></div>';return rows.map(e=>'<div class="log-row"><time>'+formatTime(e.mission)+'</time><b>'+describe(e)+'</b></div>').join('');}
function formatTime(ms){const s=Math.max(0,ms/1000);return Math.floor(s/60)+':'+String(Math.floor(s%60)).padStart(2,'0')+'.'+Math.floor((s%1)*10);}
function describe(e){const t=stationLabel(e.task)||e.task;switch(e.type){case'ownership':return t+' owner → '+String(e.owner).toUpperCase()+' · epoch '+e.epoch;case'handoff':return t+' handoff to '+e.to.toUpperCase()+' measured '+e.latency+' ms';case'handoff_start':return t+' safe handoff started';case'command_rejected':return 'REJECTED '+t+' command · '+e.reason;case'threat_destroyed':return e.threat+' destroyed by '+e.battery+' · '+e.owner;case'hit':return e.battery+' hit '+e.target+' · '+e.owner+' · '+e.damage+' damage';case'damage_taken':return 'Ship damage '+e.amount+'% · shield absorbed '+e.absorbed;case'mission_arrival':return 'Arrival recorded at '+e.progress+'% · hull '+e.hull+'%';default:return e.type.replaceAll('_',' ')+' · '+(e.owner||e.threat||e.task||'recorded');}}
function renderCoord(){const types=['ownership','handoff','handoff_start','command_rejected'];$('coordLog').innerHTML=eventRows(events.filter(e=>types.includes(e.type)).slice(-80).reverse());}

document.querySelectorAll('.station').forEach(el=>{const station=el.dataset.station;el.querySelector('.reclaim').addEventListener('click',()=>claim(station));el.querySelectorAll('[data-action]').forEach(btn=>{const action=btn.dataset.action;btn.addEventListener('pointerdown',ev=>{ev.preventDefault();if(action==='release'){release(station);return;}humanCommand(station,()=>{if(action==='left')ship.navInput=-1;if(action==='right')ship.navInput=1;if(action==='up')ship.boost=true;if(action==='cycle')cycleTarget(station);if(action==='fire')fireBattery(station,'human');if(action.startsWith('shield'))ship.shieldFace=action.replace('shield','').toLowerCase();});});});});
document.addEventListener('keydown',e=>{if(!running||e.repeat)return;if(e.key==='ArrowLeft')humanCommand('nav',()=>ship.navInput=-1);if(e.key==='ArrowRight')humanCommand('nav',()=>ship.navInput=1);if(e.key==='ArrowUp')humanCommand('nav',()=>ship.boost=true);if(e.key.toLowerCase()==='a')humanCommand('batteryA',()=>fireBattery('batteryA','human'));if(e.key.toLowerCase()==='b')humanCommand('batteryB',()=>fireBattery('batteryB','human'));});
$('deployBtn').addEventListener('click',()=>