<!-- SAGA · part 56 -->
cted});
          selected = null;
          status('Deleted');
          // Panel stays open
        } else if(tool === 'color' && selected){
          var colors = [0xffd700, 0x00ccff, 0xff4444, 0xffffff, 0x1a1a1a];
          selected.traverse(function(o){ if(o.isMesh) o.material.color.setHex(colors[Math.floor(Math.random()*colors.length)]); });
          status('Recolored');
          // Panel stays open
        } else {
          status('Tool: ' + tool + ' active — tap a block in the world');
          // Panel stays open (tap ✕ to close and tap blocks)
        }
      }
    });
  });
  panel.querySelector('#creator-close').addEventListener('click', function(){
    panel.style.display = 'none';
  });
  // Tap blocks in world
  var raycaster = new THREE.Raycaster();
  var mouse = new THREE.Vector2();
  document.addEventListener('click', function(e){
    if(e.target && e.target.closest && e.target.closest('#block-ring')) return;
    if(panel.style.display === 'flex') return;
    if(!window._sagaCamera) return;
    var x = (e.clientX / window.innerWidth) * 2 - 1;
    var y = -(e.clientY / window.innerHeight) * 2 + 1;
    mouse.set(x, y);
    raycaster.setFromCamera(mouse, window._sagaCamera);
    var hits = raycaster.intersectObjects(placedBlocks, true);
    if(hits.length > 0){
      var obj = hits[0].object;
      while(obj.parent && !obj.userData.creatorBlock) obj = obj.parent;
      selected = obj;
      /* v90 — tap a branch box and it names its page */
      if(obj.userData.branchBox && typeof say === 'function'){
        say('Branch ' + obj.userData.branchBox + ' — /playaspace/' + obj.userData.branchBox);
      }
      /* v86 — tap Playa's monument and he unfolds (same as the playa2 code) */
      if(obj.userData.playaMonument && typeof window._unfoldPlaya === 'function'){
        window._unfoldPlaya();
        if(typeof say === 'function') say('Playa 2.0 unfolds');
      }
      showRing(obj);
      if(activeTool === 'move'){
        // Move with no-overlap check
        var oldX = selected.position.x;
        selected.position.x += 5;
        if(wouldOverlap(selected)){
          selected.position.x = oldX;
          if(typeof say === 'function') say('Blocked — would overlap');
        }
      } else if(activeTool === 'rotate'){
        selected.rotation.y += Math.PI/4;
      } else if(activeTool === 'scale'){
        selected.scale.multiplyScalar(1.2);
        if(wouldOverlap(selected)){
          selected.scale.multiplyScalar(1/1.2);
          if(typeof say === 'function') say('Blocked — would overlap');
        }
      } else {
        if(typeof say === 'function') say('Selected ' + (selected.userData.blockType || 'block'));
      }
    } else {
      hideRing();
    }
  });
  // IN-WORLD RING MENU — tiny tool options orbiting the selected block
  var ringBlock = null;
  var ringEl = document.createElement('div');
  ringEl.id = 'block-ring';
  ringEl.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;z-index:10001;pointer-events:none;display:none;';
  var ringTools = [
    {n:'duplicate', i:'📋'},
    {n:'color', i:'🎨'},
    {n:'move', i:'\u2725'},
    {n:'rotate', i:'🔄'},
    {n:'delete', i:'🗑️'},
    {n:'layer', i:'\u25c8'}
  ];
  ringTools.forEach(function(t){
    var b = document.createElement('button');
    b.textContent = t.i;
    b.setAttribute('aria-label', t.n);
    b.style.cssText = 'position:absolute;width:52px;height:52px;border-radius:50%;background:rgba(10,10,18,0.92);border:2px solid #ffd700;font-size:22px;pointer-events:auto;cursor:pointer;color:#ffd700;padding:0;';
    b.addEventListener('click', function(ev){ ev.stopPropagation(); applyRingTool(t.n); });
    ringEl.appendChild(b);
  });
  document.body.appendChild(ringEl);
  function showRing(block){
    ringBlock = block;
    if(selected && !selected.userData.layers) tagLayers(selected);
    if(selected) selected.userData.selLayer = -1;
    refreshLayerBtn();
    ringEl.style.display = 'block';
  }
  function hideRing(){ ringBlock = null; ringEl.style.display = 'none'; }
  function applyRingTool(name){
    if(!selected) return;
    if(name === 'duplicate'){
      var copy = selected.userData.blockType ? makeBlock(selected.userData.blockType) : selected.clone(true);
      copy.position.copy(selected.position);
      copy.position.x += 10;
      copy.userData.creatorBlock = true;
      copy.userData.blockType = selected.userData.blockType;
      if(!wouldOverlap(copy)){
        scene.add(copy); placedBlocks.push(copy);
        undoStack.push({action:'add', obj:copy});
        tagLayers(copy);
        cascadeIn(copy);
        if(typeof say === 'function' && (!copy.userData.layers || copy.userData.layers.length <= 1)) say('Duplicated');
      } else if(typeof say === 'function') say('Blocked \u2014 would overlap');
    } else if(name === 'color'){
      var colors = [0xffd700, 0x00ccff, 0xff4444, 0xffffff, 0x1a1a1a];
      var tgt = ringTarget();
      if(tgt === selected){
        s