<!-- SOLID CITY · part 2008 -->
ICES');
    }else if(summit.phase==='siege'){
      if(summit.ignition<1)summit.ignition=Math.min(1,summit.ignition+dt/1.294);
      updateShards(dt);if(summit.phase==='done')return;
      if(summit.spawnQueue>0){summit.spawnTimer-=dt;if(summit.spawnTimer<=0){spawnOne();summit.spawnTimer=.28}}
      else if(summit.shards.length===0){
        if(summit.wave<WAVES.length-1){summit.wave++;summit.spawnedThisWave=0;summit.spawnQueue=WAVES[summit.wave];summit.spawnTimer=1.6;toast('WAVE '+(summit.wave+1)+' OF 3 — HOLD');log('formation','Wave '+(summit.wave+1)+' of 3 · '+WAVES[summit.wave]+' shards','BEACON')}
        else openChoice();
      }
      setSummitText('WAVE '+(summit.wave+1)+' OF 3 — DEFEND THE BEACON · '+Math.round(summit.beaconHp)+'%');
    }else if(summit.phase==='choice'){
      summit.choiceTimer+=dt;
      if(summit.choiceTimer>15&&!summit.choice)makeChoice('hold');
    }else if(summit.phase==='pulse'){
      var an=summit.anchor;
      if(summit.pulseR===0){
        if(an&&dist(an,BEACON)<34){
          summit.pulseR=1;summit.beaconHp=100;
          an.hull=0;an.disabled=99999;an.vx=an.vy=0;an.x=BEACON.x;an.y=BEACON.y;
          summit.shards=[];
          for(var k2=0;k2<40;k2++){var pa2=Math.random()*6.283;sparks.push({x:BEACON.x+Math.cos(pa2)*40,y:BEACON.y+Math.sin(pa2)*40,vx:Math.cos(pa2)*260,vy:Math.sin(pa2)*260,life:.8,color:'gold'})}
          summit.lost.push({name:an.name,reason:'anchored the beacon core'});
          log('hit',an.name+' anchored the beacon core','BEACON');toast('THE CORE TAKES ITS ANCHOR');
        }
      }else{
        summit.pulseR+=dt*PHI*320;
        if(summit.pulseR>1000)endSummit('anchor');
      }
      setSummitText('THE CORE TAKES ITS ANCHOR');
    }else if(summit.phase==='final'){
      updateShards(dt);if(summit.phase==='done')return;
      if(summit.spawnQueue>0){summit.spawnTimer-=dt;if(summit.spawnTimer<=0){spawnOne();summit.spawnTimer=.22}}
      else if(summit.shards.length===0)endSummit('hold');
      setSummitText('THE LAST WAVE — NO SHIP RETURNS · '+Math.round(summit.beaconHp)+'%');
    }
  }
  function endSummit(kind){
    if(summit.phase==='done')return;
    summit.phase='done';running=false;paused=false;
    document.getElementById('pauseTrigger').hidden=true;
    document.getElementById('pauseOverlay').classList.remove('open');
    document.getElementById('summitBar').hidden=true;
    document.getElementById('summitChoices').hidden=true;
    var title,copy;
    if(kind==='fracture'){
      title='The constellation broke';
      copy='<b>The fleet endures:</b> '+ships.map(function(s){return s.name}).join(', ')+'.<br><b>Lost:</b> The Meridian Beacon — overrun by the storm.<br><span class="debt">The beacon went dark with the constellation. Form the octagon faster; spend the storm before it spends you.</span>';
    }else{
      var lostNames=summit.lost.map(function(l){return l.name});
      var home=ships.filter(function(s){return lostNames.indexOf(s.name)<0}).map(function(s){return s.name});
      if(kind==='anchor')title='The anchor holds';
      else title=summit.lost.length?'The debt remains':'The octagon holds';
      copy='<b>Home:</b> '+(home.length?home.join(', '):'No one')+'.<br><b>Lost:</b> '+(summit.lost.length?summit.lost.map(function(l){return l.name+' — '+l.reason}).join('; '):'No one')+'.';
      if(kind==='anchor')copy+='<br><span class="debt">One ship for the storm. The other seven fly because it held.</span>';
      else if(!summit.lost.length)copy+='<br><span class="debt">Eight ships, one constellation. Nothing was given that the storm could keep.</span>';
      else copy+='<br><span class="debt">They held the line. Their names stay on the board.</span>';
    }
    var d=Math.round(elapsedMs()/1000),hand=events.filter(function(e){return e.type==='handoff'}).length;
    copy+='<br><small>Mission time '+Math.floor(d/60)+'m '+d%60+'s · '+hand+' control handoffs · '+eventCounts.hit+' confirmed hits. Every figure is drawn from this battle ledger.</small>';
    document.getElementById('winner').textContent=title;
    document.getElementById('summary').innerHTML=copy;
    document.getElementById('debrief').classList.add('open');
    log('formation','Summit resolved · '+title,'BEACON');
  }
  function drawSummitField(ctx){
    if(!summit.active||summit.phase==='done')return;
    var i,a,vx,vy;
    ctx.save();
    ctx.strokeStyle='rgba(255,255,255,.22)';ctx.lineWidth=1;
    ships.forEach(function(s){if(s.disabled>0)return;var v=unionVertex(s);ctx.beginPath();ctx.moveTo(s.x,s.y);ctx.lineTo(v.x,v.y);ctx.stroke()});
    ctx.strokeStyle='rgba(255,201,82,.35)';ctx.lineWidth=2;ctx.beginPath();
    for(i=0;i<=8;i++){a=(i%8*45+22.5)*Math.PI/180;vx=BEACON.x+UNION_R*Math.cos(a);vy=BEACON.y+UNION_R*Math.sin(a);if(i===0)ctx.moveTo(vx,vy);else ctx.lineTo(vx,vy)}
    ctx.stroke();
    for(i=0;i<8;i++){a=(i*45+22.5)*Math.PI/180;vx=BEACON.x+UNION_R*Math.cos(a);vy=BEACON.y+UNION_R*Math.sin(a);
      var lit=summit.ignition