Rebuilt the cold-start splash to a best-in-class standard:
- Determinate progress bar driven by real milestones (mount creep →
relays-warm nudge → 100% on ready) with a sliding shine highlight —
reads as genuine loading, not an infinite spinner.
- Choreographed staggered entrance (logo → wordmark → bar → status rise
in sequence) on an expressive ease curve.
- Signature logo treatment: rotating red→lime conic halo ring + a gentle
breathing pulse, over a dual breathing glow and a masked skate-map grid
texture for depth.
- Satisfying "ready" beat: bar fills to 100%, status swaps to a lime
check "Ready", then a soft scale-up crossfade reveals the app.
- 8px-grid spacing, refined tracking/typography.
- Fully respects prefers-reduced-motion (all motion gated) and safe-area
insets on all four edges; identical on phone and desktop; still capped
hard at 2.6s so it never traps the user.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
Make the landing feel "already loaded" instead of dismissing on bare
connection:
- MapPage fires `skatespots:content-ready` once the first spots query
settles. The splash now dismisses on that signal (populated reveal),
falling back to a short grace window after `relays-warm` for non-map
cold-start routes, and still capped hard at 2.2s so it never traps.
- App shell eases in under the departing splash via a pure-opacity
`appReveal` animation (no translate, so a full-bleed map never shifts),
respecting prefers-reduced-motion. Result is a smooth crossfade onto
content that's already there rather than a pop-in.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
A. Relay pre-warming — NostrProvider now opens the read-relay WebSockets
the moment it mounts (fire-and-forget limit:0 probes with a 4s abort),
instead of NPool's lazy open on first query. Sockets are already
connected by the time the map queries run, so first events land sooner.
Failures are swallowed so a dead relay never delays or breaks boot.
B. Branded SplashScreen — an intentional cold-start moment (logo with a
neon glow pulse, a red→lime progress sweep, and rotating skater-voiced
status lines) that replaces the "is it broken?" empty-map flash. It
dismisses the instant relays report warm (`skatespots:relays-warm`
event fired on the first relay response) OR at a hard 1.6s cap —
whichever comes first — with a 650ms minimum to avoid flicker. Shown
once per session. Fully respects prefers-reduced-motion and safe-area
insets; works identically on phone and desktop, never blocks the user.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>