← back to Commercialrealestate
TK-10330 CRCP flagship layout redesign — industry-grade (Four Horsemen/graphic-agent panel)
86a0499b6cfa33a2cd0f4771f1969b1a57660382 · 2026-08-08 07:51:10 -0700 · Steve Abrams
Additive override layer on crcp.html (preserves every JS-bound ID; reversible):
- honest cold-load: skeleton KPI tiles (never-blank strip) + amber reconnecting
pulse + 'can't reach server' banner (was: green 'live' pulse over empty panels)
- fresh session lands useful: opens the primary deal-sourcing panels
(Call Segments -> Top Brokers -> Top Firms -> FHA Expiring) instead of a wall
of collapsed drawers; returning users keep saved layout
- terminal chrome: panel radius 13->5px + gold category left-rail, muted section
headers w/ rule (was shouting gold all-caps), color-railed KPI tiles 30->26px
- tables: header rail + zebra + row hover + discoverable sort (up-down) hint
- compact single-line header, nav muted w/ gold active state
Verified in Day + Night, 0 console errors. Deploy to Kamatera stays Steve-gated.
Files touched
Diff
commit 86a0499b6cfa33a2cd0f4771f1969b1a57660382
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sat Aug 8 07:51:10 2026 -0700
TK-10330 CRCP flagship layout redesign — industry-grade (Four Horsemen/graphic-agent panel)
Additive override layer on crcp.html (preserves every JS-bound ID; reversible):
- honest cold-load: skeleton KPI tiles (never-blank strip) + amber reconnecting
pulse + 'can't reach server' banner (was: green 'live' pulse over empty panels)
- fresh session lands useful: opens the primary deal-sourcing panels
(Call Segments -> Top Brokers -> Top Firms -> FHA Expiring) instead of a wall
of collapsed drawers; returning users keep saved layout
- terminal chrome: panel radius 13->5px + gold category left-rail, muted section
headers w/ rule (was shouting gold all-caps), color-railed KPI tiles 30->26px
- tables: header rail + zebra + row hover + discoverable sort (up-down) hint
- compact single-line header, nav muted w/ gold active state
Verified in Day + Night, 0 console errors. Deploy to Kamatera stays Steve-gated.
---
public/crcp.html | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 106 insertions(+), 1 deletion(-)
diff --git a/public/crcp.html b/public/crcp.html
index 022161f..de31976 100644
--- a/public/crcp.html
+++ b/public/crcp.html
@@ -143,6 +143,67 @@
html[data-theme="dark"] { --panel:var(--card); --panel2:var(--bg2); --fg:var(--ink); }
html[data-theme="light"] { --panel:var(--card); --panel2:var(--bg2); --fg:var(--ink); }
</style>
+<style>
+ /* ── TK-10330: industry-grade layout redesign (override layer) ──────────────
+ Loads LAST, so these rules win by cascade order. Additive + fully reversible;
+ preserves every JS-bound ID/DOM hook. Builds on the shared day/night tokens.
+ Design consensus: graphic-designer + ui-ux-designer panels — move from
+ "consumer card app" toward a CoStar/Crexi/Bloomberg-tier deal terminal. */
+
+ /* — Header: compact single-line toolbar, differentiated zones — */
+ header{padding:0 22px;min-height:46px;gap:12px;border-bottom:2px solid var(--line);background:var(--headbg,var(--bg));backdrop-filter:saturate(1.1) blur(6px);}
+ header h1{font-size:15px;font-weight:700;letter-spacing:.2px;white-space:nowrap;}
+ header h1 b{color:var(--gold);}
+ header h1::after{content:'';display:inline-block;width:1px;height:15px;background:var(--line);margin:0 4px 0 12px;vertical-align:-2px;}
+ header .nav a{color:var(--muted);font-size:12.5px;font-weight:500;}
+ header .nav a:hover{color:var(--ink,var(--fg));}
+ header .nav a.active{color:var(--gold);font-weight:600;}
+ .live{font-size:11.5px;}
+ .expandall{border-radius:5px;padding:5px 10px;font-size:11.5px;}
+
+ /* — Panels: terminal radius + gold category rail + muted section headers — */
+ .panel{border-radius:5px;border-left:2px solid var(--gold);margin-bottom:12px;padding:14px 16px;}
+ .panel h3{font-size:11px;font-weight:600;letter-spacing:.5px;color:var(--muted);
+ border-bottom:1px solid var(--line);padding-bottom:9px;margin-bottom:11px;align-items:center;}
+ .panel h3 .caret{color:var(--gold);}
+ .panel h3 .c{font-size:10.5px;}
+
+ /* — KPI tiles: color-coded top rail, tighter terminal density — */
+ .tiles{gap:11px;margin-bottom:16px;}
+ .tile{border-radius:6px;padding:12px 14px;border-top:2px solid var(--line);}
+ .tile.gold{border-top-color:var(--gold);}
+ .tile.active{border-top-color:var(--active);}
+ .tile.draft{border-top-color:var(--draft);}
+ .tile.staged{border-top-color:var(--staged);}
+ .tile .k{font-size:10px;letter-spacing:.7px;font-weight:600;}
+ .tile .v{font-size:26px;line-height:1.08;margin-top:2px;}
+ .tile .sub{font-size:10px;margin-top:1px;}
+ /* persistent (not hover-only) drill affordance so it's discoverable */
+ .tile.clickable::after{opacity:.3;}
+ .tile.clickable:hover::after{opacity:1;}
+
+ /* — Tables: header rail, zebra, hover, discoverable sort affordance — */
+ td,th{padding:7px 8px;}
+ th{font-size:10px;letter-spacing:.5px;}
+ #segTbl thead th,#brTbl thead th,#fmTbl thead th,#xpTbl thead th{
+ background:var(--bg2,transparent);border-bottom:1px solid var(--line);}
+ /* sort affordance is already owned by the page's native th.srt.asc/.desc glyphs
+ + col-resize.js's .cr-sort span — do NOT add an idle ::after here or it double-renders */
+ #segTbl tbody tr:nth-child(even) td,#brTbl tbody tr:nth-child(even) td,
+ #fmTbl tbody tr:nth-child(even) td{background:var(--stripe,transparent);}
+ #segTbl tbody tr:hover td,#brTbl tbody tr:hover td,
+ #fmTbl tbody tr:hover td,#xpTbl tbody tr:hover td{background:var(--hover,rgba(121,184,255,.10));}
+
+ /* — Loading / connection state: skeleton shimmer + honest pulse — */
+ @keyframes crcpShimmer{0%{opacity:.45}50%{opacity:.9}100%{opacity:.45}}
+ .tile.skel .v{color:transparent;background:var(--line);border-radius:4px;height:24px;width:62%;margin-top:5px;animation:crcpShimmer 1.3s ease-in-out infinite;}
+ .tile.skel .sub{color:transparent;background:var(--line);border-radius:3px;height:8px;width:75%;margin-top:6px;opacity:.5;}
+ .pulse.reconnecting{background:var(--gold);animation:pWarn 1.6s infinite;}
+ @keyframes pWarn{0%{box-shadow:0 0 0 0 rgba(200,162,75,.55)}70%{box-shadow:0 0 0 9px rgba(200,162,75,0)}100%{box-shadow:0 0 0 0 rgba(200,162,75,0)}}
+ #crcpConnBanner{display:none;margin:0 0 14px;background:rgba(231,76,60,.10);border:1px solid var(--del);
+ border-radius:6px;padding:9px 13px;font-size:12.5px;color:var(--del);}
+ #crcpConnBanner.show{display:block;}
+</style>
</head>
<body>
<header>
@@ -581,13 +642,22 @@ async function poll(){
dens.addEventListener('input',()=>{ document.documentElement.style.setProperty('--tilemin', dens.value+'px'); localStorage.setItem(LS_DENS, dens.value); });
// which panels were left open last time (default: ALL collapsed)
let open; try{ open=new Set(JSON.parse(localStorage.getItem(LS_OPEN)||'[]')); }catch(e){ open=new Set(); }
+ const fresh = localStorage.getItem(LS_OPEN)===null; // no saved layout yet (TK-10330)
const save=()=>localStorage.setItem(LS_OPEN, JSON.stringify([...open]));
const panels=[...document.querySelectorAll('.panel')];
panels.forEach((p,i)=>{
const h=p.querySelector('h3'); if(!h) return;
const key=h.textContent.trim().slice(0,40)||('p'+i); p.dataset.pk=key;
if(!h.querySelector('.caret')){ const c=document.createElement('span'); c.className='caret'; c.textContent='▸'; h.prepend(c); }
- if(!open.has(key)) p.classList.add('collapsed'); // start collapsed until activated
+ // TK-10330: land useful, not a wall of closed drawers. On a FRESH session open the
+ // primary deal-sourcing workflow panels (segments -> call list -> firms -> urgency);
+ // returning users keep whatever layout they saved.
+ if(fresh){
+ const KT=key.toLowerCase();
+ const seedOpen = KT.includes('call segments')||KT.includes('top brokers')||KT.includes('top firms')||KT.includes('fha approval expiring');
+ if(seedOpen) open.add(key); else p.classList.add('collapsed');
+ }
+ else if(!open.has(key)) p.classList.add('collapsed'); // start collapsed until activated
h.addEventListener('click',()=>{
p.classList.toggle('collapsed');
if(p.classList.contains('collapsed')) open.delete(key); else open.add(key);
@@ -827,5 +897,40 @@ loadSegments(); setInterval(loadSegments, 20000);
document.addEventListener('DOMContentLoaded',wireToggle);
})();
</script>
+<script>
+// ── TK-10330: honest loading / connection state ────────────────────────────
+// The cold-load used to read as "broken": empty KPI strip + empty panels while a
+// green "live" pulse sat next to "reconnecting…". This adds (a) skeleton KPI tiles
+// so the strip is never blank, (b) a real error banner, and (c) an honest amber
+// pulse while reconnecting. Purely additive — poll() still owns the real render.
+(function(){
+ function seedSkeletonTiles(){
+ var t=document.getElementById('tiles');
+ if(!t || t.children.length) return; // poll() already filled it
+ var labels=['Listings','Brokers','Firms','Condos','Res. agents','FHA-approved','Broker edges'];
+ var cls=['gold','active','draft','staged','draft','active','gold'];
+ t.innerHTML=labels.map(function(k,i){
+ return '<div class="tile skel '+cls[i]+'"><div class="k">'+k+'</div><div class="v">—</div><div class="sub"> </div></div>';
+ }).join('');
+ }
+ function ensureBanner(){
+ var w=document.querySelector('.wrap'); if(!w) return null;
+ var b=document.getElementById('crcpConnBanner');
+ if(!b){ b=document.createElement('div'); b.id='crcpConnBanner';
+ b.textContent='⚠ Can’t reach the server — showing the last known data. Retrying…';
+ w.insertBefore(b, w.firstChild); }
+ return b;
+ }
+ function tick(){
+ var lt=document.getElementById('livetxt'); var pulse=document.querySelector('.pulse'); var b=ensureBanner();
+ var reconnecting = lt && /reconnect/i.test(lt.textContent||'');
+ if(pulse) pulse.classList.toggle('reconnecting', !!reconnecting);
+ if(b) b.classList.toggle('show', !!reconnecting);
+ // once real tiles arrive, the skeleton class is naturally gone (poll replaces innerHTML)
+ }
+ function start(){ seedSkeletonTiles(); tick(); setInterval(tick, 1500); }
+ if(document.readyState==='loading') document.addEventListener('DOMContentLoaded',start); else start();
+})();
+</script>
</body>
</html>
← af6cf04 TK-10358 yoloforever c2 Cody-gate fix: repair IREA row unquo
·
back to Commercialrealestate
·
auto-data-snapshot: 2026-08-08T07:55:02 (9 data files) — .pl 6c1cc89 →