<!-- RUBY-BACKUP · part 451 -->
.SphereGeometry(0.3, 12, 12),
    new THREE.MeshBasicMaterial({color: 0x00ffff, transparent: true, opacity: 0.4}));
  innerGlow.position.set(0, 1.0, 0);
  g.add(innerGlow);
  g.position.set(x, y, z);
  g.userData.crystal = crystal;
  g.userData.innerGlow = innerGlow;
  g.userData.isCapsule = true;
  return g;
}
var DELIVERY_CAPSULE = null;
function deliverCapsule(){
  if(CAPSULE_DELIVERED) return;
  if(typeof scene==='undefined' || typeof mePos==='undefined') return;
  var px = mePos.x * 0.13, pz = mePos.z * 0.13;
  /* the capsule is on its way to Soliditronium */
  /* Soliditronium dome is at (25, 25) */
  var startX = px - 20, startZ = pz - 20;
  var destX = 25, destZ = 25;
  DELIVERY_CAPSULE = buildDeliveryCapsule(startX, 8, startZ);
  scene.add(DELIVERY_CAPSULE);
  CAPSULE_DELIVERED = true;
  try{ localStorage.setItem('ruby-capsule-delivered', '1'); }catch(e){}
  codeStatus('a golden capsule flies overhead... on its way to Soliditronium');
  /* it travels toward the dome */
  var t = 0;
  var journey = setInterval(function(){
    t += 0.02;
    if(!DELIVERY_CAPSULE){ clearInterval(journey); return; }
    var cx = startX + (destX - startX) * t;
    var cz = startZ + (destZ - startZ) * t;
    var cy = 8 + Math.sin(t * Math.PI * 3) * 1.5;
    DELIVERY_CAPSULE.position.set(cx, cy, cz);
    DELIVERY_CAPSULE.rotation.y += 0.03;
    /* WHILE on its way — it notices the player below */
    /* it detours. It flips. */
    if(t >= 0.4 && !DELIVERY_CAPSULE.userData.flipped){
      DELIVERY_CAPSULE.userData.flipped = true;
      clearInterval(journey);
      /* descends to the player */
      var dx = DELIVERY_CAPSULE.position.x, dy = DELIVERY_CAPSULE.position.y, dz = DELIVERY_CAPSULE.position.z;
      var dt = 0;
      var descend = setInterval(function(){
        dt += 0.03;
        if(!DELIVERY_CAPSULE){ clearInterval(descend); return; }
        var nx = dx + (px + 3 - dx) * dt;
        var nz = dz + (pz + 3 - dz) * dt;
        var ny = dy + (0 - dy) * dt;
        DELIVERY_CAPSULE.position.set(nx, ny, nz);
        if(dt >= 1){
          clearInterval(descend);
          codeStatus('it was on its way to Soliditronium... but it flipped to you');
          setTimeout(function(){ flipCapsule(); }, 2000);
        }
      }, 50);
    }
    if(t >= 1 && !DELIVERY_CAPSULE.userData.flipped){
      clearInterval(journey);
    }
  }, 50);
}
function flipCapsule(){
  if(!DELIVERY_CAPSULE) return;
  /* the capsule flips — presents the thing to them */
  var g = DELIVERY_CAPSULE;
  /* animate: top half flips back */
  var t = 0;
  var flip = setInterval(function(){
    t += 0.05;
    g.rotation.x = -t * 0.5;
    g.position.y = Math.sin(t * 2) * 0.2;
    if(t >= Math.PI){
      clearInterval(flip);
      g.rotation.x = -Math.PI * 0.5;
      /* the crystal rises, presented to them */
      presentCrystal();
    }
  }, 50);
  codeStatus('the capsule flips open...');
}

/* INVENTORY — and the price of the forbidden */

/* WEAPONS — the laser cannon is the prize */
var WEAPONS = [
  {id: 'pistol', name: 'Pistol', value: 100, description: 'Standard sidearm'},
  {id: 'shotgun', name: 'Shotgun', value: 300, description: 'Pump-action, 5-pellet spread'},
  {id: 'rifle', name: 'Rifle', value: 500, description: 'Long range, precise'},
  {id: 'laser-cannon', name: 'Laser Cannon', value: 2000, description: 'Cyan beam. One-shots targets. The prize.'}
];
function giveWeapon(weaponId){
  var w = WEAPONS.find(function(x){ return x.id === weaponId; });
  if(!w) return;
  var inv = getInventory();
  if(inv.find(function(i){ return i.id === w.id; })){
    codeStatus('you already own the '+w.name);
    return;
  }
  addToInventory({id: w.id, name: w.name, value: w.value, description: w.description});
  unlockAchievement('Owns '+w.name);
}
function showWeapons(){
  if(!weaponsStoreOpen()){
    codeStatus('the gun stores are closed. Finding a new one is impossible.');
    return;
  }
  var html = WEAPONS.map(function(w, i){
    return '<div style="margin:8px 0;padding:10px;border:1px solid #ff6600;border-radius:5px;">'
      + '<b>'+w.name+'</b> — '+w.value+' credits<br><small>'+w.description+'</small><br>'
      + '<button onclick="buyWeapon('+i+')" style="margin-top:5px;">BUY</button></div>';
  }).join('');
  var d = document.createElement('div');
  d.id = 'weapon-panel';
  d.style.cssText = 'position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10000;background:rgba(30,15,5,0.95);border:3px solid #ff6600;border-radius:12px;padding:20px;color:#fff;max-width:400px;max-height:70%;overflow:auto;';
  loadCredits();
  d.innerHTML = '<b style="color:#ff6600">WEAPONS</b> (you have '+CREDITS+' credits)<br><br>'+html
    + '<br><button onclick="document.getElementById(\'weapon-panel\').remove()">CLOSE</button>';
  document.body.appendChild(d);
}
function buyWeapon(idx){
  loadCredits();
  var w = WEAPONS[idx];
  if(!w) return;
  if(CREDITS < w.value){
    codeStatus('not enough credits — need '+w.value);
 