<!-- RUBY-BACKUP · part 116 -->
gSite();
    var beacon = new THREE.Group();
    /* pillar of light */
    var beamGeo = new THREE.CylinderGeometry(0.3, 0.5, 20, 12, 1, true);
    var beamMat = new THREE.MeshBasicMaterial({
      color: 0xffd700, transparent: true, opacity: 0.3,
      side: THREE.DoubleSide, depthWrite: false
    });
    var beam = new THREE.Mesh(beamGeo, beamMat);
    beam.position.y = 10;
    beacon.add(beam);
    /* ground ring */
    var ringGeo = new THREE.RingGeometry(1.5, 2.0, 32);
    var ringMat = new THREE.MeshBasicMaterial({
      color: 0xffd700, transparent: true, opacity: 0.8,
      side: THREE.DoubleSide
    });
    var ring = new THREE.Mesh(ringGeo, ringMat);
    ring.rotation.x = -Math.PI/2;
    ring.position.y = 0.1;
    beacon.add(ring);
    beacon.position.set(site.x, 0, site.z);
    /* not in the world — only on the map screen */
    beacon.visible = false;
    if(typeof scene!=='undefined') scene.add(beacon);
    LANDING_BEACON = beacon;
  }catch(e){}
}
setTimeout(function(){
  try{
    recordLandingSite();
    buildLandingBeacon();
  }catch(e){}
}, 5000);
/* ship engines playfully pulse */
setInterval(function(){
  try{
    if(typeof PLAYER_SHIP!=='undefined' && PLAYER_SHIP){
      var t = Date.now() * 0.003;
      var glow = 1.5 + Math.sin(t) * 0.5;
      PLAYER_SHIP.traverse(function(m){
        if(m.isMesh && m.material && m.material.emissive && m.material.emissive.getHex()===0xff6600){
          m.material.emissiveIntensity = glow;
        }
      });
    }
  }catch(e){}
}, 50);
/* YOUR SHIP: the 1 block you get at the start is a spaceship */
var PLAYER_SHIP = null;
function buildPlayerShip(){
  try{
    if(PLAYER_SHIP) return PLAYER_SHIP;
    var ship = new THREE.Group();
    var hullMat = new THREE.MeshStandardMaterial({color:0x8a9aaa, metalness:0.8, roughness:0.3});
    var accentMat = new THREE.MeshStandardMaterial({color:0xd8a920, metalness:0.9, roughness:0.2});
    var glassMat = new THREE.MeshStandardMaterial({color:0x66ccff, metalness:0.1, roughness:0.1, transparent:true, opacity:0.8});
    var engineMat = new THREE.MeshStandardMaterial({color:0xff6600, emissive:0xff6600, emissiveIntensity:2});
    /* hull — elongated */
    var hull = new THREE.Mesh(new THREE.BoxGeometry(1.2, 0.6, 3.0), hullMat);
    ship.add(hull);
    /* nose */
    var nose = new THREE.Mesh(new THREE.ConeGeometry(0.6, 1.2, 8), accentMat);
    nose.rotation.x = Math.PI/2;
    nose.position.z = 2.1;
    ship.add(nose);
    /* cockpit */
    var cockpit = new THREE.Mesh(new THREE.SphereGeometry(0.45, 12, 12), glassMat);
    cockpit.position.set(0, 0.5, 0.5);
    cockpit.scale.set(1, 0.7, 1.3);
    ship.add(cockpit);
    /* wings */
    var wingL = new THREE.Mesh(new THREE.BoxGeometry(1.8, 0.12, 1.0), hullMat);
    wingL.position.set(-1.2, 0, -0.5);
    ship.add(wingL);
    var wingR = new THREE.Mesh(new THREE.BoxGeometry(1.8, 0.12, 1.0), hullMat);
    wingR.position.set(1.2, 0, -0.5);
    ship.add(wingR);
    /* wingtip lights */
    var tipL = new THREE.Mesh(new THREE.SphereGeometry(0.08, 8, 8), new THREE.MeshStandardMaterial({color:0xff0000, emissive:0xff0000, emissiveIntensity:2}));
    tipL.position.set(-2.1, 0, -0.5);
    ship.add(tipL);
    var tipR = new THREE.Mesh(new THREE.SphereGeometry(0.08, 8, 8), new THREE.MeshStandardMaterial({color:0x00ff00, emissive:0x00ff00, emissiveIntensity:2}));
    tipR.position.set(2.1, 0, -0.5);
    ship.add(tipR);
    /* engines */
    var engL = new THREE.Mesh(new THREE.CylinderGeometry(0.22, 0.28, 0.8, 10), engineMat);
    engL.rotation.x = Math.PI/2;
    engL.position.set(-0.7, -0.1, -1.7);
    ship.add(engL);
    var engR = new THREE.Mesh(new THREE.CylinderGeometry(0.22, 0.28, 0.8, 10), engineMat);
    engR.rotation.x = Math.PI/2;
    engR.position.set(0.7, -0.1, -1.7);
    ship.add(engR);
    /* gold trim */
    var trim = new THREE.Mesh(new THREE.BoxGeometry(1.25, 0.08, 3.05), accentMat);
    trim.position.y = 0.32;
    ship.add(trim);
    ship.userData.isPlayerShip = true;
    ship.userData.isBlock = true; /* it counts as your 1 block */
    ship.userData.maxPassengers = 1; /* holds 1 only — him or her */
    ship.userData.passenger = null;
    ship.userData.usable = true; /* usable from the map — travel from day one */
    ship.userData.sellable = false; /* unsellable — it is yours, your 1 block */
    PLAYER_SHIP = ship;
    return ship;
  }catch(e){ return null; }
}

/* SHIP LAW: 1 passenger only — him or her, never both, never more */

/* SHIP LAW: it sits on the deck unusable unsellable — until earned */
function canUseShip(ship){
  try{
    if(!ship || !ship.userData) return false;
    return ship.userData.usable === true;
  }catch(e){ return false; }
}
function tryUseShip(ship){
  if(!canUseShip(ship)){
    try{ codeStatus('the ship sits — unusable. Earn it.'); }catch(e){}
    return false;
  }
  return true;
}
function tryBoardShip(ship, who){
  try{
    if(!ship || !ship.userData) return false;
    if(ship.userData.passenger){
   