<!-- RUBY-BACKUP · part 72 -->
g);
}


/* ---------------- PULLEY SCROLL MENU ----------------
   Tap any block -> the menu unrolls like a rope dropping from a pulley.
   Gold on black, thumb-sized rows, linear unroll (nothing teleports).
   Rows drive the same functions the codes call. */
var menuEl=null, menuOpen=false, menuTarget=null, rigTargetPre=null, rigTargetPrePoint=null;
function menuRows(){
  var tg=menuTarget?menuTarget.tg:null;
  if(!tg) return [];
  var isPul=tg.kind==='pulley';
  var anchored=!!getAnchor(tg);
  var rows=[
    {act:'grab', ic:'\u270B', label:'Grab', why:'pick it up and move it'},
    isPul
      ? {act:'rigfrom', ic:'\u27BF', label:'Rig from here', why:'rope starts at this pulley'}
      : {act:'pulleyhere', ic:'\u2699', label:'Pulley here', why:'a wheel to redirect your pull'},
    isPul
      ? null
      : {act:'rigthis', ic:'\u27BF', label:'Rig this', why:'rope it and pull it'},
    isPul
      ? null
      : (anchored
          ? {act:'unanchor', ic:'\uD83D\uDCCC', label:'Unanchor', why:'free it to move again'}
          : {act:'anchor', ic:'\uD83D\uDCCC', label:'Anchor', why:'pin it — pulls reshape it'}),
    (!isPul && tg.kind==='frame')
      ? {act:'diamond', ic:'\u25C6', label:'Diamond', why:'pull corners into a diamond'}
      : null,
    {act:'lift', ic:'\u2B06', label:'Lift', why:'raise the ground here'},
    {act:'setdown', ic:'\u2B07', label:'Set down', why:'lower it back down'},
    {act:'detach', ic:'\u2702', label:'Detach', why:'cut one rope free'},
    {act:'unrig', ic:'\u274C', label:'Unrig', why:'clear every rope'},
    {act:'delete', ic:'\u2716', label:'Delete', why:'remove it'},
    {act:'duplicate', ic:'\u29C9', label:'Duplicate', why:'make another'}
  ];
  var out=[];
  for(var i=0;i<rows.length;i++) if(rows[i]) out.push(rows[i]);
  return out;
}
function closeMenu(){
  if(!menuOpen) return;
  menuOpen=false; menuTarget=null;
  try{
    if(menuEl){
      var el=menuEl; menuEl=null;
      el.style.maxHeight='0px';
      setTimeout(function(){ try{ if(el.parentNode) el.parentNode.removeChild(el); }catch(e){} },260);
    }
  }catch(e){ menuEl=null; }
}
function openMenu(tg, pointW, sx, sy){
  closeMenu();
  menuTarget={tg:tg, pointW:pointW.clone()};
  try{
    var rows=menuRows();
    var el=document.createElement('div');
    el.id='pulleyMenu';
    var mw=216, mh=Math.min(360, 64+rows.length*52);
    var lx=Math.max(8, Math.min(sx+14, window.innerWidth-mw-8));
    var ly=sy+14;
    if(ly+mh>window.innerHeight-8) ly=Math.max(8, sy-mh-14);
    el.style.cssText='position:fixed;left:'+lx+'px;top:'+ly+'px;width:'+mw+'px;'
      +'z-index:30000;background:rgba(10,8,4,0.96);border:2px solid #d8a920;border-radius:16px;'
      +'box-shadow:0 0 24px rgba(216,169,32,0.35);overflow:hidden;'
      +'max-height:0px;transition:max-height 0.25s linear;';
    var html='<div style="padding:10px 12px 6px 12px;color:#ffd700;font-family:Georgia,serif;'
      +'font-size:13px;letter-spacing:3px;border-bottom:1px solid #8a6a1c;">'
      +'<span style="display:inline-block;animation:pmspin 1.2s linear infinite;">\u25C9</span> PULLEY</div>'
      +'<div style="overflow-y:auto;-webkit-overflow-scrolling:touch;max-height:300px;padding:6px;">';
    for(var i=0;i<rows.length;i++){
      html+='<div class="pm-row" data-act="'+rows[i].act+'" style="display:flex;align-items:center;gap:12px;'
        +'padding:11px 10px;margin:2px 0;border-radius:10px;cursor:pointer;'
        +'color:#ffd700;font-family:Georgia,serif;font-size:16px;'
        +'-webkit-tap-highlight-color:transparent;">'
        +'<span style="font-size:20px;width:28px;text-align:center;">'+rows[i].ic+'</span>'
        +'<span><span>'+rows[i].label+'</span>'
        +'<span style="display:block;font-size:11px;color:#8a6a1c;font-style:italic;">'+(rows[i].why||'')+'</span></span></div>';
    }
    html+='</div>';
    el.innerHTML=html;
    var st=document.createElement('style');
    st.textContent='@keyframes pmspin{from{transform:rotate(0deg);}to{transform:rotate(360deg);}}'
      +'.pm-row:active{background:rgba(216,169,32,0.25);}';
    el.appendChild(st);
    document.body.appendChild(el);
    menuEl=el; menuOpen=true;
    var rows2=el.querySelectorAll('.pm-row');
    for(var j=0;j<rows2.length;j++){
      (function(row){
        var fired=false;
        function go(e){
          if(fired) return; fired=true;
          try{ if(e){ e.preventDefault(); e.stopPropagation(); } }catch(x){}
          menuAct(row.getAttribute('data-act'));
        }
        row.addEventListener('touchstart',go,{passive:false});
        row.addEventListener('mousedown',go);
      })(rows2[j]);
    }
    void el.offsetHeight;
    el.style.maxHeight=mh+'px';
  }catch(e){ closeMenu(); }
}
function rootOf(obj){
  try{
    var o=obj;
    while(o && o.parent && !o.parent.isScene) o=o.parent;
    return o||obj;
  }catch(e){ return obj; }
}
function menuAct(act){
  if(act==='lift'){ try{closeMenu();}catch(e){} if(typeof armLift==='function') armLift