<!-- RUBY-BACKUP · part 96 -->
.position.set(x, groundY(x, z), z);
  k.rotation.y = Math.random()*Math.PI*2;
  scene.add(k);
  npcKings.push(k);
  persistKings();
  return k;
}
function loadKings(){
  var ks = [];
  try{ ks = JSON.parse(localStorage.getItem('ruby-kings-v1')||'[]'); }catch(e){}
  ks.forEach(function(k){ spawnKingNPC(k.x, k.z); });
}

/* ultra-dense intaglio linework, drawn once, worn by the nested shells */
function makeIntaglioTex(){
  var c = document.createElement('canvas'); c.width = c.height = 512;
  var x = c.getContext('2d');
  x.clearRect(0,0,512,512);
  var i, a, p;
  x.lineWidth = 1;
  x.strokeStyle = 'rgba(255,215,0,0.5)';
  for(i=-512;i<1024;i+=5){
    x.beginPath(); x.moveTo(i,0); x.lineTo(i+512,512); x.stroke();
    x.beginPath(); x.moveTo(i+512,0); x.lineTo(i,512); x.stroke();
  }
  x.strokeStyle = 'rgba(255,215,0,0.26)';
  for(i=0;i<512;i+=5){ x.beginPath(); x.moveTo(0,i); x.lineTo(512,i); x.stroke(); }
  x.strokeStyle = 'rgba(255,215,0,0.34)';
  for(var r=8;r<360;r+=9){
    x.beginPath();
    for(a=0;a<=Math.PI*2+0.01;a+=0.05){
      var rr = r + Math.sin(a*9)*3;
      p = [256+Math.cos(a)*rr, 256+Math.sin(a)*rr];
      if(a===0) x.moveTo(p[0],p[1]); else x.lineTo(p[0],p[1]);
    }
    x.stroke();
  }
  var t = new T.CanvasTexture(c);
  t.wrapS = t.wrapT = T.RepeatWrapping;
  return t;
}
var intaglioMat = new T.MeshBasicMaterial({map:makeIntaglioTex(), transparent:true, opacity:0.5, depthWrite:false, side:T.DoubleSide});
var LINEWORK_ON = false; /* ultra-dense intaglio linework within and outside blocks */
/* the pyramid family wears the ultra-dense intaglio linework even in solid mode:
   gold ground, engraved bright — everything that connects, lined up */
function makeFamilyTex(){
  var c = document.createElement('canvas'); c.width = c.height = 512;
  var x = c.getContext('2d');
  x.fillStyle = '#7d5c10'; x.fillRect(0,0,512,512);
  x.lineWidth = 1;
  x.strokeStyle = 'rgba(255,225,130,0.55)';
  for(var i=-512;i<1024;i+=5){
    x.beginPath(); x.moveTo(i,0); x.lineTo(i+512,512); x.stroke();
    x.beginPath(); x.moveTo(i+512,0); x.lineTo(i,512); x.stroke();
  }
  x.strokeStyle = 'rgba(255,225,130,0.3)';
  for(i=0;i<512;i+=5){ x.beginPath(); x.moveTo(0,i); x.lineTo(512,i); x.stroke(); }
  x.strokeStyle = 'rgba(255,235,170,0.4)';
  for(var r=8;r<360;r+=9){
    x.beginPath();
    for(var a=0;a<=Math.PI*2+0.01;a+=0.05){
      var rr = r + Math.sin(a*9)*3, p = [256+Math.cos(a)*rr, 256+Math.sin(a)*rr];
      if(a===0) x.moveTo(p[0],p[1]); else x.lineTo(p[0],p[1]);
    }
    x.stroke();
  }
  var t = new T.CanvasTexture(c);
  t.wrapS = t.wrapT = T.RepeatWrapping;
  return t;
}
var familyMat = new T.MeshStandardMaterial({map:makeFamilyTex(), roughness:0.35, metalness:0.85, emissive:0x3a2a08, emissiveIntensity:0.25});
var FAMILY = {pyramid:1, tri:1, pdown:1, poff:1, poffdown:1};

/* render modes: solid gold, nested intaglio shells, camera centered on largest, intaglio radiating from largest */
var RENDER_MODES = ['solid','nested','center','radiate'];
var RENDER_LABELS = {solid:'Solid', nested:'Nested', center:'Center', radiate:'Radiate'};
var RENDER_ICONS = {
  solid: '<svg viewBox="0 0 24 24"><rect x="6" y="6" width="12" height="12" fill="#ffd700"/></svg>',
  nested: '<svg viewBox="0 0 24 24"><rect x="4" y="4" width="16" height="16" fill="none" stroke="#ffd700" stroke-width="2"/><rect x="8.5" y="8.5" width="7" height="7" fill="none" stroke="#ffd700" stroke-width="1.5"/><rect x="11" y="11" width="2" height="2" fill="#ffd700"/></svg>',
  center: '<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="8" fill="none" stroke="#ffd700" stroke-width="2"/><circle cx="12" cy="12" r="2" fill="#ffd700"/></svg>',
  radiate: '<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="2.5" fill="none" stroke="#ffd700" stroke-width="2"/><circle cx="12" cy="12" r="6.5" fill="none" stroke="#ffd700" stroke-width="1.5"/><path d="M12 1 L12 5 M12 19 L12 23 M1 12 L5 12 M19 12 L23 12" stroke="#ffd700" stroke-width="1.5"/></svg>'
};
var renderMode = 'solid';
try{ var _rm = localStorage.getItem('ruby-render-mode'); if(RENDER_MODES.indexOf(_rm)>=0) renderMode = _rm; }catch(e){}

var stones = new T.Group(); scene.add(stones);
var shapeBaseGeo = {};
function baseGeo(shape){
  if(!shapeBaseGeo[shape]) shapeBaseGeo[shape] = shapeGeo(shape, window.MINIMUM);
  return shapeBaseGeo[shape];
}
/* each stone is a group at its ground cell; its look is rebuilt for the render mode */
function buildStoneVisual(g){
  for(var i=g.children.length-1;i>=0;i--) g.remove(g.children[i]);
  var ud = g.userData, base = ud.shape||'cube', k1 = ud.k1||1, r = ud.rubies||1;
  var ghostly = !!ud.ghost;
  if(renderMode==='nested' && !ghostly){
    for(var i=1;i<=r;i++){
      var sh = new T.Mesh(baseGeo(base), intaglioMat);
      var sc = i*k1;
      sh.scale.set(sc,sc,sc);
      sh.position.y = sc*window.MINIMUM/2;
      g.add(sh);
    }
  }else{
    /* the ghost twin is always its see-through intaglio self, in every mode */
    var m = new T.Mesh