<!-- SOLID CITY · part 3635 -->
on.set(x, ty, z);
    g.rotation.y = R() * Math.PI * 2;
    root.add(g); trees.push(g);
    foot.push([x, z, trunkR * 2.6, trunkR * 2.6, ty, ty + trunkH, 0]);
  }
  function ohiaTree(x, z, ty, h) {
    var g = new T.Group();
    var trunkH = h * 0.30, trunkR = 1.3 + h * 0.024;
    var trunk = new T.Mesh(new T.CylinderGeometry(trunkR * 0.7, trunkR, trunkH, 8), trunkMat);
    trunk.position.y = trunkH / 2; g.add(trunk);
    var n = 3, cr = h * 0.22;
    for (var i = 0; i < n; i++) {
      var s = new T.Mesh(new T.SphereGeometry(cr * (1 - i * 0.18), 10, 8), i % 2 ? leafMat : leafDeepMat);
      s.position.set((R() - 0.5) * cr * 0.9, trunkH + cr * 0.75 + i * cr * 0.55, (R() - 0.5) * cr * 0.9);
      s.scale.y = 0.82; g.add(s);
    }
    g.position.set(x, ty, z);
    root.add(g); trees.push(g);
    foot.push([x, z, trunkR * 2.6, trunkR * 2.6, ty, ty + trunkH, 0]);
  }
  // scatter: ring r=130..300 around village center, plus groves between terraces
  var placed = 0, guard = 0;
  function clearOf(x, z) {
    // keep off terraces (r 60 + margin) and the road corridor
    for (var i = 0; i < TER.length; i++) {
      if (Math.hypot(x - TER[i].x, z - TER[i].z) < TER[i].r + 14) return false;
    }
    return true;
  }
  while (placed < 96 && guard++ < 900) {
    var a = R() * Math.PI * 2, rr = 130 + R() * 170;
    var tx = Math.cos(a) * rr, tz = Math.sin(a) * rr;
    if (!clearOf(tx, tz)) continue;
    // the Bore's corridor: keep the tunnel's perfect line clear (bore tie-in, 2026-10-11)
    // nudges consume no RNG — the forest is otherwise exactly as the King saw it
    if (Math.abs(tx) < 18 && tz < -100 && tz > -340) tx += tx < 0 ? -16 : 16;
    // elders: first 10 are the truly massive ones
    var h = placed < 10 ? 37 + R() * 5 : 25 + R() * 12;
    var ty = -20 - R() * 30;  // trees root into the mountainside around the terraces
    if (R() < 0.55) pineTree(tx, tz, ty, h); else ohiaTree(tx, tz, ty, h);
    placed++;
  }
  // a few ancients standing close among the huts (edges only)
  [[-52, -40, -14], [52, 30, -14], [-55, 60, -30], [55, 120, -32]].forEach(function (p) {
    var h = 34 + R() * 6;
    if (R() < 0.5) pineTree(p[0], p[1], p[2], h); else ohiaTree(p[0], p[1], p[2], h);
  });

  // ---------- switchback road: climbs C → B → A ----------
  var roadMat = new T.MeshLambertMaterial({ color: 0x4a3f30 });
  function roadSeg(x1, z1, y1, x2, z2, y2, w) {
    w = w || 9;
    var len = Math.hypot(x2 - x1, z2 - z1);
    var seg = new T.Mesh(new T.BoxGeometry(len, 1.1, w), roadMat);
    seg.position.set((x1 + x2) / 2, (y1 + y2) / 2 - 0.2, (z1 + z2) / 2);
    seg.rotation.y = -Math.atan2(z2 - z1, x2 - x1);
    // pitch to follow the climb
    var pitch = Math.atan2(y2 - y1, len);
    seg.rotateOnAxis(new T.Vector3(0, 0, 1), 0); // keep flat-ish; terraces carry the height
    root.add(seg);
  }
  // road path: enters low from the south, switchbacks up
  var P1 = [0, 150, -36], P2 = [-44, 120, -36], P3 = [-44, 40, -27],
      P4 = [40, 40, -27], P5 = [40, -40, -9], P6 = [-36, -40, -9], P7 = [-36, -85, 0], P8 = [-20, -120, 2], P9 = [8, -150, 6], P10 = [24, -175, 10];
  var path = [P1, P2, P3, P4, P5, P6, P7, P8, P9, P10];
  for (var sgi = 0; sgi < path.length - 1; sgi++) {
    var A0 = path[sgi], B0 = path[sgi + 1];
    roadSeg(A0[0], A0[1], A0[2], B0[0], B0[1], B0[2]);
  }
  // torches along the road
  var torches = [];
  path.forEach(function (p, idx) {
    if (idx % 2) return;
    [6.5, -6.5].forEach(function (off) {
      var pole = new T.Mesh(new T.CylinderGeometry(0.22, 0.3, 4.6, 6), woodDarkMat);
      pole.position.set(p[0] + off, p[2] + 2.3, p[1]); root.add(pole);
      var fl = new T.Mesh(new T.ConeGeometry(0.55, 1.7, 8),
        new T.MeshBasicMaterial({ color: C.fire, transparent: true, opacity: 0.92 }));
      fl.position.set(p[0] + off, p[2] + 5.3, p[1]); fl.name = 'flame'; root.add(fl);
      var pl = new T.PointLight(0xff9a40, 1.0, 34);
      pl.position.set(p[0] + off, p[2] + 5.6, p[1]); root.add(pl);
      torches.push({ fl: fl, pl: pl, seed: R() * 10 });
      foot.push([p[0] + off, p[1], 0.9, 0.9, p[2], p[2] + 4.6, 0]);
    });
  });

  // ---------- NEW HUTS: two clusters off the road ----------
  hut(-56, 14, -18, 2.6, 1); hut(-62, -16, -18, 1.2, 0.95);
  hut(56, 12, -18, -0.8, 1.05); hut(62, -18, -18, 2.2, 0.9);
  hut(52, 132, -36, -2.4, 1); hut(64, 108, -36, 0.8, 0.95);
  hut(-52, 134, -36, 2.4, 1.05); hut(-64, 110, -36, -0.6, 0.9);

  // ---------- WATERFALL: upper slope above Terrace A ----------
  var falls = [];
  (function () {
    var fx = 24, fz = -196;
    var cliff = new T.Mesh(new T.BoxGeometry(46, 52, 10), basaltMat);
    cliff.position.set(fx, 22, fz - 8); root.add(cliff);
    foot.push([fx, fz - 8, 46, 10, -4, 48, 0]);
    var sheet = new T.Mesh(new T.PlaneGeometry(9, 44),
      new T.MeshBasicMaterial({ color: 0xbfe8ff, transparent: true, opacity: 0.8 }));
    sheet.position.set(fx, 22, fz - 2.4); sheet.rotation.x = 0.06; root.add(sheet);
    falls.