[object Object]

← back to Commercialrealestate

Add shared two-hamburger corner navigation to every CRCP page

619dd53a55b152f644baae0d6e1e7c9dbf89a066 · 2026-08-06 15:25:38 -0700 · Steve

New public/corner-nav.js (self-injecting, zero-dep) drops onto all 26 pages via
one <script> tag before </body>:
- TOP-LEFT hamburger -> slide-in site nav, grouped into 5 collapsible accordion
  sections; current page highlighted + its section auto-expanded
- TOP-RIGHT hamburger -> 'On this page' jump links built from the page's own
  headings + a collapsed full-site menu; degrades gracefully when no headings
- overlay + Esc + click-out close; reserves header corner space so titles /
  existing nav / the index Filters button clear both hamburgers
Verified in real Chrome on crcp (title clears), index (no Filters overlap),
map (no header - graceful). Idempotent injection, one tag per page.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 619dd53a55b152f644baae0d6e1e7c9dbf89a066
Author: Steve <steve@designerwallcoverings.com>
Date:   Thu Aug 6 15:25:38 2026 -0700

    Add shared two-hamburger corner navigation to every CRCP page
    
    New public/corner-nav.js (self-injecting, zero-dep) drops onto all 26 pages via
    one <script> tag before </body>:
    - TOP-LEFT hamburger -> slide-in site nav, grouped into 5 collapsible accordion
      sections; current page highlighted + its section auto-expanded
    - TOP-RIGHT hamburger -> 'On this page' jump links built from the page's own
      headings + a collapsed full-site menu; degrades gracefully when no headings
    - overlay + Esc + click-out close; reserves header corner space so titles /
      existing nav / the index Filters button clear both hamburgers
    Verified in real Chrome on crcp (title clears), index (no Filters overlap),
    map (no header - graceful). Idempotent injection, one tag per page.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 public/admin.html           |   1 +
 public/broker-grid.html     |   1 +
 public/brokers.html         |   1 +
 public/condos.html          |   1 +
 public/corner-nav.js        | 184 ++++++++++++++++++++++++++++++++++++++++++++
 public/crcp.html            |   1 +
 public/credit-unions.html   |   1 +
 public/deals-flow.html      |   3 +-
 public/deals.html           |   1 +
 public/fha-leads.html       |   3 +-
 public/fha-loans.html       |   1 +
 public/gov-agents.html      |   1 +
 public/graphics.html        |   1 +
 public/index.html           |   1 +
 public/just-listed.html     |   1 +
 public/lenders.html         |   1 +
 public/lending.html         |   1 +
 public/licensed-agents.html |   1 +
 public/licensed.html        |   1 +
 public/linkedin.html        |   1 +
 public/loan-officers.html   |   1 +
 public/map.html             |   1 +
 public/mls.html             |   1 +
 public/mortgage-market.html |   1 +
 public/rent-rolls.html      |   1 +
 public/sales.html           |   1 +
 public/sba-lenders.html     |   1 +
 27 files changed, 212 insertions(+), 2 deletions(-)

diff --git a/public/admin.html b/public/admin.html
index b3d092c..a43d7c0 100644
--- a/public/admin.html
+++ b/public/admin.html
@@ -219,5 +219,6 @@ $('#gp').addEventListener('keydown',e=>{if(e.key==='Enter')$('#gBtn').click();})
 
 boot();
 </script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/broker-grid.html b/public/broker-grid.html
index 60d34e1..c37b8dc 100644
--- a/public/broker-grid.html
+++ b/public/broker-grid.html
@@ -450,5 +450,6 @@ fetch('/api/brokers/all').then(r=>r.json()).then(d=>{DATA=d.brokers||[];autoCols
   <script src="/col-resize.js" defer></script>
   <script src="/global-search.js" defer></script>
   <script src="/sort-bar.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/brokers.html b/public/brokers.html
index 1620cc1..c081256 100644
--- a/public/brokers.html
+++ b/public/brokers.html
@@ -401,5 +401,6 @@ $('#firmq').oninput=()=>highlight($('#firmq').value);
   });
 });
 </script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/condos.html b/public/condos.html
index ac1b0de..df4bf4b 100644
--- a/public/condos.html
+++ b/public/condos.html
@@ -646,5 +646,6 @@ boot();
   <script src="/col-resize.js" defer></script>
   <script src="/global-search.js" defer></script>
   <script src="/sort-bar.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/corner-nav.js b/public/corner-nav.js
new file mode 100644
index 0000000..2184c6a
--- /dev/null
+++ b/public/corner-nav.js
@@ -0,0 +1,184 @@
+/* corner-nav.js — shared two-hamburger navigation for every CRCP page.
+   Drop-in: <script src="/corner-nav.js" defer></script>
+   • TOP-LEFT  ☰  → slide-in drawer of SITE navigation, grouped into collapsible sections.
+   • TOP-RIGHT ▤  → slide-in drawer of "On this page" jump links, built from the page's own headings.
+   Self-contained (injects its own CSS, reads nothing from the host page), idempotent, a11y-friendly. */
+(function () {
+  if (window.__cornerNav) return; window.__cornerNav = true;
+
+  var CUR = (location.pathname.split('/').pop() || 'index.html').toLowerCase();
+
+  // ── site map: grouped so each group is one collapsible accordion section ──────────
+  var GROUPS = [
+    { title: 'Explore & Properties', items: [
+      ['index.html', '🏙️ CRE Explorer'], ['just-listed.html', '🆕 Just Listed'],
+      ['sales.html', '💰 Sales'], ['condos.html', '🏢 Condos'],
+      ['rent-rolls.html', '📋 Rent Rolls'], ['mls.html', '🗂️ MLS'], ['map.html', '🗺️ Map'] ] },
+    { title: 'Deals', items: [
+      ['deals.html', '🤝 Deals'], ['deals-flow.html', '🔀 Deal Flow'] ] },
+    { title: 'Brokers & Agents', items: [
+      ['crcp.html', '🎛️ Control Panel'], ['brokers.html', '🎯 Brokers'],
+      ['broker-grid.html', '▦ Broker Grid'], ['licensed.html', '📇 Licensed'],
+      ['licensed-agents.html', '🧾 Licensed Agents'], ['loan-officers.html', '🏦 Loan Officers'],
+      ['linkedin.html', '💼 LinkedIn'] ] },
+    { title: 'Lending & Capital', items: [
+      ['lending.html', '🏛️ Lending'], ['fha-loans.html', '◆ FHA Loans'],
+      ['fha-leads.html', '◆ FHA Leads'], ['lenders.html', '🏦 Lenders'],
+      ['credit-unions.html', '🏦 Credit Unions'], ['sba-lenders.html', '🏦 SBA Lenders'],
+      ['mortgage-market.html', '📈 Mortgage Market'] ] },
+    { title: 'Ops & Admin', items: [
+      ['admin.html', '⚙️ Admin'], ['gov-agents.html', '🏛️ Gov Agents'], ['graphics.html', '🖼️ Graphics'] ] }
+  ];
+
+  // ── styles (scoped under .cnav*, safe over any dark page; falls back if no CSS vars) ─
+  var css = '' +
+    '.cnav-burger{position:fixed;top:10px;z-index:9998;display:flex;align-items:center;gap:6px;' +
+      'background:rgba(20,25,37,.92);color:#e6e8ec;border:1px solid rgba(255,255,255,.14);' +
+      'border-radius:10px;padding:8px 11px;font-size:15px;line-height:1;cursor:pointer;' +
+      'box-shadow:0 2px 10px rgba(0,0,0,.35);backdrop-filter:blur(3px);}' +
+    '.cnav-burger:hover{border-color:#C8A24B;color:#C8A24B;}' +
+    '.cnav-burger.left{left:10px;} .cnav-burger.right{right:10px;}' +
+    '.cnav-burger .lbl{font-size:12px;letter-spacing:.3px;} @media(max-width:640px){.cnav-burger .lbl{display:none;}}' +
+    '.cnav-ov{position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:9998;opacity:0;pointer-events:none;transition:opacity .18s;}' +
+    '.cnav-ov.on{opacity:1;pointer-events:auto;}' +
+    '.cnav-drawer{position:fixed;top:0;bottom:0;width:min(320px,86vw);background:#11161f;color:#e6e8ec;z-index:9999;' +
+      'border:0;box-shadow:0 0 40px rgba(0,0,0,.5);display:flex;flex-direction:column;transition:transform .2s ease;' +
+      'font:14px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;}' +
+    '.cnav-drawer.left{left:0;border-right:1px solid #232a38;transform:translateX(-104%);}' +
+    '.cnav-drawer.right{right:0;border-left:1px solid #232a38;transform:translateX(104%);}' +
+    '.cnav-drawer.on{transform:translateX(0);}' +
+    '.cnav-hd{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid #232a38;' +
+      'font-size:12px;text-transform:uppercase;letter-spacing:.7px;color:#C8A24B;}' +
+    '.cnav-hd button{background:none;border:0;color:#8A93A2;font-size:20px;cursor:pointer;line-height:1;}' +
+    '.cnav-hd button:hover{color:#e6e8ec;}' +
+    '.cnav-body{overflow-y:auto;padding:8px 0 20px;flex:1;}' +
+    '.cnav-sec{border-bottom:1px solid #1b212c;}' +
+    '.cnav-sec>h4{margin:0;padding:11px 16px;font-size:12px;font-weight:700;letter-spacing:.4px;color:#c7cdd6;' +
+      'cursor:pointer;user-select:none;display:flex;align-items:center;justify-content:space-between;}' +
+    '.cnav-sec>h4:hover{color:#fff;}' +
+    '.cnav-sec>h4 .car{color:#C8A24B;transition:transform .15s;font-size:11px;}' +
+    '.cnav-sec.collapsed>h4 .car{transform:rotate(-90deg);}' +
+    '.cnav-sec.collapsed .cnav-list{display:none;}' +
+    '.cnav-list{padding:2px 0 8px;}' +
+    '.cnav-list a{display:block;padding:7px 16px 7px 22px;color:#c7cdd6;text-decoration:none;font-size:13.5px;border-left:2px solid transparent;}' +
+    '.cnav-list a:hover{background:rgba(200,162,75,.08);color:#fff;}' +
+    '.cnav-list a.cur{color:#C8A24B;border-left-color:#C8A24B;background:rgba(200,162,75,.10);font-weight:600;}' +
+    '.cnav-empty{padding:14px 16px;color:#8A93A2;font-size:13px;}';
+  var st = document.createElement('style'); st.textContent = css; document.head.appendChild(st);
+
+  function el(tag, cls, html) { var e = document.createElement(tag); if (cls) e.className = cls; if (html != null) e.innerHTML = html; return e; }
+
+  // ── overlay ───────────────────────────────────────────────────────────────────────
+  var ov = el('div', 'cnav-ov');
+  document.body.appendChild(ov);
+
+  function closeAll() {
+    document.querySelectorAll('.cnav-drawer.on').forEach(function (d) { d.classList.remove('on'); });
+    ov.classList.remove('on');
+    document.querySelectorAll('.cnav-burger').forEach(function (b) { b.setAttribute('aria-expanded', 'false'); });
+  }
+  ov.addEventListener('click', closeAll);
+  document.addEventListener('keydown', function (e) { if (e.key === 'Escape') closeAll(); });
+
+  // ── a collapsible accordion section ────────────────────────────────────────────────
+  function section(title, expanded) {
+    var sec = el('div', 'cnav-sec' + (expanded ? '' : ' collapsed'));
+    var h = el('h4', null, '<span>' + title + '</span><span class="car">▾</span>');
+    var list = el('div', 'cnav-list');
+    h.addEventListener('click', function () { sec.classList.toggle('collapsed'); });
+    sec.appendChild(h); sec.appendChild(list);
+    sec._list = list;
+    return sec;
+  }
+
+  // ── build one drawer ────────────────────────────────────────────────────────────────
+  function drawer(side, title) {
+    var d = el('div', 'cnav-drawer ' + side);
+    var hd = el('div', 'cnav-hd', '<span>' + title + '</span>');
+    var x = el('button', null, '✕'); x.setAttribute('aria-label', 'Close'); x.addEventListener('click', closeAll);
+    hd.appendChild(x);
+    var body = el('div', 'cnav-body');
+    d.appendChild(hd); d.appendChild(body);
+    document.body.appendChild(d);
+    d._body = body;
+    return d;
+  }
+
+  // LEFT — site navigation
+  var left = drawer('left', 'Navigate');
+  GROUPS.forEach(function (g) {
+    var hasCur = g.items.some(function (it) { return it[0].toLowerCase() === CUR; });
+    var sec = section(g.title, hasCur); // auto-expand the group holding the current page
+    g.items.forEach(function (it) {
+      var a = el('a', it[0].toLowerCase() === CUR ? 'cur' : '', it[1]);
+      a.href = '/' + it[0];
+      a.addEventListener('click', closeAll);
+      sec._list.appendChild(a);
+    });
+    left._body.appendChild(sec);
+  });
+
+  // RIGHT — "On this page" jump links, from the page's own headings
+  var right = drawer('right', 'On this page');
+  function slug(s) { return s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '').slice(0, 40) || 'sec'; }
+  function buildOnThisPage() {
+    right._body.innerHTML = '';
+    var sec = section('Sections', true);
+    // section-like headings: page h2s + panel/section h3s, visible + with text, excluding our own chrome
+    var nodes = Array.prototype.slice.call(document.querySelectorAll('main h2, section > h2, h2.sec, .panel > h3, section > h3'));
+    var seen = {}, count = 0;
+    nodes.forEach(function (n) {
+      if (n.closest('.cnav-drawer')) return;
+      if (!n.offsetParent && n.offsetHeight === 0) return; // hidden
+      var txt = (n.textContent || '').replace(/\s+/g, ' ').trim();
+      txt = txt.replace(/^[▸▾▿▶◀⌄˅▼>\s]+/, ''); // strip leading collapse-caret glyphs
+      if (!txt) return; txt = txt.slice(0, 46);
+      if (!n.id) { var s = slug(txt); var u = s, i = 2; while (document.getElementById(u)) { u = s + '-' + (i++); } n.id = u; }
+      if (seen[n.id]) return; seen[n.id] = 1;
+      var a = el('a', '', txt);
+      a.href = '#' + n.id;
+      a.addEventListener('click', function () { closeAll(); });
+      sec._list.appendChild(a); count++;
+    });
+    if (count) { right._body.appendChild(sec); }
+    else { right._body.appendChild(el('div', 'cnav-empty', 'No jump-to sections on this page. Use the ☰ menu (top-left) to navigate the site.')); }
+    // always offer the full site menu as a second collapsed section on the right too
+    var nav = section('Go to another page', false);
+    GROUPS.forEach(function (g) {
+      g.items.forEach(function (it) {
+        var a = el('a', it[0].toLowerCase() === CUR ? 'cur' : '', it[1]);
+        a.href = '/' + it[0]; a.addEventListener('click', closeAll); nav._list.appendChild(a);
+      });
+    });
+    right._body.appendChild(nav);
+  }
+
+  // ── the two hamburgers ──────────────────────────────────────────────────────────────
+  function burger(side, glyph, label, onOpen) {
+    var b = el('button', 'cnav-burger ' + side, glyph + ' <span class="lbl">' + label + '</span>');
+    b.setAttribute('aria-label', label); b.setAttribute('aria-expanded', 'false');
+    var target = side === 'left' ? left : right;
+    b.addEventListener('click', function (e) {
+      e.stopPropagation();
+      var open = target.classList.contains('on');
+      closeAll();
+      if (!open) { if (onOpen) onOpen(); target.classList.add('on'); ov.classList.add('on'); b.setAttribute('aria-expanded', 'true'); }
+    });
+    document.body.appendChild(b);
+    return b;
+  }
+  burger('left', '☰', 'Menu', null);
+  burger('right', '▤', 'Sections', buildOnThisPage);
+
+  // Reserve corner space on the page's top bar so its title / existing nav / buttons
+  // don't hide under the two hamburgers (they sit as fixed chips over the corners).
+  function reserve() {
+    var bar = document.querySelector('header');
+    if (!bar) return;
+    var cs = getComputedStyle(bar);
+    var pl = parseInt(cs.paddingLeft, 10) || 0, pr = parseInt(cs.paddingRight, 10) || 0;
+    bar.style.paddingLeft = Math.max(pl, 104) + 'px';
+    bar.style.paddingRight = Math.max(pr, 120) + 'px';
+  }
+  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', reserve); else reserve();
+})();
diff --git a/public/crcp.html b/public/crcp.html
index 81beab1..2bc512c 100644
--- a/public/crcp.html
+++ b/public/crcp.html
@@ -777,5 +777,6 @@ loadSegments(); setInterval(loadSegments, 20000);
 })();
 </script>
   <script src="/col-resize.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/credit-unions.html b/public/credit-unions.html
index 4a72dd0..5874d74 100644
--- a/public/credit-unions.html
+++ b/public/credit-unions.html
@@ -73,5 +73,6 @@ window.GRID_CONFIG = {
 <script src="/column-manager.js" defer></script>
 <script src="/lending-grid.js" defer></script>
 <script src="/col-resize.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/deals-flow.html b/public/deals-flow.html
index 9b73ece..bc71b7d 100644
--- a/public/deals-flow.html
+++ b/public/deals-flow.html
@@ -326,4 +326,5 @@ Promise.all([
   DATA=c.concat(e).concat(f);
   buildRail();render();loadMe();
 }).catch(()=>{$('#count').textContent='failed to load deal data';});
-</script></body></html>
+</script><script src="/corner-nav.js" defer></script>
+</body></html>
diff --git a/public/deals.html b/public/deals.html
index 1de9556..f7e1df2 100644
--- a/public/deals.html
+++ b/public/deals.html
@@ -290,5 +290,6 @@ pull();   // initial load
 </script>
   <script src="/col-resize.js" defer></script>
   <script src="/global-search.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/fha-leads.html b/public/fha-leads.html
index b0ec50d..232ec5f 100644
--- a/public/fha-leads.html
+++ b/public/fha-leads.html
@@ -139,4 +139,5 @@ $('#sort').innerHTML=COLS.map(c=>`<option value="${c.k}"${c.k==='spread'?' selec
 $('#dens').value=dens;
 fetch('/data/fha-loans.json').then(r=>r.json()).then(j=>{DATA=(j.rows||[]).filter(r=>r.rate!=null);buildRail();render();})
   .catch(()=>{$('#count').textContent='failed to load /data/fha-loans.json';});
-</script></body></html>
+</script><script src="/corner-nav.js" defer></script>
+</body></html>
diff --git a/public/fha-loans.html b/public/fha-loans.html
index 39dcd15..52e7bec 100644
--- a/public/fha-loans.html
+++ b/public/fha-loans.html
@@ -497,5 +497,6 @@ load();
 </script>
   <script src="/col-resize.js" defer></script>
   <script src="/global-search.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/gov-agents.html b/public/gov-agents.html
index 83fb79b..be22168 100644
--- a/public/gov-agents.html
+++ b/public/gov-agents.html
@@ -273,5 +273,6 @@ loadIndex();
 </script>
   <script src="/column-manager.js" defer></script>
   <script src="/col-resize.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/graphics.html b/public/graphics.html
index 97948a9..5645eea 100644
--- a/public/graphics.html
+++ b/public/graphics.html
@@ -208,5 +208,6 @@ const HOVER=(evt,els)=>{ const t=evt&&evt.native&&evt.native.target; if(t) t.sty
 })().catch(e=>{ $('#stats').innerHTML='<span style="color:var(--red)">load error: '+e.message+'</span>'; });
 </script>
   <script src="/col-resize.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/index.html b/public/index.html
index 851c30e..e60fdb5 100644
--- a/public/index.html
+++ b/public/index.html
@@ -2015,5 +2015,6 @@ fetch('data/ranked.json').then(r=>r.json()).then(async d=>{
 </script>
   <script src="/col-resize.js" defer></script>
   <script src="/global-search.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/just-listed.html b/public/just-listed.html
index 7dbe501..035b5d8 100644
--- a/public/just-listed.html
+++ b/public/just-listed.html
@@ -181,4 +181,5 @@ fetch('/data/listings.json').then(r=>r.json()).then(d=>{
 }).catch(()=>{$('#count').textContent='failed to load /data/listings.json';});
 </script>  <script src="/global-search.js" defer></script>
   <script src="/sort-bar.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body></html>
diff --git a/public/lenders.html b/public/lenders.html
index cbaebe5..54116f5 100644
--- a/public/lenders.html
+++ b/public/lenders.html
@@ -76,5 +76,6 @@ window.GRID_CONFIG = {
 <script src="/column-manager.js" defer></script>
 <script src="/lending-grid.js" defer></script>
 <script src="/col-resize.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/lending.html b/public/lending.html
index ab792b1..cabba14 100644
--- a/public/lending.html
+++ b/public/lending.html
@@ -97,5 +97,6 @@ async function counts(){
 }
 counts();
 </script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/licensed-agents.html b/public/licensed-agents.html
index 5b3885f..6f0e8ff 100644
--- a/public/licensed-agents.html
+++ b/public/licensed-agents.html
@@ -282,5 +282,6 @@ buildFieldBar();
 if(localStorage.getItem('laMode')==='brokers') setMode('brokers'); else { $('#fieldbar').style.display='flex'; load(); }
 </script>
   <script src="/col-resize.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/licensed.html b/public/licensed.html
index 42c6284..e1999a9 100644
--- a/public/licensed.html
+++ b/public/licensed.html
@@ -209,4 +209,5 @@ document.addEventListener('click',async e=>{
 boot().catch(e=>{$('#count').textContent='Failed to load: '+e.message;});
 </script>  <script src="/global-search.js" defer></script>
   <script src="/sort-bar.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body></html>
diff --git a/public/linkedin.html b/public/linkedin.html
index 5a1af0d..4da5053 100644
--- a/public/linkedin.html
+++ b/public/linkedin.html
@@ -246,5 +246,6 @@ document.addEventListener('keydown',e=>{ if(e.key==='Escape') $('#ov').classList
 
 load();
 </script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/loan-officers.html b/public/loan-officers.html
index 4e82f2b..63953b3 100644
--- a/public/loan-officers.html
+++ b/public/loan-officers.html
@@ -84,5 +84,6 @@ fetch('/api/lending/loan-officers', { credentials:'same-origin' }).then(r=>r.jso
   if(!(d.officers||[]).length){ document.getElementById('emptyState').classList.remove('hide'); document.getElementById('tableView').classList.add('hide'); }
 }).catch(()=>{});
 </script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/map.html b/public/map.html
index 74a2750..66424ea 100644
--- a/public/map.html
+++ b/public/map.html
@@ -270,5 +270,6 @@ function buildLegend(){
   };
 })();
 </script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/mls.html b/public/mls.html
index 37fba9f..7398bf1 100644
--- a/public/mls.html
+++ b/public/mls.html
@@ -612,5 +612,6 @@ document.addEventListener('click', async e=>{
   <script src="/col-resize.js" defer></script>
   <script src="/global-search.js" defer></script>
   <script src="/sort-bar.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/mortgage-market.html b/public/mortgage-market.html
index 61dffd7..853e66d 100644
--- a/public/mortgage-market.html
+++ b/public/mortgage-market.html
@@ -65,5 +65,6 @@ window.GRID_CONFIG = {
 <script src="/column-manager.js" defer></script>
 <script src="/lending-grid.js" defer></script>
 <script src="/col-resize.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/rent-rolls.html b/public/rent-rolls.html
index 454d2d6..218002b 100644
--- a/public/rent-rolls.html
+++ b/public/rent-rolls.html
@@ -434,5 +434,6 @@ fetch('/api/rent-rolls').then(r=>r.json()).then(d=>{
   <script src="/col-resize.js" defer></script>
   <script src="/global-search.js" defer></script>
   <script src="/sort-bar.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/sales.html b/public/sales.html
index a899e20..bd62f81 100644
--- a/public/sales.html
+++ b/public/sales.html
@@ -385,5 +385,6 @@ fetch('/api/closed-sales?limit=5000').then(r=>r.json()).then(d=>{
   <script src="/col-resize.js" defer></script>
   <script src="/global-search.js" defer></script>
   <script src="/sort-bar.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>
diff --git a/public/sba-lenders.html b/public/sba-lenders.html
index c7690cb..ce8cc80 100644
--- a/public/sba-lenders.html
+++ b/public/sba-lenders.html
@@ -72,5 +72,6 @@ window.GRID_CONFIG = {
 <script src="/column-manager.js" defer></script>
 <script src="/lending-grid.js" defer></script>
 <script src="/col-resize.js" defer></script>
+<script src="/corner-nav.js" defer></script>
 </body>
 </html>

← e8c77da docs: LA current-sales sourcing memo (ULA/deeds, public-reco  ·  back to Commercialrealestate  ·  fix(brokers): resolve relative API fetches against location. 955b371 →