<!-- RUBY-BACKUP · part 352 -->
ulb.userData.permanent = true; g.add(bulb);
      /* gold collar above bulb */
      var collar = new THREE.Mesh(new THREE.CylinderGeometry(0.1, 0.1, 0.03, 12), goldTrim);
      collar.position.set(lx, 0.64, lz); collar.userData.permanent = true; g.add(collar);
      /* upper shaft */
      var upper = new THREE.Mesh(new THREE.CylinderGeometry(0.08, 0.09, 0.28, 12), pearl);
      upper.position.set(lx, 0.8, lz); upper.userData.permanent = true; g.add(upper);
      /* capital — flared top */
      var cap = new THREE.Mesh(new THREE.CylinderGeometry(0.13, 0.08, 0.1, 12), pearlDark);
      cap.position.set(lx, 0.99, lz); cap.userData.permanent = true; g.add(cap);
    });
  });

  /* === STRETCHER — low crossbar with center medallion === */
  var str1 = new THREE.Mesh(new THREE.BoxGeometry(2.5, 0.08, 0.08), pearlDark);
  str1.position.y = 0.25; str1.userData.permanent = true; g.add(str1);
  var str2 = new THREE.Mesh(new THREE.BoxGeometry(0.08, 0.08, 1.7), pearlDark);
  str2.position.y = 0.25; str2.userData.permanent = true; g.add(str2);
  /* center medallion — gold diamond */
  var med = new THREE.Mesh(new THREE.OctahedronGeometry(0.12), goldTrim);
  med.position.y = 0.25; med.userData.permanent = true; g.add(med);

  g.position.set(x, 0, z);
  scene.add(g);
  codeStatus('intricate white table — gold inlay, turned legs, carved apron');
  return g;
}
function buildWhiteTable(x, z){
  if(typeof scene==='undefined') return;
  var g = new THREE.Group();
  /* pearl white — like her cape: a little metal, low roughness, satin sheen */
  var pearlWhite = new THREE.MeshStandardMaterial({color: 0xf5f3ee, metalness: 0.35, roughness: 0.22});
  var shadowWhite = new THREE.MeshStandardMaterial({color: 0xe8e4da, metalness: 0.3, roughness: 0.3});
  /* tabletop: 3 x 0.15 x 2 */
  var top = new THREE.Mesh(new THREE.BoxGeometry(3, 0.15, 2), pearlWhite);
  top.position.y = 1.1;
  top.userData.permanent = true;
  g.add(top);
  /* beveled edge — a thinner slab under the top for craft */
  var edge = new THREE.Mesh(new THREE.BoxGeometry(2.7, 0.08, 1.7), shadowWhite);
  edge.position.y = 1.0;
  edge.userData.permanent = true;
  g.add(edge);
  /* four legs — tapered boxes */
  var legGeo = new THREE.BoxGeometry(0.18, 1.0, 0.18);
  var legPos = [[-1.3, -0.85], [1.3, -0.85], [-1.3, 0.85], [1.3, 0.85]];
  legPos.forEach(function(p){
    var leg = new THREE.Mesh(legGeo, pearlWhite);
    leg.position.set(p[0], 0.5, p[1]);
    leg.userData.permanent = true;
    g.add(leg);
    /* little foot */
    var foot = new THREE.Mesh(new THREE.BoxGeometry(0.26, 0.06, 0.26), shadowWhite);
    foot.position.set(p[0], 0.03, p[1]);
    foot.userData.permanent = true;
    g.add(foot);
  });
  /* crossbar for strength — like real joinery */
  var bar1 = new THREE.Mesh(new THREE.BoxGeometry(2.6, 0.1, 0.12), shadowWhite);
  bar1.position.y = 0.35; bar1.userData.permanent = true; g.add(bar1);
  var bar2 = new THREE.Mesh(new THREE.BoxGeometry(0.12, 0.1, 1.7), shadowWhite);
  bar2.position.y = 0.35; bar2.userData.permanent = true; g.add(bar2);
  g.position.set(x, 0, z);
  scene.add(g);
  codeStatus('white table built — pearl finish, like her cape');
  return g;
}

/* PULL HER APART — PROVOLTA piece by piece on the white table */
var DISSECT_GROUP = null;




/* SHE BLINKS — eyes blink while she stands, blink-out when dismissed */
var HER_BLINK_TIMER = null;
var HER_EYE_MESHES = [];
function findHerEyes(group){
  HER_EYE_MESHES = [];
  try{
    group.traverse(function(o){
      if(o.isMesh){
        var n = (o.name || '').toLowerCase();
        var mn = (o.material && o.material.name ? o.material.name : '').toLowerCase();
        if(n.indexOf('eye') >= 0 || mn.indexOf('eye') >= 0 || n.indexOf('hud') >= 0){
          HER_EYE_MESHES.push(o);
          if(!o.userData.origScaleY) o.userData.origScaleY = o.scale.y;
        }
      }
    });
  }catch(e){}
}
function herBlink(){
  /* close eyes */
  HER_EYE_MESHES.forEach(function(e){
    try{ e.scale.y = e.userData.origScaleY * 0.1; }catch(err){}
  });
  setTimeout(function(){
    /* open eyes */
    HER_EYE_MESHES.forEach(function(e){
      try{ e.scale.y = e.userData.origScaleY; }catch(err){}
    });
  }, 150);
}
function startHerBlinking(){
  stopHerBlinking();
  findHerEyes(BROUGHT_HER);
  /* blink every 3-6 seconds, randomly */
  function schedule(){
    HER_BLINK_TIMER = setTimeout(function(){
      herBlink();
      schedule();
    }, 3000 + Math.random()*3000);
  }
  schedule();
  /* first blink soon */
  setTimeout(herBlink, 1200);
}
function stopHerBlinking(){
  if(HER_BLINK_TIMER){
    clearTimeout(HER_BLINK_TIMER);
    HER_BLINK_TIMER = null;
  }
  HER_EYE_MESHES = [];
}
function dismissHer(){
  /* blink-out: eyes close, she fades */
  if(!BROUGHT_HER) return;
  stopHerBlinking();
  findHerEyes(BROUGHT_HER);
  herBlink();
  var g = BROUGHT_HER;
  var op = 1;
  var fade = setInterval(function(){
    op -= 0.1;
    try{
      g.traverse(function(o){
        if(o.isMesh && o.m