<!-- RUBY-BACKUP · part 93 -->
x;color:#ffd700;font:12px sans-serif;z-index:50;opacity:0.9;pointer-events:none;';
  document.body.appendChild(tag);
  var cbtn = document.getElementById('chatbtn'); if(cbtn) cbtn.style.display = 'block';
  pullWatch(); postPresence(); pullPresence(); pullChat(); pullStones(); pollRoomVersion();
  
/* ROOM VERSION SYNC — see new builds without reload */
var lastRoomV = 0;
function pollRoomVersion(){
  if(!WATCH_ID) return;
  fetch('/api/ruby/version/'+encodeURIComponent(WATCH_ID)).then(function(r){ return r.json(); }).then(function(d){
    if(!d || !d.ok) return;
    if(d.v > lastRoomV){
      lastRoomV = d.v;
      /* new build — full pull, ignore the since filter */
      lastStoneT = 0;
      pullStones();
    }
  }).catch(function(){});
}
setInterval(function(){ pullWatch(); postPresence(); pullPresence(); pullChat(); pullStones(); pollRoomVersion(); pollRoomVersion(); }, 3000);
}

var canvas = document.getElementById('view');
var renderer;
try{
  renderer = new T.WebGLRenderer({canvas:canvas, antialias:true, preserveDrawingBuffer:true});
}catch(e){
  document.getElementById('boot').textContent='THE WORLD WOULD NOT OPEN';
  return;
}
renderer.setPixelRatio(Math.min(window.devicePixelRatio||1, 2));
/* default (linear) output — sRGB output washed the dark world out to haze */

var scene = new T.Scene(); window.scene = scene;
scene.background = new T.Color(0x0b0906);
/* the map: 800 x 800 x 800 rubies — 800 Minimums of 0.13 = 104 world units.
   smaller ground, faster to wake. the stones and their 2-unit snap do not change. */
var MAP_RUBIES = 18462; /* 2400 units — the highways go far */
var MAP_UNITS = MAP_RUBIES * 0.13;   /* 1200 */
scene.fog = new T.Fog(0x0b0906, 45, MAP_UNITS + 6);

var camera = new T.PerspectiveCamera(55, 1, 0.1, 6000); window.camera = camera; /* far plane extended for sky height 2000 */
var camT = { th: 0.85, ph: 0.95, r: 13 };   /* close enough to read the ruby */
/* Camera starts at eye level on load — not foot level */
setTimeout(function(){
  try{
    if(typeof mePos !== 'undefined' && typeof camera !== 'undefined'){
      var _gy = (typeof fortifiedGroundY === 'function') ? fortifiedGroundY(mePos.x, mePos.z) : 0;
      if(camera.position.y < _gy + 1.5) camera.position.y = _gy + 3;
    }
  }catch(e){}
}, 1500);
var camGoal = { th: 0.85, ph: 0.95, r: 13 };
/* Snap camera behind the body — called when View joystick is released */
window.snapCamera = function(){
  try{
    if(typeof WALK !== 'undefined' && WALK){
      if(typeof camYaw !== 'undefined' && typeof faceYaw !== 'undefined'){
        camYaw = faceYaw; camPitch = 0.55;
      }
    }else if(typeof camGoal !== 'undefined' && typeof faceYaw !== 'undefined'){
      camGoal.th = faceYaw; camGoal.ph = 0.55;
    }
  }catch(e){}
};
/* Snap a world point to the intaglio linework — hands land on lines, not gaps.
   The texture is 512px with lines every 5px. We snap in world space
   using the minimum unit (0.13) divided to intaglio density. */
window.snapToIntaglio = function(pt){
  try{
    var grid = 0.13 / 4; /* intaglio density: quarter-minimum */
    var layer = 0.13; /* one layer in — the hand rests on layer 2 */
    /* Pull one layer inward from the surface toward the body */
    var dx = (typeof mePos !== 'undefined' ? mePos.x : 0) - pt.x;
    var dz = (typeof mePos !== 'undefined' ? mePos.z : 0) - pt.z;
    var len = Math.sqrt(dx*dx + dz*dz) || 1;
    var ix = pt.x + (dx/len) * layer;
    var iz = pt.z + (dz/len) * layer;
    return {
      x: Math.round(ix / grid) * grid,
      y: pt.y,
      z: Math.round(iz / grid) * grid
    };
  }catch(e){ return {x: pt.x, y: pt.y, z: pt.z}; }
};
function snapToIntaglio(pt){ return window.snapToIntaglio(pt); }
/* GLORIOUS MARQUEE — announcements for powers and news */
window._marquees = [];
window.marquee = function(text, style){
  style = style || 'gold';
  var colors = {
    gold:   {fg:'#ffd700', bg:'rgba(20,15,5,0.9)', border:'#d8a920'},
    power:  {fg:'#ff6b35', bg:'rgba(25,10,5,0.92)', border:'#ff6b35'},
    news:   {fg:'#7ec8ff', bg:'rgba(5,15,25,0.92)', border:'#4a90d9'},
    glory:  {fg:'#fff',    bg:'rgba(30,20,5,0.95)', border:'#ffd700'}
  };
  var c = colors[style] || colors.gold;
  var m = document.createElement('div');
  m.className = 'glory-marquee';
  m.style.cssText = 'position:fixed;top:50%;left:0;right:0;z-index:99998;'
    + 'background:'+c.bg+';border-top:3px solid '+c.border+';border-bottom:3px solid '+c.border+';'
    + 'padding:12px 0;overflow:hidden;pointer-events:none;'
    + 'transform:translateY(-50%);';
  m.innerHTML = '<div style="white-space:nowrap;display:inline-block;'
    + 'color:'+c.fg+';font-family:Georgia,serif;font-size:28px;font-weight:bold;letter-spacing:4px;'
    + 'text-shadow:0 0 20px '+c.fg+';'
    + 'animation:marquee-scroll 8s linear infinite;">'
    + text + ' &nbsp; ◆ &nbsp; ' + text + ' &nbsp; ◆ &nbsp; ' + text + '</div>';
  document.body.appendChild(m);
  window._marquees.push(m);
  /* Auto-remove af