[object Object]

← back to Commercialrealestate

nav-agent: add universal grid-controls drop-in (field-toggle panel + sort/group/density + movable/removable/expandable panels) to all internal grid pages

680d4422000488d50f835c275a62e3944f9f548e · 2026-08-13 08:01:41 -0700 · Steve Abrams

Files touched

Diff

commit 680d4422000488d50f835c275a62e3944f9f548e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Thu Aug 13 08:01:41 2026 -0700

    nav-agent: add universal grid-controls drop-in (field-toggle panel + sort/group/density + movable/removable/expandable panels) to all internal grid pages
---
 data/residential-report.html       |  24 +-
 public/admin.html                  |   2 +
 public/broker-grid.html            |   2 +
 public/condos.html                 |   2 +
 public/contractors.html            |   4 +-
 public/crcp-grid.css               |  58 ++++-
 public/crcp-grid.css.pre-3view.bak |  56 +++++
 public/crcp-grid.js                | 270 +++++++++++++++++++++--
 public/crcp-grid.js.pre-3view.bak  | 191 ++++++++++++++++
 public/crcp.html                   |   2 +
 public/credit-unions.html          |   2 +
 public/deals-flow.html             |   4 +-
 public/deals.html                  |   2 +
 public/fha-leads.html              |   4 +-
 public/fha-loans.html              |   2 +
 public/gov-agents.html             |   2 +
 public/graphics.html               |   2 +
 public/index.html                  |   2 +
 public/just-listed.html            |   4 +-
 public/lenders.html                |   2 +
 public/licensed-agents.html        |   2 +
 public/licensed.html               |   4 +-
 public/loan-officers.html          |   2 +
 public/mls.html                    |   2 +
 public/mortgage-market.html        |   2 +
 public/nav-agent/nav-agent.css     |  93 ++++++++
 public/nav-agent/nav-agent.js      | 433 +++++++++++++++++++++++++++++++++++++
 public/parcel.html                 |   4 +-
 public/rent-rolls.html             |   2 +
 public/sales.html                  |   2 +
 public/sba-lenders.html            |   2 +
 31 files changed, 1144 insertions(+), 41 deletions(-)

diff --git a/data/residential-report.html b/data/residential-report.html
index b90076e..c632e39 100644
--- a/data/residential-report.html
+++ b/data/residential-report.html
@@ -1,46 +1,46 @@
 <!doctype html><html><body style="margin:0;background:#0e1116;color:#e6edf3;font-family:-apple-system,Helvetica,Arial,sans-serif;padding:22px">
   <div style="max-width:760px;margin:0 auto">
-    <h1 style="font-size:20px;margin:0 0 3px">🏠 LA County Residential Pulse <span style="color:#3fb950">· 2026-08-12</span></h1>
+    <h1 style="font-size:20px;margin:0 0 3px">🏠 LA County Residential Pulse <span style="color:#3fb950">· 2026-08-13</span></h1>
     <div style="color:#8b949e;font-size:12px;margin-bottom:16px">Redfin for-sale + in-escrow · last 7 days · <a href="https://crcp.agentabrams.com/mls.html" style="color:#58a6ff">open all listings →</a></div>
     <table style="width:100%;border-spacing:8px;margin:-8px 0 18px"><tr>
       <td style="padding:14px 16px;background:#161b22;border:1px solid #2a313c;border-radius:10px;text-align:center">
-    <div style="font-size:26px;font-weight:700;color:#e6edf3">13,933</div>
+    <div style="font-size:26px;font-weight:700;color:#e6edf3">13,907</div>
     <div style="font-size:11px;color:#8b949e;text-transform:uppercase;letter-spacing:.5px;margin-top:2px">Active</div></td><td style="padding:14px 16px;background:#161b22;border:1px solid #2a313c;border-radius:10px;text-align:center">
-    <div style="font-size:26px;font-weight:700;color:#d29922">7,862</div>
+    <div style="font-size:26px;font-weight:700;color:#d29922">7,953</div>
     <div style="font-size:11px;color:#8b949e;text-transform:uppercase;letter-spacing:.5px;margin-top:2px">In Escrow</div></td><td style="padding:14px 16px;background:#161b22;border:1px solid #2a313c;border-radius:10px;text-align:center">
-    <div style="font-size:26px;font-weight:700;color:#3fb950">1,442</div>
+    <div style="font-size:26px;font-weight:700;color:#3fb950">1,355</div>
     <div style="font-size:11px;color:#8b949e;text-transform:uppercase;letter-spacing:.5px;margin-top:2px">Just Listed</div></td><td style="padding:14px 16px;background:#161b22;border:1px solid #2a313c;border-radius:10px;text-align:center">
-    <div style="font-size:26px;font-weight:700;color:#ffa600">799</div>
+    <div style="font-size:26px;font-weight:700;color:#ffa600">774</div>
     <div style="font-size:11px;color:#8b949e;text-transform:uppercase;letter-spacing:.5px;margin-top:2px">Price Cuts</div></td><td style="padding:14px 16px;background:#161b22;border:1px solid #2a313c;border-radius:10px;text-align:center">
-    <div style="font-size:26px;font-weight:700;color:#58a6ff">42</div>
+    <div style="font-size:26px;font-weight:700;color:#58a6ff">39</div>
     <div style="font-size:11px;color:#8b949e;text-transform:uppercase;letter-spacing:.5px;margin-top:2px">Just Sold</div></td><td style="padding:14px 16px;background:#161b22;border:1px solid #2a313c;border-radius:10px;text-align:center">
-    <div style="font-size:26px;font-weight:700;color:#f85149">7,500</div>
+    <div style="font-size:26px;font-weight:700;color:#f85149">7,662</div>
     <div style="font-size:11px;color:#8b949e;text-transform:uppercase;letter-spacing:.5px;margin-top:2px">Withdrawn</div></td>
     </tr></table>
     <h3 style="font-size:13px;text-transform:uppercase;color:#8b949e;margin:18px 0 6px">🆕 Just Listed (newest 7d)</h3>
     <table style="width:100%;border-collapse:collapse;font-size:13px">
     <tr style="color:#8b949e;text-align:left"><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Address</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">City</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Type</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Price</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Bd/Ba</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">DOM</th></tr>
-    <tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/1883-Rising-Glen-Rd-90069/home/7122213" style="color:#58a6ff;text-decoration:none">1883 Rising Glen Rd</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$9,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/6</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Arcadia/800-Hampton-Rd-91006/home/7229012" style="color:#58a6ff;text-decoration:none">800 Hampton</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Arcadia</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$9,880,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">6/9</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Westlake-Village/949-W-Stafford-Rd-91361/home/196682854" style="color:#58a6ff;text-decoration:none">949 W Stafford</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Westlake Village</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$7,900,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/5.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Manhattan-Beach/840-18th-St-90266/home/6707484" style="color:#58a6ff;text-decoration:none">840 18th</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Manhattan Beach</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$7,499,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/5.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Hidden-Hills/25225-Eldorado-Meadow-Rd-91302/home/3303202" style="color:#58a6ff;text-decoration:none">25225 Eldorado Mdw</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Hidden Hills</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$7,449,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">6/6.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Manhattan-Beach/1658-Ruhland-Ave-90266/home/6701973" style="color:#58a6ff;text-decoration:none">1658 Ruhland Ave</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Manhattan Beach</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$5,799,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/4.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/4830-Los-Feliz-Blvd-90027/home/7133722" style="color:#58a6ff;text-decoration:none">4830 Los Feliz Blvd</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$4,595,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/6</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Malibu/6262-Trancas-Canyon-Rd-90265/home/6858134" style="color:#58a6ff;text-decoration:none">6262 Trancas Canyon Rd</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Malibu</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$4,350,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/3</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Santa-Clarita/29906-N-Camino-los-Robles-91354/home/204551567" style="color:#58a6ff;text-decoration:none">29906 N Camino Los Robles</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Santa Clarita</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,999,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/5.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Sherman-Oaks/15656-Crownridge-Pl-91403/home/4901661" style="color:#58a6ff;text-decoration:none">15656 Crownridge Pl</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Sherman Oaks</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/6</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Hermosa-Beach/567-24th-Pl-90254/home/6714103" style="color:#58a6ff;text-decoration:none">567 24th Pl</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Hermosa Beach</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,950,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/3</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Bradbury/677-Deodar-Ln-91008/home/7974325" style="color:#58a6ff;text-decoration:none">677 N Deodar</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Bradbury</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,900,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">7/5.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Pacific-Palisades/1545-Umeo-Rd-90272/home/6846840" style="color:#58a6ff;text-decoration:none">1545 Umeo Rd</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Pacific Palisades</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,799,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">3/2</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/San-Marino/1164-Adair-St-91108/home/7016726" style="color:#58a6ff;text-decoration:none">1164 Adair St</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">San Marino</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,700,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/3.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/San-Dimas/2005-Trail-Ridge-Ln-91773/home/173285979" style="color:#58a6ff;text-decoration:none">2005 Trail Ridge Ln</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">San Dimas</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,695,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/5.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Glendale/1663-Vista-Dr-91201/home/7145855" style="color:#58a6ff;text-decoration:none">1663 Vista</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Glendale</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,375,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">7/7</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Rowland-Heights/2251-Cascade-Way-91748/home/8113188" style="color:#58a6ff;text-decoration:none">2251 Cascade</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Rowland Heights</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,350,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/11420-Biona-Dr-90066/home/6738962" style="color:#58a6ff;text-decoration:none">11420 Biona Dr</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,249,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/4</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/San-Marino/1206-Winston-Ave-91108/home/7014928" style="color:#58a6ff;text-decoration:none">1206 Winston Ave</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">San Marino</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,088,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/3.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/247-S-Carmelina-Ave-90049/home/6838700" style="color:#58a6ff;text-decoration:none">247 S Carmelina</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,999,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/4</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr>
+    <tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Westlake-Village/949-W-Stafford-Rd-91361/home/196682854" style="color:#58a6ff;text-decoration:none">949 W Stafford</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Westlake Village</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$7,900,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/5.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Manhattan-Beach/840-18th-St-90266/home/6707484" style="color:#58a6ff;text-decoration:none">840 18th</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Manhattan Beach</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$7,499,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/5.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Hidden-Hills/25225-Eldorado-Meadow-Rd-91302/home/3303202" style="color:#58a6ff;text-decoration:none">25225 Eldorado Mdw</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Hidden Hills</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$7,449,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">6/6.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/3640-S-Barrington-Ave-90066/home/6739159" style="color:#58a6ff;text-decoration:none">3640 S Barrington Ave</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$5,595,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">6/7</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Studio-City/11210-Briarcliff-Ln-91604/home/8113707" style="color:#58a6ff;text-decoration:none">11210 Briarcliff Ln</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Studio City</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$4,795,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Santa-Clarita/29906-N-Camino-los-Robles-91354/home/204551567" style="color:#58a6ff;text-decoration:none">29906 N Camino Los Robles</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Santa Clarita</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,999,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/5.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Pacific-Palisades/1545-Umeo-Rd-90272/home/6846840" style="color:#58a6ff;text-decoration:none">1545 Umeo Rd</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Pacific Palisades</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,799,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">3/2</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Diamond-Bar/24106-Lodge-Pole-Rd-91765/home/8064243" style="color:#58a6ff;text-decoration:none">24106 Lodge Pole Rd</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Diamond Bar</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,790,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">6/6.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/San-Marino/1164-Adair-St-91108/home/7016726" style="color:#58a6ff;text-decoration:none">1164 Adair St</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">San Marino</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,700,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/3.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/San-Dimas/2005-Trail-Ridge-Ln-91773/home/173285979" style="color:#58a6ff;text-decoration:none">2005 Trail Ridge Ln</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">San Dimas</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,695,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/5.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Tarzana/4949-Bilmoor-Ave-91356/home/4239257" style="color:#58a6ff;text-decoration:none">4949 Bilmoor Ave</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Tarzana</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,595,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/5.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Calabasas/24142-Park-Riviera-91302/home/3518697" style="color:#58a6ff;text-decoration:none">24142 Park Riviera</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Calabasas</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,450,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Rowland-Heights/2251-Cascade-Way-91748/home/8113188" style="color:#58a6ff;text-decoration:none">2251 Cascade</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Rowland Heights</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,350,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/11420-Biona-Dr-90066/home/6738962" style="color:#58a6ff;text-decoration:none">11420 Biona Dr</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,249,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/4</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/247-S-Carmelina-Ave-90049/home/6838700" style="color:#58a6ff;text-decoration:none">247 S Carmelina</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,999,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/4</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Calabasas/3469-Cordova-Dr-91302/home/3512153" style="color:#58a6ff;text-decoration:none">3469 Cordova Dr</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Calabasas</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,900,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/4</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Calabasas/4433-Tedregal-Ct-91302/home/3511173" style="color:#58a6ff;text-decoration:none">4433 Tedregal Ct</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Calabasas</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,899,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/3.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Santa-Monica/907-23rd-St-90403/home/6769195" style="color:#58a6ff;text-decoration:none">907 23rd St</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Santa Monica</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,800,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">3/2</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Glendale/1357-Doverwood-Dr-91207/home/7165475" style="color:#58a6ff;text-decoration:none">1357 Doverwood</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Glendale</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,799,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/3</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Sherman-Oaks/14800-McCormick-St-91411/home/4744562" style="color:#58a6ff;text-decoration:none">14800 Mccormick</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Sherman Oaks</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,650,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">5/4.5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1d</td></tr>
     </table>
     <h3 style="font-size:13px;text-transform:uppercase;color:#8b949e;margin:20px 0 6px">✅ Just Sold (closed escrow, 7d)</h3>
     <table style="width:100%;border-collapse:collapse;font-size:13px">
     <tr style="color:#8b949e;text-align:left"><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Address</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">City</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Type</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Sold</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Date</th></tr>
-    <tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">859 S Gretna Green Way</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$1,635,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Fri Jun 12</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">2005 Mathews Ave Unit B</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Redondo Beach</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$1,845,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Fri May 22</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">9620 Sepulveda #39</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">North Hills</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$459,950</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Wed May 20</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">121 E 223rd St #3</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Carson</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$760,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Thu May 14</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">15111 Freeman</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Lawndale</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$665,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Thu May 07</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">727 Meridian Ave Unit D</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">South Pasadena</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$1,420,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Wed May 06</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">1011 N Ogden Dr #103</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">West Hollywood</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$1,400,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Wed May 06</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">1149 Magnolia #16</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Gardena</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$420,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Wed Apr 01</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">3711 Baldwin St #1304</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$687,500</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Tue Mar 31</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">13360 Burbank Blvd #10</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Sherman Oaks</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$775,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Mon Jan 12</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">1826 Garvey #9</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Alhambra</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$699,888</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Wed Dec 31</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">7650 Topanga Cyn</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Canoga Park</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$425,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Thu Nov 13</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">301 W Loraine St #5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Glendale</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$1,060,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Wed Oct 01</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">330 Cordova #307</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Pasadena</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$925,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Thu Sep 25</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">12750 Centralia #91</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Lakewood</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$550,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Fri Aug 08</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">422 W Route 66 #47</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Glendora</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$610,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Tue Jun 24</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">18347 Saticoy #24</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Reseda</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$625,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Fri Jun 20</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">18347 Saticoy St #39</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Reseda</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$625,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Fri Jun 20</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">4040 Grand Vw #65</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$750,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Wed Jun 18</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">15539 Woodruff #7</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Bellflower</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$660,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Fri Apr 18</td></tr>
+    <tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">859 S Gretna Green Way</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$1,635,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Fri Jun 12</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">607 W Duarte Rd Unit D</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Monrovia</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$765,888</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Wed May 27</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">2005 Mathews Ave Unit B</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Redondo Beach</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$1,845,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Fri May 22</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">121 E 223rd St #3</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Carson</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$760,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Thu May 14</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">727 Meridian Ave Unit D</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">South Pasadena</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$1,420,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Wed May 06</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">1011 N Ogden Dr #103</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">West Hollywood</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$1,400,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Wed May 06</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">1149 Magnolia #16</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Gardena</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$420,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Wed Apr 01</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">3711 Baldwin St #1304</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$687,500</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Tue Mar 31</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">13360 Burbank Blvd #10</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Sherman Oaks</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$775,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Mon Jan 12</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">1826 Garvey #9</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Alhambra</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$699,888</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Wed Dec 31</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">7650 Topanga Cyn</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Canoga Park</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$425,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Thu Nov 13</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">301 W Loraine St #5</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Glendale</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$1,060,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Wed Oct 01</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">12750 Centralia #91</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Lakewood</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$550,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Fri Aug 08</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">422 W Route 66 #47</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Glendora</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$610,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Tue Jun 24</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">18347 Saticoy St #39</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Reseda</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$625,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Fri Jun 20</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">4040 Grand Vw #65</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$750,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Wed Jun 18</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">228 S San Marino Ave Unit B</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">San Gabriel</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$1,055,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Tue May 20</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">15539 Woodruff #7</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Bellflower</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$660,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Fri Apr 18</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">18730 Hatteras #47</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Tarzana</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$769,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Wed Mar 26</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">10125 De Soto Ave #2</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Chatsworth</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$620,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Fri Dec 13</td></tr>
     </table>
     <h3 style="font-size:13px;text-transform:uppercase;color:#8b949e;margin:20px 0 6px">💸 Price Cuts (biggest, 7d)</h3>
     <table style="width:100%;border-collapse:collapse;font-size:13px">
     <tr style="color:#8b949e;text-align:left"><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Address</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">City</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Type</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Was</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Now</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Cut</th></tr>
-    <tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Malibu/10936-Pacific-View-Dr-90265/home/4694102" style="color:#58a6ff;text-decoration:none">10936 Pacific Vw</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Malibu</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$6,500,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,000,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$4,500,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Manhattan-Beach/3216-The-Strand-90266/home/6710053" style="color:#58a6ff;text-decoration:none">3216 The Strand</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Manhattan Beach</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$24,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$21,000,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$3,995,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Malibu/6625-Zumirez-Dr-90265/home/6856153" style="color:#58a6ff;text-decoration:none">6625 Zumirez Dr</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Malibu</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$28,500,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$26,500,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$2,000,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/201-S-Bristol-Ave-90049/home/6839030" style="color:#58a6ff;text-decoration:none">201 S Bristol Ave</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$16,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$15,250,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$1,745,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Pacific-Palisades/1580-Sorrento-Dr-90272/home/6847205" style="color:#58a6ff;text-decoration:none">1580 Sorrento Dr</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Pacific Palisades</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$21,500,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$19,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$1,505,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/11730-Stonehenge-Ln-90077/home/6831124" style="color:#58a6ff;text-decoration:none">11730 Stonehenge Ln</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$11,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$10,495,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$1,500,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/13241-Riviera-Ranch-Rd-90049/home/58301772" style="color:#58a6ff;text-decoration:none">13241 Riviera Ranch Rd</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$10,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$9,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$1,000,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Hidden-Hills/6021-John-Muir-Rd-91302/home/3291587" style="color:#58a6ff;text-decoration:none">6021 John Muir Rd</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Hidden Hills</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$11,750,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$10,750,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$1,000,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/2666-Aberdeen-Ave-90027/home/7133151" style="color:#58a6ff;text-decoration:none">2666 Aberdeen Ave</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$8,195,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$7,495,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$700,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Santa-Clarita/10262-Sierra-Hwy-91390/home/6364448" style="color:#58a6ff;text-decoration:none">10262 Sierra Hwy</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Santa Clarita</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,700,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,099,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$601,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Rancho-Palos-Verdes/64-Laurel-Dr-90275/home/177421053" style="color:#58a6ff;text-decoration:none">64 Laurel Dr</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Rancho Palos Verdes</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$8,500,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$7,999,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$501,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/521-S-Bentley-Ave-90049/home/6828982" style="color:#58a6ff;text-decoration:none">521 S Bentley</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,649,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,149,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$500,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/2495-S-Barrington-Ave-90064/home/6754500" style="color:#58a6ff;text-decoration:none">2495 S Barrington</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,495,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$500,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Venice/29-27th-Ave-90291/home/6734171" style="color:#58a6ff;text-decoration:none">29 27th Ave</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Venice</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$10,000,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$9,500,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$500,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Pasadena/954-Hillside-Ter-91105/home/7187442" style="color:#58a6ff;text-decoration:none">954 Hillside Ter</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Pasadena</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$5,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$5,495,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$500,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Calabasas/736-Crater-Oak-Dr-91302/home/6854101" style="color:#58a6ff;text-decoration:none">736 Crater Oak Dr</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Calabasas</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,600,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,100,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$500,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/3036-Castle-St-90039/home/7062115" style="color:#58a6ff;text-decoration:none">3036 Castle St</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,998,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,500,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$498,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Santa-Monica/527-7th-St-90402/home/6782029" style="color:#58a6ff;text-decoration:none">527 7th St</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Santa Monica</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$7,950,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$7,495,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$455,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Palos-Verdes-Estates/702-Via-La-Cuesta-90274/home/7723640" style="color:#58a6ff;text-decoration:none">702 via La Cuesta</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Palos Verdes Estates</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$8,398,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$7,998,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$400,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/801-Devon-Ave-90024/home/6824744" style="color:#58a6ff;text-decoration:none">801 Devon Ave</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$7,750,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$7,395,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$355,000</span></td></tr>
+    <tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/10939-Chalon-Rd-90077/home/6829574" style="color:#58a6ff;text-decoration:none">10939 Chalon Rd</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$65,000,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$49,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$15,005,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Malibu/10936-Pacific-View-Dr-90265/home/4694102" style="color:#58a6ff;text-decoration:none">10936 Pacific Vw</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Malibu</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$6,500,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,000,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$4,500,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Manhattan-Beach/3216-The-Strand-90266/home/6710053" style="color:#58a6ff;text-decoration:none">3216 The Strand</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Manhattan Beach</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$24,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$21,000,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$3,995,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Malibu/6625-Zumirez-Dr-90265/home/6856153" style="color:#58a6ff;text-decoration:none">6625 Zumirez Dr</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Malibu</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$28,500,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$26,500,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$2,000,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/201-S-Bristol-Ave-90049/home/6839030" style="color:#58a6ff;text-decoration:none">201 S Bristol Ave</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$16,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$15,250,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$1,745,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Pacific-Palisades/1580-Sorrento-Dr-90272/home/6847205" style="color:#58a6ff;text-decoration:none">1580 Sorrento Dr</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Pacific Palisades</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$21,500,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$19,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$1,505,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/11730-Stonehenge-Ln-90077/home/6831124" style="color:#58a6ff;text-decoration:none">11730 Stonehenge Ln</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$11,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$10,495,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$1,500,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/13241-Riviera-Ranch-Rd-90049/home/58301772" style="color:#58a6ff;text-decoration:none">13241 Riviera Ranch Rd</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$10,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$9,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$1,000,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Hidden-Hills/6021-John-Muir-Rd-91302/home/3291587" style="color:#58a6ff;text-decoration:none">6021 John Muir Rd</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Hidden Hills</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$11,750,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$10,750,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$1,000,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/2666-Aberdeen-Ave-90027/home/7133151" style="color:#58a6ff;text-decoration:none">2666 Aberdeen Ave</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$8,195,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$7,495,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$700,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/121-S-Rockingham-Ave-90049/home/6838979" style="color:#58a6ff;text-decoration:none">121 S Rockingham Ave</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$11,500,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$10,850,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$650,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Santa-Clarita/10262-Sierra-Hwy-91390/home/6364448" style="color:#58a6ff;text-decoration:none">10262 Sierra Hwy</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Santa Clarita</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,700,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,099,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$601,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Venice/3011-Ocean-Front-Walk-90291/home/6734260" style="color:#58a6ff;text-decoration:none">3011 Ocean Front Walk</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Venice</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$10,500,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$9,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$505,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Rancho-Palos-Verdes/64-Laurel-Dr-90275/home/177421053" style="color:#58a6ff;text-decoration:none">64 Laurel Dr</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Rancho Palos Verdes</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$8,500,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$7,999,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$501,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Calabasas/736-Crater-Oak-Dr-91302/home/6854101" style="color:#58a6ff;text-decoration:none">736 Crater Oak Dr</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Calabasas</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,600,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$2,100,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$500,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/521-S-Bentley-Ave-90049/home/6828982" style="color:#58a6ff;text-decoration:none">521 S Bentley</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,649,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,149,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$500,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/2495-S-Barrington-Ave-90064/home/6754500" style="color:#58a6ff;text-decoration:none">2495 S Barrington</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,495,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$500,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Pasadena/954-Hillside-Ter-91105/home/7187442" style="color:#58a6ff;text-decoration:none">954 Hillside Ter</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Pasadena</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$5,995,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$5,495,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$500,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Venice/29-27th-Ave-90291/home/6734171" style="color:#58a6ff;text-decoration:none">29 27th Ave</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Venice</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$10,000,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$9,500,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$500,000</span></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/3036-Castle-St-90039/home/7062115" style="color:#58a6ff;text-decoration:none">3036 Castle St</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,998,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,500,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><span style="color:#ffa600">-$498,000</span></td></tr>
     </table>
     <h3 style="font-size:13px;text-transform:uppercase;color:#8b949e;margin:20px 0 6px">↩️ Fell Out of Escrow (back on market)</h3>
     <table style="width:100%;border-collapse:collapse;font-size:13px">
     <tr style="color:#8b949e;text-align:left"><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Address</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">City</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Type</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Price</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Bd/Ba</th></tr>
-    <tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Sherman-Oaks/3499-Beverly-Glen-Blvd-91423/home/4872436" style="color:#58a6ff;text-decoration:none">3499 Beverly Glen Blvd</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Sherman Oaks</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$3,950,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/5</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Woodland-Hills/23036-Victory-Blvd-91367/home/3218174" style="color:#58a6ff;text-decoration:none">23036 Victory Blvd</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Woodland Hills</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$1,189,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">6/4</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Pasadena/257-Bella-Vista-Ave-91107/home/7218645" style="color:#58a6ff;text-decoration:none">257 Bella Vis</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Pasadena</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$1,000,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">2/1</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Burbank/1440-N-Evergreen-St-91505/home/5317253" style="color:#58a6ff;text-decoration:none">1440 N Evergreen</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Burbank</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$949,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">3/1</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Los-Angeles/441-N-Commonwealth-Ave-90004/home/7110987" style="color:#58a6ff;text-decoration:none">441 N Commonwealth Ave</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$850,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">1/1</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Panorama-City/9591-N-Corbina-Ln-91402/home/182337402" style="color:#58a6ff;text-decoration:none">9591 N Corbina Ln</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Panorama City</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$819,900</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/3</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Lancaster/42301-Woodstone-Ln-93536/home/6358910" style="color:#58a6ff;text-decoration:none">42301 Woodstone</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Lancaster</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$750,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/3</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Lancaster/48038-93rd-St-W-93536/home/6389871" style="color:#58a6ff;text-decoration:none">48038 W 93rd St</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Lancaster</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$519,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/2</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Lancaster/43600-Santa-Rosa-Cir-93535/home/6339162" style="color:#58a6ff;text-decoration:none">43600 Santa Rosa Cir</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Lancaster</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$425,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/2</td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Lancaster/45339-Raysack-Ave-93535/home/6353294" style="color:#58a6ff;text-decoration:none">45339 Raysack Ave</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Lancaster</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">SFR</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$280,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">4/2</td></tr>
+    <tr><td style="padding:6px 8px;border-bottom:1px solid #20262f"><a href="https://www.redfin.com/CA/Canyon-Country/17955-River-Cir-91387/unit-4/home/6033143" style="color:#58a6ff;text-decoration:none">17955 River Cir #4</a></td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Canyon Country</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">Condo</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">$515,000</td><td style="padding:6px 8px;border-bottom:1px solid #20262f">3/3</td></tr>
     </table>
     <h3 style="font-size:13px;text-transform:uppercase;color:#8b949e;margin:20px 0 6px">🤝 In Escrow by City</h3>
     <table style="width:100%;border-collapse:collapse;font-size:13px">
     <tr style="color:#8b949e;text-align:left"><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">City</th><th style="padding:6px 8px;border-bottom:1px solid #2a313c;font-size:11px;text-transform:uppercase">Pending / Contingent</th></tr>
-    <tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>1087</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Lancaster</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>365</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Long Beach</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>301</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Palmdale</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>301</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Torrance</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>192</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Santa Clarita</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>183</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Brentwood</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>157</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Whittier</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>156</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Pasadena</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>145</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Woodland Hills</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>127</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Van Nuys</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>109</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Redondo Beach</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>108</b></td></tr>
+    <tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Los Angeles</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>1103</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Lancaster</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>366</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Palmdale</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>307</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Long Beach</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>306</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Torrance</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>192</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Santa Clarita</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>189</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Whittier</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>160</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Brentwood</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>158</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Pasadena</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>145</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Woodland Hills</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>127</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Van Nuys</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>110</b></td></tr><tr><td style="padding:6px 8px;border-bottom:1px solid #20262f">Redondo Beach</td><td style="padding:6px 8px;border-bottom:1px solid #20262f"><b>109</b></td></tr>
     </table>
     <div style="color:#8b949e;font-size:11px;margin-top:22px;border-top:1px solid #2a313c;padding-top:10px">
       Fell-Out accrues as listings transition Pending→Active across sweeps. Just-Sold cross-references recorded sales; escrow lag means more sales surface over the following weeks.</div>
diff --git a/public/admin.html b/public/admin.html
index a43d7c0..efae571 100644
--- a/public/admin.html
+++ b/public/admin.html
@@ -49,6 +49,7 @@ tr:hover td{background:#12171f}
 .nlist .n .id{color:var(--blue);font-size:11px}
 .nlist .n .tx{white-space:pre-wrap;margin-top:4px;font-size:12px}
 </style>
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <header>
@@ -220,5 +221,6 @@ $('#gp').addEventListener('keydown',e=>{if(e.key==='Enter')$('#gBtn').click();})
 boot();
 </script>
 <script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/broker-grid.html b/public/broker-grid.html
index 9afc7a1..320a79d 100644
--- a/public/broker-grid.html
+++ b/public/broker-grid.html
@@ -92,6 +92,7 @@
   .rail .rsec.collapsed > h4::after { transform:rotate(-90deg); }
   .rail .rsec.collapsed > *:not(h4) { display:none !important; }
 </style>
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <header>
@@ -482,5 +483,6 @@ fetch('/api/brokers/all').then(r=>r.json()).then(d=>{DATA=d.brokers||[];autoCols
   <script src="/global-search.js" defer></script>
   <script src="/sort-bar.js" defer></script>
 <script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/condos.html b/public/condos.html
index 800b837..beb8fa5 100644
--- a/public/condos.html
+++ b/public/condos.html
@@ -132,6 +132,7 @@
   #modal .litem a.dl,#modal .maddr a.dl{color:var(--blue);text-decoration:none;} #modal .litem a.dl:hover,#modal .maddr a.dl:hover{text-decoration:underline;}
   #modal .src{font-size:12px;color:var(--mut);margin-top:12px;border-top:1px solid var(--line);padding-top:10px;}
 </style>
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <header>
@@ -816,5 +817,6 @@ boot();
   <script src="/global-search.js" defer></script>
   <script src="/sort-bar.js" defer></script>
 <script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/contractors.html b/public/contractors.html
index 7bdf20f..828d137 100644
--- a/public/contractors.html
+++ b/public/contractors.html
@@ -69,7 +69,8 @@ input.dealf{background:var(--card);border:1px solid var(--line);color:var(--ink)
 .finance{background:rgba(88,166,255,.08);border:1px solid rgba(88,166,255,.25);border-radius:8px;padding:2px 7px;font-size:10.5px;color:var(--blue);cursor:pointer;text-decoration:none}
 .finance:hover{border-color:var(--blue)}
 @media(max-width:760px){.rail{display:none}}
-</style></head><body>
+</style>  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
+</head><body>
 <header>
   <h1><b>Contractors for this deal</b> · CSLB licensed</h1>
   <span class="badge">🔨 vendor & borrower graph</span>
@@ -337,4 +338,5 @@ $('#body').addEventListener('click',e=>{
 })();
 </script>
 <script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body></html>
diff --git a/public/crcp-grid.css b/public/crcp-grid.css
index 9642cd2..9071c95 100644
--- a/public/crcp-grid.css
+++ b/public/crcp-grid.css
@@ -25,6 +25,22 @@
 .cg-mini button{background:var(--cg-card,#161b22);color:var(--cg-mut,#8b949e);border:1px solid var(--cg-line,#2a313c);border-radius:7px;padding:4px 9px;font-size:11px;cursor:pointer;}
 .cg-mini button:hover{border-color:var(--cg-acc,#58a6ff);color:var(--cg-ink,#e6edf3);}
 .cg-top{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:13px 18px;border-bottom:1px solid var(--cg-line,#2a313c);position:sticky;top:0;background:var(--cg-topbg,rgba(14,17,22,.94));backdrop-filter:blur(6px);z-index:6;}
+/* active-filter summary bar (removable chips + clear all) */
+.cg-active{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:12px 18px 0;}
+.cg-active:empty{display:none;}
+.cg-af-lbl{font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--cg-mut,#8b949e);}
+.cg-af{display:inline-flex;align-items:center;gap:6px;font-size:12px;cursor:pointer;
+  background:var(--cg-accbg,rgba(200,162,75,.12));color:var(--cg-ink,#e6edf3);
+  border:1px solid var(--cg-acc,#58a6ff);border-radius:14px;padding:3px 10px;white-space:nowrap;}
+.cg-af b{color:var(--cg-acc,#58a6ff);font-weight:700;}
+.cg-af:hover{background:var(--cg-acc,#58a6ff);color:var(--cg-railbg,#0b0e13);}
+.cg-af:hover b{color:var(--cg-railbg,#0b0e13);}
+.cg-af-clear{font-size:12px;background:none;border:0;cursor:pointer;padding:3px 6px;
+  color:var(--cg-mut,#8b949e);text-decoration:underline;}
+.cg-af-clear:hover{color:var(--cg-acc,#58a6ff);}
+.cg-af-copy{font-size:12px;background:none;border:1px solid var(--cg-line,#2a313c);cursor:pointer;padding:3px 10px;
+  border-radius:8px;color:var(--cg-mut,#8b949e);}
+.cg-af-copy:hover{color:var(--cg-acc,#58a6ff);border-color:var(--cg-acc,#58a6ff);}
 .cg-q{min-width:240px;background:var(--cg-card,#161b22);color:var(--cg-ink,#e6edf3);border:1px solid var(--cg-line,#2a313c);border-radius:8px;padding:8px 11px;font-size:13px;}
 .cg-seg{display:inline-flex;border:1px solid var(--cg-line,#2a313c);border-radius:8px;overflow:hidden;}
 .cg-seg button{background:var(--cg-card,#161b22);color:var(--cg-mut,#8b949e);border:0;border-right:1px solid var(--cg-line,#2a313c);padding:7px 12px;font-size:12px;cursor:pointer;}
@@ -42,7 +58,13 @@
 .cg-sub{font-size:12px;color:var(--cg-mut,#8b949e);}
 .cg-r{display:flex;justify-content:space-between;font-size:12px;gap:10px;}
 .cg-r .cg-k{color:var(--cg-mut,#8b949e);}
-.cg-empty{padding:50px;text-align:center;color:var(--cg-mut,#8b949e);}
+.cg-empty{padding:64px 24px;text-align:center;color:var(--cg-mut,#8b949e);display:flex;flex-direction:column;align-items:center;gap:8px;}
+.cg-empty-ic{font-size:40px;line-height:1;opacity:.5;}
+.cg-empty-t{font-size:18px;font-weight:700;color:var(--cg-ink,#e6edf3);}
+.cg-empty-s{font-size:13px;}
+.cg-empty-btn{margin-top:10px;text-decoration:none;background:var(--cg-acc,#58a6ff);color:var(--cg-railbg,#0b0e13);
+  border:0;border-radius:8px;padding:9px 18px;font-size:13px;font-weight:700;cursor:pointer;}
+.cg-empty-btn:hover{filter:brightness(1.08);}
 .cg-listwrap{overflow-x:auto;margin:18px;border:1px solid var(--cg-line,#2a313c);border-radius:12px;}
 .cg-tbl{width:100%;border-collapse:collapse;font-size:12.5px;white-space:nowrap;}
 .cg-tbl th,.cg-tbl td{text-align:right;padding:9px 13px;border-top:1px solid var(--cg-line,#2a313c);}
@@ -53,4 +75,36 @@
 .cg-tbl tr.red td{background:rgba(248,81,73,.07);}
 .cg-la{font-weight:600;color:var(--cg-ink,#e6edf3);}
 .cg-lc{color:var(--cg-mut,#8b949e);font-size:11px;}
-@media(max-width:820px){.cg-rail{display:none;}}
+/* mobile filter access: rail becomes an off-canvas drawer opened by the .cg-filt-btn */
+.cg-filt-btn{display:none;align-items:center;gap:6px;background:var(--cg-card,#161b22);color:var(--cg-ink,#e6edf3);
+  border:1px solid var(--cg-acc,#58a6ff);border-radius:8px;padding:8px 12px;font-size:13px;cursor:pointer;white-space:nowrap;}
+.cg-rail-backdrop{position:fixed;inset:0;z-index:1250;background:rgba(0,0,0,.5);opacity:0;visibility:hidden;transition:opacity .2s;}
+.cg-rail-backdrop.open{opacity:1;visibility:visible;}
+@media(max-width:820px){
+  .cg-filt-btn{display:inline-flex;}
+  .cg-top{padding-left:66px;} /* clear the fixed upper-left hamburger */
+  .cg-rail{position:fixed;top:0;left:0;height:100%;width:290px;max-width:86vw;z-index:1300;
+    transform:translateX(-100%);transition:transform .22s ease;box-shadow:2px 0 22px rgba(0,0,0,.55);}
+  .cg-rail.open{transform:translateX(0);}
+}
+/* --- USRE adaptations (nationalrealestate) --- */
+.cg-sort{background:var(--cg-card,#161b22);color:var(--cg-ink,#e6edf3);border:1px solid var(--cg-line,#2a313c);border-radius:8px;padding:8px 10px;font-size:13px;}
+.cg-sortth{cursor:pointer;user-select:none;}
+.cg-sortth:hover{color:var(--cg-ink,#e6edf3);}
+/* density slider drives list-view row padding + font size via --cg-dens (1..12) */
+.cg-tbl{font-size:calc(15.5px - var(--cg-dens,3)*0.45px);font-variant-numeric:tabular-nums;}
+.cg-tbl th,.cg-tbl td{padding:calc(14px - var(--cg-dens,3)*1px) calc(16px - var(--cg-dens,3)*0.8px);}
+.cg-tbl tr[data-ri]{cursor:pointer;}
+.cg-tbl tr.dim td,.cg-card.dim{opacity:.45;}
+/* --- compact LIST view (one scannable row per record; density-aware) --- */
+.cg-rows{display:flex;flex-direction:column;gap:calc(10px - var(--cg-dens,3)*0.9px);padding:16px;}
+.cg-lrow{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;background:var(--cg-card,#161b22);border:1px solid var(--cg-line,#2a313c);border-radius:10px;padding:calc(13px - var(--cg-dens,3)*0.8px) 14px;cursor:pointer;}
+.cg-lrow:hover{border-color:var(--cg-acc,#58a6ff);}
+.cg-lrow.red{border-color:var(--cg-red,#f85149);}
+.cg-lrow.dim{opacity:.45;}
+.cg-lmain{flex:0 0 clamp(180px,22vw,280px);min-width:180px;display:flex;flex-direction:column;gap:2px;}
+.cg-lmain .cg-la{font-weight:600;color:var(--cg-ink,#e6edf3);font-size:calc(15px - var(--cg-dens,3)*0.25px);}
+.cg-lsub{color:var(--cg-mut,#8b949e);font-size:11.5px;}
+.cg-lmeta{flex:1 1 auto;min-width:0;display:flex;flex-wrap:wrap;gap:5px 18px;align-items:baseline;font-size:calc(13.5px - var(--cg-dens,3)*0.4px);font-variant-numeric:tabular-nums;color:var(--cg-ink,#e6edf3);}
+.cg-lm{white-space:nowrap;}
+.cg-lmk{color:var(--cg-mut,#8b949e);font-size:10px;text-transform:uppercase;letter-spacing:.4px;margin-right:4px;}
diff --git a/public/crcp-grid.css.pre-3view.bak b/public/crcp-grid.css.pre-3view.bak
new file mode 100644
index 0000000..9642cd2
--- /dev/null
+++ b/public/crcp-grid.css.pre-3view.bak
@@ -0,0 +1,56 @@
+/* crcp-grid.css — styles for the reusable CrcpGrid engine. Namespaced .cg-* so it never
+ * collides with a host page. Colors read the host's CSS vars with safe fallbacks, so the
+ * engine inherits each page's theme (condos dark, fha-loans glass, sales gold) automatically. */
+.cg-shell{display:flex;align-items:flex-start;}
+.cg-rail{flex:0 0 250px;align-self:stretch;border-right:1px solid var(--cg-line,#2a313c);background:var(--cg-railbg,rgba(0,0,0,.18));position:sticky;top:0;max-height:100vh;overflow-y:auto;padding-bottom:30px;}
+.cg-main{flex:1 1 auto;min-width:0;--cg-cols:3;}
+.cg-sec{padding:12px 15px;border-bottom:1px solid var(--cg-line,#2a313c);}
+.cg-sec h4{margin:0 0 9px;font-size:11px;text-transform:uppercase;letter-spacing:.6px;color:var(--cg-mut,#8b949e);cursor:pointer;display:flex;align-items:center;justify-content:space-between;user-select:none;}
+.cg-sec h4::after{content:'▾';font-size:11px;margin-left:8px;transition:transform .15s;}
+.cg-sec.collapsed h4::after{transform:rotate(-90deg);}
+.cg-sec.collapsed > *:not(h4){display:none !important;}
+.cg-chips{display:flex;flex-wrap:wrap;gap:6px;}
+.cg-chip{background:var(--cg-card,#161b22);color:var(--cg-mut,#8b949e);border:1px solid var(--cg-line,#2a313c);border-radius:16px;padding:4px 10px;font-size:12px;cursor:pointer;user-select:none;}
+.cg-chip:hover{color:var(--cg-ink,#e6edf3);}
+.cg-chip.active{border-color:var(--cg-acc,#58a6ff);color:var(--cg-acc,#58a6ff);background:var(--cg-accbg,rgba(88,166,255,.10));}
+.cg-ct{color:var(--cg-mut,#8b949e);font-size:10px;margin-left:4px;}
+.cg-row2{display:flex;gap:8px;}
+.cg-fld{flex:1;}
+.cg-fld label{display:block;font-size:10px;color:var(--cg-mut,#8b949e);margin-bottom:3px;}
+.cg-fld input{width:100%;background:var(--cg-card,#161b22);color:var(--cg-ink,#e6edf3);border:1px solid var(--cg-line,#2a313c);border-radius:8px;padding:7px 9px;font-size:13px;}
+.cg-ftogs{display:flex;flex-direction:column;gap:1px;max-height:300px;overflow-y:auto;}
+.cg-ftog{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--cg-ink,#e6edf3);cursor:pointer;padding:3px 4px;border-radius:6px;}
+.cg-ftog:hover{background:var(--cg-accbg,rgba(88,166,255,.06));}
+.cg-mini{margin-top:8px;display:flex;gap:5px;}
+.cg-mini button{background:var(--cg-card,#161b22);color:var(--cg-mut,#8b949e);border:1px solid var(--cg-line,#2a313c);border-radius:7px;padding:4px 9px;font-size:11px;cursor:pointer;}
+.cg-mini button:hover{border-color:var(--cg-acc,#58a6ff);color:var(--cg-ink,#e6edf3);}
+.cg-top{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:13px 18px;border-bottom:1px solid var(--cg-line,#2a313c);position:sticky;top:0;background:var(--cg-topbg,rgba(14,17,22,.94));backdrop-filter:blur(6px);z-index:6;}
+.cg-q{min-width:240px;background:var(--cg-card,#161b22);color:var(--cg-ink,#e6edf3);border:1px solid var(--cg-line,#2a313c);border-radius:8px;padding:8px 11px;font-size:13px;}
+.cg-seg{display:inline-flex;border:1px solid var(--cg-line,#2a313c);border-radius:8px;overflow:hidden;}
+.cg-seg button{background:var(--cg-card,#161b22);color:var(--cg-mut,#8b949e);border:0;border-right:1px solid var(--cg-line,#2a313c);padding:7px 12px;font-size:12px;cursor:pointer;}
+.cg-seg button:last-child{border-right:0;}
+.cg-seg button.active{background:var(--cg-acc,#1f6feb);color:#fff;}
+.cg-dens{font-size:12px;color:var(--cg-mut,#8b949e);display:flex;align-items:center;gap:7px;}
+.cg-dens input{accent-color:var(--cg-acc,#58a6ff);}
+.cg-count{margin-left:auto;font-size:12px;color:var(--cg-mut,#8b949e);}
+.cg-count b{color:var(--cg-ink,#e6edf3);}
+.cg-grid{display:grid;gap:16px;padding:18px;grid-template-columns:repeat(var(--cg-cols,3),minmax(0,1fr));}
+.cg-grid.cg-listhost{display:block;}
+.cg-card{background:var(--cg-card,#161b22);border:1px solid var(--cg-line,#2a313c);border-radius:12px;padding:15px;display:flex;flex-direction:column;gap:5px;}
+.cg-card.red{border-color:var(--cg-red,#f85149);}
+.cg-name{font-weight:600;font-size:14px;color:var(--cg-ink,#e6edf3);}
+.cg-sub{font-size:12px;color:var(--cg-mut,#8b949e);}
+.cg-r{display:flex;justify-content:space-between;font-size:12px;gap:10px;}
+.cg-r .cg-k{color:var(--cg-mut,#8b949e);}
+.cg-empty{padding:50px;text-align:center;color:var(--cg-mut,#8b949e);}
+.cg-listwrap{overflow-x:auto;margin:18px;border:1px solid var(--cg-line,#2a313c);border-radius:12px;}
+.cg-tbl{width:100%;border-collapse:collapse;font-size:12.5px;white-space:nowrap;}
+.cg-tbl th,.cg-tbl td{text-align:right;padding:9px 13px;border-top:1px solid var(--cg-line,#2a313c);}
+.cg-tbl th{position:sticky;top:0;background:var(--cg-railbg,#0b0e13);color:var(--cg-mut,#8b949e);font-size:10px;text-transform:uppercase;letter-spacing:.5px;border-top:0;}
+.cg-tbl td.cg-stick,.cg-tbl th.cg-stick{text-align:left;position:sticky;left:0;background:var(--cg-card,#161b22);}
+.cg-tbl th.cg-stick{background:var(--cg-railbg,#0b0e13);}
+.cg-tbl tr:hover td{background:var(--cg-accbg,rgba(88,166,255,.06));}
+.cg-tbl tr.red td{background:rgba(248,81,73,.07);}
+.cg-la{font-weight:600;color:var(--cg-ink,#e6edf3);}
+.cg-lc{color:var(--cg-mut,#8b949e);font-size:11px;}
+@media(max-width:820px){.cg-rail{display:none;}}
diff --git a/public/crcp-grid.js b/public/crcp-grid.js
index 1bfc75d..574bd9a 100644
--- a/public/crcp-grid.js
+++ b/public/crcp-grid.js
@@ -2,7 +2,10 @@
  * Config-driven, theme-agnostic (inherits the host page's CSS vars via cg-grid.css).
  * One page = one CrcpGrid.mount(opts) call. Mirrors the proven condos.html engine so
  * every list page gets the SAME behavior: left-rail facets, per-field show/hide toggles,
- * grid/list view toggle, density slider, live search, localStorage persistence.
+ * grid / list / table view toggle, density slider, live search, localStorage persistence.
+ * Three view modes: 'grid' (image/data cards), 'list' (one compact scannable row per
+ * record), 'table' (dense all-columns spreadsheet with click-to-sort headers). EVERY
+ * non-badge field is sortable via the topbar Sort select (both directions).
  *
  * opts = {
  *   data:      [row,...],            // all rows (client-side faceting)
@@ -16,7 +19,12 @@
  *   storageKey:'fha',               // localStorage namespace
  *   cols:      3,                   // default density
  *   onRow:     row => ({cls}),      // optional per-row class hook (e.g. red flag)
+ *   onRowClick:row => {},           // optional whole-row click handler (list + cards)
+ *   sort:      {k:'score',dir:-1},  // default sort (USRE adaptation; persisted, select + th-click)
  * }
+ * USRE adaptations (nationalrealestate): sort <select> in the topbar + clickable list-view
+ * column headers (both persisted), density slider also drives list row padding/font via
+ * --cg-dens, onRowClick hook. Engine otherwise identical to the CRCP original.
  */
 (function (global) {
   const esc = s => String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;');
@@ -60,6 +68,25 @@
       });
     }
 
+    // ---- sort state (persisted) ----
+    let SORT = O.sort || null; // {k, dir:1|-1}; k='' = source order
+    try { const s = JSON.parse(localStorage.getItem(KEY + 'Sort') || 'null'); if (s && typeof s.k === 'string') SORT = s; } catch (e) {}
+    const saveSort = () => { try { localStorage.setItem(KEY + 'Sort', JSON.stringify(SORT)); } catch (e) {} };
+    function sortRows(rows) {
+      if (!SORT || !SORT.k) return rows;
+      const f = fields.find(x => x.k === SORT.k);
+      if (!f) return rows;
+      const dir = SORT.dir || 1;
+      return [...rows].sort((a, b) => {
+        const va = fval(a, f), vb = fval(b, f);
+        const na = va == null || va === '', nb = vb == null || vb === '';
+        if (na && nb) return 0; if (na) return 1; if (nb) return -1; // nulls last either dir
+        if (typeof va === 'number' || typeof vb === 'number' || f.money || f.num || f.pct)
+          return ((+va) - (+vb)) * dir;
+        return String(va).localeCompare(String(vb)) * dir;
+      });
+    }
+
     // ---- filter state ----
     const F = { q: '', chips: {}, ranges: {} };
     facets.forEach(fc => { if (fc.type === 'chip') F.chips[fc.k] = new Set(); else F.ranges[fc.k] = { min: null, max: null }; });
@@ -76,6 +103,35 @@
       return true;
     }
 
+    // ---- URL sync: filters/search/sort <-> query string (shareable views) ----
+    function readFromURL() {
+      if (O.urlSync === false) return;
+      const sp = new URLSearchParams(location.search);
+      if (![...sp.keys()].length) return;
+      facets.forEach(fc => {
+        if (fc.type === 'chip') { const v = sp.get(fc.k); if (v) v.split(',').forEach(x => F.chips[fc.k].add(x)); }
+        else {
+          const mn = sp.get(fc.k + '_min'), mx = sp.get(fc.k + '_max');
+          if (mn != null && mn !== '') F.ranges[fc.k].min = +mn;
+          if (mx != null && mx !== '') F.ranges[fc.k].max = +mx;
+        }
+      });
+      const q = sp.get('q'); if (q) F.q = q.toLowerCase();
+      const so = sp.get('sort'); if (so) { const [k, d] = so.split(':'); if (k) SORT = { k, dir: d === 'asc' ? 1 : -1 }; }
+    }
+    function syncURL() {
+      if (O.urlSync === false) return;
+      const sp = new URLSearchParams();
+      facets.forEach(fc => {
+        if (fc.type === 'chip') { const set = F.chips[fc.k]; if (set && set.size) sp.set(fc.k, [...set].join(',')); }
+        else { const r = F.ranges[fc.k]; if (r) { if (r.min != null) sp.set(fc.k + '_min', r.min); if (r.max != null) sp.set(fc.k + '_max', r.max); } }
+      });
+      if (F.q) sp.set('q', F.q);
+      if (SORT && SORT.k) sp.set('sort', SORT.k + ':' + (SORT.dir < 0 ? 'desc' : 'asc'));
+      const qs = sp.toString();
+      try { history.replaceState(null, '', location.pathname + (qs ? '?' + qs : '') + location.hash); } catch (e) {}
+    }
+
     // ---- rail ----
     function buildRail() {
       const rail = $(O.rail);
@@ -86,12 +142,20 @@
           data.forEach(r => { const v = gv(r, fc); if (v != null && v !== '') counts[v] = (counts[v] || 0) + 1; });
           const ent = Object.entries(counts).sort((a, b) => b[1] - a[1]).slice(0, fc.max || 20);
           if (!ent.length) return;
-          html += `<div class="cg-sec collapsed"><h4>${esc(fc.l)}</h4><div class="cg-chips" data-facet="${esc(fc.k)}">` +
-            ent.map(([k, c]) => `<span class="cg-chip" data-v="${esc(k)}">${esc(k)}<span class="cg-ct">${c}</span></span>`).join('') + `</div></div>`;
+          // render FROM F: mark active chips + auto-expand a section that has a live filter
+          const set = F.chips[fc.k];
+          const secCls = (set && set.size) ? 'cg-sec' : 'cg-sec collapsed';
+          html += `<div class="${secCls}"><h4>${esc(fc.l)}</h4><div class="cg-chips" data-facet="${esc(fc.k)}">` +
+            ent.map(([k, c]) => `<span class="cg-chip${set && set.has(String(k)) ? ' active' : ''}" data-v="${esc(k)}">${esc(k)}<span class="cg-ct">${c}</span></span>`).join('') + `</div></div>`;
         } else {
-          html += `<div class="cg-sec collapsed"><h4>${esc(fc.l)}</h4><div class="cg-row2" data-facet="${esc(fc.k)}">` +
-            `<div class="cg-fld"><label>Min</label><input type="number" class="cg-min" placeholder="any"></div>` +
-            `<div class="cg-fld"><label>Max</label><input type="number" class="cg-max" placeholder="any"></div></div></div>`;
+          const rg = F.ranges[fc.k] || {};
+          const active = rg.min != null || rg.max != null;
+          const secCls = active ? 'cg-sec' : 'cg-sec collapsed';
+          const mn = rg.min != null ? ` value="${esc(rg.min)}"` : '';
+          const mx = rg.max != null ? ` value="${esc(rg.max)}"` : '';
+          html += `<div class="${secCls}"><h4>${esc(fc.l)}</h4><div class="cg-row2" data-facet="${esc(fc.k)}">` +
+            `<div class="cg-fld"><label>Min</label><input type="number" class="cg-min" placeholder="any"${mn}></div>` +
+            `<div class="cg-fld"><label>Max</label><input type="number" class="cg-max" placeholder="any"${mx}></div></div></div>`;
         }
       });
       html += `<div class="cg-sec"><h4>Fields — show / hide</h4><div class="cg-ftogs">` +
@@ -127,64 +191,228 @@
     // ---- renderers ----
     function cards(rows) {
       const vis = fields.filter(f => VIS[f.k] && !f.badge && f.k !== 'title');
-      return rows.map(r => {
+      return rows.map((r, i) => {
         const t = O.title ? O.title(r) : { name: r.name || '', sub: '' };
         const rc = O.onRow ? (O.onRow(r).cls || '') : '';
         const nm = t.href ? `<a href="${esc(t.href)}" target="_blank" rel="noopener noreferrer" style="color:inherit">${esc(t.name)}</a>` : esc(t.name);
-        return `<div class="cg-card ${rc}">` +
+        return `<div class="cg-card ${rc}" data-ri="${i}">` +
           `<div class="cg-name">${nm}</div>${t.sub ? `<div class="cg-sub">${esc(t.sub)}</div>` : ''}` +
           (O.badgeHtml ? O.badgeHtml(r) : '') +
           vis.map(f => `<div class="cg-r"><span class="cg-k">${esc(f.l)}</span><span>${fmt(fval(r, f), f)}</span></div>`).join('') +
           `</div>`;
       }).join('');
     }
-    function list(rows) {
+    function tableView(rows) {
       const cols = fields.filter(f => f.col && VIS[f.k] && !f.badge);
-      const head = `<th class="cg-stick">${esc((O.titleCol || 'Name'))}</th>` + cols.map(f => `<th>${esc(f.l)}</th>`).join('');
-      const body = rows.map(r => {
+      const arrow = k => (SORT && SORT.k === k) ? (SORT.dir < 0 ? ' ▼' : ' ▲') : '';
+      const titleK = O.titleSortK || '';
+      const head = `<th class="cg-stick cg-sortth" data-k="${esc(titleK)}">${esc((O.titleCol || 'Name'))}${arrow(titleK)}</th>` +
+        cols.map(f => `<th class="cg-sortth" data-k="${esc(f.k)}">${esc(f.l)}${arrow(f.k)}</th>`).join('');
+      const body = rows.map((r, i) => {
         const t = O.title ? O.title(r) : { name: '', sub: '' };
         const rc = O.onRow ? (O.onRow(r).cls || '') : '';
         const nm = t.href ? `<a href="${esc(t.href)}" target="_blank" rel="noopener noreferrer" style="color:inherit">${esc(t.name)}</a>` : esc(t.name);
-        return `<tr class="${rc}"><td class="cg-stick"><span class="cg-la">${nm}</span>${t.sub ? `<div class="cg-lc">${esc(t.sub)}</div>` : ''}</td>` +
+        return `<tr class="${rc}" data-ri="${i}"><td class="cg-stick"><span class="cg-la">${nm}</span>${t.sub ? `<div class="cg-lc">${esc(t.sub)}</div>` : ''}</td>` +
           cols.map(f => `<td>${fmt(fval(r, f), f)}</td>`).join('') + `</tr>`;
       }).join('');
       return `<div class="cg-listwrap"><table class="cg-tbl"><thead><tr>${head}</tr></thead><tbody>${body}</tbody></table></div>`;
     }
+    // compact single-row-per-record list: title on the left, every visible field
+    // flowing as inline key/value pairs on the right. Denser than cards, scannable,
+    // no fixed columns. Sorted via the topbar Sort select (all fields).
+    function listCompact(rows) {
+      const vis = fields.filter(f => VIS[f.k] && !f.badge && f.k !== 'title');
+      return `<div class="cg-rows">` + rows.map((r, i) => {
+        const t = O.title ? O.title(r) : { name: r.name || '', sub: '' };
+        const rc = O.onRow ? (O.onRow(r).cls || '') : '';
+        const nm = t.href ? `<a href="${esc(t.href)}" target="_blank" rel="noopener noreferrer" style="color:inherit">${esc(t.name)}</a>` : esc(t.name);
+        return `<div class="cg-lrow ${rc}" data-ri="${i}">` +
+          `<div class="cg-lmain"><span class="cg-la">${nm}</span>${t.sub ? `<span class="cg-lsub">${esc(t.sub)}</span>` : ''}${O.badgeHtml ? O.badgeHtml(r) : ''}</div>` +
+          `<div class="cg-lmeta">` +
+          vis.map(f => `<span class="cg-lm"><span class="cg-lmk">${esc(f.l)}</span>${fmt(fval(r, f), f)}</span>`).join('') +
+          `</div></div>`;
+      }).join('') + `</div>`;
+    }
 
-    let VIEW = localStorage.getItem(KEY + 'View') || O.view || 'grid';
+    // ---- active-filter summary bar (removable chips + clear all) ----
+    function activeFilterHTML() {
+      const parts = [];
+      facets.forEach(fc => {
+        if (fc.type === 'chip') {
+          const set = F.chips[fc.k];
+          if (set) set.forEach(v => parts.push(
+            `<span class="cg-af" data-fk="${esc(fc.k)}" data-aft="chip" data-v="${esc(v)}">${esc(fc.l)}: ${esc(v)} <b>✕</b></span>`));
+        } else {
+          const r = F.ranges[fc.k];
+          if (r && (r.min != null || r.max != null)) {
+            const txt = (r.min != null && r.max != null) ? esc(r.min) + '–' + esc(r.max)
+              : (r.min != null) ? '≥ ' + esc(r.min) : '≤ ' + esc(r.max);
+            parts.push(`<span class="cg-af" data-fk="${esc(fc.k)}" data-aft="range">${esc(fc.l)}: ${txt} <b>✕</b></span>`);
+          }
+        }
+      });
+      if (F.q) parts.push(`<span class="cg-af" data-aft="q">“${esc(F.q)}” <b>✕</b></span>`);
+      if (!parts.length) return '';
+      return `<span class="cg-af-lbl">Filters</span>` + parts.join('') +
+        `<button class="cg-af-clear" data-clearall="1">Clear all</button>` +
+        `<button class="cg-af-copy" data-copy="1" title="Copy a shareable link to this filtered view">🔗 Copy link</button>`;
+    }
+    function clearFilter(el) {
+      if (el.dataset.clearall != null) {
+        facets.forEach(fc => { if (fc.type === 'chip') F.chips[fc.k].clear(); else F.ranges[fc.k] = { min: null, max: null }; });
+        F.q = ''; const q = $(O.mount + ' .cg-q'); if (q) q.value = '';
+      } else if (el.dataset.aft === 'q') {
+        F.q = ''; const q = $(O.mount + ' .cg-q'); if (q) q.value = '';
+      } else if (el.dataset.aft === 'chip') {
+        F.chips[el.dataset.fk].delete(el.dataset.v);
+      } else if (el.dataset.aft === 'range') {
+        F.ranges[el.dataset.fk] = { min: null, max: null };
+      }
+      buildRail(); render(); // buildRail re-renders the rail from F so it stays in sync
+    }
+
+    let stored = null; try { stored = localStorage.getItem(KEY + 'View'); } catch (e) {}
+    // v2 migration: the old engine's 'list' WAS the dense table. The new engine renames
+    // that spreadsheet to 'table' and adds a distinct compact 'list'. Re-point a *stored*
+    // legacy 'list' to 'table' exactly once so returning users keep the view they had.
+    try {
+      if (stored === 'list' && !localStorage.getItem(KEY + 'ViewV2')) { stored = 'table'; localStorage.setItem(KEY + 'View', 'table'); }
+      localStorage.setItem(KEY + 'ViewV2', '1');
+    } catch (e) {}
+    let VIEW = stored || O.view || 'grid';
     const CAP = O.cap || 1500; // DOM render cap for perf; count still reflects the full match set
+    let lastShown = [];
     function render() {
-      const rows = data.filter(pass);
+      const rows = sortRows(data.filter(pass));
       const shown = rows.length > CAP ? rows.slice(0, CAP) : rows;
+      lastShown = shown;
       const g = $(O.mount + ' .cg-grid');
-      if (!rows.length) { g.className = 'cg-grid'; g.innerHTML = '<div class="cg-empty">no matches for these filters.</div>'; }
-      else if (VIEW === 'list') { g.className = 'cg-grid cg-listhost'; g.innerHTML = list(shown); }
+      if (!rows.length) {
+        g.className = 'cg-grid';
+        g.innerHTML = '<div class="cg-empty"><div class="cg-empty-ic">⌕</div>' +
+          '<div class="cg-empty-t">No matches</div>' +
+          '<div class="cg-empty-s">No results match the current filters.</div>' +
+          '<button class="cg-af-clear cg-empty-btn" data-clearall="1">Clear all filters</button></div>';
+      }
+      else if (VIEW === 'table') { g.className = 'cg-grid cg-listhost'; g.innerHTML = tableView(shown); }
+      else if (VIEW === 'list') { g.className = 'cg-grid cg-listhost'; g.innerHTML = listCompact(shown); }
       else { g.className = 'cg-grid'; g.innerHTML = cards(shown); }
       const cnt = $(O.mount + ' .cg-count');
       if (cnt) cnt.innerHTML = `<b>${rows.length.toLocaleString()}</b> of ${data.length.toLocaleString()}` + (rows.length > CAP ? ` <span style="opacity:.7">(first ${CAP.toLocaleString()} shown)</span>` : '');
+      const sel = $(O.mount + ' .cg-sort');
+      if (sel) sel.value = SORT && SORT.k ? SORT.k + ':' + (SORT.dir < 0 ? 'desc' : 'asc') : '';
+      const ab = $(O.mount + ' .cg-active');
+      if (ab) ab.innerHTML = activeFilterHTML();
+      // render() rebuilds the whole table via innerHTML, so the previous
+      // col-resize enhancement is gone. Re-enhance deterministically instead of
+      // waiting on the async MutationObserver (which races the first interaction).
+      if (window.ColResize && window.ColResize.refresh) window.ColResize.refresh();
+      syncURL();
     }
 
     // ---- topbar ----
     function buildTop() {
       const m = $(O.mount);
+      // ALL data points are sortable — not just the curated table columns.
+      const titleSK = O.titleSortK || '';
+      const sortable = fields.filter(f => !f.badge && f.k !== 'title' && f.k !== titleSK);
+      const titleOpts = titleSK
+        ? `<option value="${esc(titleSK)}:asc">${esc(O.titleCol || 'Name')} A→Z</option><option value="${esc(titleSK)}:desc">${esc(O.titleCol || 'Name')} Z→A</option>`
+        : '';
+      const sortOpts = `<option value="">Sort…</option>` + titleOpts + sortable.map(f =>
+        `<option value="${esc(f.k)}:desc">${esc(f.l)} ↓</option><option value="${esc(f.k)}:asc">${esc(f.l)} ↑</option>`).join('');
       m.insertAdjacentHTML('afterbegin',
         `<div class="cg-top">` +
+        `<button type="button" class="cg-filt-btn" aria-label="Filters">☰ Filters</button>` +
         `<input type="text" class="cg-q" placeholder="search…">` +
-        `<span class="cg-seg"><button data-view="grid" class="${VIEW === 'grid' ? 'active' : ''}">▦ Grid</button><button data-view="list" class="${VIEW === 'list' ? 'active' : ''}">☰ List</button></span>` +
+        `<select class="cg-sort" title="Sort">${sortOpts}</select>` +
+        `<span class="cg-seg"><button data-view="grid" class="${VIEW === 'grid' ? 'active' : ''}">▦ Grid</button><button data-view="list" class="${VIEW === 'list' ? 'active' : ''}">☰ List</button><button data-view="table" class="${VIEW === 'table' ? 'active' : ''}">▤ Table</button></span>` +
         `<label class="cg-dens">Density <input type="range" class="cg-cols" min="1" max="12" step="1" value="${O.cols || 3}"></label>` +
-        `<span class="cg-count"></span></div><div class="cg-grid"></div>`);
+        `<span class="cg-count"></span></div><div class="cg-active"></div><div class="cg-grid"></div>`);
       const q = m.querySelector('.cg-q');
+      if (F.q) q.value = F.q; // reflect a search restored from the URL
       q.addEventListener('input', () => { clearTimeout(q._t); q._t = setTimeout(() => { F.q = q.value.trim().toLowerCase(); render(); }, 160); });
+      m.querySelector('.cg-sort').addEventListener('change', e => {
+        const v = e.target.value;
+        if (!v) SORT = null;
+        else { const [k, d] = v.split(':'); SORT = { k, dir: d === 'desc' ? -1 : 1 }; }
+        saveSort(); render();
+      });
       m.querySelector('.cg-seg').addEventListener('click', e => { const b = e.target.closest('button[data-view]'); if (!b) return; VIEW = b.dataset.view; localStorage.setItem(KEY + 'View', VIEW); m.querySelectorAll('.cg-seg button').forEach(x => x.classList.toggle('active', x.dataset.view === VIEW)); render(); });
       const cols = m.querySelector('.cg-cols');
-      const setCols = v => { m.style.setProperty('--cg-cols', v); localStorage.setItem(KEY + 'Cols', v); };
+      const setCols = v => { m.style.setProperty('--cg-cols', v); m.style.setProperty('--cg-dens', v); localStorage.setItem(KEY + 'Cols', v); };
       cols.addEventListener('input', e => setCols(e.target.value));
       const sc = localStorage.getItem(KEY + 'Cols'); if (sc) { cols.value = sc; }
       setCols(cols.value);
+      // mobile: "Filters" button opens the existing rail as an off-canvas drawer
+      const filtBtn = m.querySelector('.cg-filt-btn');
+      const railEl = $(O.rail);
+      if (filtBtn && railEl) {
+        const bd = document.createElement('div'); bd.className = 'cg-rail-backdrop'; document.body.appendChild(bd);
+        const openRail = () => { railEl.classList.add('open'); bd.classList.add('open'); };
+        const closeRail = () => { railEl.classList.remove('open'); bd.classList.remove('open'); };
+        filtBtn.addEventListener('click', () => railEl.classList.contains('open') ? closeRail() : openRail());
+        bd.addEventListener('click', closeRail);
+        document.addEventListener('keydown', e => { if (e.key === 'Escape') closeRail(); });
+      }
+      // th-click sorting + whole-row click (delegated; grid re-renders under us)
+      m.addEventListener('click', e => {
+        const cp = e.target.closest('.cg-af-copy');
+        if (cp) {
+          const done = () => { const t = cp.textContent; cp.textContent = '✓ Copied'; setTimeout(() => cp.textContent = t, 1200); };
+          if (navigator.clipboard) navigator.clipboard.writeText(location.href).then(done, done); else done();
+          return;
+        }
+        const af = e.target.closest('.cg-af, .cg-af-clear');
+        if (af) { clearFilter(af); return; }
+        // A click on the resize handle (or the tail of a resize drag) must NOT
+        // sort — otherwise grabbing the handle re-renders the whole table
+        // mid-gesture and the column never resizes. col-resize owns the handle.
+        if (e.target.closest('.cr-handle') || document.body.classList.contains('cr-dragging')) return;
+        const th = e.target.closest('.cg-sortth');
+        if (th && th.dataset.k) {
+          const k = th.dataset.k;
+          SORT = (SORT && SORT.k === k) ? { k, dir: -SORT.dir } : { k, dir: -1 };
+          saveSort(); render(); return;
+        }
+        if (O.onRowClick && !e.target.closest('a')) {
+          const tr = e.target.closest('tr[data-ri]');
+          if (tr) { O.onRowClick(lastShown[+tr.dataset.ri], tr); return; }
+          const card = e.target.closest('.cg-card[data-ri]');
+          if (card) O.onRowClick(lastShown[+card.dataset.ri], card);
+        }
+      });
+    }
+
+    // Export the CURRENTLY filtered + sorted rows (uncapped) as a CSV Blob — so a
+    // download reflects exactly what the user filtered to, not the whole dataset.
+    function exportCSV(opts) {
+      opts = opts || {};
+      const rows = sortRows(data.filter(pass));
+      const cols = fields.filter(f => !f.badge && f.k !== 'name'); // 'name' handled as the title column
+      const csvEsc = v => { if (v == null) return ''; v = String(v); return /[",\n]/.test(v) ? '"' + v.replace(/"/g, '""') + '"' : v; };
+      const header = ['Name'].concat(cols.map(f => f.l));
+      const lines = [header.map(csvEsc).join(',')];
+      rows.forEach(r => {
+        const t = O.title ? O.title(r) : { name: r.name || '' };
+        lines.push([csvEsc(t.name)].concat(cols.map(f => csvEsc(fval(r, f)))).join(','));
+      });
+      const blob = new Blob([lines.join('\n')], { type: 'text/csv;charset=utf-8' });
+      const url = URL.createObjectURL(blob);
+      const a = document.createElement('a');
+      a.href = url; a.download = opts.filename || 'export.csv';
+      document.body.appendChild(a); a.click(); a.remove();
+      setTimeout(() => URL.revokeObjectURL(url), 1000);
+      return rows.length;
     }
 
-    buildTop(); buildRail(); render();
-    return { render, setData(d) { O.data.length = 0; d.forEach(x => O.data.push(x)); buildRail(); render(); } };
+    readFromURL(); buildTop(); buildRail(); render();
+    return {
+      render,
+      setData(d) { O.data.length = 0; d.forEach(x => O.data.push(x)); buildRail(); render(); },
+      exportCSV,
+      filteredCount() { return data.filter(pass).length; },
+    };
   }
 
   global.CrcpGrid = { mount: opts => new CrcpGrid(opts) };
diff --git a/public/crcp-grid.js.pre-3view.bak b/public/crcp-grid.js.pre-3view.bak
new file mode 100644
index 0000000..1bfc75d
--- /dev/null
+++ b/public/crcp-grid.js.pre-3view.bak
@@ -0,0 +1,191 @@
+/* crcp-grid.js — reusable Amazon-style faceted grid engine for the CRE fleet.
+ * Config-driven, theme-agnostic (inherits the host page's CSS vars via cg-grid.css).
+ * One page = one CrcpGrid.mount(opts) call. Mirrors the proven condos.html engine so
+ * every list page gets the SAME behavior: left-rail facets, per-field show/hide toggles,
+ * grid/list view toggle, density slider, live search, localStorage persistence.
+ *
+ * opts = {
+ *   data:      [row,...],            // all rows (client-side faceting)
+ *   fields:    [{k,l,def,col,badge,money,num,date,calc,suf,pct}],  // every data point (card rows + list cols)
+ *   facets:    [{k,l,type:'chip'|'range',calc,order,max}],         // rail filters (auto-derived if omitted)
+ *   mount:     '#cgMain',            // container for topbar + grid
+ *   rail:      '#cgRail',            // container for the left rail
+ *   title:     row => ({name, sub}),// card/list title + subline
+ *   search:    row => 'text blob',   // searchable string
+ *   badgeHtml: row => '<span>...'|'',// optional status badge html (card + list)
+ *   storageKey:'fha',               // localStorage namespace
+ *   cols:      3,                   // default density
+ *   onRow:     row => ({cls}),      // optional per-row class hook (e.g. red flag)
+ * }
+ */
+(function (global) {
+  const esc = s => String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;');
+  const $ = (sel, root) => (root || document).querySelector(sel);
+
+  function fmt(v, f) {
+    if (v == null || v === '') return '—';
+    if (f.money) return '$' + (+v).toLocaleString() + (f.suf || '');
+    if (f.pct)   return (+v).toFixed(2) + '%';
+    if (f.num)   return (+v).toLocaleString() + (f.suf || '');
+    if (f.date)  { try { return new Date(v).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' }); } catch (e) { return '—'; } }
+    return esc(v) + (f.suf || '');
+  }
+
+  function CrcpGrid(opts) {
+    const O = opts;
+    const KEY = O.storageKey || 'cg';
+    const fields = O.fields;
+    const data = O.data || [];
+    const fval = (row, f) => f.calc ? f.calc(row) : row[f.k];
+
+    // ---- field visibility (persisted) ----
+    const VIS = (function () {
+      let s = {}; try { s = JSON.parse(localStorage.getItem(KEY + 'Fields') || '{}'); } catch (e) {}
+      const o = {}; fields.forEach(f => o[f.k] = (f.k in s) ? !!s[f.k] : !!f.def); return o;
+    })();
+    const saveVis = () => { try { localStorage.setItem(KEY + 'Fields', JSON.stringify(VIS)); } catch (e) {} };
+
+    // ---- auto-derive facets if not provided ----
+    let facets = O.facets;
+    if (!facets) {
+      facets = [];
+      fields.forEach(f => {
+        if (f.badge || f.k === 'title') return;
+        const vals = data.map(r => fval(r, f)).filter(v => v != null && v !== '');
+        if (!vals.length) return;
+        const numeric = f.money || f.num || f.pct || vals.every(v => typeof v === 'number' || /^\d+(\.\d+)?$/.test(v));
+        const uniq = new Set(vals.map(String));
+        if (!numeric && uniq.size <= 24) facets.push({ k: f.k, l: f.l, type: 'chip', calc: f.calc });
+        else if (numeric) facets.push({ k: f.k, l: f.l, type: 'range', calc: f.calc, money: f.money });
+      });
+    }
+
+    // ---- filter state ----
+    const F = { q: '', chips: {}, ranges: {} };
+    facets.forEach(fc => { if (fc.type === 'chip') F.chips[fc.k] = new Set(); else F.ranges[fc.k] = { min: null, max: null }; });
+
+    const gv = (row, fc) => fc.calc ? fc.calc(row) : row[fc.k];
+    function pass(row) {
+      for (const fc of facets) {
+        if (fc.type === 'chip') { const set = F.chips[fc.k]; if (set.size && !set.has(String(gv(row, fc)))) return false; }
+        else { const r = F.ranges[fc.k], v = gv(row, fc);
+          if (r.min != null && !(+v >= r.min)) return false;
+          if (r.max != null && !(+v <= r.max)) return false; }
+      }
+      if (F.q) { const blob = (O.search ? O.search(row) : fields.map(f => fval(row, f)).join(' ')).toLowerCase(); if (!blob.includes(F.q)) return false; }
+      return true;
+    }
+
+    // ---- rail ----
+    function buildRail() {
+      const rail = $(O.rail);
+      let html = '';
+      facets.forEach(fc => {
+        if (fc.type === 'chip') {
+          const counts = {};
+          data.forEach(r => { const v = gv(r, fc); if (v != null && v !== '') counts[v] = (counts[v] || 0) + 1; });
+          const ent = Object.entries(counts).sort((a, b) => b[1] - a[1]).slice(0, fc.max || 20);
+          if (!ent.length) return;
+          html += `<div class="cg-sec collapsed"><h4>${esc(fc.l)}</h4><div class="cg-chips" data-facet="${esc(fc.k)}">` +
+            ent.map(([k, c]) => `<span class="cg-chip" data-v="${esc(k)}">${esc(k)}<span class="cg-ct">${c}</span></span>`).join('') + `</div></div>`;
+        } else {
+          html += `<div class="cg-sec collapsed"><h4>${esc(fc.l)}</h4><div class="cg-row2" data-facet="${esc(fc.k)}">` +
+            `<div class="cg-fld"><label>Min</label><input type="number" class="cg-min" placeholder="any"></div>` +
+            `<div class="cg-fld"><label>Max</label><input type="number" class="cg-max" placeholder="any"></div></div></div>`;
+        }
+      });
+      html += `<div class="cg-sec"><h4>Fields — show / hide</h4><div class="cg-ftogs">` +
+        fields.map(f => `<label class="cg-ftog"><input type="checkbox" data-fk="${esc(f.k)}" ${VIS[f.k] ? 'checked' : ''}><span>${esc(f.l)}</span>${f.col ? '<span class="cg-ct" title="List column">▤</span>' : ''}</label>`).join('') +
+        `</div><div class="cg-mini"><button data-all="1">All</button><button data-none="1">None</button><button data-def="1">Default</button></div></div>`;
+      rail.innerHTML = html;
+
+      // wire facets
+      rail.querySelectorAll('.cg-chips').forEach(box => box.addEventListener('click', e => {
+        const c = e.target.closest('.cg-chip'); if (!c) return;
+        const set = F.chips[box.dataset.facet]; const v = c.dataset.v;
+        set.has(v) ? set.delete(v) : set.add(v); c.classList.toggle('active'); render();
+      }));
+      rail.querySelectorAll('.cg-row2').forEach(box => {
+        const k = box.dataset.facet;
+        box.querySelector('.cg-min').addEventListener('input', e => { F.ranges[k].min = e.target.value ? +e.target.value : null; render(); });
+        box.querySelector('.cg-max').addEventListener('input', e => { F.ranges[k].max = e.target.value ? +e.target.value : null; render(); });
+      });
+      // field toggles
+      rail.querySelector('.cg-ftogs').addEventListener('change', e => { const cb = e.target.closest('input[data-fk]'); if (!cb) return; VIS[cb.dataset.fk] = cb.checked; saveVis(); render(); });
+      const mini = rail.querySelector('.cg-mini');
+      mini.addEventListener('click', e => {
+        const b = e.target.closest('button'); if (!b) return;
+        if (b.dataset.all) fields.forEach(f => VIS[f.k] = true);
+        else if (b.dataset.none) fields.forEach(f => VIS[f.k] = false);
+        else if (b.dataset.def) fields.forEach(f => VIS[f.k] = !!f.def);
+        saveVis(); buildRail(); render();
+      });
+      // collapsible headers
+      rail.querySelectorAll('.cg-sec > h4').forEach(h => h.addEventListener('click', () => h.parentElement.classList.toggle('collapsed')));
+    }
+
+    // ---- renderers ----
+    function cards(rows) {
+      const vis = fields.filter(f => VIS[f.k] && !f.badge && f.k !== 'title');
+      return rows.map(r => {
+        const t = O.title ? O.title(r) : { name: r.name || '', sub: '' };
+        const rc = O.onRow ? (O.onRow(r).cls || '') : '';
+        const nm = t.href ? `<a href="${esc(t.href)}" target="_blank" rel="noopener noreferrer" style="color:inherit">${esc(t.name)}</a>` : esc(t.name);
+        return `<div class="cg-card ${rc}">` +
+          `<div class="cg-name">${nm}</div>${t.sub ? `<div class="cg-sub">${esc(t.sub)}</div>` : ''}` +
+          (O.badgeHtml ? O.badgeHtml(r) : '') +
+          vis.map(f => `<div class="cg-r"><span class="cg-k">${esc(f.l)}</span><span>${fmt(fval(r, f), f)}</span></div>`).join('') +
+          `</div>`;
+      }).join('');
+    }
+    function list(rows) {
+      const cols = fields.filter(f => f.col && VIS[f.k] && !f.badge);
+      const head = `<th class="cg-stick">${esc((O.titleCol || 'Name'))}</th>` + cols.map(f => `<th>${esc(f.l)}</th>`).join('');
+      const body = rows.map(r => {
+        const t = O.title ? O.title(r) : { name: '', sub: '' };
+        const rc = O.onRow ? (O.onRow(r).cls || '') : '';
+        const nm = t.href ? `<a href="${esc(t.href)}" target="_blank" rel="noopener noreferrer" style="color:inherit">${esc(t.name)}</a>` : esc(t.name);
+        return `<tr class="${rc}"><td class="cg-stick"><span class="cg-la">${nm}</span>${t.sub ? `<div class="cg-lc">${esc(t.sub)}</div>` : ''}</td>` +
+          cols.map(f => `<td>${fmt(fval(r, f), f)}</td>`).join('') + `</tr>`;
+      }).join('');
+      return `<div class="cg-listwrap"><table class="cg-tbl"><thead><tr>${head}</tr></thead><tbody>${body}</tbody></table></div>`;
+    }
+
+    let VIEW = localStorage.getItem(KEY + 'View') || O.view || 'grid';
+    const CAP = O.cap || 1500; // DOM render cap for perf; count still reflects the full match set
+    function render() {
+      const rows = data.filter(pass);
+      const shown = rows.length > CAP ? rows.slice(0, CAP) : rows;
+      const g = $(O.mount + ' .cg-grid');
+      if (!rows.length) { g.className = 'cg-grid'; g.innerHTML = '<div class="cg-empty">no matches for these filters.</div>'; }
+      else if (VIEW === 'list') { g.className = 'cg-grid cg-listhost'; g.innerHTML = list(shown); }
+      else { g.className = 'cg-grid'; g.innerHTML = cards(shown); }
+      const cnt = $(O.mount + ' .cg-count');
+      if (cnt) cnt.innerHTML = `<b>${rows.length.toLocaleString()}</b> of ${data.length.toLocaleString()}` + (rows.length > CAP ? ` <span style="opacity:.7">(first ${CAP.toLocaleString()} shown)</span>` : '');
+    }
+
+    // ---- topbar ----
+    function buildTop() {
+      const m = $(O.mount);
+      m.insertAdjacentHTML('afterbegin',
+        `<div class="cg-top">` +
+        `<input type="text" class="cg-q" placeholder="search…">` +
+        `<span class="cg-seg"><button data-view="grid" class="${VIEW === 'grid' ? 'active' : ''}">▦ Grid</button><button data-view="list" class="${VIEW === 'list' ? 'active' : ''}">☰ List</button></span>` +
+        `<label class="cg-dens">Density <input type="range" class="cg-cols" min="1" max="12" step="1" value="${O.cols || 3}"></label>` +
+        `<span class="cg-count"></span></div><div class="cg-grid"></div>`);
+      const q = m.querySelector('.cg-q');
+      q.addEventListener('input', () => { clearTimeout(q._t); q._t = setTimeout(() => { F.q = q.value.trim().toLowerCase(); render(); }, 160); });
+      m.querySelector('.cg-seg').addEventListener('click', e => { const b = e.target.closest('button[data-view]'); if (!b) return; VIEW = b.dataset.view; localStorage.setItem(KEY + 'View', VIEW); m.querySelectorAll('.cg-seg button').forEach(x => x.classList.toggle('active', x.dataset.view === VIEW)); render(); });
+      const cols = m.querySelector('.cg-cols');
+      const setCols = v => { m.style.setProperty('--cg-cols', v); localStorage.setItem(KEY + 'Cols', v); };
+      cols.addEventListener('input', e => setCols(e.target.value));
+      const sc = localStorage.getItem(KEY + 'Cols'); if (sc) { cols.value = sc; }
+      setCols(cols.value);
+    }
+
+    buildTop(); buildRail(); render();
+    return { render, setData(d) { O.data.length = 0; d.forEach(x => O.data.push(x)); buildRail(); render(); } };
+  }
+
+  global.CrcpGrid = { mount: opts => new CrcpGrid(opts) };
+})(window);
diff --git a/public/crcp.html b/public/crcp.html
index b0a0a28..35168cf 100644
--- a/public/crcp.html
+++ b/public/crcp.html
@@ -204,6 +204,7 @@
     border-radius:6px;padding:9px 13px;font-size:12.5px;color:var(--del);}
   #crcpConnBanner.show{display:block;}
 </style>
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <header>
@@ -933,5 +934,6 @@ loadSegments(); setInterval(loadSegments, 20000);
   if(document.readyState==='loading') document.addEventListener('DOMContentLoaded',start); else start();
 })();
 </script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/credit-unions.html b/public/credit-unions.html
index 5874d74..4bf87e2 100644
--- a/public/credit-unions.html
+++ b/public/credit-unions.html
@@ -6,6 +6,7 @@
 <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Crect width='16' height='16' rx='3' fill='%230c0f15'/%3E%3Ctext x='8' y='12' font-size='9' text-anchor='middle' fill='%23C8A24B'%3E%F0%9F%A4%9D%3C/text%3E%3C/svg%3E">
 <title>Credit Unions — with LA County offices (NCUA)</title>
 <link rel="stylesheet" href="/lending-grid.css">
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <header>
@@ -74,5 +75,6 @@ window.GRID_CONFIG = {
 <script src="/lending-grid.js" defer></script>
 <script src="/col-resize.js" defer></script>
 <script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/deals-flow.html b/public/deals-flow.html
index 53abd32..749d6d2 100644
--- a/public/deals-flow.html
+++ b/public/deals-flow.html
@@ -98,7 +98,8 @@ select{background:var(--card);border:1px solid var(--line);color:var(--ink);bord
 .roleopt.sel{border-color:var(--acc);background:rgba(63,185,80,.12)}
 .roleopt b{display:block;color:#fff;font-size:12.5px}
 .roleopt span{font-size:10px;color:var(--mut)}
-</style></head><body>
+</style>  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
+</head><body>
 <header>
   <h1><b>Closed Deal Flow</b> · LA Commercial</h1>
   <span class="badge">100% public record</span>
@@ -463,4 +464,5 @@ Promise.all([
   render();loadMe();
 }).catch(()=>{$('#count').textContent='failed to load deal data';});
 </script><script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body></html>
diff --git a/public/deals.html b/public/deals.html
index f7e1df2..39891b5 100644
--- a/public/deals.html
+++ b/public/deals.html
@@ -95,6 +95,7 @@
     .ctrl-btn.spin .ico{animation:none;}
   }
 </style>
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <div class="wrap">
@@ -291,5 +292,6 @@ pull();   // initial load
   <script src="/col-resize.js" defer></script>
   <script src="/global-search.js" defer></script>
 <script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/fha-leads.html b/public/fha-leads.html
index 232ec5f..cf209b6 100644
--- a/public/fha-leads.html
+++ b/public/fha-leads.html
@@ -32,7 +32,8 @@ tr:hover td{background:#131922}
 .prov{font-size:11px;color:var(--mut);margin:2px 0 12px;line-height:1.5}
 .stat{display:inline-block;background:var(--card);border:1px solid var(--line);border-radius:9px;padding:8px 12px;margin:0 8px 10px 0}
 .stat b{font-size:19px;color:#fff}.stat span{display:block;font-size:10px;text-transform:uppercase;color:var(--mut);letter-spacing:.4px}
-</style></head><body>
+</style>  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
+</head><body>
 <header>
   <h1><b>Assumable-Loan Leads</b> · FHA Multifamily</h1>
   <span class="badge">100% public data · resellable</span>
@@ -140,4 +141,5 @@ $('#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><script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body></html>
diff --git a/public/fha-loans.html b/public/fha-loans.html
index b7d3337..024e114 100644
--- a/public/fha-loans.html
+++ b/public/fha-loans.html
@@ -137,6 +137,7 @@
   @media(prefers-reduced-motion:reduce){body::before{animation:none;}.glass{animation:none;opacity:1;transform:none;}}
 </style>
 <link rel="stylesheet" href="/crcp-theme.css">
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <div class="wrap">
@@ -526,5 +527,6 @@ load();
 })();
 </script>
 <script src="/crcp-theme.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/gov-agents.html b/public/gov-agents.html
index 38a5d0d..122c652 100644
--- a/public/gov-agents.html
+++ b/public/gov-agents.html
@@ -62,6 +62,7 @@
   #modal .x{position:absolute;top:12px;right:14px;background:none;border:0;color:var(--mut);font-size:22px;cursor:pointer;}
   #modal .litem{display:flex;justify-content:space-between;gap:12px;padding:5px 0;border-bottom:1px solid #20262f;font-size:13px;} #modal .litem .m{color:var(--mut);}
 </style>
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <header>
@@ -301,5 +302,6 @@ loadIndex();
   <script src="/column-manager.js" defer></script>
   <script src="/col-resize.js" defer></script>
 <script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/graphics.html b/public/graphics.html
index e010903..83d7f20 100644
--- a/public/graphics.html
+++ b/public/graphics.html
@@ -40,6 +40,7 @@
   @media(max-width:820px){ main{grid-template-columns:1fr;} }
 </style>
 <link rel="stylesheet" href="/crcp-theme.css">
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <header>
@@ -240,5 +241,6 @@ const HOVER=(evt,els)=>{ const t=evt&&evt.native&&evt.native.target; if(t) t.sty
   <script src="/col-resize.js" defer></script>
 <script src="/corner-nav.js" defer></script>
 <script src="/crcp-theme.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/index.html b/public/index.html
index dca815a..3ebb3a6 100644
--- a/public/index.html
+++ b/public/index.html
@@ -380,6 +380,7 @@
 </style>
 <script async src="https://www.googletagmanager.com/gtag/js?id=G-7R2X3B2V18"></script><script>window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','G-7R2X3B2V18');</script>
 <link rel="stylesheet" href="/crcp-theme.css">
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <header>
@@ -2080,5 +2081,6 @@ function loadRanked(_retry){ return fetch('data/ranked.json').then(r=>{ if(!r.ok
   if(document.readyState==='loading') document.addEventListener('DOMContentLoaded',mount); else mount();
 })();
 </script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/just-listed.html b/public/just-listed.html
index 1f21974..73838b3 100644
--- a/public/just-listed.html
+++ b/public/just-listed.html
@@ -73,7 +73,8 @@ td.wrap{white-space:normal;min-width:220px;max-width:380px;color:var(--mut)}
 td a.f{color:var(--blue);text-decoration:none}
 td a.f:hover{text-decoration:underline}
 .empty{color:var(--mut);padding:40px;text-align:center}
-</style></head><body>
+</style>  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
+</head><body>
 <header>
   <h1><b>Just Listed</b> · Active Inventory</h1>
   <span class="badge" id="srcBadge">active listings</span>
@@ -296,4 +297,5 @@ fetch('/data/listings.json').then(r=>r.json()).then(d=>{
 </script>  <script src="/global-search.js" defer></script>
   <script src="/sort-bar.js" defer></script>
 <script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body></html>
diff --git a/public/lenders.html b/public/lenders.html
index 54116f5..b1ac01a 100644
--- a/public/lenders.html
+++ b/public/lenders.html
@@ -6,6 +6,7 @@
 <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Crect width='16' height='16' rx='3' fill='%230c0f15'/%3E%3Ctext x='8' y='12' font-size='9' text-anchor='middle' fill='%23C8A24B'%3E%F0%9F%8F%A6%3C/text%3E%3C/svg%3E">
 <title>Lenders — Banks with LA County branches (FDIC)</title>
 <link rel="stylesheet" href="/lending-grid.css">
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <header>
@@ -77,5 +78,6 @@ window.GRID_CONFIG = {
 <script src="/lending-grid.js" defer></script>
 <script src="/col-resize.js" defer></script>
 <script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/licensed-agents.html b/public/licensed-agents.html
index 6f0e8ff..b719612 100644
--- a/public/licensed-agents.html
+++ b/public/licensed-agents.html
@@ -60,6 +60,7 @@
   #modal .kv{margin-top:8px;display:grid;grid-template-columns:auto 1fr;gap:5px 12px;font-size:13px;}
   #modal .kv .k{color:var(--mut);} #modal .kv .v a{color:var(--blue);text-decoration:none;}
 </style>
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <header>
@@ -283,5 +284,6 @@ if(localStorage.getItem('laMode')==='brokers') setMode('brokers'); else { $('#fi
 </script>
   <script src="/col-resize.js" defer></script>
 <script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/licensed.html b/public/licensed.html
index e1999a9..ba90f6a 100644
--- a/public/licensed.html
+++ b/public/licensed.html
@@ -53,7 +53,8 @@ input#q{min-width:230px}
 #modal h3{margin:0 0 3px;font-size:19px}#modal .x{position:absolute;top:11px;right:14px;background:none;border:0;color:var(--mut);font-size:22px;cursor:pointer;line-height:1}
 #modal .mrow{display:flex;justify-content:space-between;gap:12px;padding:5px 0;border-bottom:1px solid var(--line);font-size:13px}
 #modal .mrow .mk{color:var(--mut);text-transform:capitalize}#modal .mrow .mv{text-align:right;word-break:break-word}
-</style></head><body>
+</style>  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
+</head><body>
 <header>
   <div><h1>📋 Licensed Directory <span class="sub" id="scope"></span></h1></div>
   <div class="tabs" id="tabs"></div>
@@ -210,4 +211,5 @@ 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>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body></html>
diff --git a/public/loan-officers.html b/public/loan-officers.html
index 63953b3..499c129 100644
--- a/public/loan-officers.html
+++ b/public/loan-officers.html
@@ -12,6 +12,7 @@
   .compliance a{color:var(--blue);} .compliance .lk{display:inline-block;margin-top:8px;margin-right:14px;}
   .empty{margin:20px;padding:40px 24px;text-align:center;color:var(--mut);border:1px dashed var(--line);border-radius:12px;}
 </style>
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <header>
@@ -85,5 +86,6 @@ fetch('/api/lending/loan-officers', { credentials:'same-origin' }).then(r=>r.jso
 }).catch(()=>{});
 </script>
 <script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/mls.html b/public/mls.html
index 865f715..a31f7f9 100644
--- a/public/mls.html
+++ b/public/mls.html
@@ -109,6 +109,7 @@
   .heatleg .hb { width:52px; height:8px; border-radius:4px; background:linear-gradient(90deg,hsl(0,70%,45%),hsl(60,70%,45%),hsl(120,70%,45%)); }
 </style>
 <link rel="stylesheet" href="/crcp-theme.css">
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <header>
@@ -680,5 +681,6 @@ document.addEventListener('click', async e=>{
   <script src="/sort-bar.js" defer></script>
 <script src="/corner-nav.js" defer></script>
 <script src="/crcp-theme.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/mortgage-market.html b/public/mortgage-market.html
index 853e66d..c375a16 100644
--- a/public/mortgage-market.html
+++ b/public/mortgage-market.html
@@ -6,6 +6,7 @@
 <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Crect width='16' height='16' rx='3' fill='%230c0f15'/%3E%3Ctext x='8' y='12' font-size='9' text-anchor='middle' fill='%23C8A24B'%3E%F0%9F%93%8A%3C/text%3E%3C/svg%3E">
 <title>Residential Mortgage Market — LA County lenders (CFPB / HMDA)</title>
 <link rel="stylesheet" href="/lending-grid.css">
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <header>
@@ -66,5 +67,6 @@ window.GRID_CONFIG = {
 <script src="/lending-grid.js" defer></script>
 <script src="/col-resize.js" defer></script>
 <script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/nav-agent/nav-agent.css b/public/nav-agent/nav-agent.css
new file mode 100644
index 0000000..702094c
--- /dev/null
+++ b/public/nav-agent/nav-agent.css
@@ -0,0 +1,93 @@
+/* ============================================================================
+ * Nav Agent — universal grid-controls drop-in  (v1.0)
+ * Left field-toggle panel + sort-every-field + grouping + movable/removable/
+ * expandable data panels.  Zero dependencies. Additive & defensive.
+ * Honors the house internal-line-viewer spec (left panel, density type-scale,
+ * tight cards, localStorage-persisted).
+ * ==========================================================================*/
+
+:root{
+  --na-acc:var(--acc,#1f9e8f);
+  --na-line:var(--line,#2a2f3a);
+  --na-bg:var(--panel,#12151c);
+  --na-bg2:var(--bg,#0c0e13);
+  --na-fg:var(--fg,#e7e9ee);
+  --na-mut:var(--mut,#8b93a3);
+}
+
+/* ---- launcher (bottom-left cog) --------------------------------------- */
+.na-launch{position:fixed;left:14px;bottom:14px;z-index:2147483000;
+  width:42px;height:42px;border-radius:50%;border:1px solid var(--na-line);
+  background:var(--na-bg);color:var(--na-fg);font-size:19px;cursor:pointer;
+  display:flex;align-items:center;justify-content:center;
+  box-shadow:0 4px 18px rgba(0,0,0,.45);transition:transform .15s}
+.na-launch:hover{transform:scale(1.08);border-color:var(--na-acc)}
+
+/* ---- left field/sort/group panel -------------------------------------- */
+.na-panel{position:fixed;left:0;top:0;bottom:0;width:290px;z-index:2147483001;
+  background:var(--na-bg);border-right:1px solid var(--na-line);color:var(--na-fg);
+  display:flex;flex-direction:column;font:13px/1.4 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
+  transform:translateX(-100%);transition:transform .2s ease;box-shadow:2px 0 24px rgba(0,0,0,.4)}
+.na-panel.open{transform:translateX(0)}
+.na-panel header{display:flex;align-items:center;gap:8px;padding:12px 14px;
+  border-bottom:1px solid var(--na-line);font-weight:600;letter-spacing:.3px}
+.na-panel header .na-title{flex:1}
+.na-panel header button{background:none;border:0;color:var(--na-mut);cursor:pointer;font-size:16px;padding:2px 6px;border-radius:4px}
+.na-panel header button:hover{color:var(--na-fg);background:rgba(255,255,255,.06)}
+.na-body{flex:1;overflow:auto;padding:8px 12px 40px}
+.na-sec{border-top:1px solid var(--na-line);padding:10px 0}
+.na-sec:first-child{border-top:0}
+.na-sec>.na-h{display:flex;align-items:center;gap:6px;cursor:pointer;
+  font-weight:600;color:var(--na-mut);text-transform:uppercase;font-size:11px;letter-spacing:.6px;user-select:none}
+.na-sec>.na-h::before{content:'▸';font-size:9px;transition:transform .15s}
+.na-sec.open>.na-h::before{transform:rotate(90deg)}
+.na-sec .na-c{display:none;padding:8px 2px 2px}
+.na-sec.open .na-c{display:block}
+.na-search{width:100%;box-sizing:border-box;background:var(--na-bg2);border:1px solid var(--na-line);
+  color:var(--na-fg);border-radius:6px;padding:8px 10px;margin:4px 0 10px;font-size:13px}
+.na-fieldrow{display:flex;align-items:center;gap:8px;padding:4px 2px;cursor:pointer;border-radius:4px}
+.na-fieldrow:hover{background:rgba(255,255,255,.04)}
+.na-fieldrow input{accent-color:var(--na-acc);cursor:pointer}
+.na-fieldrow .na-cnt{margin-left:auto;color:var(--na-mut);font-size:11px}
+.na-row{display:flex;gap:6px;align-items:center;margin:6px 0}
+.na-row label{color:var(--na-mut);min-width:52px}
+.na-row select,.na-row input[type=range]{flex:1;background:var(--na-bg2);border:1px solid var(--na-line);
+  color:var(--na-fg);border-radius:6px;padding:6px 8px;font-size:13px}
+.na-mini{display:flex;gap:6px;flex-wrap:wrap;margin-top:6px}
+.na-mini button{background:var(--na-bg2);border:1px solid var(--na-line);color:var(--na-fg);
+  border-radius:6px;padding:5px 9px;font-size:12px;cursor:pointer}
+.na-mini button:hover,.na-mini button.on{border-color:var(--na-acc);color:var(--na-acc)}
+.na-reset{width:100%;margin-top:14px;background:var(--na-bg2);border:1px solid var(--na-line);
+  color:var(--na-fg);border-radius:6px;padding:9px;cursor:pointer;font-size:13px}
+.na-reset:hover{border-color:#c0563f;color:#e08a76}
+.na-note{color:var(--na-mut);font-size:11px;padding:2px;line-height:1.5}
+
+/* ---- grouping headers injected into the grid -------------------------- */
+.na-group-h{grid-column:1/-1;display:flex;align-items:center;gap:8px;
+  padding:8px 4px;margin:6px 0 2px;border-bottom:1px solid var(--na-line);
+  color:var(--na-acc);font-weight:600;font-size:13px;cursor:pointer;user-select:none}
+.na-group-h .na-gcount{color:var(--na-mut);font-weight:400}
+.na-group-h.collapsed + .na-group-body{display:none}
+table .na-group-h{display:table-row}
+table .na-group-h td{padding:8px 6px;color:var(--na-acc);font-weight:600;border-bottom:1px solid var(--na-line)}
+
+/* ---- movable / resizable / removable data-panel chrome ---------------- */
+.na-wrap{position:relative}
+.na-bar{display:flex;align-items:center;gap:6px;padding:4px 8px;cursor:move;
+  background:var(--na-bg);border:1px solid var(--na-line);border-bottom:0;
+  border-radius:6px 6px 0 0;color:var(--na-mut);font-size:12px;user-select:none}
+.na-bar .na-bt{flex:1;font-weight:600;color:var(--na-fg)}
+.na-bar button{background:none;border:0;color:var(--na-mut);cursor:pointer;font-size:14px;padding:1px 5px;border-radius:4px}
+.na-bar button:hover{color:var(--na-fg);background:rgba(255,255,255,.08)}
+.na-wrap.na-float{position:fixed;z-index:2000;box-shadow:0 10px 40px rgba(0,0,0,.55);
+  background:var(--na-bg2);border-radius:6px;resize:both;overflow:auto;min-width:280px;min-height:160px}
+.na-wrap.na-collapsed .na-inner{display:none}
+.na-wrap.na-removed{display:none}
+.na-wrap.na-max{position:fixed;inset:12px;z-index:2001;background:var(--na-bg2);
+  box-shadow:0 10px 60px rgba(0,0,0,.6);overflow:auto;resize:none}
+.na-restorebar{position:fixed;left:14px;bottom:66px;z-index:2147483000;display:flex;flex-direction:column;gap:6px}
+.na-restorebar button{background:var(--na-bg);border:1px solid var(--na-line);color:var(--na-fg);
+  border-radius:6px;padding:6px 10px;font-size:12px;cursor:pointer}
+.na-restorebar button:hover{border-color:var(--na-acc)}
+
+@media (max-width:640px){.na-panel{width:86vw}}
diff --git a/public/nav-agent/nav-agent.js b/public/nav-agent/nav-agent.js
new file mode 100644
index 0000000..89119e2
--- /dev/null
+++ b/public/nav-agent/nav-agent.js
@@ -0,0 +1,433 @@
+/* ============================================================================
+ * Nav Agent — universal grid-controls drop-in  (v1.0)
+ *
+ * Drop one <script src=".../nav-agent.js" defer></script> (+ the CSS) onto any
+ * page. It auto-detects the primary data grid (a <table> or a .grid/.card list),
+ * then injects:
+ *   • a LEFT collapsible panel: text search, per-FIELD show/hide toggles,
+ *     sort-by-any-field (asc/desc), group-by-any-field, density slider
+ *   • movable / resizable / collapsible / removable / maximizable panel chrome
+ *     on the grid itself
+ * All state persists to localStorage, namespaced per page path, so every
+ * surface remembers its own layout. Strictly additive & wrapped in try/catch —
+ * if it can't understand a page it degrades (panel chrome + search + density)
+ * and never throws into the host page.
+ *
+ * Manual control:  window.NavAgent.mount({ target:'#grid', title:'Deals' })
+ * Opt-out a page:  <body data-nav-agent="off">
+ * Force a target:  <div id="grid" data-nav-grid> ... </div>
+ * ==========================================================================*/
+(function () {
+  'use strict';
+  if (window.NavAgent) return;
+
+  var _uid = 0;
+  var navKey = function (target) {
+    if (!target.getAttribute('data-na-uid')) target.setAttribute('data-na-uid', target.id || ('g' + (++_uid)));
+    return 'navagent:' + location.pathname + ':' + target.getAttribute('data-na-uid');
+  };
+  var load = function (key) { try { return JSON.parse(localStorage.getItem(key)) || {}; } catch (e) { return {}; } };
+  var save = function (key, s) { try { localStorage.setItem(key, JSON.stringify(s)); } catch (e) {} };
+  var slug = function (t) { return String(t || '').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') || 'f'; };
+  var txt = function (el) { return (el && el.textContent || '').trim(); };
+  // magnitude-aware numeric parse — $2.1B > $780M > 42.  Handles K/M/B/T + commas.
+  var num = function (v) {
+    var s = String(v).replace(/,/g, '').trim();
+    var m = s.match(/-?\d*\.?\d+/); if (!m) return null;
+    var n = parseFloat(m[0]); if (isNaN(n)) return null;
+    var suf = (s.slice(m.index + m[0].length).match(/[kmbt]/i) || [''])[0].toLowerCase();
+    var mult = { k: 1e3, m: 1e6, b: 1e9, t: 1e12 }[suf] || 1;
+    return n * mult;
+  };
+  var el = function (tag, cls, html) { var e = document.createElement(tag); if (cls) e.className = cls; if (html != null) e.innerHTML = html; return e; };
+
+  /* -- target detection -------------------------------------------------- */
+  function findTarget(opt) {
+    if (opt && opt.target) return document.querySelector(opt.target);
+    var q = document.querySelector('[data-nav-grid]');
+    if (q) return q;
+    // biggest visible table wins, else #grid, else first .grid, else .cards
+    var tables = [].slice.call(document.querySelectorAll('table'))
+      .filter(function (t) { return t.querySelector('tbody tr') && t.offsetParent !== null; })
+      .sort(function (a, b) { return b.querySelectorAll('tr').length - a.querySelectorAll('tr').length; });
+    if (tables[0] && tables[0].querySelectorAll('tr').length > 2) return tables[0];
+    return document.querySelector('#grid') || document.querySelector('.grid') ||
+           document.querySelector('.cards') || tables[0] || null;
+  }
+
+  /* -- field model ------------------------------------------------------- */
+  // Returns { kind:'table'|'cards', fields:[{key,label,idx?,cls?}], items() }
+  function model(target) {
+    if (target.tagName === 'TABLE') {
+      var ths = [].slice.call(target.querySelectorAll('thead th, thead td'));
+      if (!ths.length) { // header-less table: synthesize from first row
+        var r0 = target.querySelector('tbody tr, tr');
+        ths = r0 ? [].slice.call(r0.children).map(function (_, i) { var s = el('th'); s.textContent = 'Col ' + (i + 1); return s; }) : [];
+      }
+      var fields = ths.map(function (th, i) { return { key: slug(txt(th)) + '-' + i, label: txt(th) || ('Col ' + (i + 1)), idx: i }; });
+      return {
+        kind: 'table', fields: fields,
+        rows: function () { return [].slice.call(target.querySelectorAll('tbody tr')).filter(function (r) { return !r.classList.contains('na-group-h'); }); },
+        cellText: function (row, f) { var c = row.children[f.idx]; return txt(c); }
+      };
+    }
+    // card grid — infer fields from repeated child element classes / [data-field]
+    var cards = [].slice.call(target.children).filter(function (c) { return c.nodeType === 1 && !c.classList.contains('na-group-h') && !c.classList.contains('na-group-body'); });
+    var sample = cards.slice(0, 24), seen = {}, order = [];
+    sample.forEach(function (card) {
+      [].slice.call(card.querySelectorAll('[data-field]')).forEach(function (n) {
+        var k = n.getAttribute('data-field'); if (!seen[k]) { seen[k] = { key: slug(k), label: k, cls: '[data-field="' + k + '"]', df: k, hits: 0 }; order.push(seen[k]); } seen[k].hits++;
+      });
+      // also collect direct-child element classes as coarse fields when no data-field present
+      [].slice.call(card.children).forEach(function (n) {
+        var cls = (n.className && typeof n.className === 'string') ? n.className.split(/\s+/)[0] : '';
+        if (!cls || cls.indexOf('na-') === 0) return;
+        var k = 'c-' + cls;
+        if (!seen[k]) { seen[k] = { key: slug(cls), label: cls.replace(/[-_]/g, ' '), cls: '.' + cls, hits: 0 }; order.push(seen[k]); } seen[k].hits++;
+      });
+    });
+    // keep fields present on a majority of sampled cards (stable structure)
+    var min = Math.max(1, Math.floor(sample.length * 0.4));
+    var fields = order.filter(function (f) { return f.hits >= min; });
+    return {
+      kind: 'cards', cards: true, fields: fields,
+      rows: function () { return [].slice.call(target.children).filter(function (c) { return c.nodeType === 1 && !c.classList.contains('na-group-h') && !c.classList.contains('na-group-body') && c.offsetParent !== null || (c.nodeType === 1 && !c.classList.contains('na-group-h')); }); },
+      cellText: function (card, f) { var n = f.df ? card.querySelector('[data-field="' + f.df + '"]') : card.querySelector(f.cls); return txt(n); }
+    };
+  }
+
+  /* -- one instance ------------------------------------------------------ */
+  function Agent(target, opt) {
+    var key = navKey(target);
+    var st = load(key);
+    var M = model(target);
+    var self = { target: target, model: M, state: st, key: key };
+    var applyingSort = false;
+
+    /* field show/hide via CONTAINER classes (survives host re-renders) */
+    function fieldStyleTag() {
+      var id = 'na-style-' + key.replace(/[^a-z0-9]/gi, '');
+      var tag = document.getElementById(id) || (function () { var t = el('style'); t.id = id; document.head.appendChild(t); return t; })();
+      var css = '';
+      (st.hidden || []).forEach(function (key) {
+        var f = M.fields.filter(function (x) { return x.key === key; })[0]; if (!f) return;
+        if (M.kind === 'table') {
+          css += 'table[data-na] thead th:nth-child(' + (f.idx + 1) + '),table[data-na] tbody td:nth-child(' + (f.idx + 1) + '){display:none}';
+        } else {
+          css += target.getAttribute('data-na-sel') + ' ' + f.cls + '{display:none}';
+        }
+      });
+      tag.textContent = css;
+    }
+
+    function applySort() {
+      if (!st.sort) return;
+      var f = M.fields.filter(function (x) { return x.key === st.sort; })[0]; if (!f) return;
+      var dir = st.dir === 'desc' ? -1 : 1;
+      var rows = M.rows();
+      if (!rows.length) return;
+      applyingSort = true;
+      // detect numeric
+      var numeric = rows.slice(0, 12).every(function (r) { var v = M.cellText(r, f); return v === '' || num(v) !== null; });
+      rows.sort(function (a, b) {
+        var va = M.cellText(a, f), vb = M.cellText(b, f);
+        if (numeric) { var na = num(va), nb = num(vb); na = na == null ? -Infinity : na; nb = nb == null ? -Infinity : nb; return (na - nb) * dir; }
+        return va.localeCompare(vb, undefined, { numeric: true }) * dir;
+      });
+      var parent = M.kind === 'table' ? target.querySelector('tbody') : target;
+      rows.forEach(function (r) { parent.appendChild(r); });
+      applyGroup(); // grouping depends on sorted order
+      applyingSort = false;
+    }
+
+    function clearGroups() {
+      [].slice.call(target.querySelectorAll('.na-group-h')).forEach(function (n) { n.remove(); });
+    }
+
+    function applyGroup() {
+      clearGroups();
+      if (!st.group) return;
+      var f = M.fields.filter(function (x) { return x.key === st.group; })[0]; if (!f) return;
+      var rows = M.rows(), last = null, parent = M.kind === 'table' ? target.querySelector('tbody') : target;
+      var counts = {};
+      rows.forEach(function (r) { var v = M.cellText(r, f) || '—'; counts[v] = (counts[v] || 0) + 1; });
+      rows.forEach(function (r) {
+        var v = M.cellText(r, f) || '—';
+        if (v !== last) {
+          var h;
+          if (M.kind === 'table') { h = el('tr', 'na-group-h'); var td = el('td'); td.colSpan = M.fields.length; td.innerHTML = '▸ ' + esc(v) + ' <span class="na-gcount">(' + counts[v] + ')</span>'; h.appendChild(td); }
+          else { h = el('div', 'na-group-h', '▸ ' + esc(v) + ' <span class="na-gcount">(' + counts[v] + ')</span>'); }
+          parent.insertBefore(h, r); last = v;
+        }
+      });
+    }
+
+    function applySearch() {
+      var qraw = (st.q || '').toLowerCase();
+      M.rows().forEach(function (r) {
+        var show = !qraw || r.textContent.toLowerCase().indexOf(qraw) >= 0;
+        r.style.display = show ? '' : 'none';
+      });
+    }
+
+    function applyAll() { fieldStyleTag(); applySort(); applySearch(); }
+
+    /* re-apply after host re-renders (debounced, ignores our own mutations).
+       If the FIELD SET changed (async data arrived, filter repopulated), tell
+       mount() to rebuild the panel UI. */
+    function fieldSig(m) { return m.kind + ':' + m.fields.map(function (f) { return f.key; }).join(','); }
+    var sig = fieldSig(M);
+    var t;
+    var mo = new MutationObserver(function () {
+      if (applyingSort) return;
+      clearTimeout(t); t = setTimeout(function () {
+        M = model(target); self.model = M;
+        var ns = fieldSig(M);
+        if (ns !== sig) { sig = ns; if (self.onFields) try { self.onFields(); } catch (e) {} }
+        applyAll();
+      }, 140);
+    });
+    try { mo.observe(M.kind === 'table' ? (target.querySelector('tbody') || target) : target, { childList: true }); } catch (e) {}
+
+    self.applyAll = applyAll;
+    self.applySort = applySort;
+    self.applyGroup = applyGroup;
+    self.applySearch = applySearch;
+    self.save = function () { save(key, st); };
+    return self;
+  }
+
+  function esc(s) { return String(s).replace(/[&<>"]/g, function (c) { return ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' })[c]; }); }
+
+  /* -- panel UI ---------------------------------------------------------- */
+  function buildPanel(agent, opt) {
+    var M = agent.model, st = agent.state;
+    var panel = el('aside', 'na-panel');
+    panel.setAttribute('role', 'dialog'); panel.setAttribute('aria-label', 'View controls');
+    var title = (opt && opt.title) || document.title || 'View';
+    panel.appendChild(el('header', null,
+      '<span class="na-title">⚙ View · ' + esc(title) + '</span>' +
+      '<button class="na-x" title="Close">✕</button>'));
+    var body = el('div', 'na-body'); panel.appendChild(body);
+
+    // search
+    var search = el('input', 'na-search'); search.type = 'search'; search.placeholder = 'Search all fields…';
+    search.value = st.q || '';
+    search.addEventListener('input', function () { st.q = search.value; agent.save(); agent.applySearch(); });
+    body.appendChild(search);
+
+    function section(label, openDefault) {
+      var s = el('div', 'na-sec' + (openDefault ? ' open' : ''));
+      s.appendChild(el('div', 'na-h', label));
+      var c = el('div', 'na-c'); s.appendChild(c);
+      s.querySelector('.na-h').addEventListener('click', function () { s.classList.toggle('open'); });
+      body.appendChild(s); return c;
+    }
+
+    var haveFields = M.fields && M.fields.length;
+
+    // FIELDS toggle
+    if (haveFields) {
+      var fc = section('Fields (' + M.fields.length + ')', true);
+      st.hidden = st.hidden || [];
+      M.fields.forEach(function (f) {
+        var row = el('label', 'na-fieldrow');
+        var cb = el('input'); cb.type = 'checkbox'; cb.checked = st.hidden.indexOf(f.key) < 0;
+        cb.addEventListener('change', function () {
+          var i = st.hidden.indexOf(f.key);
+          if (cb.checked && i >= 0) st.hidden.splice(i, 1);
+          else if (!cb.checked && i < 0) st.hidden.push(f.key);
+          agent.save(); agent.applyAll();
+        });
+        row.appendChild(cb);
+        row.appendChild(el('span', null, esc(f.label)));
+        fc.appendChild(row);
+      });
+      var mini = el('div', 'na-mini',
+        '<button data-all>All</button><button data-none>None</button>');
+      mini.querySelector('[data-all]').onclick = function () { st.hidden = []; agent.save(); agent.applyAll(); refreshChecks(); };
+      mini.querySelector('[data-none]').onclick = function () { st.hidden = M.fields.map(function (f) { return f.key; }); agent.save(); agent.applyAll(); refreshChecks(); };
+      fc.appendChild(mini);
+      function refreshChecks() { [].slice.call(fc.querySelectorAll('.na-fieldrow input')).forEach(function (cb, i) { cb.checked = st.hidden.indexOf(M.fields[i].key) < 0; }); }
+    }
+
+    // SORT
+    if (haveFields) {
+      var sc = section('Sort', true);
+      var srow = el('div', 'na-row', '<label>Field</label>');
+      var sel = el('select'); sel.appendChild(new Option('— none —', ''));
+      M.fields.forEach(function (f) { sel.appendChild(new Option(f.label, f.key)); });
+      sel.value = st.sort || ''; srow.appendChild(sel); sc.appendChild(srow);
+      var dir = el('div', 'na-mini', '<button data-asc>▲ Asc</button><button data-desc>▼ Desc</button>');
+      function markDir() { dir.querySelector('[data-asc]').classList.toggle('on', st.dir !== 'desc'); dir.querySelector('[data-desc]').classList.toggle('on', st.dir === 'desc'); }
+      sel.addEventListener('change', function () { st.sort = sel.value; agent.save(); agent.applySort(); });
+      dir.querySelector('[data-asc]').onclick = function () { st.dir = 'asc'; markDir(); agent.save(); agent.applySort(); };
+      dir.querySelector('[data-desc]').onclick = function () { st.dir = 'desc'; markDir(); agent.save(); agent.applySort(); };
+      markDir(); sc.appendChild(dir);
+    }
+
+    // GROUP
+    if (haveFields) {
+      var gc = section('Group by', false);
+      var grow = el('div', 'na-row', '<label>Field</label>');
+      var gsel = el('select'); gsel.appendChild(new Option('— none —', ''));
+      M.fields.forEach(function (f) { gsel.appendChild(new Option(f.label, f.key)); });
+      gsel.value = st.group || ''; grow.appendChild(gsel); gc.appendChild(grow);
+      gsel.addEventListener('change', function () { st.group = gsel.value; agent.save(); agent.applyGroup(); });
+    }
+
+    // DENSITY (only if the target reacts to --cols or has a page density var)
+    var dc = section('Density', false);
+    var drow = el('div', 'na-row', '<label>Cols</label>');
+    var rng = el('input'); rng.type = 'range'; rng.min = 2; rng.max = 12; rng.value = st.cols || getComputedCols(agent.target) || 5;
+    rng.addEventListener('input', function () { st.cols = +rng.value; agent.save(); setCols(agent.target, +rng.value); });
+    drow.appendChild(rng); dc.appendChild(drow);
+    dc.appendChild(el('div', 'na-note', 'Adjusts grid columns where the layout supports it.'));
+    if (st.cols) setCols(agent.target, st.cols);
+
+    if (!haveFields) body.appendChild(el('div', 'na-note',
+      'No structured fields detected on this grid — field toggles, sort & group need <code>&lt;table&gt;</code> headers or <code>[data-field]</code>/classed card elements. Search, density and the movable panel are active.'));
+
+    var reset = el('button', 'na-reset', '↺ Reset this page’s view');
+    reset.onclick = function () { try { localStorage.removeItem(agent.key); } catch (e) {} location.reload(); };
+    body.appendChild(reset);
+
+    panel.querySelector('.na-x').onclick = function () { panel.classList.remove('open'); };
+    document.body.appendChild(panel);
+    return panel;
+  }
+
+  function getComputedCols(t) { try { var v = getComputedStyle(t).getPropertyValue('--cols'); return v ? parseInt(v) : null; } catch (e) { return null; } }
+  function setCols(t, n) {
+    try {
+      t.style.setProperty('--cols', n);
+      // fallback for grids without a --cols hook
+      if (!/grid-template-columns/.test(t.style.cssText) && getComputedStyle(t).display === 'grid')
+        t.style.gridTemplateColumns = 'repeat(' + n + ',minmax(0,1fr))';
+    } catch (e) {}
+  }
+
+  /* -- movable / resizable / removable panel chrome ---------------------- */
+  function chrome(agent, opt) {
+    var t = agent.target;
+    if (t.closest('.na-wrap')) return;
+    var wrap = el('div', 'na-wrap');
+    var title = (opt && opt.title) || document.title || 'Data';
+    var bar = el('div', 'na-bar',
+      '<span class="na-bt">▤ ' + esc(title) + '</span>' +
+      '<button data-collapse title="Collapse">▁</button>' +
+      '<button data-max title="Maximize / float">⤢</button>' +
+      '<button data-remove title="Remove panel">✕</button>');
+    var inner = el('div', 'na-inner');
+    t.parentNode.insertBefore(wrap, t);
+    wrap.appendChild(bar); wrap.appendChild(inner); inner.appendChild(t);
+
+    var g = agent.state.geo || {};
+    bar.querySelector('[data-collapse]').onclick = function () { wrap.classList.toggle('na-collapsed'); persist(); };
+    bar.querySelector('[data-max]').onclick = function () { wrap.classList.toggle('na-max'); wrap.classList.remove('na-float'); persist(); };
+    bar.querySelector('[data-remove]').onclick = function () { wrap.classList.add('na-removed'); addRestore(); persist(); };
+
+    // drag to float/move
+    var down = null;
+    bar.addEventListener('mousedown', function (e) {
+      if (e.target.tagName === 'BUTTON') return;
+      var r = wrap.getBoundingClientRect();
+      if (!wrap.classList.contains('na-float')) { wrap.classList.add('na-float'); wrap.style.left = r.left + 'px'; wrap.style.top = r.top + 'px'; wrap.style.width = r.width + 'px'; }
+      down = { x: e.clientX, y: e.clientY, l: parseFloat(wrap.style.left) || r.left, t: parseFloat(wrap.style.top) || r.top };
+      e.preventDefault();
+    });
+    window.addEventListener('mousemove', function (e) {
+      if (!down) return;
+      wrap.style.left = (down.l + e.clientX - down.x) + 'px';
+      wrap.style.top = Math.max(0, down.t + e.clientY - down.y) + 'px';
+    });
+    window.addEventListener('mouseup', function () { if (down) { down = null; persist(); } });
+
+    function persist() {
+      agent.state.geo = {
+        float: wrap.classList.contains('na-float'), max: wrap.classList.contains('na-max'),
+        collapsed: wrap.classList.contains('na-collapsed'), removed: wrap.classList.contains('na-removed'),
+        left: wrap.style.left, top: wrap.style.top, width: wrap.style.width, height: wrap.style.height
+      };
+      agent.save();
+    }
+    function addRestore() {
+      var rb = document.querySelector('.na-restorebar') || (function () { var b = el('div', 'na-restorebar'); document.body.appendChild(b); return b; })();
+      var btn = el('button', null, '⟲ ' + esc(title));
+      btn.onclick = function () { wrap.classList.remove('na-removed'); btn.remove(); persist(); };
+      rb.appendChild(btn);
+    }
+    // restore saved geometry
+    if (g.float) { wrap.classList.add('na-float'); ['left', 'top', 'width', 'height'].forEach(function (k) { if (g[k]) wrap.style[k] = g[k]; }); }
+    if (g.max) wrap.classList.add('na-max');
+    if (g.collapsed) wrap.classList.add('na-collapsed');
+    if (g.removed) { wrap.classList.add('na-removed'); addRestore(); }
+  }
+
+  /* -- public mount ------------------------------------------------------ */
+  var API = {
+    instances: [],
+    mount: function (opt) {
+      opt = opt || {};
+      try {
+        var target = findTarget(opt);
+        if (!target) return null;
+        if (target.__naMounted) return target.__naAgent;
+        target.__naMounted = true;
+        if (target.tagName === 'TABLE') target.setAttribute('data-na', '1');
+        else target.setAttribute('data-na-sel', target.id ? '#' + target.id : '.' + (target.className.split(/\s+/)[0] || 'grid'));
+        var agent = Agent(target, opt);
+        target.__naAgent = agent;
+        // (re)build the panel — called again by the observer when fields change
+        function makePanel() {
+          var wasOpen = agent._panel && agent._panel.classList.contains('open');
+          if (agent._panel) agent._panel.remove();
+          agent._panel = buildPanel(agent, opt);
+          if (wasOpen) agent._panel.classList.add('open');
+        }
+        agent.onFields = makePanel;
+        makePanel();
+        chrome(agent, opt);
+        agent.applyAll();
+
+        // single launcher toggles every panel on the page
+        if (!document.querySelector('.na-launch')) {
+          var b = el('button', 'na-launch', '⚙'); b.title = 'View controls';
+          b.onclick = function () {
+            var anyOpen = document.querySelector('.na-panel.open');
+            [].slice.call(document.querySelectorAll('.na-panel')).forEach(function (p) { p.classList.toggle('open', !anyOpen); });
+          };
+          document.body.appendChild(b);
+        }
+        API.instances.push(agent);
+        return agent;
+      } catch (e) { if (window.console) console.warn('[nav-agent] mount skipped:', e); return null; }
+    }
+  };
+  window.NavAgent = API;
+
+  function boot() {
+    try {
+      var body = document.body;
+      if (!body || body.getAttribute('data-nav-agent') === 'off') return;
+      // wait a tick for API-driven grids to render their first batch
+      var tries = 0;
+      (function attempt() {
+        var t = findTarget();
+        var populated = false;
+        if (t) {
+          if (t.tagName === 'TABLE') populated = !!t.querySelector('tbody tr');
+          else {
+            var kids = [].slice.call(t.children).filter(function (c) { return c.nodeType === 1; });
+            // ignore an empty-state placeholder (a lone div, often "No … match")
+            populated = !!t.querySelector('.card') || kids.length >= 2;
+          }
+        }
+        if (populated || tries++ > 32) { API.mount(); return; } // mount anyway after ~8s; observer fills fields when data arrives
+        setTimeout(attempt, 250);
+      })();
+    } catch (e) {}
+  }
+  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot);
+  else boot();
+})();
diff --git a/public/parcel.html b/public/parcel.html
index 2be28a3..7fc4c3e 100644
--- a/public/parcel.html
+++ b/public/parcel.html
@@ -38,7 +38,8 @@ a.ext{color:var(--blue);text-decoration:none}a.ext:hover{text-decoration:underli
 .full{grid-column:1/-1}
 .loading{color:var(--mut);padding:40px 0}
 .err{color:var(--bad);padding:24px 0}
-</style></head><body>
+</style>  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
+</head><body>
 <header>
   <h1><b>Parcel Detail</b> · CRCP</h1>
   <span class="pill county">100% public record</span>
@@ -154,4 +155,5 @@ function render(d){
 load();
 </script>
 <script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body></html>
diff --git a/public/rent-rolls.html b/public/rent-rolls.html
index 218002b..d421827 100644
--- a/public/rent-rolls.html
+++ b/public/rent-rolls.html
@@ -110,6 +110,7 @@
   #modal .x{position:absolute;top:12px;right:14px;background:none;border:0;color:var(--muted);font-size:22px;cursor:pointer;z-index:2;}
   .hide{display:none;}
 </style>
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <div class="wrap">
@@ -435,5 +436,6 @@ fetch('/api/rent-rolls').then(r=>r.json()).then(d=>{
   <script src="/global-search.js" defer></script>
   <script src="/sort-bar.js" defer></script>
 <script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/sales.html b/public/sales.html
index 4b30313..68688e5 100644
--- a/public/sales.html
+++ b/public/sales.html
@@ -84,6 +84,7 @@
   .rail .rsec.collapsed > h4::after { transform:rotate(-90deg); }
   .rail .rsec.collapsed > *:not(h4) { display:none !important; }
 </style>
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <header>
@@ -412,5 +413,6 @@ fetch('/api/closed-sales?limit=5000').then(r=>r.json()).then(d=>{
   <script src="/global-search.js" defer></script>
   <script src="/sort-bar.js" defer></script>
 <script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>
diff --git a/public/sba-lenders.html b/public/sba-lenders.html
index ce8cc80..a3579b5 100644
--- a/public/sba-lenders.html
+++ b/public/sba-lenders.html
@@ -6,6 +6,7 @@
 <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Crect width='16' height='16' rx='3' fill='%230c0f15'/%3E%3Ctext x='8' y='12' font-size='9' text-anchor='middle' fill='%23C8A24B'%3E%F0%9F%92%BC%3C/text%3E%3C/svg%3E">
 <title>SBA Lenders — 7(a) &amp; 504 originators (CA · LA breakout)</title>
 <link rel="stylesheet" href="/lending-grid.css">
+  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head>
 <body>
 <header>
@@ -73,5 +74,6 @@ window.GRID_CONFIG = {
 <script src="/lending-grid.js" defer></script>
 <script src="/col-resize.js" defer></script>
 <script src="/corner-nav.js" defer></script>
+  <script src="/nav-agent/nav-agent.js" defer></script><!-- nav-agent -->
 </body>
 </html>

← 3fd8465 auto-data-snapshot: 2026-08-13T07:20:35 (1 data files) — dat  ·  back to Commercialrealestate  ·  condos.html: add compact-list view (3rd mode) + shared three badc059 →