<!-- RUBY-BACKUP · part 370 -->

  var idx = 0;
  codeStatus('part: ' + parts[0] + ' — tap Pick again for next');
  /* store for cycling */
  _padEl._parts = parts;
  _padEl._partIdx = 0;
  /* change button to cycle */
  var btns = _padEl.querySelectorAll('button');
  for(var i=0; i<btns.length; i++){
    if(btns[i].textContent === 'Pick a Part'){
      btns[i].onclick = function(){
        _padEl._partIdx = (_padEl._partIdx + 1) % _padEl._parts.length;
        codeStatus('part: ' + _padEl._parts[_padEl._partIdx]);
      };
      break;
    }
  }
}
function hideHandPad(){
  if(_padEl){
    try{ document.body.removeChild(_padEl); }catch(e){}
    _padEl = null;
  }
  PAD_FOLLOW = false;
  window._crownLockTarget = null;
  /* object stays where it is — as he left it */
  codeStatus('she rests where you left her');
}
/* follow logic — runs each frame */
function updatePadFollow(){
  if(!PAD_FOLLOW || !PAD_SELECTED) return;
  try{
    if(typeof camera==='undefined' || !camera) return;
    var dir = new THREE.Vector3();
    camera.getWorldDirection(dir);
    dir.y = 0; dir.normalize();
    var tx = camera.position.x + dir.x * PAD_DIST;
    var tz = camera.position.z + dir.z * PAD_DIST;
    var ty = camera.position.y + PAD_HEIGHT_OFF;
    /* smooth follow */
    PAD_SELECTED.position.lerp(new THREE.Vector3(tx, ty, tz), 0.1);
  }catch(e){}
}
/* === CHEAT CODES — save views, record video, smooth glide === */
var SAVED_CAMS = {};
try{
  var sc = localStorage.getItem('ruby-saved-cams');
  if(sc) SAVED_CAMS = JSON.parse(sc);
}catch(e){}
function saveCamSlot(n){
  try{
    SAVED_CAMS[n] = {
      yaw: (typeof camYaw!=='undefined'?camYaw:0),
      pitch: (typeof camPitch!=='undefined'?camPitch:0.5),
      dist: (typeof camDist!=='undefined'?camDist:13),
      tx: (typeof lookTarget!=='undefined'?lookTarget.x:0),
      tz: (typeof lookTarget!=='undefined'?lookTarget.z:0)
    };
    localStorage.setItem('ruby-saved-cams', JSON.stringify(SAVED_CAMS));
    codeStatus('view saved to slot '+n);
  }catch(e){ codeStatus('could not save'); }
}
var DEFAULT_CAMS = {
  '1': 'vfar',
  '2': 'crown',
  '3': 'vleft',
  '4': 'vright',
  '5': 'vtop'
};
function goCamSlot(n){
  var s = SAVED_CAMS[n];
  if(!s){
    /* default original first picks */
    var def = DEFAULT_CAMS[n];
    if(def && typeof Mainframe!=='undefined'){ Mainframe.run(def); return; }
    codeStatus('slot '+n+' is empty'); return;
  }
  if(typeof GLIDE_ON!=='undefined' && GLIDE_ON){
    startCamGlide(s);
  } else {
    try{
      camYaw = s.yaw; camPitch = s.pitch; camDist = s.dist;
      if(typeof lookTarget!=='undefined'){ lookTarget.x = s.tx; lookTarget.z = s.tz; }
    }catch(e){}
  }
  codeStatus('camera: slot '+n);
}
/* smooth glide between views */
var GLIDE_ON = false;
var _glideAnim = null;
function startCamGlide(target){
  try{
    if(_glideAnim) cancelAnimationFrame(_glideAnim);
    var from = {
      yaw: camYaw, pitch: camPitch, dist: camDist,
      tx: lookTarget.x, tz: lookTarget.z
    };
    var start = performance.now();
    var dur = 1200;
    function step(t){
      var k = Math.min(1, (t-start)/dur);
      var e = k*k*(3-2*k);
      try{
        camYaw = from.yaw + (target.yaw - from.yaw)*e;
        camPitch = from.pitch + (target.pitch - from.pitch)*e;
        camDist = from.dist + (target.dist - from.dist)*e;
        lookTarget.x = from.tx + (target.tx - from.tx)*e;
        lookTarget.z = from.tz + (target.tz - from.tz)*e;
      }catch(err){}
      if(k < 1) _glideAnim = requestAnimationFrame(step);
      else _glideAnim = null;
    }
    _glideAnim = requestAnimationFrame(step);
  }catch(e){}
}
/* video recording */
var _recorder = null;
var _recChunks = [];
function toggleRecord(){
  try{
    if(_recorder && _recorder.state === 'recording'){
      _recorder.stop();
      return;
    }
    if(typeof renderer==='undefined' || !renderer.domElement){
      codeStatus('no canvas to record'); return;
    }
    var stream = renderer.domElement.captureStream(30);
    _recChunks = [];
    _recorder = new MediaRecorder(stream, {mimeType:'video/webm'});
    _recorder.ondataavailable = function(e){
      if(e.data.size > 0) _recChunks.push(e.data);
    };
    _recorder.onstop = function(){
      try{
        var blob = new Blob(_recChunks, {type:'video/webm'});
        var file = new File([blob], 'ruby-'+Date.now()+'.webm', {type:'video/webm'});
        if(navigator.share && navigator.canShare && navigator.canShare({files:[file]})){
          navigator.share({files:[file], title:'Ruby Video'}).catch(function(){});
          codeStatus('video shared — save it');
        } else {
          var a = document.createElement('a');
          a.href = URL.createObjectURL(blob);
          a.download = 'ruby-'+Date.now()+'.webm';
          document.body.appendChild(a);
          a.click();
          setTimeout(function(){ document.body.removeChild(a); }, 1000);
          codeStatus('video saved');
        }
      }catch(e){ codeStatus('save failed'); }
      _recorder