<!-- RUBY-BACKUP · part 27 -->
    try{
      var body = document.getElementById('cb-body');
      if(!body) return;
      function onTap(elm, fn){
        try{
          elm.addEventListener('touchstart', function(e){ try{ e.preventDefault(); e.stopPropagation(); }catch(x){} fn(e); }, {passive:false});
          elm.addEventListener('mousedown', function(e){ try{ e.stopPropagation(); }catch(x){} fn(e); });
        }catch(e){}
      }
      /* chain remove */
      var rms = body.querySelectorAll('.cb-rm');
      for(var r=0;r<rms.length;r++){
        (function(elm){
          onTap(elm, function(){
            var i = parseInt(elm.getAttribute('data-i'), 10);
            if(!isNaN(i)) chain.splice(i,1);
            renderBody();
          });
        })(rms[r]);
      }
      /* save */
      var sv = document.getElementById('cb-save');
      if(sv) onTap(sv, saveCode);
      var nm = document.getElementById('cb-name');
      if(nm) nm.addEventListener('keydown', function(e){ if(e.key==='Enter') saveCode(); });
      /* arg form buttons */
      var ac = document.getElementById('cb-argcancel');
      if(ac) onTap(ac, function(){ pendingAct = null; pendingVals = {}; renderBody(); });
      var aa = document.getElementById('cb-argadd');
      if(aa) onTap(aa, addPendingToChain);
      var tns = body.querySelectorAll('.cb-tapnode');
      for(var t=0;t<tns.length;t++){
        (function(elm){
          onTap(elm, function(){
            var k = parseInt(elm.getAttribute('data-k'), 10);
            armNodePick(k);
          });
        })(tns[t]);
      }
      var ins = body.querySelectorAll('.cb-argin');
      for(var q=0;q<ins.length;q++){
        (function(inp){
          inp.addEventListener('input', function(){
            var k = parseInt(inp.getAttribute('data-k'), 10);
            pendingVals[k] = inp.value;
          });
          inp.addEventListener('change', function(){
            var k = parseInt(inp.getAttribute('data-k'), 10);
            pendingVals[k] = inp.value;
          });
        })(ins[q]);
      }
      /* palette actions */
      var acts = body.querySelectorAll('.cb-act');
      for(var a=0;a<acts.length;a++){
        (function(elm){
          onTap(elm, function(){
            var s = parseInt(elm.getAttribute('data-sec'), 10);
            var j = parseInt(elm.getAttribute('data-idx'), 10);
            pickAction(s, j);
          });
        })(acts[a]);
      }
    }catch(e){}
  }

  function pickAction(s, j){
    try{
      var act = SECTIONS[s].acts[j];
      if(!act) return;
      if(!act.args || !act.args.length){
        var line = act.code, label = act.code;
        if(act.fixed) line = act.fixed;
        chain.push({line:line, label:label});
        renderBody();
        return;
      }
      pendingAct = act; pendingVals = {};
      renderBody();
      try{
        var f = document.getElementById('cb-argform');
        if(f) f.scrollIntoView({block:'nearest'});
      }catch(e){}
    }catch(e){}
  }

  function addPendingToChain(){
    try{
      if(!pendingAct) return;
      var act = pendingAct;
      var parts = [], labels = [];
      for(var k=0;k<act.args.length;k++){
        var v = (pendingVals[k]==null?'':String(pendingVals[k])).trim();
        if(!v){ status('fill every part first'); return; }
        var ag = act.args[k];
        parts.push(v);
        labels.push(ag.t==='node' ? shortId(v) : v);
      }
      var base = act.fixed || act.code;
      var line = base + (parts.length ? ' '+parts.join(' ') : '');
      chain.push({line:line, label:base+' \u2192 '+labels.join(', ')});
      pendingAct = null; pendingVals = {};
      renderBody();
    }catch(e){}
  }

  function saveCode(){
    try{
      var nmEl = document.getElementById('cb-name');
      var name = nmEl ? String(nmEl.value||'').trim().toLowerCase() : '';
      if(!/^[a-z][a-z0-9_]{1,24}$/.test(name)){ status('name it: a-z, 0-9, _ (e.g. fortress)'); return; }
      if(RESERVED.indexOf(name) >= 0){ status('"'+name+'" is already a code'); return; }
      if(!chain.length){ status('chain is empty — tap actions first'); return; }
      // self-recursion guard
      for(var i=0;i<chain.length;i++){
        if(String(chain[i].line).trim().toLowerCase() === name){
          status('a code cannot call itself'); return;
        }
      }
      var all = loadCodes();
      var over = !!all[name];
      all[name] = {t: Date.now(), chain: chain.slice()};
      saveCodes(all);
      status('code "'+name+'" saved'+(over?' (replaced)':'')+' — '+chain.length+' steps');
      chain = [];
      if(nmEl) nmEl.value = '';
      renderBody();
    }catch(e){}
  }

  function listCodes(){
    try{
      var all = loadCodes();
      var names = Object.keys(all);
      if(!names.length){ status('no built codes yet — open codebuilder'); return; }
      status(names.length+' built: '+names.join(', '));
      try{ console.log('[codebuilder] mycodes:', names); }catch(e){}
    }catch(e){}
  }

  function forgetCode(name){
    