<!-- RUBY-BACKUP · part 231 -->
00ff00, 0x0088ff];
  colors.forEach(function(col, i){
    var s = buildSlide(-4+i*2, 0.2, 0, col);
    pg2.add(s);
  });
  var merry2 = buildMerryGoRound(0, 0.2, 4);
  pg2.add(merry2);
  pg2.position.set(px-25, 0, pz-15);
  scene.add(pg2);
  PLAYGROUNDS.push(pg2);
  codeStatus('future playgrounds — slides, swings, merry-go-rounds. For joy.');
}
function clearPlaygrounds(){
  if(PLAYGROUNDS){
    PLAYGROUNDS.forEach(function(p){
      try{ scene.remove(p); }catch(e){}
      p.traverse(function(o){ if(o.userData.anim) clearInterval(o.userData.anim); });
    });
    PLAYGROUNDS = null;
  }
  codeStatus('playgrounds cleared');
}

/* THE DARK PLACES */
var DARK_PLACES = null;
function buildStormBeach(x, z){
  var g = new THREE.Group();
  /* beach */
  var sand = new THREE.Mesh(new THREE.PlaneGeometry(30, 20),
    new THREE.MeshStandardMaterial({color: 0x8a7a5a, roughness: 1}));
  sand.rotation.x = -Math.PI/2; sand.position.y = 0.05;
  g.add(sand);
  /* violent ocean */
  var ocean = new THREE.Mesh(new THREE.PlaneGeometry(30, 15),
    new THREE.MeshStandardMaterial({color: 0x1a3a5a, roughness: 0.2, metalness: 0.4}));
  ocean.rotation.x = -Math.PI/2; ocean.position.set(0, 0.1, -15);
  g.add(ocean);
  /* waves — animated */
  var waves = [];
  for(var w=0; w<8; w++){
    var wave = new THREE.Mesh(new THREE.BoxGeometry(28, 0.5+Math.random()*0.8, 1.5),
      new THREE.MeshStandardMaterial({color: 0x2a5a8a, transparent: true, opacity: 0.8}));
    wave.position.set(0, 0.3, -8-w*2);
    g.add(wave);
    waves.push(wave);
  }
  var t = 0;
  var stormAnim = setInterval(function(){
    t += 0.05;
    waves.forEach(function(wv, i){
      wv.position.y = 0.3 + Math.sin(t*2+i)*0.4;
      wv.position.z += 0.05;
      if(wv.position.z > -5) wv.position.z = -22;
    });
  }, 50);
  g.userData.anim = stormAnim;
  /* lightning — random strikes */
  var boltMat = new THREE.MeshBasicMaterial({color: 0xffffff});
  var boltAnim = setInterval(function(){
    if(Math.random() < 0.3){
      var bolt = new THREE.Mesh(new THREE.CylinderGeometry(0.05, 0.05, 10, 6), boltMat);
      bolt.position.set((Math.random()-0.5)*25, 5, -10-Math.random()*10);
      g.add(bolt);
      setTimeout(function(){ g.remove(bolt); }, 150);
    }
  }, 800);
  g.userData.boltAnim = boltAnim;
  /* dark storm clouds */
  for(var ci=0; ci<10; ci++){
    var cloud = new THREE.Mesh(new THREE.SphereGeometry(3+Math.random()*2, 8, 8),
      new THREE.MeshStandardMaterial({color: 0x2a2a3a, transparent: true, opacity: 0.8}));
    cloud.position.set((Math.random()-0.5)*30, 12+Math.random()*4, -10-Math.random()*10);
    cloud.scale.y = 0.5;
    g.add(cloud);
  }
  /* sign */
  var sign = buildStreetSign('STORM BEACH', 0, 8, 0);
  sign.position.y = 0;
  g.add(sign);
  g.position.set(x*0.13, 0, z*0.13);
  return g;
}
function buildLostSoulsPeak(x, z){
  var g = new THREE.Group();
  /* jagged peak */
  var peak = new THREE.Mesh(new THREE.ConeGeometry(6, 14, 7),
    new THREE.MeshStandardMaterial({color: 0x2a2a3a, roughness: 1, flatShading: true}));
  peak.position.y = 7;
  g.add(peak);
  /* lost souls — floating, glowing, mournful */
  var souls = [];
  for(var s=0; s<12; s++){
    var soul = new THREE.Mesh(new THREE.SphereGeometry(0.3, 10, 10),
      new THREE.MeshStandardMaterial({
        color: 0x88aaff, emissive: 0x88aaff, emissiveIntensity: 1.5,
        transparent: true, opacity: 0.6
      }));
    var ang = Math.random()*Math.PI*2;
    var rad = 3+Math.random()*4;
    soul.position.set(Math.cos(ang)*rad, 4+Math.random()*8, Math.sin(ang)*rad);
    soul.userData = {ang: ang, rad: rad, speed: 0.005+Math.random()*0.01, yBase: soul.position.y};
    g.add(soul);
    souls.push(soul);
  }
  var t = 0;
  var soulAnim = setInterval(function(){
    t += 0.02;
    souls.forEach(function(sl){
      sl.userData.ang += sl.userData.speed;
      sl.position.x = Math.cos(sl.userData.ang)*sl.userData.rad;
      sl.position.z = Math.sin(sl.userData.ang)*sl.userData.rad;
      sl.position.y = sl.userData.yBase + Math.sin(t*2+sl.userData.ang)*0.5;
      sl.material.opacity = 0.4 + Math.sin(t*3+sl.userData.ang)*0.25;
    });
  }, 50);
  g.userData.anim = soulAnim;
  var sign = buildStreetSign('LOST SOULS PEAK', 0, 10, 0);
  g.add(sign);
  g.position.set(x*0.13, 0, z*0.13);
  return g;
}
function buildUnderworldFallacy(x, z){
  var g = new THREE.Group();
  /* impossible geometry — Penrose-like */
  var darkRed = new THREE.MeshStandardMaterial({color: 0x4a0a0a, roughness: 0.8});
  var glowRed = new THREE.MeshStandardMaterial({color: 0xff2222, emissive: 0xff2222, emissiveIntensity: 1});
  /* floating paradox cubes — rotating impossibly */
  var cubes = [];
  for(var i=0; i<5; i++){
    var cube = new THREE.Mesh(new THREE.BoxGeometry(1.5, 1.5, 1.5), darkRed);
    cube.position.set((Math.random()-0.5)*10, 2+Math.random()*4, (Math.random()-0.5)*10);
    /* edges glow */
    var edges = new THREE.LineSegments(
      new THREE.EdgesGeometry(cube.geometry),
      new