<!-- SOLID CITY · part 1928 -->
eginPath();ctx.moveTo(x,y);ctx.lineTo(x+(x/(w*.5))*len,y+(y/(h*.5))*len);ctx.stroke()});ctx.restore();ctx.globalAlpha=1;
    ctx.save();ctx.strokeStyle='#42506a66';ctx.lineWidth=1;var horizon=h*.28,deck=h*.91;for(var g=0;g<9;g++){var gx=w/2+(g-4)*w*.055;ctx.beginPath();ctx.moveTo(w/2+(gx-w/2)*.08,horizon);ctx.lineTo(gx,deck);ctx.stroke()}for(g=1;g<8;g++){var q=g/8,y=horizon+(deck-horizon)*q*q;ctx.beginPath();ctx.moveTo(w*.08+(w*.42)*(1-q),y);ctx.lineTo(w*.92-(w*.42)*(1-q),y);ctx.stroke()}ctx.strokeStyle='#ffc84a33';ctx.beginPath();ctx.moveTo(w*.08,deck);ctx.lineTo(w*.46,horizon);ctx.moveTo(w*.92,deck);ctx.lineTo(w*.54,horizon);ctx.stroke();ctx.restore();
    corridorPickups.forEach(function(p){var q=corridorPoint(p.x,p.band,p.z,w,h),colors={shield:'#6ef2ff',spread:'#ff9b57',rapid:'#fff26a',repair:'#72ff9d'};ctx.save();ctx.translate(q.x,q.y);ctx.rotate(p.phase);ctx.strokeStyle=colors[p.type];ctx.shadowColor=colors[p.type];ctx.shadowBlur=12;ctx.strokeRect(-8*q.scale,-8*q.scale,16*q.scale,16*q.scale);ctx.restore()});
    corridorThreats.slice().sort(function(a,b){return b.z-a.z}).forEach(function(t){var p=corridorPoint(t.x,t.band,t.z,w,h),r=18*p.scale;ctx.save();ctx.translate(p.x,p.y);ctx.rotate(t.phase);ctx.shadowColor=t.type==='enemy'?'#ff2844':'#ff9b28';ctx.shadowBlur=8+12*p.scale;ctx.fillStyle=t.type==='enemy'?'#2b0710':'#76502d';ctx.strokeStyle=t.type==='enemy'?'#ff5b66':'#ffc16c';ctx.lineWidth=Math.max(1,2*p.scale);ctx.beginPath();if(t.type==='enemy'){ctx.moveTo(0,-r);ctx.lineTo(r*.8,r*.7);ctx.lineTo(0,r*.35);ctx.lineTo(-r*.8,r*.7)}else{for(var i=0;i<8;i++){var a=i/8*6.28,rr=r*(.78+(i%3)*.12);i?ctx.lineTo(Math.cos(a)*rr,Math.sin(a)*rr):ctx.moveTo(Math.cos(a)*rr,Math.sin(a)*rr)}ctx.closePath()}ctx.fill();ctx.stroke();ctx.restore();if(t.z<.48){ctx.fillStyle='#fff';ctx.font='900 7px ui-monospace,monospace';ctx.textAlign='center';ctx.fillText(bandName(t.band),p.x,p.y-r-7)}});
    corridorShots.forEach(function(s){var p=corridorPoint(s.x,s.alt,s.z,w,h);ctx.strokeStyle=s.color;ctx.lineWidth=2;ctx.shadowColor=s.color;ctx.shadowBlur=8;ctx.beginPath();ctx.moveTo(p.x,p.y+10*p.scale);ctx.lineTo(p.x,p.y-18*p.scale);ctx.stroke();ctx.shadowBlur=0});
    if(ships[0].alive&&ships[1].alive&&flight.mode==='formation'){var a={x:w/2+ships[0].corridorX*w*.37,y:h*.72-ships[0].altitude*h*.2},b={x:w/2+ships[1].corridorX*w*.37,y:h*.72-ships[1].altitude*h*.2};ctx.save();ctx.strokeStyle='#73ffe066';ctx.setLineDash([5,7]);ctx.beginPath();ctx.moveTo(a.x,a.y);ctx.lineTo(b.x,b.y);ctx.stroke();ctx.restore()}
    ships.forEach(function(s,i){if(s.alive)drawCorridorShip(ctx,s,w,h,i===index)});
    if(flight.mode==='separation'){var partner=ships[index?0:1],dx=partner.corridorX-ships[index].corridorX,da=partner.altitude-ships[index].altitude;ctx.fillStyle=index?'#ffc84a':'#44e1d0';ctx.font='900 9px ui-monospace,monospace';ctx.textAlign='center';ctx.fillText('HOME '+(da>.2?'↑':da<-.2?'↓':'↔'),w/2+clamp(dx,-1,1)*38,h*.19)}
    ctx.fillStyle='rgba(0,0,0,.18)';ctx.fillRect(0,0,w,28);ctx.fillRect(0,h-18,w,18)
  }
  function frame(t){if(!last)last=t;var dt=Math.max(0,Math.min(.033,(t-last)/1000));last=t;if(running)update(dt);render();requestAnimationFrame(frame)}
  function begin(){intro.hidden=true;debrief.hidden=true;levelBeat.hidden=true;init();running=false;logH('mission launched · AI has Ship Two');showLevelBrief(1)}
  function formatTime(seconds){var n=Math.max(0,Math.floor(seconds));return String(Math.floor(n/60)).padStart(2,'0')+':'+String(n%60).padStart(2,'0')}
  function endRun(reason){if(!running)return;running=false;runEnding=true;var victory=reason!=='defeat',levelReached=Math.max(1,level),finalScore=metrics.kills*100+metrics.rescues*300+metrics.reunions*200+levelReached*1000;var isNewBest=finalScore>sessionBest.score;if(isNewBest){sessionBest={score:finalScore,kills:metrics.kills,level:levelReached,time:elapsed,formation:metrics.formationTime,reunions:metrics.reunions,rescues:metrics.rescues,shield:metrics.shieldHits,friendly:metrics.friendlyFire}};document.querySelector('#outcome').textContent=victory?'MISSION COMPLETE · VICTORY':'FORMATION LOST · DEFEAT';document.querySelector('#mScore').textContent=String(finalScore).padStart(5,'0');document.querySelector('#newBest').classList.toggle('show',isNewBest);document.querySelector('#mKills').textContent=metrics.kills;document.querySelector('#mLevel').textContent=levelReached;document.querySelector('#mTime').textContent=formatTime(elapsed);document.querySelector('#mFormation').textContent=Math.round(metrics.formationTime)+'s';document.querySelector('#mReunions').textContent=metrics.reunions;document.querySelector('#mRescues').textContent=metrics.rescues;document.querySelector('#mShield').textContent=metrics.shieldHits;document.querySelector('#mFriendly').textContent=metrics.friendlyFire;document.querySelector('#mAvoid').textContent=metrics.avoided;document.querySelector('#mHits').textContent=metrics.meteorHits;document.querySelector('#mSeparations').text