<!-- SOLID CITY · part 1975 -->
en3 + 1.5, 0.07, 0.35), lineWhite);
      edge.position.set(0, 0.04, ez); pitchG.add(edge);
    });
    root.add(grp);
    roadSegs.push({ x1: x1, z1: z1, y1: y1, x2: x2, z2: z2, y2: y2 });
  }
  var RX = 140, RZ = 122;                 // road starts at the lot's east edge, on the lane line
  var roadPts = [[RX, RZ, lotY]];
  for (var rx = RX + 30; rx <= 612; rx += 30) roadPts.push([rx, RZ, groundY(rx, RZ) + 0.32]);
  for (var pi2 = 0; pi2 < roadPts.length - 1; pi2++) {
    addRoadSlab(roadPts[pi2][0], roadPts[pi2][1], roadPts[pi2][2], roadPts[pi2 + 1][0], roadPts[pi2 + 1][1], roadPts[pi2 + 1][2], 0);
  }
  zones.push({ kind: 'road', segs: roadSegs });
  // junction disc on the capital shelf
  var jx = 628, jz = RZ, jy = groundY(jx, jz) + 0.3;
  var disc = new T.Mesh(new T.CylinderGeometry(16, 16, 0.5, 24), asphalt2);
  disc.position.set(jx, jy - 0.25, jz); root.add(disc);
  var discRing = new T.Mesh(new T.TorusGeometry(15.4, 0.35, 6, 32), goldTrim);
  discRing.rotation.x = Math.PI / 2; discRing.position.set(jx, jy + 0.05, jz); root.add(discRing);
  zones.push({ kind: 'flat', x0: jx - 16, x1: jx + 16, z0: jz - 16, z1: jz + 16, y: jy });
  standingPlate('TO THE CAPITAL', jx - 10, jz - 14, jy, 0.5, 34);
  standingPlate('THE LONG ROAD', RX + 8, RZ - 12, lotY, -0.6, 34);

  root.userData = {
    footprint: foot,
    zones: zones,
    cars: cars,
    lotY: lotY,
    deckY: deckY,
    update: function (t) {
      var p = 0.26 + 0.09 * Math.sin(t * 1.7);
      for (var i = 0; i < glowMats.length; i++) glowMats[i].opacity = p;
    }
  };
  return root;
}
export default createFirstParking;


===== FILE: public/city/first-city-parking.js.bak-stalllamp-20261013 =====
/* SOLID CITY — THE SOUTH LOT (2026-10-13, by order of the King)
 * The First City's podium ended in a sheer edge over the brown shelf — too big
 * for a walker to travel over. The King's answer: do something amazing in the
 * brown area. A parking lot of futuristic rides, designed so the avatar — the
 * real human of this world — can jump in one and roll.
 * Local frame: origin at the podium's south edge centre (world -1300,-620).
 * +X = east (toward the capital), +Z = south (toward the lot and the road).
 * Contents: a flush APRON at podium-deck height, a RAMP down to the shelf,
 * the SOUTH LOT (stalls, lamps, signs), 14 RIDES (Darts + Haulers, true
 * avatar scale, seats + dash inside the glass), and THE LONG ROAD east —
 * pitched to the land, slab by slab — to a junction on the capital shelf.
 * The podium itself is walkable through the placer's standY: the edge is fixed.
 */
export function createFirstParking(o) {
  var T = o.THREE, groundAt = o.groundAt, deckY = o.deckY;
  var root = new T.Group(); root.name = 'first-city-parking';
  var foot = [];       // collision footprints (local): [x,z,w,d,y0,y1,rot]
  var zones = [];      // stand zones for the placer
  var cars = [];       // the rides
  var R = (function (a) { return function () { a |= 0; a = a + 0x6D2B79F5 | 0; var t = Math.imul(a ^ a >>> 15, 1 | a); t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t; return ((t ^ t >>> 14) >>> 0) / 4294967296; }; })(4242);

  function textPlate(text, w) {
    var c = document.createElement('canvas'); c.width = 512; c.height = 128;
    var g = c.getContext('2d');
    g.fillStyle = '#101418'; g.fillRect(0, 0, 512, 128);
    g.strokeStyle = '#d8aa48'; g.lineWidth = 5; g.strokeRect(7, 7, 498, 114);
    g.fillStyle = '#e8c86a'; g.textAlign = 'center'; g.textBaseline = 'middle';
    g.font = 'bold ' + (w || 40) + 'px Georgia,serif'; g.fillText(text, 256, 66);
    var t = new T.CanvasTexture(c); t.encoding = T.sRGBEncoding; t.anisotropy = 4; return t;
  }
  function plateMesh(text, w, h, fs) {
    var m = new T.Mesh(new T.PlaneGeometry(w, h), new T.MeshBasicMaterial({ map: textPlate(text, fs) }));
    return m;
  }

  // ---------- materials ----------
  var asphalt = new T.MeshLambertMaterial({ color: 0x23262e });
  var asphalt2 = new T.MeshLambertMaterial({ color: 0x2b2f38 });
  var concrete = new T.MeshLambertMaterial({ color: 0x3a3f47 });
  var steel = new T.MeshLambertMaterial({ color: 0x596270 });
  var gold = new T.MeshLambertMaterial({ color: 0xd8aa48, emissive: 0x4a2e08, emissiveIntensity: 0.7 });
  var goldTrim = new T.MeshBasicMaterial({ color: 0xd8aa48 });
  var lineWhite = new T.MeshBasicMaterial({ color: 0xdfe6ee });
  var darkGlass = new T.MeshLambertMaterial({ color: 0x14222e, emissive: 0x0a141c, transparent: true, opacity: 0.86 });
  var tyreM = new T.MeshLambertMaterial({ color: 0x0c0d10 });
  var seatM = new T.MeshLambertMaterial({ color: 0x1c1f26 });
  var dashM = new T.MeshLambertMaterial({ color: 0x14161c });

  // ---------- THE APRON (flush with the podium deck) ----------
  var APRON = { x0: -140, x1: 140, z0: 0, z1: 26 };
  var apron = new T.Mesh(new T.BoxGeometry(280, 40, 26), concrete);
  apron.position.set(0, deckY - 20, 13); root.add(apron);
  var apronLip = new T.Mesh(new T.BoxGeometry(280, 0.35, 1.2), g