<!-- RUBY-BACKUP · part 468 -->
1, 1].forEach(function(s){
    for(var i=0; i<8; i++){
      var wallH = 8 + Math.random()*4;
      var wall = new THREE.Mesh(
        new THREE.BoxGeometry(width/8, wallH, depth),
        paliMat
      );
      wall.position.set(s*(width/2 + width/16), wallH/2, (Math.random()-0.5)*2);
      wall.rotation.z = s*0.08;
      g.add(wall);
    }
  });
  /* waterfalls — down the pali */
  var wf1 = buildWaterfall(-width/2+0.5, 0, 0, 9);
  g.add(wf1);
  var wf2 = buildWaterfall(width/2-0.5, 0, depth/4, 10);
  g.add(wf2);
  /* tropical plants */
  for(var p=0; p<25; p++){
    var plantH = 0.5 + Math.random()*1.2;
    /* trunk */
    var trunk = new THREE.Mesh(
      new THREE.CylinderGeometry(0.06, 0.09, plantH, 6),
      new THREE.MeshStandardMaterial({color: 0x5a3a1a, roughness: 0.9})
    );
    trunk.position.set(
      (Math.random()-0.5)*width*0.8,
      plantH/2,
      (Math.random()-0.5)*depth*0.8
    );
    g.add(trunk);
    /* fronds */
    for(var f=0; f<5; f++){
      var frond = new THREE.Mesh(
        new THREE.PlaneGeometry(0.3, 1.2),
        new THREE.MeshStandardMaterial({color: 0x3a8a3a, roughness: 0.8, side: THREE.DoubleSide})
      );
      var fa = f*(Math.PI*2/5);
      frond.position.set(
        trunk.position.x + Math.cos(fa)*0.4,
        plantH + 0.2,
        trunk.position.z + Math.sin(fa)*0.4
      );
      frond.rotation.set(Math.random()*0.5, fa, 0.6);
      g.add(frond);
    }
  }
  /* river — flows through the valley, from the waterfalls */
  var riverCurve = new THREE.CatmullRomCurve3([
    new THREE.Vector3(-width/2+0.5, 0.15, 0),
    new THREE.Vector3(-width/4, 0.15, depth/8),
    new THREE.Vector3(0, 0.15, -depth/8),
    new THREE.Vector3(width/4, 0.15, depth/6),
    new THREE.Vector3(width/2-0.5, 0.15, depth/4)
  ]);
  var riverGeo = new THREE.TubeGeometry(riverCurve, 40, 0.6, 8, false);
  var riverMat = new THREE.MeshStandardMaterial({
    color: 0x2299cc, transparent: true, opacity: 0.8,
    roughness: 0.1, metalness: 0.3
  });
  var river = new THREE.Mesh(riverGeo, riverMat);
  g.add(river);
  /* riverbed — stones */
  var bedGeo = new THREE.TubeGeometry(riverCurve, 40, 0.75, 8, false);
  var bed = new THREE.Mesh(bedGeo,
    new THREE.MeshStandardMaterial({color: 0x6a5a4a, roughness: 1}));
  bed.position.y = -0.15;
  g.add(bed);
  /* flow animation */
  var flowT = 0;
  var flowAnim = setInterval(function(){
    flowT += 0.02;
    riverMat.opacity = 0.75 + Math.sin(flowT*2)*0.1;
    /* move texture offset for flow illusion */
    if(riverMat.map) riverMat.map.offset.x -= 0.01;
  }, 50);
  g.userData.flowAnim = flowAnim;
  /* mist — hanging in the valley */
  for(var m=0; m<6; m++){
    var mist = new THREE.Mesh(
      new THREE.SphereGeometry(2+Math.random()*2, 8, 8),
      new THREE.MeshStandardMaterial({color: 0xffffff, transparent: true, opacity: 0.12})
    );
    mist.position.set(
      (Math.random()-0.5)*width*0.7,
      3+Math.random()*3,
      (Math.random()-0.5)*depth*0.7
    );
    mist.scale.y = 0.4;
    g.add(mist);
  }
  g.position.set(x*0.13, 0, z*0.13);
  return g;
}
function buildValleys(){
  if(typeof scene==='undefined' || typeof mePos==='undefined') return;
  if(VALLEYS){
    VALLEYS.forEach(function(v){
      try{ scene.remove(v); }catch(e){}
      /* stop waterfall anims */
      v.traverse(function(o){ if(o.userData.anim) clearInterval(o.userData.anim); });
    });
  }
  VALLEYS = [];
  var px = mePos.x, pz = mePos.z;
  /* three valleys, like the islands */
  var v1 = buildHawaiianValley(px-150, pz-40, 20, 40);
  scene.add(v1); VALLEYS.push(v1);
  var v2 = buildHawaiianValley(px+140, pz+50, 24, 45);
  scene.add(v2); VALLEYS.push(v2);
  var v3 = buildHawaiianValley(px+20, pz-150, 18, 35);
  scene.add(v3); VALLEYS.push(v3);
  codeStatus('valleys like Hawaii — pali walls, waterfalls, mist. Like home.');
}
function clearValleys(){
  if(VALLEYS){
    VALLEYS.forEach(function(v){
      try{ scene.remove(v); }catch(e){}
      v.traverse(function(o){ if(o.userData.anim) clearInterval(o.userData.anim); });
      if(v.userData.flowAnim) clearInterval(v.userData.flowAnim);
    });
    VALLEYS = null;
  }
  codeStatus('valleys cleared');
}
function buildWildTerrain(){
  if(typeof scene==='undefined' || typeof mePos==='undefined') return;
  if(TERRAIN_GROUP){
    TERRAIN_GROUP.forEach(function(o){ try{ scene.remove(o); }catch(e){} });
  }
  TERRAIN_GROUP = [];
  var px = mePos.x, pz = mePos.z;
  /* islands — some with volcanoes */
  var islands = [
    {x: px-80, z: pz-60, r: 12, v: true},
    {x: px+70, z: pz-80, r: 10, v: false},
    {x: px-60, z: pz+70, r: 14, v: true},
    {x: px+80, z: pz+60, r: 8, v: false}
  ];
  islands.forEach(function(isl){
    var island = buildIsland(isl.x, isl.z, isl.r, isl.v);
    scene.add(island);
    TERRAIN_GROUP.push(island);
  });
  /* long mountains */
  var m1 = buildMountainRange(px-100, pz+20, 12, 6);
  scene.add(m1); TERRAIN_GROUP.push(m1);
  var m2 = buildMountainRange(px+100, pz-20, 10, 5)