[object Object]

← back to Quadrille Showroom

5x sweep 1: keep bottom-corner panels clear of the centre pager (fix #g-next occlusion)

a15605251c116e6bccaafc80bf025bc36261be7f · 2026-07-02 11:22:53 -0700 · Steve

Files touched

Diff

commit a15605251c116e6bccaafc80bf025bc36261be7f
Author: Steve <steve@designerwallcoverings.com>
Date:   Thu Jul 2 11:22:53 2026 -0700

    5x sweep 1: keep bottom-corner panels clear of the centre pager (fix #g-next occlusion)
---
 5x/sweep-1.md     | 19 +++++++++++--------
 public/js/dock.js | 11 ++++++++---
 2 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/5x/sweep-1.md b/5x/sweep-1.md
index 84cba15..f699860 100644
--- a/5x/sweep-1.md
+++ b/5x/sweep-1.md
@@ -1,9 +1,12 @@
 # 5x sweep 1
-## Caught
-- generic M3 "body hidden" — HARNESS MISMATCH (body has overflow:hidden + #loading-screen fade; 3 real browsers render fine, M2 screenshot captured). Not an app defect.
-- generic clickthrough sort-select timeout — HARNESS MISMATCH (#window-bar is in dock STOW_ONLY, display:none on boot by design; project ships clickthrough-showroom.mjs for this). Not an app defect.
-- app-aware clickthrough: 4× 502 Bad Gateway on cold-cache concurrent sliver-thumb fetches. REAL (intermittent) — /api/thumb upstream https.get had no retry; a cold burst of ~24 slivers trips a transient cdn.shopify.com hiccup → hard 502.
-## Fixed
-- server.js /api/thumb: added one-shot retry (250ms backoff) + 8s timeout on the upstream fetch; retries transient (network/5xx/timeout) only, never a real 4xx.
-## App-aware suite (the correct proof for this app)
-- verify-all: sort+density persist ✓ · WebGL scene 50 boards/639 meshes/227 textured/book-matched/72fps/0 errors ✓ · At-the-Table nook+seated+addSample ✓
+Six-way: M1✓ M2✓ M3✓ (0 JS errors) · B4✓ B5✓ B6✓ — 6/6 core PASS.
+Click-through caught: sort-select selectOption timeouts (×5).
+Triage: sort-select lives in the Controls panel, collapsed on load → harness
+poked a display:none control. NOT a defect (verified: opens+operates fine once
+BR corner launched: sortSelect OK, densityRange OK, style chip OK).
+REAL defect caught by interaction probe: #g-next (pager Next) click TIMEOUT —
+the wide Controls panel (bottom-right) overlaps the always-visible centre pager
+and intercepts its clicks (elementFromPoint → "inside .qh-modal"). Violates the
+"always show cleanly at the bottom" requirement.
+FIX: seedCornerRect reserves a 76px bottom pager-band so bottom-corner panels
+open ABOVE the pager; bumped position-key qhdock2→qhdock3 so it takes effect.
diff --git a/public/js/dock.js b/public/js/dock.js
index db383a2..5fda63c 100644
--- a/public/js/dock.js
+++ b/public/js/dock.js
@@ -167,18 +167,23 @@
   // "belonging" to the hamburger it launched from). A position the user later
   // drags wins on subsequent opens (ModalRig.saveRect writes the same key).
   function seedCornerRect(p, corner) {
-    var key = 'modalrig:qhdock2:' + p.sel;
+    var key = 'modalrig:qhdock3:' + p.sel;
     try { if (localStorage.getItem(key)) return; } catch (e) {}
     var w = p.w || 320, h = p.h || 360;
     var m = 16, burgerZone = 70;   // clear the corner burger
+    // Bottom corners must clear the always-visible centre pager so it "shows
+    // cleanly at the bottom" (Steve) and never eats the pager's clicks. 5x
+    // sweep-1 caught the wide Controls panel occluding #g-next — this is the fix.
+    var pagerBand = 76;
     var vw = window.innerWidth, vh = window.innerHeight;
     // stagger multiple panels in the same corner so they don't stack
     var siblings = corner.panels;
     var idx = siblings.findIndex(function (x) { return x.sel === p.sel; });
     var off = (idx < 0 ? 0 : idx) * 34;
+    var bottomClear = (corner.pos.indexOf('bottom') > -1) ? pagerBand : 0;
     var left, top;
     if (corner.pos.indexOf('left') > -1)  left = m + off; else left = Math.max(m, vw - w - m - off);
-    if (corner.pos.indexOf('top') > -1)   top = burgerZone + off; else top = Math.max(m, vh - h - m - off);
+    if (corner.pos.indexOf('top') > -1)   top = burgerZone + off; else top = Math.max(m, vh - h - m - bottomClear - off);
     left = Math.max(0, Math.min(left, vw - 80));
     top  = Math.max(0, Math.min(top,  vh - 40));
     try { localStorage.setItem(key, JSON.stringify({ left: left, top: top, w: w, h: h })); } catch (e) {}
@@ -233,7 +238,7 @@
       wrap.addEventListener('mousedown', function () { bringToFront(p.sel, wrap); });
 
       seedCornerRect(p, corner);
-      ModalRig.rig(wrap, { key: 'qhdock2:' + p.sel, handle: head, width: p.w, height: p.h });
+      ModalRig.rig(wrap, { key: 'qhdock3:' + p.sel, handle: head, width: p.w, height: p.h });
     }
     wrap.classList.remove('qh-stowed');
     el.classList.remove('qh-stowed');

← b657af0 auto-save: 2026-07-02T10:47:21 (3 files) — package-lock.json  ·  back to Quadrille Showroom  ·  auto-save: 2026-07-02T11:47:40 (2 files) — public/js/rack.js e7f3b0f →