<!-- RUBY-BACKUP · part 373 -->
4, 0.17),
            new THREE.MeshBasicMaterial({map: ltex, transparent: true}));
          llab.position.set(tx + ox, tableY + 0.05, tz + 1.1);
          llab.rotation.x = -Math.PI/2;
          TABLE_BODIES.add(llab);
        });
      }catch(e){}
      scene.add(TABLE_BODIES);
      /* move camera to see the table */
      try{
        if(typeof camera!=='undefined' && camera){
          var dir = new THREE.Vector3();
          camera.getWorldDirection(dir);
          dir.y = 0; dir.normalize();
          /* position camera 4 units back from table, looking at it */
          camera.position.set(tx - dir.x*4, 3.5, tz - dir.z*4);
          camera.lookAt(tx, 1.2, tz);
        }
      }catch(e){}
      codeStatus('left: original reference — right: yours to shape');
    },
    undefined,
    function(err){ codeStatus('could not lay her down'); }
  );
}
function clearTableBodies(){
  if(TABLE_BODIES){
    try{ scene.remove(TABLE_BODIES); }catch(e){}
    TABLE_BODIES = null;
    codeStatus('table cleared');
  }
}

/* TAP TO SELECT — touch a part, reconfigure its dimensions */
var SELECTED_PART = null;
var SELECT_MODE = false;
var _origEmissive = null;

/* DIMENSION INPUTS — type exact heights and widths for the selected part */
var _dimsPanel = null;
var _dimsInputs = {};
function showDimsPanel(partName, w, h, d){
  hideDimsPanel();
  _dimsPanel = document.createElement('div');
  _dimsPanel.id = 'dimspanel';
  _dimsPanel.style.cssText = 'position:fixed;left:14px;bottom:14px;z-index:10001;background:rgba(10,8,4,0.92);border:1px solid #d8a920;border-radius:12px;padding:12px;color:#ffd700;font-family:Georgia,serif;width:230px;';
  var title = document.createElement('div');
  title.textContent = partName || 'part';
  title.style.cssText = 'font-weight:bold;margin-bottom:8px;font-size:14px;';
  _dimsPanel.appendChild(title);
  /* ratio readout */
  var ratioDiv = document.createElement('div');
  ratioDiv.id = 'dimsratio';
  ratioDiv.style.cssText = 'font-size:12px;color:#8a6a1c;margin-bottom:10px;text-align:center;';
  _dimsPanel.appendChild(ratioDiv);
  var fields = [
    {key:'w', label:'Width', val:w},
    {key:'h', label:'Height', val:h},
    {key:'d', label:'Depth', val:d}
  ];
  _dimsInputs = {};
  _dimsBase = {w:w, h:h, d:d};
  fields.forEach(function(f){
    var row = document.createElement('div');
    row.style.cssText = 'margin:10px 0;';
    var topRow = document.createElement('div');
    topRow.style.cssText = 'display:flex;justify-content:space-between;align-items:center;margin-bottom:4px;';
    var lab = document.createElement('span');
    lab.textContent = f.label;
    lab.style.cssText = 'font-size:13px;';
    topRow.appendChild(lab);
    var valSpan = document.createElement('span');
    valSpan.id = 'dimsval-' + f.key;
    valSpan.textContent = f.val.toFixed(2);
    valSpan.style.cssText = 'font-size:13px;font-weight:bold;';
    topRow.appendChild(valSpan);
    row.appendChild(topRow);
    var slider = document.createElement('input');
    slider.type = 'range';
    /* no limiters — wide open */
    slider.min = '0.01';
    slider.max = (f.val * 20).toFixed(2);
    slider.step = '0.01';
    slider.value = f.val.toFixed(2);
    slider.style.cssText = 'width:100%;-webkit-appearance:none;height:6px;background:#8a6a1c;border-radius:3px;outline:none;';
    /* live update as you drag */
    slider.addEventListener('input', function(){
      valSpan.textContent = parseFloat(slider.value).toFixed(2);
      updateDimsRatio();
      applyDimsLive();
    });
    /* don't let game steal touches */
    slider.addEventListener('touchstart', function(e){ e.stopPropagation(); }, {passive:true});
    slider.addEventListener('mousedown', function(e){ e.stopPropagation(); });
    row.appendChild(slider);
    _dimsInputs[f.key] = slider;
    _dimsPanel.appendChild(row);
  });
  updateDimsRatio();
  /* close button */
  var closeBtn = document.createElement('button');
  closeBtn.textContent = '×';
  closeBtn.style.cssText = 'position:absolute;top:4px;right:8px;background:none;color:#8a6a1c;border:none;font-size:20px;';
  closeBtn.onclick = function(){ hideDimsPanel(); };
  _dimsPanel.appendChild(closeBtn);
  document.body.appendChild(_dimsPanel);
}
var _dimsBase = {w:1, h:1, d:1};
function updateDimsRatio(){
  try{
    var w = parseFloat(_dimsInputs.w.value);
    var h = parseFloat(_dimsInputs.h.value);
    var d = parseFloat(_dimsInputs.d.value);
    var el = document.getElementById('dimsratio');
    if(el) el.textContent = w.toFixed(2) + ' : ' + h.toFixed(2) + ' : ' + d.toFixed(2);
  }catch(e){}
}

/* HER DIMENSIONS ARE THE LAW — no part bigger than her maximum */
var PROVOLTA_MAX_DIMS = {x:0, y:0, z:0};
function recordProvoltaHeight(model){
  try{
    var box = new THREE.Box3().setFromObject(model);
    var s = box.getSize(new THREE.Vector3());
    if(s.x > PROVOLTA_MAX_DIMS.x) PROVOLTA_MAX_DIMS.x = s.x;
    if(s.y > PROVOLTA_MAX_DIMS.y) PROVOLTA_MAX_DIMS.y = s.y;
    if(s.z > PROVOLT