<!-- RUBY-BACKUP · part 566 -->
    if(typeof codeStatus==='function') codeStatus('PORTAL → ' + b);
          break;
        }
      }
    }catch(e){}
  }

  /* ---- SWITCH: touch to toggle ON/OFF ---- */
  var switchStates = {};
  window.getSwitchState = function(nid){ return !!switchStates[nid]; };
  window.switchNode = function(nid){
    try{
      if(!solidNodes[nid]) window.solidifyNode(nid);
      if(!solidNodes[nid]) return 'no such node';
      solidNodes[nid].mode = 'switch';
      if(!(nid in switchStates)) switchStates[nid] = false;
      paintMode(nid);
      ringMode(nid, switchStates[nid] ? 0xffd700 : 0x333333);
      if(typeof codeStatus==='function') codeStatus('SWITCH ' + nid + ' ready — touch to toggle');
      return 'switch armed';
    }catch(e){ return 'switch failed'; }
  };
  window.flipSwitch = function(nid){
    switchStates[nid] = !switchStates[nid];
    ringMode(nid, switchStates[nid] ? 0xffd700 : 0x333333);
    if(typeof codeStatus==='function') codeStatus('SWITCH ' + nid + ' → ' + (switchStates[nid]?'ON':'OFF'));
    return switchStates[nid];
  };
  function switchTick(){
    try{
      var pp = playerPos();
      if(!pp) return;
      for(var nid in solidNodes){
        var sn = solidNodes[nid];
        if(!sn || sn.mode !== 'switch' || sn.cool > Date.now()) continue;
        if(dist2D(pp, sn) < 1.5){
          window.flipSwitch(nid);
          sn.cool = Date.now() + 1500;
        }
      }
    }catch(e){}
  }

  /* ---- SENSOR: watches, reports movement ---- */
  window.sensorNode = function(nid){
    try{
      if(!solidNodes[nid]) window.solidifyNode(nid);
      if(!solidNodes[nid]) return 'no such node';
      solidNodes[nid].mode = 'sensor';
      solidNodes[nid].cool = 0;
      paintMode(nid);
      ringMode(nid, 0xff2222);
      if(typeof codeStatus==='function') codeStatus('SENSOR ' + nid + ' watching');
      return 'sensor watching';
    }catch(e){ return 'sensor failed'; }
  };
  function sensorTick(){
    try{
      if(!window.__nodeMap) return;
      var now = Date.now();
      for(var nid in solidNodes){
        var sn = solidNodes[nid];
        if(!sn || sn.mode !== 'sensor' || sn.cool > now) continue;
        for(var k in window.__nodeMap){
          if(k === nid || solidNodes[k]) continue;
          var rec = window.__nodeMap[k];
          if(!rec || !rec.obj || !rec.obj.parent) continue;
          var p = new THREE.Vector3(); rec.obj.getWorldPosition(p);
          if(Math.hypot(p.x-sn.x, p.z-sn.z) < 4){
            sn.cool = now + 2000;
            if(typeof codeStatus==='function')
              codeStatus('SENSOR ' + nid + ': movement at ' + Math.round(p.x) + ',' + Math.round(p.z));
            break;
          }
        }
      }
    }catch(e){}
  }

  /* ---- SPRING: bounce pad, real velocity ---- */
  window.springNode = function(nid){
    try{
      if(!solidNodes[nid]) window.solidifyNode(nid);
      if(!solidNodes[nid]) return 'no such node';
      solidNodes[nid].mode = 'spring';
      solidNodes[nid].cool = 0;
      paintMode(nid);
      ringMode(nid, 0x22ff44);
      if(typeof codeStatus==='function') codeStatus('SPRING ' + nid + ' — bounce!');
      return 'spring loaded';
    }catch(e){ return 'spring failed'; }
  };
  function springTick(){
    try{
      var pp = playerPos();
      if(!pp) return;
      for(var nid in solidNodes){
        var sn = solidNodes[nid];
        if(!sn || sn.mode !== 'spring' || sn.cool > Date.now()) continue;
        if(dist2D(pp, sn) < 1.5 && pp.y < sn.y + 1.5){
          // launch upward with real velocity
          if(typeof window._vy !== 'undefined') window._vy = 14;
          else if(window.FLYM === false){ /* walking — give jump */ }
          // visual compress
          if(sn.platform){ sn.platform.scale.y = 0.4; setTimeout(function(){ try{sn.platform.scale.y=1;}catch(e){} }, 180); }
          sn.cool = Date.now() + 800;
          if(typeof codeStatus==='function') codeStatus('BOING!');
        }
      }
    }catch(e){}
  }

  /* ---- ANCHOR: deep pin, immovable ---- */
  window.anchorNode = function(nid){
    try{
      if(!solidNodes[nid]) window.solidifyNode(nid);
      var sn = solidNodes[nid];
      if(!sn) return 'no such node';
      sn.mode = 'anchor';
      // pin the block itself
      if(window.__nodeMap && window.__nodeMap[nid] && window.__nodeMap[nid].obj){
        window.__nodeMap[nid].obj.userData.deepAnchored = true;
      }
      paintMode(nid);
      ringMode(nid, 0x555555);
      if(sn.platform){
        sn.platform.material.color.setHex(0x3a3a3a);
        // gold bands
        var band = new THREE.Mesh(
          new THREE.TorusGeometry(1.25, 0.08, 8, 24),
          new THREE.MeshBasicMaterial({color: 0xffd700})
        );
        band.rotation.x = Math.PI/2; band.position.y = 0.1;
        sn.platform.add(band);
      }
      if(typeof codeStatus==='function') codeStatus('ANCHOR ' + nid + ' — immovable');
      return 'anchored deep';
    }catch(e){ return 'anchor failed'; }
  };
  windo