<!-- RUBY-BACKUP · part 232 -->
 THREE.LineBasicMaterial({color: 0xff4444})
    );
    cube.add(edges);
    g.add(cube);
    cubes.push(cube);
  }
  var t = 0;
  var paradoxAnim = setInterval(function(){
    t += 0.02;
    cubes.forEach(function(cb, idx){
      cb.rotation.x = t*(0.5+idx*0.1);
      cb.rotation.y = t*(0.3+idx*0.15);
      cb.position.y += Math.sin(t*2+idx)*0.01;
    });
  }, 50);
  g.userData.anim = paradoxAnim;
  /* ground — cracked */
  var ground = new THREE.Mesh(new THREE.CircleGeometry(8, 24),
    new THREE.MeshStandardMaterial({color: 0x1a0a0a, roughness: 1}));
  ground.rotation.x = -Math.PI/2; ground.position.y = 0.05;
  g.add(ground);
  /* fallacy text — floating */
  var fallacies = ['AD HOMINEM', 'STRAW MAN', 'FALSE DILEMMA', 'CIRCULAR'];
  fallacies.forEach(function(fal, fi){
    var cv = document.createElement('canvas');
    cv.width = 256; cv.height = 48;
    var ctx = cv.getContext('2d');
    ctx.fillStyle = '#ff4444'; ctx.font = 'bold 22px Arial';
    ctx.textAlign = 'center'; ctx.fillText(fal, 128, 32);
    var tex = new THREE.CanvasTexture(cv);
    var label = new THREE.Mesh(new THREE.PlaneGeometry(2.5, 0.47),
      new THREE.MeshBasicMaterial({map: tex, transparent: true}));
    var fa = fi*(Math.PI*2/4);
    label.position.set(Math.cos(fa)*5, 3, Math.sin(fa)*5);
    label.rotation.y = -fa + Math.PI/2;
    g.add(label);
  });
  var sign = buildStreetSign('UNDERWORLD FALLACY', 0, 10, 0);
  g.add(sign);
  g.position.set(x*0.13, 0, z*0.13);
  return g;
}
function buildParadoxWormholes(x, z){
  var g = new THREE.Group();
  var wormholes = [];
  var colors = [0xff00ff, 0x00ffff, 0xffff00];
  colors.forEach(function(col, i){
    var wg = new THREE.Group();
    /* swirling portal */
    var portal = new THREE.Mesh(new THREE.TorusGeometry(1.5, 0.3, 12, 32),
      new THREE.MeshStandardMaterial({
        color: col, emissive: col, emissiveIntensity: 1.5,
        transparent: true, opacity: 0.85
      }));
    wg.add(portal);
    /* inner void */
    var void_ = new THREE.Mesh(new THREE.CircleGeometry(1.3, 24),
      new THREE.MeshBasicMaterial({color: 0x000000}));
    wg.add(void_);
    /* event horizon shimmer */
    var shimmer = new THREE.Mesh(new THREE.TorusGeometry(1.1, 0.1, 8, 24),
      new THREE.MeshBasicMaterial({color: 0xffffff, transparent: true, opacity: 0.5}));
    wg.add(shimmer);
    var ang = i*(Math.PI*2/3);
    wg.position.set(Math.cos(ang)*8, 2.5, Math.sin(ang)*8);
    wg.rotation.y = -ang + Math.PI/2;
    g.add(wg);
    wormholes.push({group: wg, portal: portal, shimmer: shimmer, speed: 0.02+i*0.01});
  });
  var t = 0;
  var wormAnim = setInterval(function(){
    t += 0.02;
    wormholes.forEach(function(wh){
      wh.portal.rotation.z += wh.speed;
      wh.shimmer.rotation.z -= wh.speed*1.5;
      wh.shimmer.material.opacity = 0.3 + Math.sin(t*4)*0.25;
    });
  }, 50);
  g.userData.anim = wormAnim;
  var sign = buildStreetSign('PARADOX WORMHOLES', 0, 12, 0);
  g.add(sign);
  g.position.set(x*0.13, 0, z*0.13);
  return g;
}
function buildFunnyHomeless(x, y, z){
  /* funny-looking, not scary — a gentle soul */
  var g = new THREE.Group();
  var skin = new THREE.MeshStandardMaterial({color: 0xc89868, roughness: 0.8});
  var coat = new THREE.MeshStandardMaterial({color: 0x6a5a4a, roughness: 1});
  /* head — big nose, kind eyes */
  var head = new THREE.Mesh(new THREE.SphereGeometry(0.16, 14, 14), skin);
  head.position.y = 1.1; g.add(head);
  var nose = new THREE.Mesh(new THREE.SphereGeometry(0.04, 8, 8), skin);
  nose.position.set(0.14, 1.08, 0); g.add(nose);
  [-1,1].forEach(function(s){
    var eye = new THREE.Mesh(new THREE.SphereGeometry(0.025, 8, 8),
      new THREE.MeshStandardMaterial({color: 0x222222}));
    eye.position.set(0.1, 1.15, s*0.06); g.add(eye);
  });
  /* smile */
  var smile = new THREE.Mesh(new THREE.TorusGeometry(0.06, 0.012, 6, 12, Math.PI),
    new THREE.MeshStandardMaterial({color: 0x6a3a2a}));
  smile.position.set(0.12, 1.02, 0); smile.rotation.z = -Math.PI/2; smile.rotation.y = Math.PI/2;
  g.add(smile);
  /* scruffy beard */
  var beard = new THREE.Mesh(new THREE.ConeGeometry(0.1, 0.2, 8),
    new THREE.MeshStandardMaterial({color: 0x888888, roughness: 1}));
  beard.position.set(0.08, 0.92, 0); beard.rotation.z = Math.PI/2;
  g.add(beard);
  /* patched coat */
  var body = new THREE.Mesh(new THREE.CylinderGeometry(0.18, 0.22, 0.7, 10), coat);
  body.position.y = 0.6; g.add(body);
  /* patch */
  var patch = new THREE.Mesh(new THREE.PlaneGeometry(0.12, 0.12),
    new THREE.MeshStandardMaterial({color: 0xaa4444, roughness: 1}));
  patch.position.set(0, 0.65, 0.21); g.add(patch);
  /* bindle — stick with bag */
  var stick = new THREE.Mesh(new THREE.CylinderGeometry(0.02, 0.02, 1.2, 6),
    new THREE.MeshStandardMaterial({color: 0x6a4a2a}));
  stick.position.set(-0.3, 1.0, 0.25); stick.rotation.z = 0.4;
  g.add(stick);
  var bag = new THREE.Mesh(new THREE.SphereGeometry(0.12, 10, 10), coat);
  bag.position.set(-0.5, 1.35, 0.25); bag.s