333 lines
16 KiB
Markdown
333 lines
16 KiB
Markdown
# Mobile Polish — Conversion & Comfort Audit Tracker
|
||
|
||
## New Rescan Items — Mobile Conversion Opportunities
|
||
|
||
Fresh opportunities from a second mobile-first pass over the main site.
|
||
These are intentionally only the new items, kept separate from the
|
||
existing audit below.
|
||
|
||
### High — conversion strategy and flow
|
||
|
||
- [ ] **Hero CTA hierarchy still prioritises browsing over booking**
|
||
- Files: `src/lib/content/homepage.ts:37-39`, `src/lib/components/HeroSection.svelte`
|
||
- Current: the yellow primary CTA is `Explore our services →`, while
|
||
`Book a Meet & Greet` is secondary.
|
||
- Why: on mobile, high-intent users should be able to choose the next
|
||
step immediately. Making the exploratory path more visually dominant
|
||
adds friction before the user reaches the lead form.
|
||
- Opportunity: test flipping the hierarchy on mobile so booking
|
||
becomes the primary CTA and service exploration becomes secondary.
|
||
|
||
- [ ] **Homepage social proof appears too late in the scroll**
|
||
- File: `src/routes/+page.svelte:143-147`
|
||
- Current order: `Services -> Values -> Testimonials -> Booking`.
|
||
- Why: testimonials are one of the strongest conversion levers, but
|
||
on mobile they arrive after several large sections. Users are asked
|
||
to keep scrolling before seeing the strongest emotional proof.
|
||
- Opportunity: move testimonials above values on the homepage, or
|
||
surface one featured review snippet earlier in the page.
|
||
|
||
- [ ] **Hero still relies on the next section for trust**
|
||
- Files: `src/lib/content/homepage.ts:43-49`, `src/lib/components/HeroSection.svelte`,
|
||
`src/lib/components/IntroStrip.svelte`
|
||
- Current: the hero presents the headline and CTAs, but the review
|
||
proof sits in the intro strip below.
|
||
- Why: on mobile, the hero needs to answer both "what is this?" and
|
||
"can I trust them?" before the user scrolls away. Separating those
|
||
two jobs weakens the first decision moment.
|
||
- Opportunity: add a compact review/trust chip directly under the
|
||
hero subtitle or near the hero CTAs on mobile.
|
||
|
||
- [ ] **Booking flow asks for dog details before it captures the lead**
|
||
- File: `src/lib/components/BookingSection.svelte:298-441`
|
||
- Current: step 1 asks for dog name, location, message, and services;
|
||
contact details are only requested in step 2.
|
||
- Why: this is a higher-friction sequence on mobile. Users often feel
|
||
more comfortable giving owner details first, then expanding into pet
|
||
specifics once they have mentally committed.
|
||
- Opportunity: test reversing the step order so step 1 captures name,
|
||
email, and phone first, then dog details second.
|
||
|
||
### Medium — mobile persuasion and CTA timing
|
||
|
||
- [ ] **Sticky mobile CTA appears on a fixed pixel threshold rather than page context**
|
||
- File: `src/lib/components/MobileBookBar.svelte:26-37`
|
||
- Current: visibility is driven by `SHOW_AFTER_PX = 480` and
|
||
`HIDE_BELOW_PX = 120`.
|
||
- Why: a fixed threshold will feel early on some phones and late on
|
||
others. It also ignores whether the hero or booking section is
|
||
actually in view.
|
||
- Opportunity: switch to an `IntersectionObserver` tied to the hero or
|
||
booking section so the bar appears based on user context rather than
|
||
raw scroll position.
|
||
|
||
- [ ] **Testimonials section pushes users off-site before finishing the proof story**
|
||
- File: `src/lib/components/TestimonialsSection.svelte:128-134`
|
||
- Current: the Instagram CTA appears near the top of the testimonials
|
||
section, before the user has fully consumed the review content.
|
||
- Why: on mobile, sending users to Instagram this early interrupts the
|
||
conversion journey and competes with the booking path.
|
||
- Opportunity: demote the Instagram CTA below the carousel, or replace
|
||
it with a tighter trust-oriented proof CTA higher up.
|
||
|
||
- [ ] **Mobile pricing pages lose the consultative "not sure?" nudge**
|
||
- File: `src/lib/components/PricingPage.svelte:12-19`
|
||
- Current: the meet-and-greet reminder prompt is gated behind
|
||
`min-width: 769px`, so desktop gets a tailored nudge and mobile
|
||
does not.
|
||
- Why: mobile users are more likely to feel overwhelmed by stacked
|
||
pricing cards, not less. Removing the consultative reassurance on
|
||
the smallest screens is directionally backwards for conversion.
|
||
- Opportunity: add an inline mobile prompt after the first pricing
|
||
section that says, in effect, "Not sure which option fits? Book a
|
||
free Meet & Greet and we’ll help you choose."
|
||
|
||
### Medium — stacked-page CTA noise
|
||
|
||
- [ ] **Stacked pricing/service cards repeat the same CTA too many times**
|
||
- Files: `src/lib/components/PricingPage.svelte:141-159`,
|
||
`src/lib/components/ServiceLandingPage.svelte:94-112`
|
||
- Current: when cards collapse to one column on mobile, each card
|
||
keeps a full "Book a Meet & Greet" button.
|
||
- Why: the repetition turns persuasive choice architecture into visual
|
||
noise. Instead of helping the user decide, the page starts feeling
|
||
like a stack of repeated asks.
|
||
- Opportunity: treat this as a shared mobile pattern across pricing
|
||
and service pages. Keep one strong CTA per section, let the popular
|
||
card carry the primary action, and demote the rest.
|
||
|
||
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.
|