<!-- SAGA · part 54 -->
xistingBox = new THREE.Box3().setFromObject(placedBlocks[i]);
      if(newBox.intersectsBox(existingBox)) return true;
    }
    return false;
  }
  function makeBlock(type){
    var g = new THREE.Group();
    if(type === 'cube'){
      g.add(new THREE.Mesh(new THREE.BoxGeometry(4,4,4), goldMat.clone()));
    } else if(type === 'hourglass'){
      var t = new THREE.Mesh(new THREE.ConeGeometry(2,3,4), goldMat.clone()); t.rotation.x = Math.PI; t.position.y = 1.5; g.add(t);
      var b = new THREE.Mesh(new THREE.ConeGeometry(2,3,4), goldMat.clone()); b.position.y = -1.5; g.add(b);
    } else if(type === 'pylon'){
      g.add(new THREE.Mesh(new THREE.CylinderGeometry(1,1.5,8,8), marbleMat.clone()));
    } else if(type === 'tetra'){
      g.add(new THREE.Mesh(new THREE.TetrahedronGeometry(3), cyanMat.clone()));
    } else if(type === 'pyramid'){
      var p1 = new THREE.Mesh(new THREE.ConeGeometry(3,2,4), goldMat.clone()); p1.position.y = 1; g.add(p1);
      var p2 = new THREE.Mesh(new THREE.ConeGeometry(2,1.5,4), marbleMat.clone()); p2.position.y = 2.75; g.add(p2);
    }
    g.traverse(function(o){ if(o.isMesh) o.castShadow = true; });
    return g;
  }
  /* v92 — LAYERS LARGE TO SMALL. Every block's meshes are sorted by size into
     layers (0 = largest). Creation cascades in large->small; tools target one layer. */
  function tagLayers(obj){
    var meshes = [];
    obj.traverse(function(o){ if(o.isMesh && o.visible !== false) meshes.push(o); });
    meshes.sort(function(a, b){
      var va = new THREE.Box3().setFromObject(a).getSize(new THREE.Vector3());
      var vb = new THREE.Box3().setFromObject(b).getSize(new THREE.Vector3());
      return (vb.x*vb.y*vb.z) - (va.x*va.y*va.z);
    });
    meshes.forEach(function(m, i){ m.userData.layer = i; });
    obj.userData.layers = meshes;
    obj.userData.selLayer = -1;
    return meshes;
  }
  function cascadeIn(obj){
    var layers = obj.userData.layers || [];
    if(layers.length <= 1) return;
    layers.forEach(function(m){
      m.userData._s0 = m.scale.clone();
      m.visible = false;
    });
    layers.forEach(function(m, i){
      setTimeout(function(){
        m.visible = true;
        m.scale.copy(m.userData._s0).multiplyScalar(0.4);
        var t0 = Date.now();
        (function pop(){
          var t = Math.min(1, (Date.now() - t0) / 260);
          var k = 0.4 + 0.6 * t;
          m.scale.copy(m.userData._s0).multiplyScalar(k);
          if(t < 1) requestAnimationFrame(pop);
          else m.scale.copy(m.userData._s0);
        })();
        if(i === layers.length - 1 && typeof say === 'function') say('Built large to small');
      }, i * 240);
    });
  }

/* SOLID'S MEMORY — every site remembers what was built on it. King order 2026-10-05.
   This code ships in ALL builds from here on. No Python on top: plain JS. */
function buildMemoryLog(){
  var site = (location.pathname.split('/')[1] || 'root');
  window._memorySite = site;
  window.logBuild = function(what){
    try{
      var log = JSON.parse(localStorage.getItem('solid-memory') || '[]');
      log.push({t:Date.now(), site:site, what:String(what)});
      if(log.length > 200) log = log.slice(-(200));
      localStorage.setItem('solid-memory', JSON.stringify(log));
    }catch(e){}
  };
  window.readMemory = function(n){
    try{
      var log = JSON.parse(localStorage.getItem('solid-memory') || '[]');
      return log.filter(function(e){ return e.site === site; }).slice(-(n || 10));
    }catch(e){ return []; }
  };
  window.logBuild('regime raised');
}

  buildMemoryLog(); /* memory before building */

  /* v93 — CASTLE. Type `castle` and the 15-piece layered castle rises large to small. */
  window.buildCastle = function(){
    try{
      var g = new THREE.Group();
      var stone = new THREE.MeshStandardMaterial({color:0x8a8a8a, roughness:0.7, metalness:0.2});
      var dark = new THREE.MeshStandardMaterial({color:0x5a5a6a, roughness:0.6, metalness:0.3});
      var goldm = new THREE.MeshStandardMaterial({color:0xd8a920, roughness:0.3, metalness:0.8});
      function part(name, geo, mat, x, y, z, ry){
        var msh = new THREE.Mesh(geo, mat);
        msh.name = name; msh.position.set(x, y, z);
        if(ry) msh.rotation.y = ry;
        msh.castShadow = true; msh.userData.creatorBlock = true;
        g.add(msh); return msh;
      }
      part('base', new THREE.BoxGeometry(30, 4, 30), stone, 0, 2, 0);
      part('keep', new THREE.BoxGeometry(12, 12, 12), stone, 0, 10, 0);
      for(var i = 0; i < 4; i++){
        var a = i * Math.PI / 2;
        part('wall-' + i, new THREE.BoxGeometry(30, 8, 2), stone, Math.sin(a) * 14, 8, Math.cos(a) * 14, a);
        part('tower-' + i, new THREE.CylinderGeometry(3, 3.5, 14, 8), dark, Math.sin(a + Math.PI / 4) * 14, 11, Math.cos(a + Math.PI / 4) * 14);
        part('spire-' + i, new THREE.ConeGeometry(2, 6, 8), goldm, Math.sin(a + Math.PI / 4) * 14, 21, Math.cos(a + Math.PI / 4) * 14);
      }
      part('flag', new THREE.BoxGeomet