<!-- SOLID CITY · part 1970 -->
dden) return;
  var c = A.camera.position, d = Math.hypot(c.x + A.origin.x - POS.x, c.z + A.origin.z - (POS.z + 122));
  M.group.visible = d < 9000;
  if (d < 3200 && M.group.userData.update) try { M.group.userData.update(S.t); } catch (e) {}
  if (M.outBtn) M.outBtn.style.display = (window.CityDrive && CityDrive.active()) ? 'block' : 'none';
  if (S.mode === 'walk' && !S.drive) {
    var pd = Math.hypot(S.p.x - POS.x, S.p.z - (POS.z + 122));
    if (pd < 300 && !M.said) { M.said = true; if (window.CityHyper && CityHyper.narrate) CityHyper.narrate('<b>The South Lot</b>: fourteen rides under the First City. Walk to one and roll \u2014 the Long Road runs east to the capital.', 10); }
    else if (pd > 600) M.said = false;
  }
}
function radar(g, blip, fl) { if (M.state === 'ready') blip(POS.x, POS.z + 122, '#ffd27a', fl ? 3 : 6, fl ? '' : 'SOUTH LOT'); }
window.CityFirstParking = { update: update, radar: radar, standY: standY, actHere: actHere, act: act, pos: POS, state: function () { return M.state; } };
})();


===== FILE: public/city/first-city-parking-place.js.bak-stalllamp-20261013 =====
/* Solid City — places THE SOUTH LOT (public/city/first-city-parking.js) below
   the First City's southern edge: apron, ramp, lot, rides, the Long Road.
   Also lends the First City's podium a standY, so a walker can travel
   shelf -> ramp -> apron -> podium: the edge the King found is fixed.
   Rides roll through window.CityDrive (city.js): walk to a car, the action
   button rolls; the action button (or the STEP OUT button) steps you out. */
(function () {
'use strict';
if (!window.SC || !SC.api) return;
var A = SC.api, S = A.S;
var POS = { x: -1300, z: -620 };            // the podium's south edge centre
var FC = { x: -1300, z: -1000 };            // the First City itself
var M = { state: 'idle', group: null, wait: 9.5, gy: null, said: false, outBtn: null };
function firstCityDeckY() {
  if (M.gy !== null) return M.gy;
  var g = (typeof groundAt === 'function') ? groundAt : null;
  if (!g) { M.gy = 20; return M.gy; }
  var max = -1000, h, ix, iz;
  for (ix = -3; ix <= 3; ix++) for (iz = -3; iz <= 3; iz++) {
    try { h = g(FC.x + ix * 70, FC.z + iz * 127); } catch (e) { h = 20; }
    if (h > max) max = h;
  }
  M.gy = max + 1.0;   // the podium deck surface, sampled exactly as its placer samples
  return M.gy;
}
function addBox(cx, cz, w, d, rot, y0, y1) {
  var out = [];
  var nx = Math.max(1, Math.ceil(w / 2.5)), nz = Math.max(1, Math.ceil(d / 2.5)), cw = w / nx, cd = d / nz, c = Math.cos(rot), s = Math.sin(rot);
  var hx = cw / 2 * Math.abs(c) + cd / 2 * Math.abs(s), hz = cw / 2 * Math.abs(s) + cd / 2 * Math.abs(c);
  for (var i = 0; i < nx; i++) for (var j = 0; j < nz; j++) {
    var ox = -w / 2 + cw * (i + 0.5), oz = -d / 2 + cd * (j + 0.5), lx = cx + ox * c + oz * s, lz = cz - ox * s + oz * c;
    var e = { x0: POS.x + lx - hx, x1: POS.x + lx + hx, z0: POS.z + lz - hz, z1: POS.z + lz + hz, y0: y0, y1: y1, firstParking: true };
    A.solids.push(e); out.push(e);
  }
  return out;
}
function removeSolids(list) {
  if (!list) return;
  list.forEach(function (e) { var i = A.solids.indexOf(e); if (i >= 0) A.solids.splice(i, 1); });
}
function collide(ud) {
  (ud.footprint || []).forEach(function (b) {
    var entries = addBox(b[0], b[1], b[2], b[3], b[6] || 0, b[4], b[5]);
    if (b[7] && String(b[7]).indexOf('car:') === 0) {
      var id = String(b[7]).slice(4);
      (ud.cars || []).forEach(function (car) { if (car.id === id) car.solids = entries; });
    }
  });
  // the lot's retaining edges (below-deck walls; the ramp gap stays open)
  var ly = ud.lotY;
  addBox(-74.5, 73, 131, 2, 0, ly - 4, ly - 0.1);
  addBox(74.5, 73, 131, 2, 0, ly - 4, ly - 0.1);
  addBox(0, 171, 280, 2, 0, ly - 4, ly - 0.1);
  addBox(-139, 122, 2, 100, 0, ly - 4, ly - 0.1);
  addBox(139, 122, 2, 100, 0, ly - 4, ly - 0.1);
}
function hyperStop() {
  var H = window.CityHyper; if (!H || !H.pois || H.pois.some(function (p) { return p.id === 'south-lot'; })) return;
  H.pois.push({ id: 'south-lot', name: 'The South Lot', short: 'SOUTH LOT', x: POS.x, z: POS.z + 122, stand: { x: POS.x, z: POS.z + 100 },
    alias: 'south lot parking rides cars dart hauler long road first city parking',
    text: 'The South Lot, under the First City\u2019s southern edge: fourteen futuristic rides waiting in the stalls. Walk to one and roll \u2014 the Long Road runs east from the lot to the capital shelf.' });
  if (H.regrid) H.regrid();
}
function outButton() {
  if (M.outBtn) return M.outBtn;
  var b = document.createElement('button');
  b.textContent = 'STEP OUT \u2B07';
  b.style.cssText = 'position:fixed;left:50%;bottom:212px;transform:translateX(-50%);z-index:60;display:none;padding:12px 22px;border-radius:24px;border:2px solid #d8aa48;background:rgba(12,14,20,0.88);color:#ffd873;font:700 15px Georgia,serif;letter-spacing:1px;';
  b.addEventListener('pointerdown', function (ev) { ev.preventDefault(); act(); });
  document.bo