<!-- RUBY-BACKUP · part 53 -->
rn;
    goldMat = new THREE.MeshStandardMaterial({color:0xd8a920, metalness:0.85, roughness:0.25, emissive:0x2a1e00});
    darkMat = new THREE.MeshStandardMaterial({color:0x3a3a3a, metalness:0.6, roughness:0.5});
  }

  function newSeedRecord(obj, pos){
    seedSeq++;
    return {
      id: 'seed_' + seedSeq,
      block: obj, pos: pos.clone(),
      core: null,
      parts: {pulleys:[], gears:[], ropes:[], web:false},
      running: true, gearAngle: 0,
      linked: [], templateName: null
    };
  }
  function activeSeed(){ return seeds.length ? seeds[seeds.length-1] : null; }
  function findSeed(id){ for(var i=0;i<seeds.length;i++) if(seeds[i].id===id) return seeds[i]; return null; }
  function findSeedByBlock(obj){
    try{
      var o = obj;
      while(o){
        if(o.userData && o.userData.seedId){
          var sd = findSeed(o.userData.seedId);
          if(sd) return sd;
        }
        o = o.parent;
      }
    }catch(e){}
    return null;
  }

  /* ---------- helpers ---------- */
  function pickBlock(sx, sy){
    try{
      if(typeof rayPick === 'function'){
        var hit = rayPick(sx, sy);
        if(hit && hit.object) return hit.object;
        if(hit && hit.obj) return hit.obj;
      }
    }catch(e){}
    return null;
  }
  function blockCenter(obj){
    var p = new THREE.Vector3();
    try{ obj.getWorldPosition(p); }catch(e){}
    return p;
  }
  function groundY(x, z){
    try{
      if(typeof fortifiedGroundY === 'function') return fortifiedGroundY(x, z);
    }catch(e){}
    return 0;
  }
  function riseIn(obj, fromY, toY, dur, done){
    var t0 = Date.now();
    obj.position.y = fromY;
    (function step(){
      try{
        var t = Math.min(1, (Date.now()-t0)/dur);
        var e = 1 - Math.pow(1-t, 3);
        obj.position.y = fromY + (toY-fromY)*e;
        if(t < 1){ requestAnimationFrame(step); }
        else if(done){ done(); }
      }catch(e){}
    })();
  }
  function sinkAway(obj, dur, done){
    var y0 = obj.position.y;
    var t0 = Date.now();
    (function step(){
      try{
        var t = Math.min(1, (Date.now()-t0)/dur);
        obj.position.y = y0 - 5*t;
        obj.traverse(function(o){
          try{
            if(o.material && o.material.transparent !== undefined){
              o.material.transparent = true;
              o.material.opacity = 1-t;
            }
          }catch(e){}
        });
        if(t < 1){ requestAnimationFrame(step); }
        else {
          try{ if(window.scene) window.scene.remove(obj); }catch(e){}
          if(done) done();
        }
      }catch(e){}
    })();
  }

  /* ---------- the seed ---------- */
  var seedArmed = false;
  var plantTplArmed = null;   // template name to plant on next tap
  var linkArmed = false, linkFirst = null;
  var unlinkArmed = false;

  function armSeed(){
    seedArmed = true;
    status('seed armed — tap one block. it becomes the machine seed.');
  }

  function plantSeed(obj, template){
    if(!obj) return null;
    var pos = blockCenter(obj);
    var sd = newSeedRecord(obj, pos);
    try{
      obj.userData.isSeed = true;
      obj.userData.seedId = sd.id;
    }catch(e){}
    /* gold core glow */
    try{
      mats();
      var box = new THREE.Box3().setFromObject(obj);
      var size = new THREE.Vector3(); box.getSize(size);
      var core = new THREE.Mesh(
        new THREE.OctahedronGeometry(Math.max(0.3, Math.min(size.x, size.y, size.z) * 0.3)),
        new THREE.MeshBasicMaterial({color:0xffd700, transparent:true, opacity:0.9})
      );
      core.position.copy(pos); core.position.y += 0.2;
      core.userData.isSeedCore = true;
      core.userData.seedId = sd.id;
      if(window.scene) window.scene.add(core);
      sd.core = core;
      (function pulse(){
        try{
          if(!core.parent) return;
          core.rotation.y += 0.03;
          core.scale.setScalar(1 + Math.sin(Date.now()/400)*0.12);
          requestAnimationFrame(pulse);
        }catch(e){}
      })();
    }catch(e){}
    seeds.push(sd);
    if(template){
      sd.templateName = template.name;
      status('template "' + template.name + '" planted — growing.');
      setTimeout(function(){ growFromTemplate(sd, template); }, 600);
    } else {
      status('seed planted — `seed grow` births the machine.');
    }
    driveLoop();
    return sd;
  }

  /* ---------- part builders (each rises from the ground) ---------- */
  function buildPulleyAt(x, z, idx, sd){
    mats();
    var gy = groundY(x, z);
    var g = new THREE.Group();
    var post = new THREE.Mesh(new THREE.CylinderGeometry(0.18, 0.24, 3.2, 10), darkMat);
    post.position.y = 1.6;
    g.add(post);
    var wheel = new THREE.Group();
    var tire = new THREE.Mesh(new THREE.TorusGeometry(PULLEY_R, 0.14, 10, 24), goldMat);
    var hub = new THREE.Mesh(new THREE.CylinderGeometry(0.12, 0.12, 0.4, 10), goldMat);
    hub.rotation.x = Math.PI/2;
    for(var s=0;s<4;s++){
      var spoke = new THREE.Mesh(new THREE.CylinderGeometry(0.05, 0