The Offline-notifications popup was covered by Smart Gallery's toolbar. Raising
its z-index could not have worked: .dash-topbar is `position: sticky; z-index: 20`,
which opens a stacking context, so .tm-menu-pop's z-index: 30 only ranked inside
the topbar. Against module content the whole topbar competed at 20 — and the
vendored photo-gallery SDK stacks up to 1400 (its own README documents this).
Adds AnchoredPopover, which portals to <body> — out of the topbar's stacking
context entirely — positions from the trigger's viewport rect, clamps to the
window edges, and closes on scroll/resize/Escape/outside-click. Applied to the
notification bell AND the user menu, which had the identical trap and would have
been reported next.
Portalling rather than z-index escalation is the fix that survives a module
raising its own z-index later.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Notifications phase 2: a /push-sw.js service worker shows a system notification
on push and, on click, focuses an open CRM tab (or opens one) and deep-links to
the thread. usePushNotifications registers the SW, requests permission, subscribes
with IIOS's VAPID key, and stores the subscription via the be-crm door. The topbar
bell becomes a real enable/disable control (hidden when push is unsupported/demo).
Dashboard listens for the SW's notif-click message + a ?thread= deep link.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>