Replace plain-text address/phone/hours on the homepage with the same
three-tile card layout used on the contact page. Consolidates the
separate hours section into the tile, removing the duplicate. Dynamic
#status and #hours-* IDs are preserved inside the tile for script.js.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two bugs prevented form submission entirely:
1. `challengeurl` attribute was renamed to `challenge` in altcha v3 — the
widget silently ignored the old name so it never fetched a challenge.
2. `altchaWidget.value` is not an exposed property on the v3 custom element;
read the solved payload from the hidden `<input name="altcha">` the widget
renders in light DOM instead.
Also clears the err-altcha error message at the start of each submit attempt
so it doesn't linger after the user completes verification and retries.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v3 moved the widget from dist/altcha.min.js to dist/main/altcha.min.js;
the old path served a cached v2 widget which expected a 'challenge'
string field and threw split-on-undefined against v3's parameters format.
Pin to @3.1.0 to prevent future surprise upgrades.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Unique title + meta description on every main-site page
- OpenGraph + Twitter card tags sitewide (hero image on homepage, logo elsewhere)
- LocalBusiness JSON-LD on homepage for Google rich results
- Custom 404 page on main-site (branded, links home + contact)
- Custom not-found page on estore
- Fix typo: "Delivery avalable" → "Delivery available"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>