<!-- SOLID CITY · part 1548 -->
 catch (e) {}
  if (window.CityStarwell) try { CityStarwell.update(dt); } catch (e) {}
  if (window.CityHyperTrain) try { CityHyperTrain.update(dt); } catch (e) {}
  if (window.CitySolidSanctuary) try { CitySolidSanctuary.update(dt); } catch (e) {}
  if (window.CityAncestorRoads) try { CityAncestorRoads.update(dt); } catch (e) {}
  if (window.CityColosseum) try { CityColosseum.update(dt); } catch (e) {}
  if (window.CityImperialColosseum) try { CityImperialColosseum.update(dt); } catch (e) {}
  if (window.CityHiddenShip) try { CityHiddenShip.update(dt); } catch (e) {}
  if (window.CityVillageMauna) try { CityVillageMauna.update(dt); } catch (e) {}
  if (window.CityMountainHomes) try { CityMountainHomes.update(dt); } catch (e) {}
  if (window.CityGateAncestors) try { CityGateAncestors.update(dt); } catch (e) {}
  if (window.CityLanternVigil) try { CityLanternVigil.update(dt); } catch (e) {}
  if (window.CityCompassMeridian) try { CityCompassMeridian.update(dt); } catch (e) {}
  if (window.CityRoostKeel) try { CityRoostKeel.update(dt); } catch (e) {}
  if (window.CityOverlookMira) try { CityOverlookMira.update(dt); } catch (e) {}
  if (window.CityEighthGate) try { CityEighthGate.update(dt); } catch (e) {}
  if (window.CityHallBecoming) try { CityHallBecoming.update(dt); } catch (e) {}
  if (window.CityFoundry) try { CityFoundry.update(dt); } catch (e) {}
  if (window.CityHyperCity) try { CityHyperCity.update(dt); } catch (e) {}
  if (window.CityFirstCity) try { CityFirstCity.update(dt); } catch (e) {}
  if (window.CityFirstParking) try { CityFirstParking.update(dt); } catch (e) {}
  if (window.CityFirstWard) try { CityFirstWard.update(dt); } catch (e) {}
  if (window.CityWards) try { CityWards.update(dt); } catch (e) {}
  if (window.CitySkyward) try { CitySkyward.update(dt); } catch (e) {}
  if (window.CityJubilee) try { CityJubilee.update(dt); } catch (e) {}
  if (window.CityWardHouses) try { CityWardHouses.update(dt); } catch (e) {}
  if (window.CityAnnex) try { CityAnnex.update(dt); } catch (e) {}
  if (window.CityQuadrantCrown) try { CityQuadrantCrown.update(dt); } catch (e) {}
  if (window.CitySpaceport) try { CitySpaceport.update(dt); } catch (e) {}
  if (window.CityLostWings) try { CityLostWings.update(dt); } catch (e) {}
  if (window.CityOctaPool) try { CityOctaPool.update(dt); } catch (e) {}
  if (window.CitySolidFigure) try { CitySolidFigure.update(dt); } catch (e) {}
  if (window.CitySolidMirror) try { CitySolidMirror.update(dt); } catch (e) {}
  if (window.CityBetweenStones) try { CityBetweenStones.update(dt); } catch (e) {}
  // ship + avatar + sable placement (scene space = absolute - origin)
  ship.position.set(S.ship.x - origin.x, S.ship.y, S.ship.z - origin.z); ship.quaternion.copy(S.ship.q);
  var fl = S.mode === 'fly' || S.mode === 'auto' || S.mode === 'launch' || S.mode === 'watch' ? 0.6 + Math.min(S.ship.speed, 3000) / 1200 + (S.ship.boost ? 0.8 : 0) : S.mode === 'countdown' ? null : 0.01;
  if (fl !== null) shipFlames.forEach(function (f) { f.scale.set(1, Math.min(fl, 2.2) * (0.9 + Math.random() * 0.2), 1); });
  avatar.position.set(S.p.x - origin.x, S.p.y, S.p.z - origin.z);
  sable.position.set(SABLE_POS.x - origin.x, SABLE_POS.y + 0.1 + Math.sin(S.t * 1.3) * 0.06, SABLE_POS.z - origin.z);
  if (S.mode === 'walk') sable.rotation.y = Math.atan2(S.p.x - SABLE_POS.x, S.p.z - SABLE_POS.z);
  sable.userData.halo.rotation.z = S.t;
  for (var i = 0; i < animated.length; i++) animated[i](S.t);
  placeCamera(dt);
  updateTerrain({ x: camAbs.x, y: camAbs.y, z: camAbs.z }, MOBILE ? 4 : 6);
  updateHUD(dt);
  renderer.render(scene, camera);
  if (PERF) { renderer.getContext().finish(); workTimes.push(performance.now() - now0); if (workTimes.length > 600) workTimes.shift(); }
}

/* ---------------- boot ---------------- */
var cityBuilt = false;
function boot() {
  $('sc-load').textContent = 'Raising the capital…';
  setTimeout(function () {
    buildCity(); cityBuilt = true; try { dispatchEvent(new Event('sc-city-built')); } catch (e) {}
    $('sc-load').textContent = 'Generating the island chain…';
    setTimeout(function () {
      camAbs.set(0, 30, 60);
      for (var n = 0; n < 6; n++) updateTerrain({ x: 0, y: 30, z: 60 }, 120);
      buildMap();
      if (window.CityPlayer) { CityPlayer.mount($('sc-hud')); CityPlayer.onChange(function (s) { NP.playing = s.playing; if (NP.draw && (s.title !== NP.t || s.playing !== NP.p)) { NP.t = s.title; NP.p = s.playing; NP.draw(s.title, s.kind, s.playing); } }); setTimeout(function () { CityPlayer.preload(); }, 200); }
      $('sc-load').textContent = 'Ready.'; $('sc-enter').disabled = false;
      if (QS.get('back') === 'workshop') { S.p.x = D.workshop.x; S.p.z = D.workshop.z + 62; S.p.face = Math.atan2(-D.workshop.x, -D.workshop.z); } else if (QS.get('back') === 'strike') { S.p.x = D.strike.x; S.p.z = D.strike.z + 58; S.p.face = Math.atan2(-D.strike.x, -D.strike.z); }
      if (QS.has('auto')) enter();
    }, 30);
  }, 30)