- First and last name are now separate required fields
- Server combines them into a full name for emails
- Sends a push notification to NTFY_URL on new inquiry (fire-and-forget)
- NTFY_URL env var wired through docker-compose
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Hold the logo for 0.6s (works on mobile touch and desktop mouse) to launch
22 balloon silhouettes floating up from the bottom. Balloons drift with a
slight sway, have a shine highlight, and naturally disappear under the navbar.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the third-party iframe form on both the homepage and contact page
with the self-hosted form: drag-and-drop photo upload, honeypot, rate
limiting, inline validation, auto-reply email. Adds multer/sharp/nodemailer
dependencies and the /api/contact endpoint to server.js.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace plausible.io with metrics.beachpartyballoons.com across all
main-site pages and estore layout.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace all bare info@ occurrences with a click-to-reveal pattern:
- New EmailLink React component (base64 decode on click, never in DOM pre-click)
- privacy, terms, refund pages use EmailLink
- contact/index.html uses a vanilla JS button with the same pattern
- PaymentForm mailto builder uses atob() to keep email out of source literals
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>