<!-- RUBY-BACKUP · part 339 -->
length; hi++){
          var o = hits[hi].object;
          var root = o;
          while(root.parent && root.parent !== scene) root = root.parent;
          if(root.userData && root.userData.isPrimitive){
            /* Deselect old */
            if(window._selectedPrimitive){
              window._selectedPrimitive.traverse(function(m){ if(m.isMesh && m.material.emissive) m.material.emissive.setHex(0); });
            }
            window._selectedPrimitive = root;
            /* Highlight new */
            root.traverse(function(m){ if(m.isMesh && m.material.emissive) m.material.emissive.setHex(0x332200); });
            window._creatorSelectMode = false;
            if(typeof codeStatus === 'function') codeStatus('selected — move, rotate, scale, duplicate, color');
            break;
          }
        }
      }catch(e){}
    });
  }
  window._creator = { open: open, close: close, toggle: function(){ OPEN ? close() : open(); } };
})();
/* DIRECTIONAL WEB — 8 directions, smooth fade */
(function(){
  // the web: each node has 8 directional exits
  var WEB = {
    'center': {
      label: '✋',
      up: 'move', up_right: 'build', right: 'build', down_right: 'camera',
      down: 'camera', down_left: 'world', left: 'world', up_left: 'move'
    },
    'move': {
      label: '🏃',
      up: 'fly', right: 'jump', down: 'center', left: 'speed',
      fn_up: function(){ if(typeof handleCheatCode==='function') try{handleCheatCode('fly');}catch(e){} },
      fn_right: function(){ if(typeof jump==='function') jump(); },
      fn_left: function(){ if(typeof codeStatus==='function') codeStatus('speed up'); }
    },
    'build': {
      label: '🧱',
      up: 'grab', right: 'streets', down: 'center', left: 'primitives',
      fn_up: function(){ if(typeof toggleGrabMode==='function') toggleGrabMode(); },
      fn_right: function(){ if(typeof buildStreets==='function') buildStreets(); },
      fn_left: function(){ if(typeof handleCheatCode==='function') try{handleCheatCode('hourglass');}catch(e){} }
    },
    'camera': {
      label: '📷',
      up: 'center', right: 'zoomin', down: 'home', left: 'zoomout',
      fn_up: function(){ if(typeof codeStatus==='function') codeStatus('camera up'); },
      fn_right: function(){ if(typeof camDist!=='undefined') camDist = Math.max(0.3, camDist-1); },
      fn_down: function(){ var b=document.getElementById('homebtn'); if(b) b.click(); },
      fn_left: function(){ if(typeof camDist!=='undefined') camDist = Math.min(60, camDist+1); }
    },
    'world': {
      label: '🌍',
      up: 'sky', right: 'center', down: 'ground', left: 'time',
      fn_up: function(){ if(typeof handleCheatCode==='function') try{handleCheatCode('dawn');}catch(e){} },
      fn_down: function(){ if(typeof handleCheatCode==='function') try{handleCheatCode('floor');}catch(e){} },
      fn_left: function(){ if(typeof handleCheatCode==='function') try{handleCheatCode('night');}catch(e){} }
    },
    'fly': { label: '🕊️', down: 'move', fn_down: function(){ if(typeof handleCheatCode==='function') try{handleCheatCode('fly');}catch(e){} } },
    'jump': { label: '⬆️', down: 'move', fn_down: function(){ if(typeof jump==='function') jump(); } },
    'speed': { label: '⚡', right: 'move', fn_right: function(){ if(typeof codeStatus==='function') codeStatus('speed'); } },
    'grab': { label: '✋', down: 'build', fn_down: function(){ if(typeof toggleGrabMode==='function') toggleGrabMode(); } },
    'streets': { label: '🛣️', left: 'build', fn_left: function(){ if(typeof buildStreets==='function') buildStreets(); } },
    'primitives': { label: '🔷', right: 'build', fn_right: function(){ if(typeof handleCheatCode==='function') try{handleCheatCode('hourglass');}catch(e){} } },
    'zoomin': { label: '🔍', left: 'camera', fn_left: function(){ if(typeof camDist!=='undefined') camDist = Math.max(0.3, camDist-2); } },
    'zoomout': { label: '🔭', right: 'camera', fn_right: function(){ if(typeof camDist!=='undefined') camDist = Math.min(60, camDist+2); } },
    'home': { label: '🏠', up: 'camera', fn_up: function(){ var b=document.getElementById('homebtn'); if(b) b.click(); } },
    'sky': { label: '☁️', down: 'world', fn_down: function(){ if(typeof handleCheatCode==='function') try{handleCheatCode('dawn');}catch(e){} } },
    'ground': { label: '🟫', up: 'world', fn_up: function(){ if(typeof handleCheatCode==='function') try{handleCheatCode('floor');}catch(e){} } },
    'time': { label: '🕐', right: 'world', fn_right: function(){ if(typeof handleCheatCode==='function') try{handleCheatCode('night');}catch(e){} } }
  };
  var current = 'center';
  var webVisible = false;
  var webEl = null;
  var touchStartX = 0, touchStartY = 0;
  function showWeb(){
    hideWeb();
    webVisible = true;
    var node = WEB[current];
    webEl = document.createElement('div');
    webEl.id = 'dirweb';
    webEl.style.cssText = 'position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10003;wi