<!-- SOLID CITY · part 1836 -->
store()}
    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)
  }

  // ASCENSION v0.1: bounded adaptive encounter director. Deterministic rules,
  // not a remote AI model. Preserves manual takeover and all original missions.
  var ascension={pressure:0,cooperation:0,phase:'CALIBRATING',sampleAt:0};
  function updateAscension(dt){
    if(!running||transitioning)return;
    ascension.sampleAt+=dt;
    if(ascension.sampleAt<.5)return;
    ascension.sampleAt=0;
    var alive=ships.filter(function(s){return s.alive});
    var hull=alive.length?alive.reduce(function(a,s){return a+s.hull/Math.max(1,s.maxHull)},0)/alive.length:0;
    var coop=flight.mode==='formation'?1:0;
    ascension.cooperation=ascension.cooperation*.88+coop*.12;
    var threat=Math.min(1,(enemies.length+meteors.length*.6+bolts.length*.3)/18);
    ascension.pressure=Math.max(0,Math.min(1,threat*.55+(1-hull)*.45));
    // A tactical director must not punish struggling pilots: only a modest
    // increase in encounter tempo for healthy, coordinated formations.
    if(level===1||level===3||level===4){
      if(hull>.72&&ascension.cooperation>.72&&threat<.55)spawnT=Math.min(spawnT,.9);
    }
    ascension.phase=ascension.pressure>.72?'DEFENSIVE':ascension.cooperation>.7?'SYNCHRONIZED':'ADAPTIVE';
    var el=document.querySelector('#ascensionState');
    if(el)el.textContent=ascension.phase+' · THREAT '+Math.round(ascension.pressure*100)+'%';
  }

  function frame(t){if(!last)last=t;var dt=Math.max(0,Math.min(.033,(t-last)/1000));last=t;if(running){update(dt);updateAscension(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').textContent=metrics.separations;document.querySelector('#mCoord').textContent=metrics.coordinated;document.querySelector('#mContinuity').textContent=metrics.assistChecks?metrics.assistContinuity+'/'+metrics.assistChecks:'NO EVENTS';document.querySelector('#bScore').textContent=sessionBest.score;document.querySelector('#bKills').textContent=sessionBest.kills;document.querySelector('#bLevel').textContent=sessionBest.level;document.querySelector('#bTime').textContent=formatTime(sessionBest.time);document.querySelector('#bFormation').textContent=Math.round(sessionBest.formation)+'s';document.querySelector('#bReunions').textContent=sessionBest.reunions;document.querySelector('#bRescues').textContent=sessionBest.rescues;document.querySelector('#bShield').textContent=sessionBest.shield;document.querySelector('#bFriendly').textContent=sessionBest.friendly;var care=metrics.rescues+metrics.reunions+metrics.coordinated;document.querySelector('#result').textContent=victory?'Both pilots returned. '+(care?'You looked after each other '+care+' times.':'Formation is always waiting.'):'Both ships fell together at Level '+levelReache