<!-- SOLID CITY · part 2189 -->
 m < 1000 ? Math.round(m) + ' m' : (m / 1000).toFixed(m < 10000 ? 1 : 0) + ' km'; }

/* ---------------- places ---------------- */
function toward(x, z, tx, tz, d) { var dx = tx - x, dz = tz - z, l = Math.hypot(dx, dz) || 1; return { x: x + dx / l * d, z: z + dz / l * d }; }
function gateOf(d) { for (var i = 0; i < A.portals.length; i++) if (A.portals[i].d === d) return A.portals[i]; return { x: d.x, z: d.z }; }
var gF = gateOf(D.plaza), gS = gateOf(D.studio), gP = gateOf(D.port), PT = D.port, ST = D.studio, SB = A.SABLE_POS;
var M0 = A.RADIO_MASTS[0] || { x: ST.x + 60, z: ST.z };
var POIS = [
  { id: 'plaza', name: 'Forum Plaza', short: 'PLAZA', x: 0, z: 0, stand: { x: 6, z: 8 }, alias: 'forum plaza square hub centre center home', text: 'The heart of Solid City: six open pavilions (posts and canopies, no walls; Solidivism) around the Crest Obelisk. The real epistles Forum is through the Forum gate.' },
  { id: 'sable', name: 'SABLE', short: 'SABLE', x: SB.x, z: SB.z, stand: toward(SB.x, SB.z, 0, 0, 4), alias: 'sable guide npc ai her', text: 'The city\u2019s AI guide. Walk up to her or tap her to talk (talking needs an epistles login).', act: 'talk' },
  { id: 'obelisk', name: 'Crest Obelisk', short: 'OBELISK', x: 0, z: 22, stand: { x: 7, z: 30 }, alias: 'crest obelisk monument', text: 'A 26 m black obelisk on a gold plinth, crowned by the turning red crest.' },
  { id: 'forumgate', name: 'Forum gate', short: 'FORUM GATE', x: gF.x, z: gF.z, stand: toward(gF.x, gF.z, 0, 0, 8), url: '/', go: 'ENTER THE FORUMS', alias: 'forum gate forums boards threads', text: D.plaza.text },
  { id: 'studio', name: 'Music Studio Tower', short: 'STUDIO', x: ST.x, z: ST.z, stand: toward(gS.x, gS.z, 0, 0, 9), url: '/ss', go: 'OPEN THE FULL MUSIC STUDIO', alias: 'music studio tower solid sound ss radio songs king', text: 'Solid Sound: write, record, sing and sell your songs. The tower\u2019s rings pulse with Studio Radio; its gate opens the full Music Studio (/ss).' },
  { id: 'masts', name: 'Radio masts', short: 'MASTS', x: M0.x, z: M0.z, stand: toward(M0.x, M0.z, ST.x, ST.z, -7), alias: 'radio mast masts antenna antennas', text: 'Three solid 90 m masts ring the tower. Stand near one and Studio Radio gets up to 30% louder.' },
  { id: 'soul', name: 'Soul Print Tower', short: 'SOUL PRINT', x: D.soul.x, z: D.soul.z, stand: toward(D.soul.x, D.soul.z, 0, 0, 29), alias: 'soul print soulprint tower her companion', text: 'Soul Print’s 140 m tower: wine-red chrome wrapped in gold chains, a blue eye on top. Walk up to the glowing door to talk with her (needs an epistles login).', act: 'soul' },
  { id: 'port', name: 'Orbital Spaceport', short: 'SPACEPORT', x: PT.x, z: PT.z, stand: { x: PT.x + 10, z: PT.z + 14 }, alias: 'orbital spaceport space port ship pad launch rocket fly flight', text: 'Board a ship, press the big red LAUNCH, and fly anywhere: the volcanoes, the outer isles, above the atmosphere.', act: 'board' },
  { id: 'ctower', name: 'Control tower', short: 'CONTROL', x: PT.x - 60, z: PT.z - 30, stand: toward(PT.x - 60, PT.z - 30, PT.x, PT.z, 14), alias: 'control tower emblem banner', text: 'Spaceport control, flying the King\u2019s emblem banner.' },
  { id: 'hangar', name: 'Hangar', short: 'HANGAR', x: PT.x + 73, z: PT.z + 35, stand: { x: PT.x + 73, z: PT.z + 35 }, alias: 'hangar', text: 'An open hangar under a gold roof on four posts.' },
  { id: 'warp', name: 'Warp Speed gate', short: 'WARP GATE', x: gP.x, z: gP.z, stand: toward(gP.x, gP.z, PT.x, PT.z, 8), url: '/warpspeed', go: 'PLAY WARP SPEED', alias: 'warp speed warpspeed arcade game gate', text: D.port.text }
];
function P(id) { for (var i = 0; i < POIS.length; i++) if (POIS[i].id === id) return POIS[i]; }
var ROMAN = ['II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X'];
function bearing(x, z) { var a = Math.atan2(x - 8600, -z), d = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']; return d[(Math.round(a / (Math.PI / 4)) + 8) % 8]; }
var FLY = [
  { id: 'home', name: 'Home: land at the Orbital Spaceport', short: 'HOME', x: PT.x, z: PT.z, home: true, alias: 'home spaceport land landing base port', text: 'Autopilot lands you on the spaceport pad.' },
  { id: 'city', name: 'Solid City', short: 'SOLID CITY', x: 60, z: -60, alt: Y + 460, alias: 'solid city city capital town', text: 'The King\u2019s capital on the west coast of the main island.' }
];
A.VOLCANOES.forEach(function (v) {
  if (!v.name) return; var nm = v.name.charAt(0) + v.name.slice(1).toLowerCase().replace(/ (\S)/g, function (m, c) { return ' ' + c.toUpperCase(); });
  FLY.push({ id: fold(v.name).replace(/\W+/g, ''), name: nm, short: v.name, x: v.x, z: v.z, alt: Math.max(0, A.heightAt(v.x, v.z)) + 650, volcano: true, alias: fold(v.name) + ' volcano', text: (v.crater ? 'An active crater: watch the lava glow. ' : 'A shield volcano, ') + 'about ' + (Math.round(A.heightAt(v.x, v.z) / 100) / 10).toFixed(1) + ' km high.' });
});
A.ISLANDS.forEach(function (isl, k) {
  if (isl.main) r