<!-- SOLID CITY · part 2819 -->
seum coconut data): the
   * niu stands 10–20 m (to 30), trunk Ø 20–30 cm swelling
   * to 40–50 at the base, crown spread 6.7–10 m, and it
   * CURVES — storm and shore wind bend it. Ours: an 11 m
   * trunk (Ø 0.32/0.52 at the foot), a 6.8 m crown, lean
   * to 0.18 rad — a young giant's proportions, world-fit. */
  var palmTrunkGeo = new T.CylinderGeometry(0.16, 0.26, 11, 7); palmTrunkGeo.translate(0, 5.5, 0);
  var palmCrownGeo = new T.IcosahedronGeometry(2.6, 0); palmCrownGeo.scale(1.3, 0.30, 1.3);
  var palms = scatter(hiTier ? 110 : 60, function (x, z, h) { if (h < 2.5 || h > 90 || slope(x, z, h) > 0.6) return null; return { x: x, z: z, y: h, ry: R() * 6.28, s: 0.85 + R() * 0.45, la: R() * 6.28, ll: 0.04 + R() * 0.14 }; });
  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);
  var leafCanGeo = new T.IcosahedronGeometry(2.6, 2);
  hashJitter(leafCanGeo, 0.34, 3.1);
  var leafs = scatter(hiTier ? 150 : 85, function (x, z, h) { if (h < 3 || h > 150 || slope(x, z, h) > 0.7) return null; return { x: x, z: z, y: h, ry: R() * 6.28, s: 0.8 + R() * 0.7 }; });
  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);
  var leafCanopies = [];
  leafs.forEach(function (p) { leafCanopies.push({ x: p.x, z: p.z, y: p.y + 5.9 * p.s, s: p.s, ry: p.ry }); if (R() < 0.35) leafCanopies.push({ x: p.x + 1.9 * p.s, z: p.z + 0.9 * p.s, y: p.y + 4.6 * p.s, s: p.s * 0.62, ry: p.ry + 1 }); });
  instanced('leaf-canopies', leafCanGeo, lambert(0xffffff, { flatShading: true }), leafCanopies,
    function (d, p) { d.position.set(p.x, p.y, p.z); d.rotation.set(0, p.ry, 0); d.scale.set(p.s, p.s * 0.74, p.s); },
    function (c) { greens(c, 0.19, 0.13); });

  /* ——— PINES ———
   * Reason: high conifers run 20–40 m in life with the
   * crown starting a third up; at world scale ours stack
   * two cones over a 3.6 m trunk to ~11–13 m of spire. */
  var pineTrunkGeo = new T.CylinderGeometry(0.16, 0.28, 3.6, 7); pineTrunkGeo.translate(0, 1.8, 0);
  var pineConeGeo = new T.ConeGeometry(2.0, 5.4, 8); pineConeGeo.translate(0, 2.7, 0);
  var pines = scatter(hiTier ? 120 : 65, function (x, z, h) { if (h < 40 || h > 330 || slope(x, z, h) > 0.75) return null; return { x: x, z: z, y: h, ry: R() * 6.28, s: 0.9 + R() * 0.6 }; });
  counts.pines = pines.length; note('pines', pines);
  instanced('pine-trunks', pineTrunkGeo, trunkMat, pines,
    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);
  var pineMat = lambert(0xffffff, { flatShading: true });
  instanced('pine-cones-1', pineConeGeo, pineMat, pines,
    function (d, p) { d.position.set(p.x, p.y + 3.1 * p.s, p.z); d.rotation.set(0, p.ry, 0); d.scale.setScalar(p.s); },
    function (c) { greens(c, 0.10, 0.07); });
  instanced('pine-cones-2', pineConeGeo, pineMat, pines,
    function (d, p) { d.position.set(p.x, p.y + 6.6 * p.s, p.z); d.rotation.set(0, p.ry + 0.4, 0); d.scale.setScalar(p.s * 0.60); },
    function (c) { greens(c, 0.10, 0.07); });

  /* ——— THE MONKEY PODS: umbrella crowns on short giants ——— */
  var podTrunkGeo = new T.CylinderGeometry(1.05, 1.45, 5.2, 9); podTrunkGeo.translate(0, 2.6, 0);
  var podCanGeo = new T.IcosahedronGeometry(1, 1); hashJitter(podCanGeo, 0.22, 5.3);
  var pods = scatterGiants(hiTier ? 14 : 8, 80, function (x, z, h) { if (h < 3 || h > 120 || slope(x, z, h) > 0.5) return null; return { x: x, z: z, y: h, ry: R() * 6.28, cr: 10 + R() * 4.5 }; });
  counts.pods = pods.length; note('pods', pods, 14);
  instanced('pod-trunks', podTrunkGeo, lambert(0x5d4630), pods,
    function