<!-- RUBY-BACKUP · part 41 -->
ormula;
    M.rope=ropeSeg(); g.add(M.rope);
    M.ring=goldRing(0.2); M.ring.position.set(axleR,M.loadY+0.6,0); M.load.add(M.ring);
    M.ring.position.set(0,0.6,0);
    var rhit=hitSphere(0.55); rhit.position.set(0,0.6,0); M.load.add(rhit);
    function layout(){
      M.load.position.set(axleR,M.loadY,0);
      aimCyl(M.rope,new T.Vector3(axleR,M.ropeTop,0),new T.Vector3(axleR,M.loadY+0.4,0));
      try{
        g.remove(M.formula);
        M.formula=textSprite('θ '+(M.theta/(2*Math.PI)).toFixed(2)+' TURN · ROPE '+(M.theta*M.axleR).toFixed(2)+'m',0.62);
        M.formula.position.set(0,gearY+0.62,0); g.add(M.formula);
      }catch(e){}
    }
    M.layout=layout;
    /* turn the gear rim */
    var a0=0;
    regHit(ghit,{
      onDown:function(x,y){ a0=screenAngle(worldPosOf(gearG),x,y); },
      onMove:function(x,y){
        var a1=screenAngle(worldPosOf(gearG),x,y);
        var d=wrapPi(a1-a0); a0=a1;
        M.theta+=d;
        var ny=M.loadY+d*M.axleR;
        M.loadY=Math.max(gy+0.5,Math.min(M.ropeTop-0.9,ny));
        gearG.rotation.z=M.theta;
        layout();
      }
    });
    /* back-drive: pull the rope/load */
    var ry0=0, rl0=0;
    regHit(rhit,{
      onDown:function(x,y){
        var wp=worldPosOf(M.ring); var wy=vPlaneY(wp,x,y);
        if(wy!==null){ ry0=wy; rl0=M.loadY; }
      },
      onMove:function(x,y){
        var wp=worldPosOf(M.ring); var wy=vPlaneY(wp,x,y);
        if(wy===null) return;
        var ny=Math.max(gy+0.5,Math.min(M.ropeTop-0.9,rl0+(wy-ry0)));
        var dth=(ny-M.loadY)/M.axleR;
        M.loadY=ny; M.theta+=dth;
        gearG.rotation.z=M.theta;
        layout();
      }
    });
    g.position.copy(base);
    scene.add(g);
    layout();
    riseIn(g,base.y,2.5,0.6);
    status('gear link — turn the gold gear, or pull the load. both drive both.');
  }catch(e){ status('gear link failed: '+e.message); }
}

/* ============================================================================
   LEVER — fulcrum and beam. Push the long end, the short end lifts the world.
   EFFORT × b = LOAD × a. Honest ratios.
   `lever` builds it. `unlever` removes it.
   ============================================================================ */
function buildLever(){
  try{
    if(typeof scene==='undefined') return;
    mats();
    var base=forwardPoint(7,0);
    var g=new T.Group();
    var gy=base.y, pivY=gy+1.15, a=1.0, b=3.0;
    /* fulcrum: triangular prism */
    var ful=new T.Mesh(new T.CylinderGeometry(0.55,0.55,0.7,3),mats().red);
    ful.position.set(0,gy+0.5,0); ful.rotation.y=Math.PI; g.add(ful);
    /* beam pivots at fulcrum top */
    var beamG=new T.Group(); beamG.position.set(0,pivY,0); g.add(beamG);
    var beam=new T.Mesh(new T.BoxGeometry(a+b+0.6,0.16,0.3),mats().wood);
    beam.position.x=(b-a)/2; beamG.add(beam);
    var M=regMachine('lever',g);
    M.a=a; M.b=b; M.pivY=pivY; M.drop=0; M.beamG=beamG;
    /* load on short end */
    M.load=new T.Mesh(new T.BoxGeometry(0.9,0.9,0.9),mats().crate);
    var llb=textSprite('10 KG',0.55); llb.position.y=-0.85; M.load.add(llb);
    beamG.add(M.load); M.load.position.set(-a,0.55,0);
    /* effort ring on long end */
    M.eff=goldRing(0.22); beamG.add(M.eff); M.eff.position.set(b,0.35,0);
    var ehit=hitSphere(0.6); ehit.position.set(b,0.35,0); beamG.add(ehit);
    var lbl=textSprite('LEVER '+(b/a)+':1',0.85); lbl.position.set(0,pivY+1.5,0); g.add(lbl);
    var formula=textSprite('EFFORT × '+b+' = LOAD × '+a,0.7); formula.position.set(0,pivY+0.95,0); g.add(formula); M.formula=formula;
    function layout(){
      var th=Math.asin(Math.max(0,Math.min(1.26,M.drop))/M.b);
      beamG.rotation.z=-th; /* effort end down */
      var loadRise=M.a*Math.sin(th);
      try{
        g.remove(M.formula);
        M.formula=textSprite('DROP '+M.drop.toFixed(2)+' → LIFT '+loadRise.toFixed(2),0.7);
        M.formula.position.set(0,pivY+0.95,0); g.add(M.formula);
      }catch(e){}
    }
    M.layout=layout;
    var ey0=0, ed0=0;
    regHit(ehit,{
      onDown:function(x,y){
        var wp=worldPosOf(M.eff); var wy=vPlaneY(wp,x,y);
        if(wy!==null){ ey0=wy; ed0=M.drop; }
      },
      onMove:function(x,y){
        var wp=worldPosOf(M.eff); var wy=vPlaneY(wp,x,y);
        if(wy===null) return;
        /* drag down increases drop */
        M.drop=Math.max(0,Math.min(1.26,ed0+(ey0-wy)));
        layout();
      }
    });
    g.position.copy(base);
    scene.add(g);
    layout();
    riseIn(g,base.y,2.5,0.6);
    status('lever — pull the gold ring DOWN. the 10 KG load rises at 1/3 the distance.');
  }catch(e){ status('lever failed: '+e.message); }
}

/* ============================================================================
   SPRING — Hooke's law, F = −kx. THE ONLY elastic thing in the system.
   Everything else is rigid. This one honestly stretches.
   `spring` builds it. Drag the load, release, watch it settle. `unspring`.
   ===================================================================