diff --git a/server/public/home.html b/server/public/home.html
index aff5ed3..501954e 100644
--- a/server/public/home.html
+++ b/server/public/home.html
@@ -120,6 +120,10 @@
.dir-row .dr-main{display:flex;flex-direction:column;min-width:0;flex:1;}
.dir-row .dr-sub{font-size:.74rem;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.dir-row .dr-tag{font-size:.62rem;font-weight:700;color:#92600b;background:#fff3cd;border-radius:99px;padding:.1rem .4rem;flex:0 0 auto;}
+ .dir-empty{display:flex;gap:.55rem;align-items:flex-start;margin:.5rem .9rem;padding:.6rem .7rem;background:#f6f8fc;border:1px solid var(--line);border-radius:10px;color:var(--muted);}
+ .dir-empty svg{flex:0 0 auto;margin-top:.05rem;color:var(--blue);}
+ .dir-empty b{display:block;font-size:.82rem;color:var(--ink);margin-bottom:.1rem;}
+ .dir-empty span{font-size:.74rem;line-height:1.35;}
/* Chat-list header (now the app's top area — the blue bar is gone). */
.side-head{padding:.85rem 1rem .75rem;border-bottom:1px solid var(--line);background:linear-gradient(180deg,#f3f7fd 0%,var(--card) 100%);}
.side-title{display:flex;align-items:center;justify-content:space-between;gap:.5rem;margin-bottom:.7rem;}
@@ -856,7 +860,7 @@
-
@@ -1413,11 +1417,22 @@ function queryDirectory(q){
if(seq!==_dirSeq) return; // a newer search superseded this one
const box=document.getElementById('dirResults'); if(!box) return;
const haveEmail=new Set(CONTACTS.map(c=>(c.email||'').toLowerCase()).filter(Boolean));
- const ext=(Array.isArray(list)?list:[]).filter(p=>!(p.email&&haveEmail.has(p.email.toLowerCase()))); // hide dups of team contacts
- if(!ext.length){ box.innerHTML=''; return; }
- box.innerHTML='On BizGaze
'+ext.map((p,i)=>{ const sub=[p.org,p.phone].filter(Boolean).join(' · ');
- return ''+pEsc(initials(p.name||'?'))+''+pEsc(p.name||p.email||'Unknown')+''+(sub?''+pEsc(sub)+'':'')+''+(p.onConnect?'':'Not on Connect')+'
'; }).join('');
- box.querySelectorAll('.dir-row').forEach(row=>{ const p=ext[+row.dataset.i]; row.onclick=()=>{ if(p.onConnect&&p.connectId) selectChat('dm', p.connectId); else toast(pEsc(p.name||'This person')+' is on BizGaze but hasn’t joined Connect yet — they’ll be reachable once they sign in.'); }; });
+ const all=Array.isArray(list)?list:[];
+ // Only people actually ON Connect can be messaged — show just those (deduped against team contacts).
+ // Everyone else (on BizGaze but not signed into Connect) is NOT listed as addable; instead we show a
+ // clear "not on Connect" / "not found" state so the user isn't confused by un-chattable rows.
+ const onc=all.filter(p=>p.onConnect && p.connectId && !(p.email&&haveEmail.has(p.email.toLowerCase())));
+ const localHit=box.parentElement && box.parentElement.querySelector('.chat-row, .contact-row');
+ if(onc.length){
+ box.innerHTML='On Connect
'+onc.map((p,i)=>{ const sub=[p.org,p.phone].filter(Boolean).join(' · ');
+ return ''+pEsc(initials(p.name||'?'))+''+pEsc(p.name||p.email||'Unknown')+''+(sub?''+pEsc(sub)+'':'')+'
'; }).join('');
+ box.querySelectorAll('.dir-row').forEach(row=>{ const p=onc[+row.dataset.i]; row.onclick=()=>selectChat('dm', p.connectId); });
+ } else if(!localHit){
+ // Nothing on Connect matched. Distinguish "exists on BizGaze but not on Connect" from "not found".
+ box.innerHTML = all.length
+ ? ''+ic('info',16)+'
Not on ConnectMatching people are on BizGaze but haven’t joined Connect yet, so they can’t be messaged.
'
+ : ''+ic('search',16)+'
Contact not foundNo Connect user matches “'+pEsc(q)+'”.
';
+ } else box.innerHTML='';
}, 280);
}
function updateRailUnread(){