<!-- RUBY-BACKUP · part 437 -->

  /* landing legs */
  for(var j=0; j<3; j++){
    var la = j*(Math.PI*2/3) + Math.PI/3;
    var leg = new THREE.Mesh(new THREE.CylinderGeometry(0.05, 0.05, 0.8, 8), dark);
    leg.position.set(Math.cos(la)*1.0, 0.4, Math.sin(la)*1.0);
    g.add(leg);
  }
  g.userData.state = 'landed';
  return g;
}

/* THE MOTHER SHIP — HOKULEA */
var MOTHERSHIP = null;
function buildMothership(){
  var g = new THREE.Group();
  var hull = new THREE.MeshStandardMaterial({color: 0xd4d4e4, metalness: 0.95, roughness: 0.15});
  var dark = new THREE.MeshStandardMaterial({color: 0x1a1a2a, metalness: 0.85, roughness: 0.25});
  var glowCyan = new THREE.MeshStandardMaterial({color: 0x00ffff, emissive: 0x00ffff, emissiveIntensity: 2});
  var glowGold = new THREE.MeshStandardMaterial({color: 0xffcc00, emissive: 0xffcc00, emissiveIntensity: 1.5});
  /* massive hull */
  var main = new THREE.Mesh(new THREE.CylinderGeometry(4, 3, 1.5, 32), hull);
  main.position.y = 3; g.add(main);
  /* upper deck */
  var upper = new THREE.Mesh(new THREE.CylinderGeometry(2.5, 3.5, 1.2, 24), hull);
  upper.position.y = 4.2; g.add(upper);
  /* command dome */
  var dome = new THREE.Mesh(new THREE.SphereGeometry(1.2, 24, 24, 0, Math.PI*2, 0, Math.PI/2), dark);
  dome.position.y = 4.8; g.add(dome);
  /* glowing ring — the heart */
  var ring = new THREE.Mesh(new THREE.TorusGeometry(3.5, 0.15, 12, 48), glowCyan);
  ring.rotation.x = Math.PI/2; ring.position.y = 3; g.add(ring);
  /* engines */
  for(var i=0; i<6; i++){
    var ang = i*(Math.PI*2/6);
    var eng = new THREE.Mesh(new THREE.CylinderGeometry(0.4, 0.5, 0.8, 12), dark);
    eng.position.set(Math.cos(ang)*2.8, 2.2, Math.sin(ang)*2.8);
    g.add(eng);
    var flame = new THREE.Mesh(new THREE.ConeGeometry(0.3, 1.0, 10), glowCyan);
    flame.position.set(Math.cos(ang)*2.8, 1.5, Math.sin(ang)*2.8);
    flame.rotation.x = Math.PI;
    g.add(flame);
  }
  /* name — HOKULEA */
  var cv = document.createElement('canvas');
  cv.width = 512; cv.height = 96;
  var ctx = cv.getContext('2d');
  ctx.fillStyle = 'rgba(10,10,20,0.9)';
  ctx.fillRect(0, 0, 512, 96);
  ctx.strokeStyle = '#ffcc00'; ctx.lineWidth = 3;
  ctx.strokeRect(6, 6, 500, 84);
  ctx.fillStyle = '#ffcc00';
  ctx.font = 'bold 52px Georgia, serif';
  ctx.textAlign = 'center'; ctx.textBaseline = 'middle';
  ctx.fillText('HOKULEA', 256, 50);
  var nameTex = new THREE.CanvasTexture(cv);
  var namePlate = new THREE.Mesh(
    new THREE.PlaneGeometry(4, 0.75),
    new THREE.MeshBasicMaterial({map: nameTex, transparent: true})
  );
  namePlate.position.set(0, 3, 3.6);
  g.add(namePlate);
  var namePlate2 = namePlate.clone();
  namePlate2.position.set(0, 3, -3.6);
  namePlate2.rotation.y = Math.PI;
  g.add(namePlate2);
  /* star of gladness — golden beacon on top */
  var star = new THREE.Mesh(new THREE.SphereGeometry(0.25, 16, 16), glowGold);
  star.position.y = 6.2; g.add(star);
  var spire = new THREE.Mesh(new THREE.CylinderGeometry(0.05, 0.08, 1.0, 8), hull);
  spire.position.y = 5.7; g.add(spire);
  g.userData.name = 'Hokulea';
  return g;
}
function summonHokulea(){
  if(typeof scene==='undefined' || typeof mePos==='undefined') return;
  if(MOTHERSHIP){
    try{ scene.remove(MOTHERSHIP.mesh); }catch(e){}
    if(MOTHERSHIP.anim) clearInterval(MOTHERSHIP.anim);
  }
  var ship = buildMothership();
  var cx = mePos.x*0.13, cz = mePos.z*0.13;
  var orbitRadius = 25;
  var orbitHeight = 35; /* high orbit */
  ship.position.set(cx + orbitRadius, orbitHeight, cz);
  scene.add(ship);
  /* stays in orbit — circles above, never lands */
  var t = 0;
  var anim = setInterval(function(){
    t += 0.008; /* slow, majestic */
    ship.position.x = cx + Math.cos(t)*orbitRadius;
    ship.position.z = cz + Math.sin(t)*orbitRadius;
    ship.position.y = orbitHeight + Math.sin(t*2)*1.0;
    /* face direction of travel */
    ship.rotation.y = -t;
  }, 50);
  MOTHERSHIP = {mesh: ship, anim: anim};
  codeStatus('HOKULEA — in orbit. She stays above, watching.');
}
function dismissHokulea(){
  if(MOTHERSHIP){
    try{ scene.remove(MOTHERSHIP.mesh); }catch(e){}
    if(MOTHERSHIP.anim) clearInterval(MOTHERSHIP.anim);
    MOTHERSHIP = null;
    codeStatus('Hokulea departs');
  }
}
function buildSpaceport(){
  if(typeof scene==='undefined' || typeof mePos==='undefined') return;
  SPACESHIPS.forEach(function(s){ try{ scene.remove(s.mesh); }catch(e){} if(s.anim) clearInterval(s.anim); });
  LANDING_PADS.forEach(function(p){ try{ scene.remove(p); }catch(e){} });
  SPACESHIPS = []; LANDING_PADS = [];
  var px = mePos.x, pz = mePos.z;
  /* spaceport — 3 landing pads */
  for(var i=0; i<3; i++){
    var x = px + 30 + i*10, z = pz + 30;
    var pad = buildLandingPad(x, z);
    scene.add(pad);
    LANDING_PADS.push(pad);
    /* ship on pad */
    if(i < 2){
      var ship = buildSpaceship();
      ship.position.set(x*0.13, 0, z*0.13);
      scene.add(ship);
      pad.userData.occupied = true;
      /* hover animation */
      (function(sh, pd){
     