From b8b9d12a826e99aa9235fa80a84a36363195c4dc Mon Sep 17 00:00:00 2001 From: ponzischeme89 Date: Wed, 6 May 2026 08:27:24 +1200 Subject: [PATCH] 4.2.1 polish --- MOBILEPOLISH.md | 236 ++++++++++++++++++ UXPOLISH.md | 143 +++++++++++ package.json | 2 +- src/lib/components/Footer.svelte | 2 +- src/lib/components/MobileBookBar.svelte | 147 +++++++++++ src/lib/components/PricingPage.svelte | 56 +++++ src/lib/components/ServiceLandingPage.svelte | 48 ++++ src/lib/components/ServicesSection.svelte | 2 +- src/lib/components/TestimonialsSection.svelte | 4 +- src/lib/content/homepage.ts | 12 +- src/lib/content/pack-walks.ts | 5 +- src/lib/styles/layout.css | 4 +- src/lib/styles/responsive.css | 53 +++- src/lib/styles/sections.css | 7 +- src/lib/types.ts | 1 + src/routes/+layout.svelte | 3 + 16 files changed, 700 insertions(+), 25 deletions(-) create mode 100644 MOBILEPOLISH.md create mode 100644 UXPOLISH.md create mode 100644 src/lib/components/MobileBookBar.svelte diff --git a/MOBILEPOLISH.md b/MOBILEPOLISH.md new file mode 100644 index 0000000..6cfc2c9 --- /dev/null +++ b/MOBILEPOLISH.md @@ -0,0 +1,236 @@ +# Mobile Polish — Conversion & Comfort Audit Tracker + +Findings from a focused mobile-experience review (≤768px, with extra +attention to 375px small-phones). Desktop is considered done. Each item +records the where, why, and the concrete change. + +> Important context for prioritisation: a dog-walking business is a +> jobs-to-be-done service that users research on the couch. Mobile +> conversion lower-bound is "they Meet & Greet". So the dial-movers +> are: thumb-reach for the booking CTA, legibility, friction-free +> form, and trust signals visible on the first scroll. + +--- + +## High — direct conversion impact + +- [x] **Hero buttons stack awkwardly at ~375px** + - File: `src/lib/styles/responsive.css` (new ≤480px block) + - Implementation: At `@media (max-width: 480px)` the hero buttons + flip to `flex-direction: column; gap: 12px;` and each button + becomes full-width with padding `16px 24px`. The 768px-specific + `padding-right: 18px` on the buttons row and the + `margin-right: 12px` on `:last-child` are both reset so the two + CTAs read as a clean stacked stack. + - Why: At 375px the side-by-side primary + outline CTAs were wrapping + unevenly and the primary's prominence collapsed. + +- [x] **Mobile header phone button is low-contrast and small** + - File: `src/lib/styles/responsive.css:88-100` + - Implementation: Background bumped from `rgba(33, 48, 33, 0.06)` → + `0.10`; padding 9px 12px → 11px 14px (and at ≤480px, 10px 12px); + `font-weight: 600`; `min-height: 44px` to meet the touch-target + minimum; icon size also bumped from 13px → 14px. + - Why: The tap-to-call on the mobile header is one of the highest + intent actions on the site. It now reads as a button rather than a + barely-visible label. + +- [x] **Booking form inputs trigger iOS zoom-on-focus** + - File: `src/lib/styles/responsive.css:453-462` + - Implementation: Input `font-size: 15px` → `16px` at ≤768px. Comment + added explaining the iOS-Safari 16px threshold so a future edit + doesn't accidentally drop it again. + - Why: Below 16px Safari auto-zooms on focus; the page jolts every + time a field is tapped. Critical at the booking conversion step. + +- [ ] **Testimonial carousel arrows hard to reach at 375px** + - File: `src/lib/components/TestimonialsSection.svelte` (mobile rules + lines ~640-660) + - Current: arrows pinned to `bottom: 24px` inside a stage with + `padding-bottom: 116px`. Visually at the bottom of a tall card — + requires deliberate stretching. + - Why: The carousel feels passive. Users don't realise they can advance + it; testimonials sell — losing that engagement matters. + - Fix: Lift arrows on small screens: + ```css + @media (max-width: 480px) { + .testimonial-arrow { bottom: 80px; } + } + ``` + +- [x] **No persistent "Book Meet & Greet" CTA on mobile after hero scrolls past** + - Files: `src/lib/components/MobileBookBar.svelte` (new), + `src/routes/+layout.svelte` (mount), `src/lib/styles/responsive.css` + (`body { padding-bottom: 64px }` at ≤768px). + - Implementation v2 — *Airbnb-style soft-container, scroll-triggered*: + - **Soft container**: a translucent white tray (`rgba(255, 255, + 255, 0.96)` with backdrop-filter blur) sits flush at the bottom + with a thin top hairline and a soft shadow. The brand-yellow CTA + pill lives *inside* the tray, not as the tray itself — so the + action stays unmistakable but the surrounding chrome is calm. + - **Scroll-triggered**: the bar slides up + fades in only after the + user has scrolled ~480px (≈ one mobile viewport, hero out of + view). Slides back out below ~120px to avoid flicker near the + top. `prefers-reduced-motion` respected — the slide is dropped, + only the opacity fade remains. + - **Hidden on `/contact-us` and `/booking`** (already in the form). + - **Resets on navigation**: `afterNavigate` resets `visible = false` + so each new page starts hidden until the user has earned it again. + - **Accessibility**: `aria-hidden` toggles with visibility; CTA + `tabindex` flips to `-1` while hidden so keyboard users don't + stumble onto an off-screen control; `pointer-events: none` while + hidden so the user can't accidentally tap it during the fade. + - **Safe-area aware**: `env(safe-area-inset-bottom)` so iPhones + with the home-bar gesture area get correct spacing. + - Body bottom-padding of 64px on mobile keeps the footer from sitting + behind the bar when it's visible at the bottom of long pages. + - Why: Sticky mobile CTAs are a validated conversion pattern (Airbnb, + Booking.com, etc.), but the v1 full-yellow bar was tonally wrong + for Goodwalk — it competed with the calm brand voice and dominated + the screen permanently. v2 keeps the conversion benefit (one-tap + booking, always one swipe away after engagement) without yelling. + +## Medium — legibility & polish + +- [x] **Hero title can wrap awkwardly at 375px** + - File: `src/lib/styles/responsive.css` (≤480px block) + - Implementation: At ≤480px the desktop H1 drops to 32px / + line-height 1.12 and the dedicated `.hero-heading-mobile` element + drops to 30px / 1.12 (it was 33.5px). The two-line "Unleashing Fun + in / Your Dog's Day!" now sits comfortably with breathing room + above the subtitle. + - Why: Previous 38px / 33.5px sizings were a hair too big for 375px; + line-2 felt cramped against the subtitle. + +- [x] **Body text 15px feels small on mobile (and on ultra-wide desktop)** + - File: `src/lib/styles/responsive.css` (≤768px body rule) + - Implementation: `body { font-size: 16px; }` at ≤768px, with a + comment noting the iOS-Safari 16px zoom threshold so this rule + isn't accidentally undone. + - Desktop (≥769px) still inherits 15px from `base.css` for now — the + ultra-wide bump is tracked separately at the bottom of this file + so it can be reasoned about independently (clamp vs. breakpoint). + - Why: 16px is the modern legibility standard on mobile, dovetails + with the iOS zoom-on-focus rule for inputs, and reduces read + fatigue on long pages (about, FAQ answers, legal). + +- [ ] **FAQ summary tap target too small** + - File: `src/lib/styles/sections.css` (`.faq summary` rules) + - Current: just text height (~22-26px) — below the 44px minimum. + - Fix: + ```css + .faq summary { + padding: 12px 0; + min-height: 44px; + display: flex; align-items: center; + } + ``` + +- [ ] **Booking service-option chips wrap awkwardly at 375px** + - File: `src/lib/styles/responsive.css:468-470` + - Fix at ≤480px: 2-up grid with tighter gap: + ```css + .booking-service-options { gap: 10px 12px; } + .booking-toggle-option { flex: 1 1 calc(50% - 6px); } + ``` + +- [ ] **Footer social icons spaced too tight for thumbs** + - File: `src/lib/styles/sections.css` (`.social-links { gap: 14px }`) + - Current 14px gap with 40px icons → centres are 54px apart. Apple + HIG wants 8px+ between targets after the 44px minimum. + - Fix: + ```css + @media (max-width: 768px) { .social-links { gap: 18px; } } + ``` + +- [ ] **Pricing cards stack to 1-col with multiple "Book" buttons in a row** + - File: `src/lib/components/PricingPage.svelte` (and ServiceLandingPage + plan grids) + - Why: After stacking, the user sees Plan → Book → Plan → Book → Plan + → Book in vertical sequence. The repetition reads as noise rather + than choice; the "popular" anchor disappears. + - Fix (opinionated): on mobile, only the popular plan keeps its CTA + button. Other plans show a smaller "Choose this plan" link instead, + or no per-card CTA at all (a single CTA appears under the grid): + ```css + @media (max-width: 768px) { + .pricing-plan-card:not(.pricing-plan-popular) .pricing-plan-cta { + display: none; + } + } + ``` + Then keep the existing under-grid `.service-plan-reassurance` pill + and add a single "Book a Meet & Greet" button below it. + +- [ ] **Mobile nav header is too tall — eats above-the-fold real estate** + - File: `src/lib/styles/responsive.css:74` + - Current: `nav { padding: 20px 24px; }` + 25px logo = ~65px header. + On iPhone 13 (844px), this leaves ~380px for hero before scroll — + less than what the Goodwalk dog-image needs to feel like a hero. + - Fix at ≤480px: + ```css + nav { padding: 14px 20px; } + .logo img { height: 22px; } + ``` + +## Low — incremental polish + +- [ ] **Hero top padding generous at 375px** + - File: `src/lib/styles/responsive.css:179` + - Reduce hero `padding-top` from 50px to 32px at ≤480px. + +- [ ] **Intro trust badge feels edge-to-edge at 375px** + - File: `src/lib/styles/responsive.css:296-301` + - Add `padding: 18px 16px; margin: 0 12px;` at ≤480px. + +- [ ] **Testimonial quote mark too large at 375px** + - File: `src/lib/components/TestimonialsSection.svelte:~595` + - Current: 44px. Reduce to 36px at ≤480px. + +- [ ] **Booking form labels could shrink slightly at 375px** + - File: `src/lib/styles/responsive.css:450` + - Optional: 16px → 15px at ≤480px to give field width back to the + input value (where it actually matters for legibility). + +- [ ] **No scroll-to-top affordance on long pages (booking, pricing)** + - Currently absent. Low priority but helpful when users have scrolled + past the booking form and want to re-read service details. Could be + folded into the same sticky-book-bar work above (one bar, both jobs). + +## Open from elsewhere + +- [ ] **Ultra-wide desktop body font feels small** *(noted by user)* + - Currently `body { font-size: 15px }` ([base.css:15](src/lib/styles/base.css#L15)). + On ≥1800px screens with the `--max-w` already widening (per the + 1800px breakpoint), 15px in long-form sections (about, FAQ answers, + legal) becomes uncomfortable. + - Suggested fix: bump to `clamp(15px, 0.95vw, 17px)` on `body`, OR + introduce a `@media (min-width: 1600px) { body { font-size: 17px; } }`. + Either keeps the desktop ≤1599px experience identical and only + expands type when there's genuinely more reading width. + +## Deliberately not actioning + +- **Drop reveal animations on mobile to "save bandwidth".** They're + IntersectionObserver-driven, cost nothing perceivable, and add brand + polish. Removing them would make the mobile site feel cheaper for no + measurable performance gain. +- **Replace the testimonial carousel with a stacked list on mobile.** + Tempting (carousels famously hide content), but the carousel is + central to the brand's "see real dogs" pitch. Better to fix the arrow + reachability and let the autoplay do the work. + +--- + +## Suggested order of attack + +If you want one batch that moves the dial: **High items 1, 2, 3, 5** +together is roughly an hour of work — they hit the hero, the header +tap-to-call, the booking form's biggest mobile bug (zoom-on-focus), and +add the sticky CTA. That's the package I'd ship first. Item 4 (carousel +arrows) is a one-line fix once you're already in `responsive.css`. + +The Medium list is best as a second pass — body-text bump, +header-padding reduction, FAQ tap-target, and pricing-card-CTA dedupe +all compound into a noticeably more "intentional on mobile" feel +without any structural change. diff --git a/UXPOLISH.md b/UXPOLISH.md new file mode 100644 index 0000000..f7345f8 --- /dev/null +++ b/UXPOLISH.md @@ -0,0 +1,143 @@ +# UX Polish — Conversion Audit Tracker + +Findings from the senior-marketing-lens audit, with completion status. Each +item has a one-line rationale and the file/line where the change lives (or +will live). + +> Only commit to "We'll reply within 24 hours" if Aless can actually hold +> to it. If response time is more like 1-2 business days, soften to +> "within one business day". + +--- + +## High — direct conversion impact + +- [x] **Hero primary CTA: "Learn more" → "Explore our services →"** + - File: `src/lib/content/homepage.ts:38` + - Why: "Learn more" is the lowest-intent CTA that exists. + +- [x] **Promise CTA: "See our services" → "Book a free Meet & Greet"** + - File: `src/lib/content/homepage.ts:59` + - Also: target changed from `#services` to `/contact-us` so the CTA goes + to the booking page instead of bouncing back up to a service list. + - Why: After the value prop + happy-dog photo, sending visitors to the + services list is a step backwards. Push them to book. + +- [x] **Booking subtitle now states response time** + - File: `src/lib/content/homepage.ts:159-162` + - Old: *"...so we can reach out to arrange your free, no-obligation Meet & Greet."* + - New: *"...We'll reply within 24 hours to arrange your free, no-obligation Meet & Greet."* + - General-enquiry variant updated to match. + - Why: Open-ended "we'll reach out" creates anxiety at submit time. + +- [x] 1 **Pricing page — Google rating trust signal above plan grid** + - File: `src/lib/components/PricingPage.svelte` + - Implementation: Pill-styled trust badge inside the green hero, + directly under the subtitle — five yellow stars + "30+ five-star + Google reviews" label + arrow, links out to Google. Styled to read + against the green hero (semi-transparent white pill) rather than + reusing the cream IntroStrip, which would have clashed. + - Why: Visitors land on pricing mid-decision; trust signal now appears + before the plan grid. + +- [x] 2 **Service plan CTAs — add free / no-obligation reassurance** + - File: `src/lib/components/ServiceLandingPage.svelte` + - Implementation: A subtle green pill *"Every booking starts with a + free, no-obligation Meet & Greet."* (yellow shield-heart icon) sits + centred directly under the plan grid on every service page, above the + Extras block. Reuses the brand-tinted-pill aesthetic so it feels + native, not tacked on. + - Why: The "Book a Meet & Greet" buttons under each plan didn't carry + risk-reversal phrasing in their immediate context. Now they do. + +## Medium — trust + polish + +- [x] 3 **Quantify the Google rating wherever it appears** + - Files: `src/lib/content/homepage.ts:46`, + `src/lib/components/Footer.svelte:89`, + `src/lib/components/TestimonialsSection.svelte:200`, + `src/lib/components/PricingPage.svelte` (new pricing-trust pill). + - Implementation: "All 5 star reviews on Google!" → "30+ five-star + Google reviews" everywhere. Aless confirmed 30+ as the count. + - Why: A specific number is dramatically more credible than "all". + +- [x] 4 **Lean into the "limited spots" angle** + - File: `src/lib/content/pack-walks.ts` (added `scarcityNote` to the + `pricing` block); `src/lib/types.ts` (added optional `scarcityNote?: + string` to ServicePageContent.pricing); rendered in + `src/lib/components/ServiceLandingPage.svelte` directly under the + plan grid as a yellow-tinted pill with a clock icon. + - Copy: *"We keep packs small (4-8 dogs) — popular days fill up fast."* + - Only set on Pack Walks (the 4-8 number is specific to that service); + the field is optional so 1:1 Walks and Puppy Visits get nothing. + - Why: Real, honest scarcity. The 4-8 cap is already a fact; saying it + out loud nudges decision-making. + +- [ ] **About page — quantify Aless's expertise** + - File: `src/lib/content/about.ts:29-30` + - Why: "years of experience" is the weakest possible claim. Replace with + concrete numbers Aless can stand behind: years operating, dogs in + rotation, first-aid certification. + +- [x] 5 **Pack Walks pricing intro — lead with the differentiator** + - File: `src/lib/content/pack-walks.ts:23-24` + - Implementation: Old intro led with "Our pack walks are a permanent + booking of at least one walk day a week..." (commitment ask first). + New intro leads with the benefits: *"Small packs of 4-8 dogs, 2-hour + outings at Auckland's scenic dog parks and beaches, with free pick-up + and drop-off included. We reinforce recall, car manners, and leash + etiquette while your dog plays. Booked as a permanent weekly slot — + gift your dog the best life!"* + - Why: Buyers scan for benefits before commitments. Lead-with-policy + framing creates resistance; lead-with-benefit framing builds desire. + +- [ ] **FAQs — reframe from policy to reassurance** + - File: `src/lib/content/homepage.ts:180-205` + - Why: Answers are correct but read like terms & conditions. Lead with + the *why* (the benefit/reassurance), then the *what*. + +## Low — incremental polish + +- [x] **Home services-card CTAs: "Learn more" → outcome-oriented** + - File: `src/lib/components/ServicesSection.svelte:29` + - Implementation: Visible label is now derived from the service title — + *"See Pack Walks pricing →"*, *"See 1:1 Walks pricing →"*, *"See + Puppy Visits pricing →"*. The previously-added screen-reader-only + "about " span was removed since the visible label now carries + that context for everyone, not just assistive tech users. + - Why: "Learn more" was the lowest-intent CTA on the page; the new + label states the destination and the next step. + +- [x] **Testimonials intro blurb — sharper jobs-to-be-done framing** + - File: `src/lib/components/TestimonialsSection.svelte:10-11` + - Old: *"Happy owners, even happier dogs. Our Auckland dog walking + clients love what the Tiny Gang brings to their dog's routine — and + you can see why. Follow along on Instagram for daily adventures..."* + - New: *"Busy parents get peace of mind. Dogs come home tired and + happy. See why 30+ Auckland families trust the Tiny Gang — follow + along on Instagram for daily adventures, wagging tails and the odd + zoomie."* + - Why: Leads with the two outcomes buyers actually care about (peace of + mind for them, exercise for the dog), keeps the brand voice + 30+ + review proof point, then makes the Instagram nudge feel like a + follow-on rather than the lead. + +- [x] **Surface "Reliability / on-time" earlier** + - File: `src/lib/content/homepage.ts:37` (hero subtitle) + - Old: *"Trusted, professional dog walking across Auckland Central..."* + - New: *"Trusted, on-time dog walking across Auckland Central..."* + - Why: Reliability/punctuality is the #1 anxiety for busy parents + booking a service that visits their home. Pulling "on-time" into the + hero subtitle (one-word swap, no length cost) puts the reassurance + above the fold. + +## Deliberately not actioning + +- **Pack Walks H1 rewrite to "Small-dog pack walks designed for calm, + confident groups."** *"Join our Tiny Gang!"* is doing brand work — it's + memorable and reinforces a phrase used everywhere else. Rewriting kills + the most distinctive asset for marginal headline clarity. +- **Booking submit button: "Send" → "Book my Meet & Greet".** The form + also handles general enquiries, so a "book my…" label would feel wrong + on a complaint email. Better fix would be to switch the label by + `enquiryType` — keep "Send my booking" / "Send my enquiry" contextually. diff --git a/package.json b/package.json index 8a96787..6aefec0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "goodwalk-svelte-port", - "version": "4.2.0", + "version": "4.2.1", "private": true, "type": "module", "scripts": { diff --git a/src/lib/components/Footer.svelte b/src/lib/components/Footer.svelte index 89d49ea..fa9b263 100644 --- a/src/lib/components/Footer.svelte +++ b/src/lib/components/Footer.svelte @@ -86,7 +86,7 @@ class="footer-reviews" > - See our 5★ Google reviews + 30+ five-star Google reviews {#if footer.email || footer.phone} diff --git a/src/lib/components/MobileBookBar.svelte b/src/lib/components/MobileBookBar.svelte new file mode 100644 index 0000000..7bcf7ee --- /dev/null +++ b/src/lib/components/MobileBookBar.svelte @@ -0,0 +1,147 @@ + + +{#if !hidden} + +{/if} + + diff --git a/src/lib/components/PricingPage.svelte b/src/lib/components/PricingPage.svelte index 40e335a..f43daf4 100644 --- a/src/lib/components/PricingPage.svelte +++ b/src/lib/components/PricingPage.svelte @@ -96,6 +96,22 @@ {#if pageContent.subtitle}

{pageContent.subtitle}

{/if} + + + + 30+ five-star Google reviews + + @@ -204,6 +220,46 @@ color: rgba(255, 255, 255, 0.7); } + .pricing-trust { + display: inline-flex; + align-items: center; + gap: 12px; + margin-top: 22px; + padding: 9px 18px; + border-radius: 999px; + background: rgba(255, 255, 255, 0.1); + border: 1px solid rgba(255, 255, 255, 0.18); + color: #fff; + font-size: 14px; + font-weight: 600; + text-decoration: none; + transition: + background 0.2s ease, + transform 0.18s cubic-bezier(0.22, 1, 0.36, 1); + } + + .pricing-trust:hover { + background: rgba(255, 255, 255, 0.18); + transform: translateY(-1px); + } + + .pricing-trust-stars { + display: inline-flex; + align-items: center; + gap: 2px; + color: var(--yellow); + font-size: 13px; + } + + .pricing-trust-label { + letter-spacing: 0.01em; + } + + :global(.pricing-trust .pricing-trust-arrow) { + font-size: 12px; + opacity: 0.85; + } + .pricing-section-heading h2 { margin: 0; text-align: center; diff --git a/src/lib/components/ServiceLandingPage.svelte b/src/lib/components/ServiceLandingPage.svelte index ba7d7ca..63efd20 100644 --- a/src/lib/components/ServiceLandingPage.svelte +++ b/src/lib/components/ServiceLandingPage.svelte @@ -113,6 +113,18 @@ {/each} + {#if pageContent.pricing.scarcityNote} +

+ + {pageContent.pricing.scarcityNote} +

+ {/if} + +

+ + Every booking starts with a free, no-obligation Meet & Greet. +

+ {#if pageContent.pricing.extras?.length}
Extras
@@ -554,6 +566,42 @@ font-family: var(--font-head); } + .service-plan-reassurance, + .service-plan-scarcity { + display: flex; + align-items: center; + justify-content: center; + gap: 10px; + width: fit-content; + margin: 24px auto 0; + padding: 8px 16px; + border-radius: 999px; + background: rgba(33, 48, 33, 0.06); + color: var(--green); + font-size: 14px; + font-weight: 600; + } + + .service-plan-scarcity { + background: rgba(255, 209, 0, 0.18); + color: #5a4500; + } + + .service-plan-reassurance + .service-plan-reassurance, + .service-plan-scarcity + .service-plan-reassurance { + margin-top: 12px; + } + + :global(.service-plan-reassurance .icon) { + color: var(--yellow); + font-size: 14px; + } + + :global(.service-plan-scarcity .icon) { + color: #b88800; + font-size: 14px; + } + .service-extras { margin-top: 30px; border-radius: 28px; diff --git a/src/lib/components/ServicesSection.svelte b/src/lib/components/ServicesSection.svelte index 1f2c980..fcceba4 100644 --- a/src/lib/components/ServicesSection.svelte +++ b/src/lib/components/ServicesSection.svelte @@ -27,7 +27,7 @@ {#if service.href} - Learn more about {service.title} + See {service.title} pricing → {/if}
diff --git a/src/lib/components/TestimonialsSection.svelte b/src/lib/components/TestimonialsSection.svelte index c18272c..c970064 100644 --- a/src/lib/components/TestimonialsSection.svelte +++ b/src/lib/components/TestimonialsSection.svelte @@ -8,7 +8,7 @@ export let testimonials: TestimonialContent[]; export let heading = 'Why people choose us!'; export let blurb = - "Happy owners, even happier dogs. Our Auckland dog walking clients love what the Tiny Gang brings to their dog's routine — and you can see why. Follow along on Instagram for daily adventures, wagging tails and the odd zoomie"; + 'Busy parents get peace of mind. Dogs come home tired and happy. See why 30+ Auckland families trust the Tiny Gang — follow along on Instagram for daily adventures, wagging tails and the odd zoomie.'; export let instagramHref = 'https://www.instagram.com/goodwalk.nz/'; export let instagramLabel = 'goodwalk.nz'; @@ -197,7 +197,7 @@ rel="noopener" > - All 5 star reviews on Google! + 30+ five-star Google reviews diff --git a/src/lib/content/homepage.ts b/src/lib/content/homepage.ts index 83ae47e..8f4d7c4 100644 --- a/src/lib/content/homepage.ts +++ b/src/lib/content/homepage.ts @@ -34,8 +34,8 @@ export const homepageContent: HomePageContent = { title: 'Unleashing Fun in', highlight: "Your Dog's Day!", mobileTitle: "Unleashing Fun in\nYour Dog's Day!", - subtitle: 'Trusted, professional dog walking across Auckland Central — pack walks, 1:1 walks, and puppy visits.', - primaryCta: { label: 'Learn more', href: '#services', variant: 'yellow' }, + subtitle: 'Trusted, on-time dog walking across Auckland Central — pack walks, 1:1 walks, and puppy visits.', + primaryCta: { label: 'Explore our services →', href: '#services', variant: 'yellow' }, secondaryCta: { label: 'Book a Meet & Greet', href: '#newlead', variant: 'outline' }, imageUrl: '/images/auckland-dog-walking-happy-dog-hero.png', imageAlt: 'Happy dog ready for a professional pack walk with Goodwalk Auckland dog walking service' @@ -43,7 +43,7 @@ export const homepageContent: HomePageContent = { intro: { text: 'Trusted by Auckland dog parents.', reviewCta: { - label: 'All 5 star reviews on Google!', + label: '30+ five-star Google reviews', href: 'https://g.page/r/CUsvrWPhkYrAEB0/', external: true } @@ -56,7 +56,7 @@ export const homepageContent: HomePageContent = { 'Professional dog walking across Auckland for small, medium and large breeds, with tailored pack walks for smaller dogs and one-on-one walks for larger breeds — giving every dog the personalised attention they deserve. Ready to join our' ], emphasis: 'TINY GANG?', - cta: { label: 'See our services', href: '#services', variant: 'green' }, + cta: { label: 'Book a free Meet & Greet', href: '/contact-us', variant: 'green' }, imageUrl: '/images/auckland-dog-walking-happy-dogs-happy-humans.webp', imageAlt: 'Woman cuddling a dog for Goodwalk Auckland dog walking services' }, @@ -157,9 +157,9 @@ export const homepageContent: HomePageContent = { booking: { title: "Let's meet!", subtitle: - "Almost there — just your contact details so we can reach out to arrange your free, no-obligation Meet & Greet.", + "Almost there — just your contact details. We'll reply within 24 hours to arrange your free, no-obligation Meet & Greet.", generalSubtitle: - "Almost there — just your contact details so we can reply properly to your message.", + "Almost there — just your contact details. We'll reply within 24 hours.", formAction: '/contact-us', serviceOptions: ['Pack Walks', '1:1 Walks', 'Puppy Visits', 'Other Services'], ownerStepLabel: 'Your details', diff --git a/src/lib/content/pack-walks.ts b/src/lib/content/pack-walks.ts index 4887c51..c8a1c80 100644 --- a/src/lib/content/pack-walks.ts +++ b/src/lib/content/pack-walks.ts @@ -21,7 +21,7 @@ export const packWalksContent: ServicePageContent = { pricing: { title: 'Tiny Gang Prices', intro: - 'Our pack walks are a permanent booking of at least one walk day a week. Our Tiny Gang pack outing typically lasts 2 hours or more, including a one-hour walk at one of Auckland’s scenic dog parks or beaches. Additionally, pick-up and drop-off services are provided for your convenience. We assist in reinforcing basic training, including recall, car manners, and leash etiquette. Gift your dog the best life!', + 'Small packs of 4-8 dogs, 2-hour outings at Auckland’s scenic dog parks and beaches, with free pick-up and drop-off included. We reinforce recall, car manners, and leash etiquette while your dog plays. Booked as a permanent weekly slot — gift your dog the best life!', plans: [ { title: '1 Walk', @@ -53,7 +53,8 @@ export const packWalksContent: ServicePageContent = { { label: 'Extra Dog', note: 'From same household', price: '$35' }, { label: 'Muddy Wash', price: '$35' }, { label: '5 Hour Day Out', note: 'Not suitable for all dogs', price: '$90' } - ] + ], + scarcityNote: 'We keep packs small (4-8 dogs) — popular days fill up fast.' }, benefits: { title: 'Tiny Gang membership benefits', diff --git a/src/lib/styles/layout.css b/src/lib/styles/layout.css index 288f745..b3d056e 100644 --- a/src/lib/styles/layout.css +++ b/src/lib/styles/layout.css @@ -58,8 +58,8 @@ nav { } .nav-links > li > a.nav-link-active { - background: #eadbbf; - color: #000; + background: #fff; + color: var(--green); } .mega-chevron { diff --git a/src/lib/styles/responsive.css b/src/lib/styles/responsive.css index 57ab389..3f77ed4 100644 --- a/src/lib/styles/responsive.css +++ b/src/lib/styles/responsive.css @@ -35,6 +35,18 @@ } @media (max-width: 768px) { + /* + * Mobile body type bumps to 16px — modern legibility standard, and + * matches the iOS-Safari zoom-on-focus threshold. Reserve room at + * the bottom of the page for the sticky MobileBookBar so the footer + * never sits behind it; the bar adds its own safe-area-inset + * padding on top of this. + */ + body { + font-size: 16px; + padding-bottom: 64px; + } + @keyframes mobileMenuBounceIn { 0% { opacity: 0; @@ -89,14 +101,16 @@ display: inline-flex; justify-self: center; align-self: center; - padding: 9px 12px; - background: rgba(33, 48, 33, 0.06); + min-height: 44px; + padding: 11px 14px; + background: rgba(33, 48, 33, 0.1); color: var(--green); font-size: 13px; + font-weight: 600; } .mobile-phone .icon { - font-size: 13px; + font-size: 14px; } .nav-links { @@ -453,7 +467,13 @@ .booking-field-card input, .booking-field-card textarea { padding: 14px 18px; - font-size: 15px; + /* + * 16px is the iOS-Safari threshold for triggering auto-zoom on + * focus. Anything smaller and the page jolts every time a field + * is tapped — kills the form's perceived quality at the most + * critical conversion step. + */ + font-size: 16px; border-width: 2px; border-radius: 18px; } @@ -554,11 +574,34 @@ @media (max-width: 480px) { .mobile-phone { gap: 6px; - padding: 9px 10px; + padding: 10px 12px; font-size: 12px; } .mobile-phone span { letter-spacing: -0.01em; } + + .hero-text h1, + .hero-heading { + font-size: 32px; + line-height: 1.12; + } + + .hero-text h1 .hero-heading-mobile { + font-size: 30px; + line-height: 1.12; + } + + .hero-buttons { + flex-direction: column; + gap: 12px; + padding-right: 0; + } + + .hero-buttons .btn { + width: 100%; + margin-right: 0 !important; + padding: 16px 24px; + } } diff --git a/src/lib/styles/sections.css b/src/lib/styles/sections.css index 64294c0..8f5ecfd 100644 --- a/src/lib/styles/sections.css +++ b/src/lib/styles/sections.css @@ -213,12 +213,8 @@ section { background: #fff; } -.promise-text h2 { - text-align: center; -} - .promise-text p { - margin-bottom: 28px; + margin: 0 auto 28px; font-size: 16px; max-width: 520px; } @@ -231,6 +227,7 @@ section { .promise-text { order: 2; + text-align: center; } .promise-img { diff --git a/src/lib/types.ts b/src/lib/types.ts index 361eab2..ffdadf8 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -124,6 +124,7 @@ export interface ServicePageContent { intro?: string; plans: ServicePricingPlan[]; extras?: ServiceExtra[]; + scarcityNote?: string; }; benefits: { title: string; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index c0882c1..7674725 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -3,6 +3,7 @@ import { navigating, page } from '$app/stores'; import { afterNavigate, disableScrollHandling } from '$app/navigation'; import { initClickTracking, trackPageView } from '$lib/analytics'; + import MobileBookBar from '$lib/components/MobileBookBar.svelte'; import RouteSkeleton from '$lib/components/RouteSkeleton.svelte'; import '$lib/styles/variables.css'; import '$lib/styles/base.css'; @@ -72,6 +73,8 @@ {/if} + +