[object Object]

← back to Agent Cabinet

Suggestion lines truly clickable: amber ◆ handle at each line midpoint (z-index above nodes, real hit-test verified) + fatter 16px line hit-band; toggles with Suggested layer

e46f97552fe826b3a38a1e43222e73f03faeac02 · 2026-06-16 15:55:33 -0700 · SteveStudio2

Files touched

Diff

commit e46f97552fe826b3a38a1e43222e73f03faeac02
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Tue Jun 16 15:55:33 2026 -0700

    Suggestion lines truly clickable: amber ◆ handle at each line midpoint (z-index above nodes, real hit-test verified) + fatter 16px line hit-band; toggles with Suggested layer
---
 pyramid.html | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/pyramid.html b/pyramid.html
index c721e57..f898e7e 100644
--- a/pyramid.html
+++ b/pyramid.html
@@ -118,6 +118,12 @@
   .mini{background:#161d2c;border:1px solid #2b3650;color:#bcd0f0;border-radius:6px;padding:3px 8px;font-size:11px;cursor:pointer;margin-left:5px}
   .mini:hover{background:#1b2435}
   .sug-hit{cursor:pointer}
+  #sug-handles{position:absolute;inset:0;pointer-events:none;z-index:6}
+  .sug-h{position:absolute;transform:translate(-50%,-50%);pointer-events:auto;cursor:pointer;width:22px;height:22px;border-radius:50%;
+    border:2px solid #0b0e14;background:#fbbf24;color:#3a2a05;font-size:12px;font-weight:900;line-height:1;display:flex;align-items:center;justify-content:center;
+    box-shadow:0 0 0 2px rgba(251,191,36,.35),0 3px 9px rgba(0,0,0,.55);transition:transform .12s}
+  .sug-h:hover{transform:translate(-50%,-50%) scale(1.4);z-index:7}
+  .sug-h.approved{background:#34d399;color:#062a1c;box-shadow:0 0 0 2px rgba(52,211,153,.4),0 3px 9px rgba(0,0,0,.55)}
   .rel-flow{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:12px;margin-bottom:4px}
   .rel-end{background:#161d2c;border:1px solid #2b3650;border-radius:6px;padding:3px 9px;font-weight:700}
   .rel-to{border-color:#fbbf24;color:#fde68a}
@@ -139,6 +145,7 @@
   <div id="pyramid">
     <svg id="lines"></svg>
     <svg id="xlines"></svg>
+    <div id="sug-handles"></div>
     <div class="tier president"><div class="tier-label" style="top:14px">President</div>
       <div class="pres-node" id="pres"><div class="t">Steve</div><div class="s">Chief Executive · steve@designerwallcoverings.com</div></div>
     </div>
@@ -423,7 +430,7 @@ function computeShared(){
 function drawCross(){
   const root=document.getElementById('pyramid'), svg=document.getElementById('xlines');
   svg.setAttribute('width',root.scrollWidth); svg.setAttribute('height',root.scrollHeight); svg.setAttribute('viewBox',`0 0 ${root.scrollWidth} ${root.scrollHeight}`);
-  let sh='', sg='';
+  let sh='', sg='', hh='';
   SHARED.forEach(s=>{
     const pts=s.insts.map(n=>midC(n.el,root)).sort((a,b)=>a.x-b.x);
     const hue=hashHue(s.id);
@@ -442,12 +449,15 @@ function drawCross(){
     const d=`M${a.x},${a.y} C${a.x},${my} ${bx},${my} ${bx},${by}`;
     const ap=dec==='approved';
     sg+=`<path d="${d}" fill="none" stroke="${ap?'#34d399':'#fbbf24'}" stroke-width="${ap?1.9:1.3}" stroke-opacity="${ap?.95:.82}" ${ap?'':'stroke-dasharray="1.5 4.5"'} marker-end="url(#${ap?'arrG':'arr'})"/>`;
-    sg+=`<path class="sug-hit" data-key="${key}" d="${d}" fill="none" stroke="transparent" stroke-width="14" pointer-events="stroke" style="cursor:pointer"/>`;
+    sg+=`<path class="sug-hit" data-key="${key}" d="${d}" fill="none" stroke="transparent" stroke-width="16" pointer-events="stroke" style="cursor:pointer"/>`;
+    const hx=(a.x+bx)/2, hy=(a.y+by)/2;
+    hh+=`<button class="sug-h${ap?' approved':''}" data-key="${key}" style="left:${hx}px;top:${hy}px" title="${offName(g.from)} → ${offName(g.to)}  ·  ${g.kind==='skill'?'/':'@'}${g.id}  (click to approve / remove)">${ap?'✓':'◆'}</button>`;
   });
   svg.innerHTML=`<defs>`+
     `<marker id="arr" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#fbbf24"/></marker>`+
     `<marker id="arrG" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#34d399"/></marker>`+
     `</defs><g id="g-shared">${sh}</g><g id="g-suggest">${sg}</g>`;
+  const hc=document.getElementById('sug-handles'); if(hc) hc.innerHTML=hh;
   applyToggles();
 }
 function applyToggles(){
@@ -456,6 +466,7 @@ function applyToggles(){
   const gs=document.getElementById('g-shared'), gg=document.getElementById('g-suggest');
   if(gs) gs.style.display = on('tg-shared')?'':'none';
   if(gg) gg.style.display = on('tg-sug')?'':'none';
+  const hc=document.getElementById('sug-handles'); if(hc) hc.style.display = on('tg-sug')?'':'none';
 }
 function buildToolbar(){
   SHARED=computeShared();
@@ -517,6 +528,7 @@ async function decide(key,action){
 legend(); build(); timeline(); buildToolbar();
 document.getElementById('pyramid').addEventListener('click', onNodeClick);
 document.getElementById('xlines').addEventListener('click', e=>{ const t=e.target.closest('.sug-hit'); if(t) openSuggestion(t.dataset.key); });
+document.getElementById('sug-handles').addEventListener('click', e=>{ const t=e.target.closest('.sug-h'); if(t) openSuggestion(t.dataset.key); });
 document.addEventListener('keydown', e=>{ if(e.key==='Escape') closePanel(); });
 function redraw(){ drawLines(); drawCross(); }
 loadSugState().then(()=>requestAnimationFrame(()=>requestAnimationFrame(redraw)));

← 2f295b3 Approve auto-commits cabinet.yaml (path-limited, local, Stev  ·  back to Agent Cabinet  ·  Pyramid: 💡 Ideas modals — 5 upgrade ideas as modals (Task R 52c593f →