<!-- LIVE · part 37 -->
sin(ga)*r*0.5);
        gully.rotation.y = -ga;
        gully.rotation.z = 0.3;
        scene.add(gully);
      }
    }

    /* CANYON LAYERS — wedding cake cliffs (Grand Canyon) */
    function canyonLayers(x, z, w, h){
      var layers = [
        {mat: limestoneMat, h: h*0.2},  /* Kaibab Limestone — cliff */
        {mat: shaleMat, h: h*0.15},     /* Shale — slope */
        {mat: sandstoneMat, h: h*0.25}, /* Coconino — cliff */
        {mat: shaleMat, h: h*0.15},     /* Shale — slope */
        {mat: new THREE.MeshStandardMaterial({color: 0xa03a2a}), h: h*0.25} /* Redwall — cliff */
      ];
      var yy = 0.13;
      var ww = w;
      for(var l = 0; l < layers.length; l++){
        var lh = layers[l].h;
        /* Cliff layers: vertical, narrower. Slope layers: wider, gentler */
        var isCliff = (l % 2 === 0);
        var layer = new THREE.Mesh(new THREE.BoxGeometry(ww, lh, ww*0.6), layers[l].mat);
        layer.position.set(x, yy + lh/2, z);
        scene.add(layer);
        yy += lh;
        if(isCliff) ww *= 0.85; /* Cliffs step inward */
        else ww *= 1.1; /* Slopes spread outward */
      }
    }

    /* SEA CLIFF — with arch */
    function seaCliff(x, z){
      /* Main cliff */
      var cliff = new THREE.Mesh(new THREE.BoxGeometry(30, 60, 20),
        new THREE.MeshStandardMaterial({color: 0xd4d4d4, roughness: 0.9})); /* White chalk */
      cliff.position.set(x, 30, z);
      scene.add(cliff);
      /* Arch */
      var archTop = new THREE.Mesh(new THREE.BoxGeometry(20, 8, 12), cliff.material);
      archTop.position.set(x + 20, 45, z);
      scene.add(archTop);
      var archLeg1 = new THREE.Mesh(new THREE.BoxGeometry(6, 35, 12), cliff.material);
      archLeg1.position.set(x + 12, 17, z);
      scene.add(archLeg1);
      var archLeg2 = new THREE.Mesh(new THREE.BoxGeometry(6, 35, 12), cliff.material);
      archLeg2.position.set(x + 28, 17, z);
      scene.add(archLeg2);
    }

    /* Apply to districts */
    /* Ahupua'a as SHIELD VOLCANOES — like real Hawaii */
    shieldVolcano(2000, 1920, 150, 80);
    shieldVolcano(-2000, 1920, 150, 85);
    shieldVolcano(0, -2580, 160, 90);

    /* Peaks as STRATOVOLCANOES — Fuji profile */
    stratovolcano(-3000, -2000, 80, 140);
    stratovolcano(-2500, -2000, 85, 150);
    stratovolcano(-2000, -2000, 80, 145);

    /* Canyon layers near the valleys */
    canyonLayers(-1800, -3500, 60, 50);
    canyonLayers(2200, 3500, 60, 55);

    /* Sea cliffs at shoreline */
    seaCliff(3080, 200);
    seaCliff(3080, 700);

  }catch(e){ console.error(e); }
}
if(typeof buildTopographyWoven === 'function'){ try{ buildTopographyWoven(); }catch(e){ console.error(e); } }

/* RIDGES & PLATEAUS — natural forms. Arêtes, cirques, plateau bridges. 2026-10-04.
   From Natural World research: ridges expand/contract, concave/convex, plateaus connect. */
function buildRidgesPlateaus(){
  try{
    var rockMat = new THREE.MeshStandardMaterial({color: 0x4a4a4a, roughness: 0.95});
    var snowMat = new THREE.MeshStandardMaterial({color: 0xffffff, roughness: 0.3});
    var waterMat = new THREE.MeshStandardMaterial({color: 0x0088cc, transparent: true, opacity: 0.7});
    var grassMat = new THREE.MeshStandardMaterial({color: 0x2a6a2a, roughness: 0.9});

    /* ARÊTE RIDGE — peak to peak via serrated spine with cols.
       Width expands and contracts naturally. */
    function areteRidge(x1, z1, x2, z2, peaks){
      var dx = x2 - x1, dz = z2 - z1;
      var len = Math.sqrt(dx*dx + dz*dz);
      var segs = peaks * 4; /* 4 segments per peak: up, crest, col, up */
      for(var i = 0; i < segs; i++){
        var t = i / (segs - 1);
        var px = x1 + dx * t;
        var pz = z1 + dz * t;
        /* Height: peaks and cols alternating */
        var peakPhase = (t * peaks) % 1;
        var isPeak = peakPhase < 0.5;
        var h;
        var w; /* Width expands at peaks, contracts at cols */
        if(isPeak){
          h = 120 + Math.sin(peakPhase * Math.PI * 2) * 40;
          w = 60 + Math.sin(peakPhase * Math.PI) * 30; /* Wide at peak */
        } else {
          h = 60 + Math.sin(peakPhase * Math.PI * 2) * 20;
          w = 15; /* Knife-edge at col */
        }
        /* Concave/convex: convex crest, concave base */
        var mtn = new THREE.Mesh(new THREE.ConeGeometry(w, h, 6), rockMat);
        mtn.position.set(px, h/2, pz);
        scene.add(mtn);
        if(h > 100){
          var cap = new THREE.Mesh(new THREE.ConeGeometry(w*0.4, h*0.25, 6), snowMat);
          cap.position.set(px, h - h*0.12, pz);
          scene.add(cap);
        }
      }
    }

    /* CIRQUE — concave bowl with tarn (lake) */
    function cirque(x, z, r){
      /* Bowl: concave */
      var bowl = new THREE.Mesh(new THREE.SphereGeometry(r, 16, 12, 0, Math.PI*2, 0, Math.PI/2), rockMat);
      bowl.rotation.x = Math.PI;
      bowl.position.set(x, 10, z);
      bowl.scale.y = 0.6;
      scene.add(bowl);
      /* Tarn */
      var tarn = new THREE.Mesh(new THREE.Ci