<!-- RUBY-BACKUP · part 25 -->
t') ? o : {};
    }catch(e){ return {}; }
  }
  function saveCodes(o){
    try{ localStorage.setItem(STORE_KEY, JSON.stringify(o)); }catch(e){}
  }
  function status(m){ try{ if(typeof codeStatus==='function') codeStatus(m); }catch(e){} }

  /* ================= RUNNER ================= */
  var running = false;
  var spliceGuard = {};
  function baseRun(line){
    try{
      var base = window.__runLineBase || window.runLine;
      if(typeof base === 'function') return base.call(window, line);
    }catch(e){}
    return false;
  }
  function runCustom(name){
    var all = loadCodes();
    var rec = all[name];
    if(!rec || !rec.chain || !rec.chain.length){ status('empty code'); return; }
    if(running){ status('a code is already running'); return; }
    running = true; spliceGuard = {};
    spliceGuard[name] = true;
    var chain = rec.chain.slice();
    var i = 0;
    status(name+': 1/'+chain.length);
    function step(){
      if(i >= chain.length){
        running = false; spliceGuard = {};
        status(name+' done');
        return;
      }
      var item = chain[i]; i++;
      status(name+': '+(i)+'/'+chain.length);
      try{
        var line = String(item.line||'').trim();
        if(/^wait\s/i.test(line)){
          var secs = parseFloat(line.replace(/^wait\s+/i,'')) || 1;
          setTimeout(step, Math.min(30, Math.max(0.2, secs))*1000);
          return;
        }
        var subName = line.toLowerCase();
        var sub = loadCodes()[subName];
        if(sub && sub.chain && sub.chain.length && !spliceGuard[subName]){
          // nested custom code: splice its chain in (guarded against loops)
          spliceGuard[subName] = true;
          chain = sub.chain.slice().concat(chain.slice(i));
          i = 0;
          setTimeout(step, 600);
          return;
        }
        if(sub && spliceGuard[subName]){
          status('skipped loop: '+subName);
          setTimeout(step, 600);
          return;
        }
        baseRun(line);
      }catch(e){}
      setTimeout(step, 600);
    }
    step();
  }

  /* ================= PANEL ================= */
  var panelEl = null, panelOpen = false;
  var chain = [];            // [{line,label}]
  var pendingAct = null;    // action awaiting args
  var pendingVals = {};     // arg index -> value

  function esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;'); }
  function shortId(id){ id = String(id||''); return id.length>8 ? '\u2026'+id.slice(-6) : id; }

  function closePanel(){
    if(!panelOpen) return;
    panelOpen = false;
    try{
      var el = panelEl; panelEl = null;
      if(el){
        el.style.maxHeight = '0px';
        setTimeout(function(){ try{ if(el.parentNode) el.parentNode.removeChild(el); }catch(e){} }, 300);
      }
    }catch(e){ panelEl = null; }
  }

  function openPanel(){
    if(panelOpen){ closePanel(); return; }
    closePanel();
    pendingAct = null; pendingVals = {};
    try{
      var el = document.createElement('div');
      el.id = 'codeBuilderPanel';
      var mw = Math.min(360, window.innerWidth - 16);
      var mh = Math.min(window.innerHeight - 110, 560);
      el.style.cssText = 'position:fixed;left:50%;top:56px;transform:translateX(-50%);width:'+mw+'px;'
        +'z-index:'+PANEL_Z+';background:rgba(10,8,4,0.97);border:2px solid #d8a920;border-radius:16px;'
        +'box-shadow:0 0 32px rgba(216,169,32,0.45);overflow:hidden;'
        +'max-height:0px;transition:max-height 0.3s linear;';
      el.innerHTML =
        '<div style="padding:12px 14px 8px 14px;color:#ffd700;font-family:Georgia,serif;'
        +'font-size:14px;letter-spacing:3px;border-bottom:1px solid #8a6a1c;'
        +'display:flex;justify-content:space-between;align-items:center;">'
        +'<span>\u270E CODE BUILDER</span>'
        +'<span id="cb-x" style="font-size:20px;padding:4px 10px;cursor:pointer;">\u2715</span></div>'
        +'<div id="cb-body" style="overflow-y:auto;-webkit-overflow-scrolling:touch;max-height:'+(mh-56)+'px;padding:8px;"></div>';
      document.body.appendChild(el);
      panelEl = el; panelOpen = true;
      function doX(e){ try{ if(e){ e.preventDefault(); e.stopPropagation(); } }catch(x){} closePanel(); }
      var xBtn = document.getElementById('cb-x');
      if(xBtn){ xBtn.addEventListener('touchstart', doX, {passive:false}); xBtn.addEventListener('mousedown', doX); }
      renderBody();
      void el.offsetHeight;
      el.style.maxHeight = mh+'px';
    }catch(e){ closePanel(); }
  }

  function chainLabel(){
    return chain.length ? chain.map(function(c){ return c.label; }).join(' \u2192 ') : '';
  }

  function renderBody(){
    try{
      var body = document.getElementById('cb-body');
      if(!body) return;
      var html = '';
      /* ---- chain ---- */
      html += '<div style="padding:8px 10px 4px 10px;color:#d8a920;font-family:Georgia,serif;'
        +'font-size:12px;letter-spacing:4px;">CHAIN ('+chai