<!-- RUBY-BACKUP · part 76 -->
eometry(0.28,0.07,10,24), goldMatLift());
  ring.position.y=2.2; g.add(ring);
  var hit=new T.Mesh(new T.SphereGeometry(0.55,8,8),
    new T.MeshBasicMaterial({visible:false}));
  hit.position.y=2.2; hit.userData.liftStake=true; g.add(hit);
  g.position.set(wx, gy*0.13, wz);
  g.scale.y=0.01;
  try{ scene.add(g); }catch(e){ return; }
  var st={group:g, ring:ring, rope:rope, hit:hit, x:gx, z:gz, baseY:gy*0.13, liftH:0};
  hit.userData.stake=st;
  liftStakes.push(st);
  /* rise in — nothing teleports */
  var t0=performance.now();
  (function rise(){
    var t=Math.min(1,(performance.now()-t0)/600);
    g.scale.y=t;
    if(t<1) requestAnimationFrame(rise);
  })();
  status('stake set — pull the gold ring UP to raise the earth');
}
function liftStakeHit(cx,cy){
  try{
    if(!liftStakes.length||typeof camera==='undefined') return null;
    setNDC(cx,cy); raycaster.setFromCamera(ndc,camera);
    var hs=[]; for(var i=0;i<liftStakes.length;i++) hs.push(liftStakes[i].hit);
    var hits=raycaster.intersectObjects(hs,false);
    return hits.length?hits[0].object.userData.stake:null;
  }catch(e){ return null; }
}
function dragLiftRing(st,cx,cy){
  /* vertical drag -> lift height. rigid 1:1: ring Y maps to earth height. */
  try{
    setNDC(cx,cy); raycaster.setFromCamera(ndc,camera);
    /* intersect with a vertical plane through the stake, facing the camera */
    var sp=st.group.position;
    var n=new T.Vector3().subVectors(camera.position,sp); n.y=0; n.normalize();
    var plane=new T.Plane().setFromNormalAndCoplanarPoint(n,sp);
    var pt=new T.Vector3();
    if(!raycaster.ray.intersectPlane(plane,pt)) return;
    var dy=(pt.y-st.baseY)/0.13; /* game units above ground */
    var target=Math.max(0,Math.min(10,dy-2.2)); /* ring rest height offset */
    var delta=target-st.liftH;
    if(Math.abs(delta)<0.02) return;
    st.liftH=target;
    liftAt(st.x, st.z, delta);
    /* ring follows rigidly: ring Y = base + lift */
    st.ring.position.y=2.2+st.liftH*0.13;
    st.hit.position.y=2.2+st.liftH*0.13;
    st.rope.position.y=1.7+(st.liftH*0.13)/2;
    st.rope.scale.y=1+st.liftH*0.13;
  }catch(e){}
}
function clearLiftStakes(){
  for(var i=0;i<liftStakes.length;i++){
    try{ if(liftStakes[i].group.parent) liftStakes[i].group.parent.remove(liftStakes[i].group); }catch(e){}
  }
  liftStakes=[];
}

/* ---------------- wire it up ---------------- */
function init(){
  var cv=null;
  try{ cv=document.getElementById('view'); }catch(e){}
  if(cv){
    cv.addEventListener('touchstart',onTS,{passive:false,capture:true});
    cv.addEventListener('touchmove',onTM,{passive:false,capture:true});
    cv.addEventListener('touchend',onTE,{passive:false,capture:true});
    cv.addEventListener('touchcancel',onTE,{passive:false,capture:true});
    cv.addEventListener('mousedown',onMD,{capture:true});
    window.addEventListener('mousemove',onMM,{capture:true});
    window.addEventListener('mouseup',onMU,{capture:true});
  }
  try{ loadLifts(); }catch(e){}
  /* the grab button drives the rigging grab */
  try{ window.toggleGrabMode=function(){ toggleRigGrab(); }; }catch(e){}
  /* codes: wrap runLine (chains: rigging -> pulley-lab -> rope-deform -> original) */
  try{
    var orig=window.runLine;
    window.runLine=function(line){
      var tl=String(line==null?'':line).trim().toLowerCase();
      if(tl==='grab'){ toggleRigGrab(); return; }
      if(tl==='pulley'){ armPulley(); return; }
      if(tl==='rig'){ armRig(); return; }
      if(tl==='unrig'){ clearRigs(); return; }
      if(tl==='unpulley'){ armUnpulley(); return; }
      if(tl==='anchor'){ armAnchor(); return; }
      if(tl==='unanchor'){ doUnanchor(); return; }
      if(tl==='lift'){ armLift(); return; }
      if(tl==='flatten'){ armFlatten(); return; }
      if(tl==='unlift'){ clearLiftStakes(); status('lift stakes cleared — the earth keeps its shape'); return; }
      if(tl==='detach'){ armDetach(); return; }
      if(tl==='setdown'){ doSetdown(); return; }
      if(tl==='righelp'){ status('grab: pick up blocks. pulley: place a wheel. rig: tap pulley, tap road. anchor: pin it. unrig: clear all.'); return; }
      if(typeof orig==='function') return orig(line);
    };
  }catch(e){}
}
if(document.readyState==='loading'){
  document.addEventListener('DOMContentLoaded',init);
}else{ init(); }

})();


===== FILE: public/ruby-backup/rope-deform.js =====
/* ============================================================================
   ROPE DEFORM — the King's physics, in the world.
   ----------------------------------------------------------------------------
   THE LAW: the ROPE is fully rigid — it transmits force 1:1, never deforms.
            the BLOCK is rigid EDGES + flexing JOINTS — its shape CAN change.
   Pull opposite corners of an anchored square -> it MUST become a diamond.
   Four-bar linkage, closed-form, exact. Edges never stretch. If no diamond
   appears, this is just another rope — and the physics is wrong.
   --------------