<!-- RUBY-BACKUP · part 436 -->
MeshStandardMaterial({color: 0xffffcc, emissive: 0xffffcc, emissiveIntensity: 0.6}));
  win.position.set(0.35, 0.5, 0.51); g.add(win);
  /* yard — green */
  var yard = new THREE.Mesh(new THREE.PlaneGeometry(2, 2),
    new THREE.MeshStandardMaterial({color: 0x2a6a2a, roughness: 1}));
  yard.rotation.x = -Math.PI/2; yard.position.y = 0.01; g.add(yard);
  g.position.set(x*0.13, 0, z*0.13);
  return g;
}

/* BUILDINGS WITH PURPOSE — every building has a reason. No cars. */
var BUILDING_PURPOSES = [
  {type: 'shop', label: 'SHOP', color: 0xffaa00, desc: 'Buy and sell'},
  {type: 'business', label: 'BUSINESS', color: 0x0088ff, desc: 'Work and trade'},
  {type: 'fire', label: 'FIRE STATION', color: 0xff2200, desc: 'Protects the city'},
  {type: 'police', label: 'POLICE', color: 0x0044ff, desc: 'Keeps the peace'},
  {type: 'market', label: 'MARKET', color: 0x88ff00, desc: 'Fresh goods'},
  {type: 'school', label: 'SCHOOL', color: 0xffff00, desc: 'Learn and grow'},
  {type: 'clinic', label: 'CLINIC', color: 0xffffff, desc: 'Heal the people'},
  {type: 'library', label: 'LIBRARY', color: 0xaa66ff, desc: 'Knowledge for all'}
];
var PURPOSE_BUILDINGS = [];
function makePurposeLabel(text, colorHex){
  var cv = document.createElement('canvas');
  cv.width = 256; cv.height = 64;
  var ctx = cv.getContext('2d');
  ctx.fillStyle = '#0a0a12';
  ctx.fillRect(0, 0, 256, 64);
  ctx.strokeStyle = '#'+colorHex.toString(16).padStart(6,'0');
  ctx.lineWidth = 3;
  ctx.strokeRect(4, 4, 248, 56);
  ctx.fillStyle = '#ffffff';
  ctx.font = 'bold 28px Arial';
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  ctx.fillText(text, 128, 34);
  var tex = new THREE.CanvasTexture(cv);
  return tex;
}
function assignBuildingPurpose(buildingGroup, purpose, x, z){
  /* add a visible label so the public can see */
  var labelTex = makePurposeLabel(purpose.label, purpose.color);
  var label = new THREE.Mesh(
    new THREE.PlaneGeometry(1.5, 0.375),
    new THREE.MeshBasicMaterial({map: labelTex, transparent: true})
  );
  /* place at entrance, visible */
  label.position.set(0, 1.2, 0.8);
  buildingGroup.add(label);
  /* color-code the entrance */
  var entrance = new THREE.Mesh(
    new THREE.PlaneGeometry(0.6, 1.0),
    new THREE.MeshStandardMaterial({
      color: purpose.color, emissive: purpose.color, emissiveIntensity: 0.5
    })
  );
  entrance.position.set(0, 0.5, 0.76);
  buildingGroup.add(entrance);
  buildingGroup.userData.purpose = purpose.type;
  buildingGroup.userData.label = purpose.label;
}

/* SPACESHIPS — the future has landing areas */
var SPACESHIPS = [];
var LANDING_PADS = [];
function buildLandingPad(x, z){
  var g = new THREE.Group();
  /* pad — circular */
  var pad = new THREE.Mesh(
    new THREE.CylinderGeometry(2, 2.2, 0.2, 24),
    new THREE.MeshStandardMaterial({color: 0x3a3a4a, metalness: 0.7, roughness: 0.4})
  );
  pad.position.y = 0.1; g.add(pad);
  /* glowing ring */
  var ring = new THREE.Mesh(
    new THREE.TorusGeometry(1.7, 0.08, 8, 32),
    new THREE.MeshStandardMaterial({color: 0x00ffff, emissive: 0x00ffff, emissiveIntensity: 1.5})
  );
  ring.rotation.x = Math.PI/2; ring.position.y = 0.22; g.add(ring);
  /* H marking */
  var hMark = new THREE.Mesh(
    new THREE.PlaneGeometry(0.8, 0.8),
    new THREE.MeshBasicMaterial({color: 0x00ffff, transparent: true, opacity: 0.6})
  );
  hMark.rotation.x = -Math.PI/2; hMark.position.y = 0.21; g.add(hMark);
  /* beacons */
  for(var i=0; i<4; i++){
    var ang = i*Math.PI/2;
    var beacon = new THREE.Mesh(
      new THREE.SphereGeometry(0.08, 10, 10),
      new THREE.MeshStandardMaterial({color: 0xffaa00, emissive: 0xffaa00, emissiveIntensity: 2})
    );
    beacon.position.set(Math.cos(ang)*2, 0.3, Math.sin(ang)*2);
    g.add(beacon);
  }
  g.position.set(x*0.13, 0, z*0.13);
  g.userData.occupied = false;
  return g;
}
function buildSpaceship(){
  var g = new THREE.Group();
  var hull = new THREE.MeshStandardMaterial({color: 0xccccdd, metalness: 0.9, roughness: 0.2});
  var dark = new THREE.MeshStandardMaterial({color: 0x2a2a3a, metalness: 0.8, roughness: 0.3});
  var glow = new THREE.MeshStandardMaterial({color: 0x00ffff, emissive: 0x00ffff, emissiveIntensity: 1.5});
  /* main hull — saucer */
  var saucer = new THREE.Mesh(new THREE.CylinderGeometry(1.2, 0.8, 0.4, 24), hull);
  saucer.position.y = 1.0; g.add(saucer);
  /* dome — cockpit */
  var dome = new THREE.Mesh(new THREE.SphereGeometry(0.4, 20, 20, 0, Math.PI*2, 0, Math.PI/2), dark);
  dome.position.y = 1.2; g.add(dome);
  /* engines — glowing */
  for(var i=0; i<3; i++){
    var ang = i*(Math.PI*2/3);
    var engine = new THREE.Mesh(new THREE.CylinderGeometry(0.15, 0.2, 0.3, 12), dark);
    engine.position.set(Math.cos(ang)*0.9, 0.8, Math.sin(ang)*0.9);
    g.add(engine);
    var flame = new THREE.Mesh(new THREE.ConeGeometry(0.12, 0.4, 10), glow);
    flame.position.set(Math.cos(ang)*0.9, 0.5, Math.sin(ang)*0.9);
    flame.rotation.x = Math.PI;
    g.add(flame);
  }