<!-- SOLID CITY · part 2814 -->
eometry(0.16, 0.26, 11, 7); palmTrunkGeo.translate(0, 5.5, 0); /* the palm's curve is its lean — the crown math follows the lean exactly, so no baked bend here */
  var palmCrownGeo = new T.IcosahedronGeometry(2.6, 0); palmCrownGeo.scale(1.3, 0.30, 1.3); fbmDisplace(palmCrownGeo, 0.55, 0.2, 6.1, 1);
  var palms = scatter(hiTier ? 110 : 60, function (x, z, h) { if (h < 2.5 || h > 90 || slope(x, z, h) > 0.6) return null; var ry = R() * 6.28, s = 0.85 + R() * 0.45, la = R() * 6.28, ll = 0.04 + R() * 0.14; var st = seatSettle(x, z, h, 0.26 * s, 0.12, 0.6); return { x: x, z: z, y: h - st, ry: ry, s: s, la: la, ll: ll }; });
  counts.palms = palms.length; note('palms', palms);
  var trunkMat = lambert(0x6e5136);
  instanced('palm-trunks', palmTrunkGeo, trunkMat, palms,
    function (d, p) { d.position.set(p.x, p.y - 0.1, p.z); d.rotation.set(Math.sin(p.la) * p.ll, p.ry, Math.cos(p.la) * p.ll); d.scale.setScalar(p.s); }, null);
  instanced('palm-crowns', palmCrownGeo, lambert(0xffffff, { flatShading: true }), palms,
    function (d, p) { var dx = Math.sin(p.ll) * Math.cos(p.la) * 11 * p.s, dz = Math.sin(p.ll) * Math.sin(p.la) * 11 * p.s; d.position.set(p.x + dx * 0.94, p.y + 11 * p.s - 0.2, p.z + dz * 0.94); d.rotation.set(0, p.ry, 0); d.scale.setScalar(p.s); },
    function (c) { greens(c, 0.22, 0.12); });

  /* ——— BROADLEAF ———
   * Researched (forestry allometry): a mature broadleaf
   * carries its crown at roughly 9–12× its trunk diameter
   * across, the crown WIDER THAN IT IS TALL in the open,
   * and no two crowns alike. The first build read as a
   * balloon on a stick (the King's photo): trunk too thin
   * (Ø 0.34 at the foot), crown a perfect ball. Now: trunk
   * Ø 0.6/0.96, crown Ø ~5.2·s flattened to 0.74 and broken
   * by position-hashed jitter, so each crown is its own. */
  var leafTrunkGeo = new T.CylinderGeometry(0.30, 0.48, 4.6, 8); leafTrunkGeo.translate(0, 2.3, 0); bendGeo(leafTrunkGeo, 0.42, 4.6);
  var leafCanGeo = new T.IcosahedronGeometry(2.6, 2);
  integrity.leafTear = fbmDisplace(leafCanGeo, 0.5, 0.34, 3.1, 1);
  var leafs = scatter(hiTier ? 150 : 85, function (x, z, h) { if (h < 3 || h > 150 || slope(x, z, h) > 0.7) return null; var ry = R() * 6.28, s = 0.8 + R() * 0.7; var st = seatSettle(x, z, h, 0.48 * s, 0.12, 0.6); return { x: x, z: z, y: h - st, ry: ry, s: s }; });
  counts.leafs = leafs.length; note('leafs', leafs);
  instanced('leaf-trunks', leafTrunkGeo, trunkMat, leafs,
    function (d, p) { d.position.set(p.x, p.y - 0.1, p.z); d.rotation.set(0, p.ry, 0); d.scale.setScalar(p.s); }, null);
  /* THE LOBES — "filling spaces in between creating
   * dimensions of leaves and shapes" (the King's words):
   * every crown is a heart lobe where the bent trunk tops
   * out, plus 3–4 satellite lobes seeded through the
   * crown's ellipsoid, each its own fbm-broken leaf mass,
   * sky showing between them — the crown's volume FILLED
   * with leaf dimensions instead of one solid ball. */
  var leafCanopies = [], branches = [], leafSpawns = [];
  var UPV = new T.Vector3(0, 1, 0), DV = new T.Vector3();
  function branchTo(arr, bx2, by2, bz2, tx, ty, tz) {
    var dx = tx - bx2, dy = ty - by2, dz = tz - bz2, len = Math.sqrt(dx * dx + dy * dy + dz * dz) || 1;
    arr.push({ x: bx2, y: by2, z: bz2, dx: dx / len, dy: dy / len, dz: dz / len, len: len, s: 1 });
  }
  leafs.forEach(function (p) {
    var bx = Math.cos(p.ry) * 0.42 * p.s, bz = -Math.sin(p.ry) * 0.42 * p.s;
    var hx = p.x + bx, hz = p.z + bz, hy = p.y + 5.9 * p.s;
    leafCanopies.push({ x: hx, z: hz, y: hy, s: p.s, ry: p.ry });
    leafSpawns.push({ x: hx, y: hy, z: hz });
    /* TRUE BRANCHES (the Algorithmic Beauty of Plants:
     * the crown is HELD UP by wood — limbs leave the trunk
     * below its bend-top and reach INTO the lobes they
     * carry, so leaf and limb tell one story) */
    var baseX = p.x + bx * 0.87, baseY = p.y + 4.3 * p.s, baseZ = p.z + bz * 0.87;
    branchTo(branches, baseX, baseY, baseZ, hx, hy - 0.5 * p.s, hz); branches[branches.length - 1].s = p.s;
    var nl = 3 + Math.floor(R() * 2);
    for (var li = 0; li < nl; li++) {
      var la2 = R() * Math.PI * 2, lr = (0.45 + R() * 0.4) * 2.6 * p.s;
      var sx = hx + Math.cos(la2) * lr, sz = hz + Math.sin(la2) * lr, sy = hy + (R() - 0.62) * 1.5 * p.s;
      leafCanopies.push({ x: sx, z: sz, y: sy, s: p.s * (0.42 + R() * 0.2), ry: R() * 6.28 });
      if (li < 2) { branchTo(branches, baseX, baseY - 0.3 * p.s, baseZ, sx, sy - 0.3 * p.s, sz); branches[branches.length - 1].s = p.s; }
    }
  });
  counts.branches = branches.length;
  var branchGeo = new T.CylinderGeometry(0.055, 0.12, 1, 5); branchGeo.translate(0, 0.5, 0);
  instanced('leaf-branches', branchGeo, trunkMat, branches,
    function (d, p) { DV.set(p.dx, p.dy, p.dz); d.quaternion.setFromUnitVectors(UPV, DV); d.position.set(p.x, p.y, p.z); d.scale.set(p.s, p.len, p.s); }, null);
  instanced('leaf-canopies', leafCanGeo, lambert(0xffffff, { flatShading: true }