dc1915bb43
Live presence (fixes stale in-call/status until refresh — impossible in apps): - server broadcasts a user's status over the chat socket on connect/disconnect, call join/leave, and status change (chat.js broadcastPresence; signaling + routes hooks). - client onPresence() updates the contact dot + open-chat header live. Chat delivery ticks (#6): chat-list row now mirrors the thread (delivered→double grey, read→blue) via a new 'with' field on the delivered relay + onChatRead/onChatDelivered. Call fixes: no bogus 'host handed over' when a 1:1 call ends (leaveMeeting forced); branded call-connecting + chat-thread loaders; header subtitle tracks live call state. Notifications: web notify + sw.js use sender/group DP + brand icon (not old wordmark); desktop shell drops Web Push so only the single native toast fires (#5). Brand: master icon/splash/loaders wired everywhere (PWA/favicon/apple-touch/.ico), branded login (blue + gold CTA), branded toasts (BZToast) on all pages, Electron splash. Desktop: dev auto-targets localhost (packaged→prod); version 0.1.3 with new multi-size icon; dropped unused node-notifier; removed home-mockup.html. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
19 lines
1.5 KiB
CSS
19 lines
1.5 KiB
CSS
/* Biz Connect — branded notification toast. BZToast.success('…') / .error / .message / .info */
|
|
.bzt-wrap{position:fixed;top:16px;right:16px;z-index:2147483600;display:flex;flex-direction:column;gap:10px;max-width:min(380px,92vw)}
|
|
@supports(top:env(safe-area-inset-top)){.bzt-wrap{top:calc(16px + env(safe-area-inset-top));right:calc(16px + env(safe-area-inset-right))}}
|
|
.bzt{display:flex;align-items:flex-start;gap:12px;background:#fff;color:#1f2430;border-radius:14px;padding:12px 14px;
|
|
box-shadow:0 12px 30px rgba(16,26,53,.20);border-left:5px solid #1F3B73;
|
|
transform:translateX(120%);opacity:0;transition:transform .3s cubic-bezier(.2,.7,.2,1),opacity .3s}
|
|
.bzt.bzt-in{transform:translateX(0);opacity:1}
|
|
.bzt.success{border-left-color:#16a34a}.bzt.error{border-left-color:#b91c1c}
|
|
.bzt-badge{flex:none;width:34px;height:34px;border-radius:50%;display:grid;place-items:center;background:#1F3B73}
|
|
.bzt.success .bzt-badge{background:#16a34a}.bzt.error .bzt-badge{background:#b91c1c}
|
|
.bzt-badge svg{width:20px;height:20px}
|
|
.bzt-body{flex:1;min-width:0;padding-top:1px}
|
|
.bzt-title{font:700 13.5px/1.3 'Segoe UI',system-ui,sans-serif;color:#1F3B73;margin:0 0 1px}
|
|
.bzt.success .bzt-title{color:#15803d}.bzt.error .bzt-title{color:#b91c1c}
|
|
.bzt-msg{font:500 13px/1.4 'Segoe UI',system-ui,sans-serif;color:#3a4152;overflow-wrap:anywhere}
|
|
.bzt-x{flex:none;background:none;border:none;color:#9aa3b2;cursor:pointer;font-size:18px;line-height:1;padding:2px 4px}
|
|
.bzt-x:hover{color:#1f2430}
|
|
@media(prefers-reduced-motion:reduce){.bzt{transition:opacity .2s}}
|