<!-- SOLID CITY · part 3169 -->
. Kheiron's heart is the fortress again — at half scale. 4 · 2 · 1.",true);
  }
  function spawnSummitPhase(){
    var p=summitData[state.summitPhase];state.targets=[];selectedTarget=null;
    for(var i=0;i<p.count;i++){
      var a=(Math.PI*2*i/p.count)-Math.PI/2;
      state.targets.push({id:nextId++,type:p.type,x:.73+Math.cos(a)*p.ring,y:.5+Math.sin(a)*p.ring,hp:p.hp,max:p.hp,alive:true,angle:a});
    }
    record('PHASE_STARTED',{phase:'S'+(state.summitPhase+1),label:p.name});
    if(state.summitPhase===2){record('HEART_EXPOSED',{});advise('The heart is open and charging. LANCE to close in — or SCREEN to hold and vent the charge.',true);}
    else advise(state.summitPhase===0?'Inner ring acquired. Four turrets, half the sky.':'Heart generators located. Starve the heart.',false);
  }
  function startGame(){
    state=initialState();events=[];nextId=1;sessionStart=performance.now();state.running=true;spawnPhase();record('SIEGE_STARTED',{});document.getElementById('intro').classList.add('hidden');document.getElementById('ending').classList.add('hidden');document.getElementById('pauseOverlay').classList.add('hidden');document.getElementById('pauseGame').classList.remove('hidden');updateStations();last=performance.now();cancelAnimationFrame(raf);raf=requestAnimationFrame(loop);
  }
  function pauseGame(){if(!state||!state.running||state.paused)return;state.paused=true;cancelAnimationFrame(raf);document.getElementById('pauseOverlay').classList.remove('hidden');record('SIEGE_PAUSED',{});}
  function resumeGame(){if(!state||!state.running||!state.paused)return;state.paused=false;document.getElementById('pauseOverlay').classList.add('hidden');record('SIEGE_RESUMED',{});last=performance.now();raf=requestAnimationFrame(loop);}
  function resize(){var r=canvas.getBoundingClientRect();DPR=Math.min(2,window.devicePixelRatio||1);W=Math.max(320,r.width);H=Math.max(280,r.height);canvas.width=Math.round(W*DPR);canvas.height=Math.round(H*DPR);ctx.setTransform(DPR,0,0,DPR,0,0);if(!stars.length){for(var i=0;i<150;i++)stars.push({x:Math.random(),y:Math.random(),s:.3+Math.random()*1.3,a:.25+Math.random()*.7});}}
  function addShot(from,to,kind,owner,damage){state.shots.push({x:from.x,y:from.y,tx:to.x,ty:to.y,t:0,d:kind==='bombard'?.7:.28,kind:kind,owner:owner,damage:damage,target:to});}
  function fireBombard(owner){
    if(state.bombardCooldown>0||!state.running)return;
    var t=selectedTarget&&selectedTarget.alive?selectedTarget:firstAlive();if(!t)return;
    var mult=state.stance==='lance'?2.2:1;
    state.bombardCooldown=1.65;addShot({x:state.ship.x+.03,y:state.ship.y},t,'bombard',owner,Math.round(52*mult));record('BOMBARDMENT_FIRED',{owner:owner,target:t.type,epoch:tasks.bombard.epoch});
  }
  function strikeWings(owner){
    if(state.wingCooldown>0||state.wings<=0||!state.running)return;
    var t=selectedTarget&&selectedTarget.alive?selectedTarget:firstAlive();if(!t)return;
    var mult=state.stance==='lance'?2.2:1;
    state.wingCooldown=.72;addShot({x:state.ship.x+.045,y:state.ship.y+.02},t,'wing',owner,Math.round((9+Math.min(13,state.wings*.8))*mult));record('WING_STRIKE',{owner:owner,target:t.type,epoch:tasks.wings.epoch});
  }
  function firstAlive(){for(var i=0;i<state.targets.length;i++)if(state.targets[i].alive)return state.targets[i];return null;}
  function hitTarget(shot){
    var t=shot.target;if(!t||!t.alive)return;t.hp-=shot.damage;burst(t.x,t.y,shot.kind==='bombard'?'#ffb33b':'#2de2d5',shot.kind==='bombard'?18:7);
    if(shot.kind==='bombard')record('BOMBARDMENT_HIT',{owner:shot.owner,target:t.type,damage:shot.damage});
    if(t.hp<=0){t.hp=0;t.alive=false;record('TARGET_DESTROYED',{owner:shot.owner,target:t.type,phase:state.phase+1,summit:state.summit?1:0});advise((shot.owner==='HUMAN'?'Direct hit. ':'AI strike confirmed. ')+t.type.toUpperCase()+' destroyed.');checkPhase();}
  }
  function checkPhase(){
    if(state.targets.some(function(t){return t.alive}))return;
    if(state.summit){
      record('PHASE_COMPLETED',{phase:'S'+(state.summitPhase+1),duration:state.time});
      if(state.summitPhase===2){endGame(true);return;}
      state.summitPhase++;state.ship.shield=Math.min(state.ship.maxShield,state.ship.shield+40);state.phaseDelay=.85;return;
    }
    record('PHASE_COMPLETED',{phase:state.phase+1,duration:state.time});
    if(state.phase===2){beginSummit();return;}
    state.phase++;state.ship.shield=Math.min(state.ship.maxShield,state.ship.shield+70);state.phaseDelay=.85;
  }
  function enemyFire(){
    var alive=state.targets.filter(function(t){return t.alive});if(!alive.length)return;
    var origin,damage;
    if(state.summit&&state.summitPhase===2){origin=firstAlive();}
    else{origin=alive[Math.floor(Math.random()*alive.length)];}
    if(state.summit){damage=state.summitPhase===0?28:state.summitPhase===1?34:42;}
    else{damage=state.phase===0?12:state.phase===1?17:23;}
    if(state.stance==='lance')damage=Math.round(damage*2.2);
    var aim={x:state.ship.