The hero is now layered like Treasures' HeroGallery:
- CampaignHeroBackground (new) — full-bleed banner image from the
currently-spotlit campaign, crossfading over ~1.5 s and panning left.
Warm tint + film grain overlay so foreground text stays legible.
- HeroGlobe — pushed to the right edge with a larger radius, slightly
translucent so the photo bleeds through. Hearts replace the old dots
for marker symbols; clicking one selects that campaign.
- HeroCampaignSpotlight (new) — minimal text overlay anchored to the
bottom-left of the hero container (title, summary, avatar + author,
location, progress bar with goal, 'View' link). No card chrome.
Land polygons are now the full Natural Earth 110m fidelity (~10.5k
vertices) instead of being heavily Douglas-Peucker'd, so coastlines
look organic rather than chunky. Back-hemisphere rings are now
properly hidden by walking each edge and either dropping back-side
vertices outright or interpolating to the sphere limb where a ring
crosses it — fixes the 'phantom continents through the front' bug.
Rings additionally fade in/out over a narrow z-band near the limb
instead of popping at z = 0.
Markers also have proper z-fade and pull off-canvas when on the back
so they can't intercept clicks they aren't visible for. Selected
markers scale 1.35x with a stronger glow so the user can tell which
campaign the spotlight refers to.
Other cleanup:
- formatCampaignAmount + formatSatsShort move out of CampaignCard.tsx
into src/lib/formatCampaignAmount.ts so CampaignCard stops failing
the react-refresh/only-export-components lint.
- Hero CTAs drop the 'Unstoppable fundraising on Nostr' pill and the
em dash from the supporting copy.
- New keyframes (heroPanLeft / heroPanRight) for the slow Ken-Burns
pan on the background photos, with prefers-reduced-motion respected.
Drops the 'Unstoppable fundraising on Nostr' pill and the em dash from the
hero copy, and adds an ambient SVG globe sitting behind the headline.
The globe is a pure-SVG orthographic projection (no WebGL, no canvas). It
renders Natural Earth 110m country boundaries pre-simplified down to ~1.5k
vertices (17 KB inline). Coloring is intentionally warm — cream sphere with
sandy-amber land — to avoid the satellite/HUD aesthetic. Campaigns whose
location string resolves to an ISO 3166-1 country appear as small glowing
markers, deduped by country.
Rotation is driven by requestAnimationFrame and applied imperatively via
refs (no React re-renders during animation), and respects
prefers-reduced-motion by holding at a static angle.