<!-- RUBY-BACKUP · part 125 -->
eBodies(){
  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 > PROVOLTA_MAX_DIMS.z) PROVOLTA_MAX_DIMS.z = s.z;
  }catch(e){}
}
function enforceHeightLaw(){
  if(!SELECTED_PART) return false;
  if(PROVOLTA_MAX_DIMS.x <= 0) return false;
  try{
    var box = new THREE.Box3().setFromObject(SELECTED_PART);
    var s = box.getSize(new THREE.Vector3());
    var cs = SELECTED_PART.scale;
    var clamped = false;
    /* each axis: part can't exceed her max in that axis */
    if(s.x > PROVOLTA_MAX_DIMS.x){
      cs.x *= PROVOLTA_MAX_DIMS.x / s.x;
      clamped = true;
    }
    if(s.y > PROVOLTA_MAX_DIMS.y){
      cs.y *= PROVOLTA_MAX_DIMS.y / s.y;
      clamped = true;
    }
    if(s.z > PROVOLTA_MAX_DIMS.z){
      cs.z *= PROVOLTA_MAX_DIMS.z / s.z;
      clamped = true;
    }
    if(clamped){
      SELECTED_PART.scale.copy(cs);
      return true;
    }
  }catch(e){}
  return false;
}
function applyDimsLive(){
  if(!SELECTED_PART) return;
  try{