Design language tweaks v3

This commit is contained in:
2026-05-15 16:27:39 +12:00
parent 580d600c47
commit b950229003
14 changed files with 2746 additions and 246 deletions
+143 -5
View File
@@ -3,6 +3,7 @@
import { reveal } from '$lib/actions/reveal'; import { reveal } from '$lib/actions/reveal';
import CtaCard from '$lib/components/CtaCard.svelte'; import CtaCard from '$lib/components/CtaCard.svelte';
import PageHeader from '$lib/components/PageHeader.svelte'; import PageHeader from '$lib/components/PageHeader.svelte';
import Icon from '$lib/components/Icon.svelte';
import { getEnhancedImage } from '$lib/enhanced-images'; import { getEnhancedImage } from '$lib/enhanced-images';
import type { AboutPageContent } from '$lib/types'; import type { AboutPageContent } from '$lib/types';
@@ -90,8 +91,9 @@
{/if} {/if}
</div> </div>
<div class="about-founder-copy"> <div class="about-founder-copy">
<article class="about-founder-note">
{#if founderSection.eyebrow} {#if founderSection.eyebrow}
<span class="about-eyebrow">{founderSection.eyebrow}</span> <span class="about-eyebrow about-founder-kicker">{founderSection.eyebrow}</span>
{/if} {/if}
<h2 class="about-founder-heading"> <h2 class="about-founder-heading">
<span class="about-founder-heading-desktop"> <span class="about-founder-heading-desktop">
@@ -104,10 +106,34 @@
<span class="about-founder-title-highlight">{founderHeadingHighlight}</span> <span class="about-founder-title-highlight">{founderHeadingHighlight}</span>
</span> </span>
</h2> </h2>
<div class="about-founder-body">
{#each founderSection.body as paragraph} {#each founderSection.body as paragraph}
<p>{paragraph}</p> <p>{paragraph}</p>
{/each} {/each}
<a href="/contact-us" class="btn btn-green btn-mobile-center">Book a free Meet &amp; Greet</a> </div>
<div class="about-founder-signoff">
<div class="about-founder-signoff-text">
<span class="about-founder-name">Aless</span>
<span class="about-founder-role">Goodwalk founder</span>
</div>
</div>
<a
class="about-founder-contact-note"
href="mailto:info@goodwalk.co.nz"
aria-label="Email Aless at Goodwalk"
>
<span class="about-founder-contact-icon">
<Icon name="fas fa-envelope" />
</span>
<span>If you are unsure about anything, feel free to email me anytime.</span>
</a>
<a href="/contact-us" class="btn btn-green btn-mobile-center about-founder-cta">
Book a free Meet &amp; Greet
</a>
</article>
</div> </div>
</div> </div>
</section> </section>
@@ -267,6 +293,20 @@
color: #0d1a0d; color: #0d1a0d;
} }
.about-founder-note {
padding: 40px 42px 34px;
background: linear-gradient(180deg, rgba(251, 251, 251, 0.98) 0%, rgba(247, 248, 246, 1) 100%);
border: 1px solid rgba(17, 20, 24, 0.08);
border-radius: 28px;
box-shadow: var(--shadow-panel-elevated);
}
.about-founder-kicker {
display: block;
width: fit-content;
margin-bottom: 18px;
}
.about-founder-heading-desktop { .about-founder-heading-desktop {
display: block; display: block;
} }
@@ -321,16 +361,91 @@
} }
.about-founder-copy p { .about-founder-copy p {
margin: 14px 0 0; margin: 0;
color: #34363a; color: #34363a;
font-size: 17px; font-size: 17px;
line-height: 1.75; line-height: 1.75;
} }
.about-founder-copy .btn { .about-founder-body {
display: grid;
gap: 14px;
}
.about-founder-signoff {
display: flex;
align-items: center;
gap: 14px;
margin-top: 28px;
padding-top: 24px;
border-top: 1px solid rgba(17, 20, 24, 0.08);
}
.about-founder-signoff-text {
display: flex;
flex-direction: column;
gap: 2px;
}
.about-founder-name {
color: #0d1a0d;
font-family: var(--font-head);
font-size: 16px;
font-weight: 700;
line-height: 1.2;
}
.about-founder-role {
color: var(--gray);
font-size: 13px;
line-height: 1.3;
}
.about-founder-contact-note {
display: inline-flex;
align-items: center;
gap: 10px;
margin-top: 20px;
padding: 12px 16px;
border-radius: 18px;
background: rgba(33, 48, 33, 0.05);
box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.06);
color: var(--gw-green);
font-size: 14px;
font-weight: 600;
line-height: 1.5;
text-decoration: none;
transition: background 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
}
.about-founder-contact-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
border-radius: 50%;
background: #fff;
box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.07);
color: var(--gw-green);
font-size: 13px;
flex: 0 0 auto;
}
.about-founder-cta {
display: flex; display: flex;
width: fit-content; width: fit-content;
margin: 28px auto 0; margin: 28px 0 0;
}
@media (hover: hover) {
.about-founder-contact-note:hover {
background: rgba(33, 48, 33, 0.08);
box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.08),
0 10px 22px rgba(17, 20, 24, 0.05);
transform: translateY(-1px);
}
} }
/* ── FAQs ── */ /* ── FAQs ── */
@@ -421,6 +536,11 @@
gap: 28px; gap: 28px;
} }
.about-founder-note {
padding: 26px 24px 24px;
border-radius: 24px;
}
.about-founder-copy h2 { .about-founder-copy h2 {
font-size: 26px; font-size: 26px;
line-height: 1.02; line-height: 1.02;
@@ -440,6 +560,24 @@
line-height: 1.7; line-height: 1.7;
} }
.about-founder-kicker {
margin-left: auto;
margin-right: auto;
}
.about-founder-contact-note {
display: flex;
width: 100%;
font-size: 13px;
padding: 11px 14px;
text-align: center;
}
.about-founder-cta {
width: 100%;
justify-content: center;
}
.about-faq { .about-faq {
padding: 60px 0; padding: 60px 0;
} }
+1 -1
View File
@@ -34,7 +34,7 @@
</div> </div>
</PageHeader> </PageHeader>
<BookingSection {booking} {allowGeneralEnquiry} /> <BookingSection {booking} {allowGeneralEnquiry} variant="card-stepper" />
<InfoSection {info} /> <InfoSection {info} />
</main> </main>
+578 -5
View File
@@ -8,6 +8,7 @@
export let booking: BookingContent; export let booking: BookingContent;
export let allowGeneralEnquiry = false; export let allowGeneralEnquiry = false;
export let variant: 'default' | 'minimal-premium' | 'card-stepper' = 'default';
type EnquiryType = 'booking' | 'general'; type EnquiryType = 'booking' | 'general';
const visitStartedStorageKey = 'goodwalk_visit_started_at'; const visitStartedStorageKey = 'goodwalk_visit_started_at';
const journeyStorageKey = 'goodwalk_journey'; const journeyStorageKey = 'goodwalk_journey';
@@ -43,6 +44,11 @@
'Tell us your puppys age, routine, toilet needs, feeding schedule, and anything important we should know before visiting.' 'Tell us your puppys age, routine, toilet needs, feeding schedule, and anything important we should know before visiting.'
} }
}; };
const bookingAvatarDogs = [
{ image: '/images/archie-auckland-dog-walking-review.jpg', alt: 'Archie' },
{ image: '/images/monty-auckland-dog-walking-review.jpg', alt: 'Monty' },
{ image: '/images/otis-auckland-dog-walking-review.jpg', alt: 'Otis' }
];
let step = 1; let step = 1;
$: headingParts = splitBookingTitle(booking.title); $: headingParts = splitBookingTitle(booking.title);
@@ -136,6 +142,7 @@
: activeServicePrompt?.messagePlaceholder || 'Describe your pet, any special needs, or anything we should know.'; : activeServicePrompt?.messagePlaceholder || 'Describe your pet, any special needs, or anything we should know.';
$: successPetName = petName.trim() || 'your dog'; $: successPetName = petName.trim() || 'your dog';
$: serviceChoiceLocked = !isGeneralEnquiry && selectedServices.length === 1 && !showServicePicker; $: serviceChoiceLocked = !isGeneralEnquiry && selectedServices.length === 1 && !showServicePicker;
$: isCardStepper = variant === 'card-stepper';
onMount(() => { onMount(() => {
const now = Date.now(); const now = Date.now();
@@ -420,7 +427,13 @@
} }
</script> </script>
<section id="newlead" use:reveal={{ delay: 70 }} class="reveal-block"> <section
id="newlead"
use:reveal={{ delay: 70 }}
class="booking-shell reveal-block"
class:booking-shell--minimal-premium={variant === 'minimal-premium'}
class:booking-shell--card-stepper={variant === 'card-stepper'}
>
<div class="form-inner"> <div class="form-inner">
{#if submitted} {#if submitted}
<SuccessModal <SuccessModal
@@ -448,6 +461,7 @@
<span class="booking-title-highlight">{headingParts.highlight}</span> <span class="booking-title-highlight">{headingParts.highlight}</span>
</h2> </h2>
<p class="booking-intro">{bookingIntro}</p> <p class="booking-intro">{bookingIntro}</p>
{#if !isCardStepper}
<div class="booking-trust-row" aria-label="Booking highlights"> <div class="booking-trust-row" aria-label="Booking highlights">
<span class="booking-trust-chip"> <span class="booking-trust-chip">
<Icon name="fas fa-comment-dots" /> <Icon name="fas fa-comment-dots" />
@@ -480,6 +494,7 @@
<span class="booking-step-label">{ownerStepLabel}</span> <span class="booking-step-label">{ownerStepLabel}</span>
</button> </button>
</div> </div>
{/if}
</div> </div>
<form <form
@@ -503,15 +518,53 @@
/> />
</div> </div>
<div class:booking-form-shell={isCardStepper}>
{#if isCardStepper}
<div class="booking-social-proof" aria-label="Goodwalk dog families">
<div class="booking-avatar-group" aria-hidden="true">
{#each bookingAvatarDogs as dog}
<span class="booking-avatar-bubble">
<img src={dog.image} alt="" loading="lazy" />
</span>
{/each}
</div>
<p>Join other happy Goodwalk dog owners across Auckland.</p>
</div>
<div class="booking-form-shell-top">
<div class="booking-stepper" aria-label="Booking form steps">
<button
type="button"
class:active={step === 1}
class="booking-step"
on:click={() => setStep(1, step !== 1)}
>
<span class="booking-step-number">1</span>
<span class="booking-step-label">{detailsStepLabel}</span>
</button>
<span class="booking-step-divider" aria-hidden="true"></span>
<button
type="button"
class:active={step === 2}
class="booking-step"
on:click={goToOwnerStep}
>
<span class="booking-step-number">2</span>
<span class="booking-step-label">{ownerStepLabel}</span>
</button>
</div>
</div>
{/if}
{#if step === 1} {#if step === 1}
<input type="hidden" name="enquiryType" value={enquiryType} /> <input type="hidden" name="enquiryType" value={enquiryType} />
<div class="booking-panel"> <div class="booking-panel">
{#if detailsStepIntro} {#if detailsStepIntro && !isCardStepper}
<div class="booking-panel-banner">{detailsStepIntro}</div> <div class="booking-panel-banner">{detailsStepIntro}</div>
{/if} {/if}
<div <div
class:booking-card-grid-with-banner={Boolean(detailsStepIntro)} class:booking-card-grid-with-banner={Boolean(detailsStepIntro) && !isCardStepper}
class="booking-card-grid booking-card-grid-dog" class="booking-card-grid booking-card-grid-dog"
> >
{#if allowGeneralEnquiry && !isGeneralEnquiry} {#if allowGeneralEnquiry && !isGeneralEnquiry}
@@ -684,12 +737,12 @@
<input type="hidden" name="message" value={message} /> <input type="hidden" name="message" value={message} />
<div class="booking-panel"> <div class="booking-panel">
{#if ownerIntro} {#if ownerIntro && !isCardStepper}
<div class="booking-panel-banner">{ownerIntro}</div> <div class="booking-panel-banner">{ownerIntro}</div>
{/if} {/if}
<div <div
class:booking-card-grid-with-banner={Boolean(ownerIntro)} class:booking-card-grid-with-banner={Boolean(ownerIntro) && !isCardStepper}
class="booking-card-grid booking-card-grid-owner" class="booking-card-grid booking-card-grid-owner"
> >
<div class="booking-field-card booking-field-card-group booking-field-card-full"> <div class="booking-field-card booking-field-card-group booking-field-card-full">
@@ -791,6 +844,8 @@
</button> </button>
</div> </div>
{/if} {/if}
</div>
</form> </form>
</div> </div>
</section> </section>
@@ -820,4 +875,522 @@
opacity: 0; opacity: 0;
pointer-events: none; pointer-events: none;
} }
.booking-shell--card-stepper {
background:
linear-gradient(180deg, rgba(255, 255, 255, 0.7), rgba(248, 247, 242, 0.9));
}
.booking-shell--card-stepper :global(.form-inner) {
max-width: 1040px;
}
.booking-shell--card-stepper .booking-header {
max-width: 840px;
margin: 0 auto 34px;
}
.booking-shell--card-stepper .booking-eyebrow {
padding: 7px 14px;
background: rgba(33, 48, 33, 0.05);
box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.05);
text-transform: none;
letter-spacing: 0.04em;
}
.booking-shell--card-stepper .booking-title {
margin-bottom: 20px;
font-size: clamp(38px, 5vw, 58px);
line-height: 1.02;
}
.booking-shell--card-stepper .booking-intro {
max-width: 42rem;
margin: 0 auto;
}
.booking-shell--card-stepper .booking-form-shell {
max-width: 900px;
margin: 0 auto;
padding: 0 24px 28px;
border-radius: 30px;
background: rgba(255, 255, 255, 0.94);
box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.06),
0 22px 52px rgba(17, 20, 24, 0.08);
}
.booking-shell--card-stepper .booking-social-proof {
display: flex;
align-items: center;
justify-content: center;
gap: 16px;
margin: 0 -24px;
padding: 16px 24px;
border-radius: 30px 30px 0 0;
background:
linear-gradient(180deg, rgba(33, 48, 33, 0.06), rgba(33, 48, 33, 0.035));
box-shadow: inset 0 -1px 0 rgba(17, 20, 24, 0.08);
}
.booking-shell--card-stepper .booking-form-shell-top {
padding: 22px 0;
border-bottom: 1px solid rgba(17, 20, 24, 0.08);
}
.booking-shell--card-stepper .booking-social-proof p {
margin: 0;
color: var(--gw-green);
font-family: var(--font-head);
font-size: 17px;
font-weight: 600;
line-height: 1.3;
text-wrap: balance;
text-align: center;
}
.booking-shell--card-stepper .booking-avatar-group {
display: flex;
align-items: center;
flex: none;
padding-left: 14px;
}
.booking-shell--card-stepper .booking-avatar-bubble {
display: inline-flex;
width: 50px;
height: 50px;
margin-left: -14px;
overflow: hidden;
border: 3px solid rgba(255, 255, 255, 0.96);
border-radius: 50%;
background: rgba(255, 255, 255, 0.16);
box-shadow: 0 8px 18px rgba(17, 20, 24, 0.08);
}
.booking-shell--card-stepper .booking-avatar-bubble img {
width: 100%;
height: 100%;
object-fit: cover;
}
.booking-shell--card-stepper .booking-stepper {
gap: 20px;
margin-top: 24px;
padding: 0;
background: transparent;
box-shadow: none;
}
.booking-shell--card-stepper .booking-step {
min-height: 50px;
padding: 10px 16px;
border-radius: 999px;
}
.booking-shell--card-stepper .booking-step.active {
background: rgba(33, 48, 33, 0.06);
}
.booking-shell--card-stepper .booking-step-number {
width: 42px;
height: 42px;
border: none;
border-radius: 13px;
background: var(--gw-green);
color: var(--yellow);
font-size: 18px;
}
.booking-shell--card-stepper .booking-step.active .booking-step-number {
background: linear-gradient(135deg, var(--gw-green), var(--green-mid));
border: none;
}
.booking-shell--card-stepper .booking-step-divider {
width: 48px;
height: 1px;
background: rgba(17, 20, 24, 0.12);
}
.booking-shell--card-stepper .booking-panel {
max-width: none;
margin: 24px 0 0;
padding: 0;
background: transparent;
box-shadow: none;
}
.booking-shell--card-stepper .booking-panel-banner {
margin-bottom: 18px;
padding: 0;
border: none;
border-radius: 0;
background: transparent;
box-shadow: none;
color: #4f555c;
font-size: 16px;
line-height: 1.65;
}
.booking-shell--card-stepper .booking-card-grid {
gap: 14px;
}
.booking-shell--card-stepper .booking-card-grid-with-banner .booking-field-card {
border-radius: 26px;
}
.booking-shell--card-stepper .booking-field-card {
border-radius: 0;
background: transparent;
box-shadow: none;
padding: 0;
}
.booking-shell--card-stepper .booking-field-card-group {
padding: 0;
}
.booking-shell--card-stepper .booking-inline-switch {
justify-content: flex-start;
padding: 0 4px;
margin-bottom: 0;
color: #5d636a;
background: transparent;
box-shadow: none;
}
.booking-shell--card-stepper .booking-field-card label,
.booking-shell--card-stepper .booking-service-label {
color: #171b20;
font-size: 15px;
font-weight: 600;
letter-spacing: 0;
text-transform: none;
}
.booking-shell--card-stepper .booking-field-card input,
.booking-shell--card-stepper .booking-field-card textarea {
border: 1px solid rgba(17, 20, 24, 0.1);
background: #fff;
box-shadow: none;
}
.booking-shell--card-stepper .booking-field-card input:hover,
.booking-shell--card-stepper .booking-field-card textarea:hover {
border-color: rgba(17, 20, 24, 0.18);
background: #fff;
box-shadow: none;
}
.booking-shell--card-stepper .booking-field-card input:focus,
.booking-shell--card-stepper .booking-field-card textarea:focus {
border-color: rgba(33, 48, 33, 0.45);
background: #fff;
box-shadow: 0 0 0 4px rgba(255, 209, 0, 0.12);
}
.booking-shell--card-stepper .booking-selected-service-chip,
.booking-shell--card-stepper .booking-check-option {
background: transparent;
}
.booking-shell--card-stepper .booking-actions {
max-width: none;
margin-left: 0;
margin-right: 0;
}
.booking-shell--card-stepper .booking-actions-next,
.booking-shell--card-stepper .booking-actions-final {
margin-top: 18px;
}
.booking-shell--card-stepper .booking-next-note {
color: #687076;
}
.booking-shell--card-stepper .booking-submit-button,
.booking-shell--card-stepper .booking-next-button {
box-shadow:
inset 0 -2px 0 rgba(0, 0, 0, 0.08),
0 12px 24px rgba(17, 20, 24, 0.1);
}
.booking-shell--minimal-premium {
background:
linear-gradient(180deg, rgba(255, 255, 255, 0.78), rgba(248, 247, 242, 0.72));
}
.booking-shell--minimal-premium :global(.form-inner) {
max-width: 980px;
}
.booking-shell--minimal-premium .booking-header {
max-width: 760px;
margin: 0 auto 34px;
}
.booking-shell--minimal-premium .booking-eyebrow {
background: rgba(33, 48, 33, 0.06);
box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.05);
color: var(--gw-green);
}
.booking-shell--minimal-premium .booking-title {
margin-bottom: 18px;
color: #11171b;
}
.booking-shell--minimal-premium .booking-intro {
max-width: 38rem;
margin: 0 auto;
color: #59606d;
font-size: 16px;
line-height: 1.65;
}
.booking-shell--minimal-premium .booking-trust-row {
justify-content: center;
gap: 10px;
margin-top: 20px;
}
.booking-shell--minimal-premium .booking-trust-chip {
background: rgba(33, 48, 33, 0.05);
box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.05);
color: var(--gw-green);
}
.booking-shell--minimal-premium .booking-stepper {
justify-content: center;
margin-top: 24px;
}
.booking-shell--minimal-premium .booking-step {
background: rgba(255, 255, 255, 0.86);
box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.06),
0 8px 18px rgba(17, 20, 24, 0.05);
}
.booking-shell--minimal-premium .booking-step.active {
background: rgba(33, 48, 33, 0.08);
}
.booking-shell--minimal-premium .booking-panel {
max-width: 860px;
margin: 0 auto;
padding: 30px;
border-radius: 32px;
background: rgba(251, 251, 251, 0.92);
box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.05),
0 22px 52px rgba(17, 20, 24, 0.08);
}
.booking-shell--minimal-premium .booking-panel-banner {
margin-bottom: 22px;
padding: 0;
border-radius: 0;
background: transparent;
box-shadow: none;
color: #59606d;
font-size: 15px;
line-height: 1.65;
}
.booking-shell--minimal-premium .booking-card-grid {
gap: 18px;
}
.booking-shell--minimal-premium .booking-field-card,
.booking-shell--minimal-premium .booking-inline-switch {
border-radius: 24px;
background: linear-gradient(180deg, rgba(251, 251, 251, 0.98), rgba(247, 248, 246, 1));
box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.05),
0 12px 26px rgba(17, 20, 24, 0.05);
}
.booking-shell--minimal-premium .booking-field-card {
padding: 24px;
}
.booking-shell--minimal-premium .booking-field-card-group {
padding: 24px;
}
.booking-shell--minimal-premium .booking-inline-switch {
padding: 16px 18px;
}
.booking-shell--minimal-premium .booking-field-card label,
.booking-shell--minimal-premium .booking-service-label {
color: #171b20;
}
.booking-shell--minimal-premium .booking-field-card input,
.booking-shell--minimal-premium .booking-field-card textarea {
border: none;
background: rgba(255, 255, 255, 0.96);
box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.08),
0 1px 0 rgba(255, 255, 255, 0.3);
}
.booking-shell--minimal-premium .booking-field-card input:hover,
.booking-shell--minimal-premium .booking-field-card textarea:hover {
border: none;
background: #fff;
box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.12),
0 4px 12px rgba(17, 20, 24, 0.04);
}
.booking-shell--minimal-premium .booking-field-card input:focus,
.booking-shell--minimal-premium .booking-field-card textarea:focus {
border: none;
background: #fff;
box-shadow:
inset 0 0 0 2px rgba(255, 209, 0, 0.6),
0 0 0 4px rgba(255, 209, 0, 0.14);
}
.booking-shell--minimal-premium .booking-selected-service-chip,
.booking-shell--minimal-premium .booking-check-option {
background: rgba(255, 255, 255, 0.9);
}
.booking-shell--minimal-premium .booking-actions {
max-width: 860px;
margin-left: auto;
margin-right: auto;
}
.booking-shell--minimal-premium .booking-actions-next {
margin-top: 18px;
}
.booking-shell--minimal-premium .booking-actions-final {
margin-top: 18px;
}
.booking-shell--minimal-premium .booking-next-note {
color: #687076;
}
.booking-shell--minimal-premium .booking-submit-button,
.booking-shell--minimal-premium .booking-next-button {
box-shadow:
inset 0 -2px 0 rgba(0, 0, 0, 0.08),
0 12px 24px rgba(17, 20, 24, 0.1);
}
@media (max-width: 768px) {
.booking-shell--card-stepper .booking-header {
margin-bottom: 26px;
}
.booking-shell--card-stepper .booking-title {
margin-bottom: 18px;
font-size: 34px;
}
.booking-shell--card-stepper .booking-form-shell {
padding: 0 18px 22px;
border-radius: 24px;
}
.booking-shell--card-stepper .booking-social-proof {
align-items: center;
flex-direction: column;
gap: 10px;
margin: 0 -18px;
padding: 14px 18px;
border-radius: 24px 24px 0 0;
}
.booking-shell--card-stepper .booking-form-shell-top {
padding: 18px 0;
}
.booking-shell--card-stepper .booking-social-proof p {
font-size: 16px;
}
.booking-shell--card-stepper .booking-stepper {
gap: 10px;
padding: 0;
}
.booking-shell--card-stepper .booking-step {
min-width: 0;
flex: 1 1 0;
justify-content: center;
gap: 8px;
padding: 10px;
}
.booking-shell--card-stepper .booking-step-number {
width: 38px;
height: 38px;
font-size: 15px;
}
.booking-shell--card-stepper .booking-step-label {
font-size: 13px;
}
.booking-shell--card-stepper .booking-step-divider {
display: none;
}
.booking-shell--card-stepper .booking-panel {
margin-top: 20px;
}
.booking-shell--card-stepper .booking-panel-banner {
font-size: 15px;
}
.booking-shell--card-stepper .booking-field-card,
.booking-shell--card-stepper .booking-field-card-group {
padding: 0;
border-radius: 0;
}
.booking-shell--card-stepper .booking-inline-switch {
border-radius: 20px;
}
.booking-shell--minimal-premium .booking-header {
margin-bottom: 26px;
}
.booking-shell--minimal-premium .booking-intro {
font-size: 15px;
line-height: 1.58;
}
.booking-shell--minimal-premium .booking-stepper {
gap: 8px;
}
.booking-shell--minimal-premium .booking-panel {
padding: 18px;
border-radius: 24px;
}
.booking-shell--minimal-premium .booking-field-card,
.booking-shell--minimal-premium .booking-field-card-group {
padding: 20px;
border-radius: 22px;
}
.booking-shell--minimal-premium .booking-inline-switch {
border-radius: 20px;
}
}
</style> </style>
+6
View File
@@ -46,6 +46,11 @@
decoding="async" decoding="async"
/> />
<p>{footer.brandText}</p> <p>{footer.brandText}</p>
<div class="footer-social-cluster">
<div class="footer-social-invite" aria-hidden="true">
<span>Join the fun</span>
<Icon name="fas fa-arrow-turn-down" className="footer-social-invite-arrow" />
</div>
<div class="social-links"> <div class="social-links">
<a href={socialLinks[0].href} target="_blank" rel="noopener" aria-label="Instagram"> <a href={socialLinks[0].href} target="_blank" rel="noopener" aria-label="Instagram">
<Icon name="fab fa-instagram" /> <Icon name="fab fa-instagram" />
@@ -57,6 +62,7 @@
<Icon name="fab fa-google" /> <Icon name="fab fa-google" />
</a> </a>
</div> </div>
</div>
{#if footer.email || footer.phone} {#if footer.email || footer.phone}
<div class="footer-contact"> <div class="footer-contact">
+112 -47
View File
@@ -14,14 +14,12 @@
let showMeetGreetPrompt = false; let showMeetGreetPrompt = false;
let dismissMeetGreetPrompt = false; let dismissMeetGreetPrompt = false;
let bookingInView = false;
let promptShown = false; let promptShown = false;
let canShowDesktopPrompt = false; let canShowDesktopPrompt = false;
const desktopPromptMediaQuery = '(min-width: 769px)'; const desktopPromptMediaQuery = '(min-width: 769px)';
const scrollDepthThreshold = 0.65;
function revealMeetGreetPrompt() { function revealMeetGreetPrompt() {
if (dismissMeetGreetPrompt || bookingInView || promptShown || !canShowDesktopPrompt) { if (dismissMeetGreetPrompt || promptShown || !canShowDesktopPrompt) {
return; return;
} }
@@ -39,7 +37,7 @@
dismissMeetGreetPrompt = true; dismissMeetGreetPrompt = true;
} }
$: if ((!canShowDesktopPrompt || bookingInView) && showMeetGreetPrompt) { $: if (!canShowDesktopPrompt && showMeetGreetPrompt) {
showMeetGreetPrompt = false; showMeetGreetPrompt = false;
} }
@@ -51,42 +49,27 @@
canShowDesktopPrompt = event.matches; canShowDesktopPrompt = event.matches;
}; };
const firstPricingSection = document.querySelector<HTMLElement>('.pricing-section');
const handleScroll = () => { const handleScroll = () => {
if (promptShown || dismissMeetGreetPrompt || bookingInView || !canShowDesktopPrompt) { if (promptShown || dismissMeetGreetPrompt || !canShowDesktopPrompt || !firstPricingSection) {
return; return;
} }
const scrollableHeight = document.documentElement.scrollHeight - window.innerHeight; const firstSectionBottom = firstPricingSection.getBoundingClientRect().bottom;
if (scrollableHeight <= 0) return; if (firstSectionBottom <= 0) {
const scrollPercent = window.scrollY / scrollableHeight;
if (scrollPercent >= scrollDepthThreshold) {
revealMeetGreetPrompt(); revealMeetGreetPrompt();
} }
}; };
window.addEventListener('scroll', handleScroll, { passive: true }); window.addEventListener('scroll', handleScroll, { passive: true });
const bookingSection = document.getElementById('newlead');
const bookingObserver = bookingSection
? new IntersectionObserver(
([entry]) => {
bookingInView = entry.isIntersecting;
},
{ threshold: 0.2 }
)
: null;
if (bookingObserver && bookingSection) {
bookingObserver.observe(bookingSection);
}
desktopPromptQuery.addEventListener('change', handleDesktopPromptViewportChange); desktopPromptQuery.addEventListener('change', handleDesktopPromptViewportChange);
handleScroll();
return () => { return () => {
window.removeEventListener('scroll', handleScroll); window.removeEventListener('scroll', handleScroll);
desktopPromptQuery.removeEventListener('change', handleDesktopPromptViewportChange); desktopPromptQuery.removeEventListener('change', handleDesktopPromptViewportChange);
bookingObserver?.disconnect();
}; };
}); });
</script> </script>
@@ -174,7 +157,7 @@
testimonials={content.testimonials} testimonials={content.testimonials}
seedKey="/our-pricing" seedKey="/our-pricing"
/> />
<BookingSection booking={pageContent.booking} /> <BookingSection booking={pageContent.booking} variant="card-stepper" />
{#if showMeetGreetPrompt} {#if showMeetGreetPrompt}
<aside class="meet-greet-prompt" aria-label="Free meet and greet reminder"> <aside class="meet-greet-prompt" aria-label="Free meet and greet reminder">
@@ -183,16 +166,36 @@
</button> </button>
<div class="meet-greet-copy"> <div class="meet-greet-copy">
<div class="meet-greet-top">
<span class="meet-greet-kicker"> <span class="meet-greet-kicker">
<Icon name="fas fa-comment-dots" /> <Icon name="fas fa-comment-dots" />
Free Meet & Greet Free Meet & Greet
</span> </span>
<div class="meet-greet-profile" aria-label="Aless from Goodwalk">
<img
class="meet-greet-avatar"
src="/images/founder-image-aless-goodwalk.jpg"
alt="Aless from Goodwalk"
width="52"
height="52"
/>
<div class="meet-greet-profile-copy">
<strong>Talk it through with Aless</strong>
<span>Founder, Goodwalk</span>
</div>
</div>
</div>
<p> <p>
Not sure which option fits best? We can talk it through together and make sure your dog ends up happy. Not sure which option fits best? Aless can help you choose the right walk or visit for your dog, routine, and temperament.
</p> </p>
</div> </div>
<a class="meet-greet-cta" href="#newlead" on:click={handleMeetGreetCta}>Book a Meet &amp; Greet</a> <a class="meet-greet-cta" href="#newlead" on:click={handleMeetGreetCta}>
<span>Book a Meet &amp; Greet</span>
<Icon name="fas fa-arrow-right" />
</a>
</aside> </aside>
{/if} {/if}
</main> </main>
@@ -276,8 +279,8 @@
height: 56px; height: 56px;
margin-bottom: 16px; margin-bottom: 16px;
border-radius: 16px; border-radius: 16px;
background: var(--gw-green); background: linear-gradient(135deg, var(--gw-green), var(--green-mid));
color: #fff; color: var(--yellow);
font-size: 22px; font-size: 22px;
} }
@@ -304,6 +307,8 @@
.pricing-plan-grid-three { .pricing-plan-grid-three {
grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-columns: repeat(3, minmax(0, 1fr));
max-width: calc(((var(--max-w) - (var(--space-container-x) * 2) - (22px * 3)) / 4 * 3) + (22px * 2));
margin-inline: auto;
} }
.pricing-section-mobile-cta, .pricing-section-mobile-cta,
@@ -317,23 +322,30 @@
bottom: 24px; bottom: 24px;
z-index: 30; z-index: 30;
display: flex; display: flex;
align-items: flex-end; flex-direction: column;
gap: 18px; gap: 18px;
width: min(420px, calc(100vw - 32px)); width: min(430px, calc(100vw - 32px));
padding: 18px 18px 18px 20px; padding: 20px;
border-radius: 28px; border-radius: 30px;
background: background:
linear-gradient(135deg, rgba(255, 255, 255, 0.98), rgba(247, 243, 232, 0.98)); radial-gradient(circle at top right, rgba(255, 209, 0, 0.12), rgba(255, 209, 0, 0) 34%),
linear-gradient(180deg, rgba(251, 251, 251, 0.98), rgba(247, 248, 246, 0.98));
box-shadow: box-shadow:
0 20px 40px rgba(17, 20, 24, 0.16), 0 20px 40px rgba(17, 20, 24, 0.14),
0 0 0 1px rgba(17, 20, 24, 0.06); inset 0 0 0 1px rgba(17, 20, 24, 0.06);
animation: meet-greet-rise 0.28s cubic-bezier(0.22, 1, 0.36, 1); animation: meet-greet-rise 0.28s cubic-bezier(0.22, 1, 0.36, 1);
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
} }
.meet-greet-copy { .meet-greet-copy {
min-width: 0; min-width: 0;
flex: 1; }
.meet-greet-top {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 14px;
} }
.meet-greet-kicker { .meet-greet-kicker {
@@ -355,22 +367,69 @@
font-size: 12px; font-size: 12px;
} }
.meet-greet-profile {
display: flex;
align-items: center;
gap: 10px;
min-width: 0;
padding: 8px 10px 8px 8px;
border-radius: 18px;
background: rgba(33, 48, 33, 0.05);
box-shadow: inset 0 0 0 1px rgba(33, 48, 33, 0.07);
}
.meet-greet-avatar {
width: 52px;
height: 52px;
border-radius: 16px;
object-fit: cover;
object-position: center top;
flex: 0 0 auto;
box-shadow:
0 8px 20px rgba(17, 20, 24, 0.12),
inset 0 0 0 1px rgba(255, 255, 255, 0.18);
}
.meet-greet-profile-copy {
display: flex;
flex-direction: column;
min-width: 0;
}
.meet-greet-profile-copy strong {
color: #16181d;
font-family: var(--font-head);
font-size: 12px;
font-weight: 700;
line-height: 1.3;
}
.meet-greet-profile-copy span {
color: #59606d;
font-size: 12px;
line-height: 1.35;
}
.meet-greet-copy p { .meet-greet-copy p {
margin: 0; margin: 14px 0 0;
color: #2f3134; color: #2f3134;
font-size: 15px; font-size: 15px;
line-height: 1.55; line-height: 1.55;
} }
.meet-greet-cta { .meet-greet-cta {
flex-shrink: 0; display: inline-flex;
align-self: center; align-items: center;
padding: 12px 18px; justify-content: center;
gap: 10px;
width: 100%;
padding: 14px 18px;
border-radius: 999px; border-radius: 999px;
background: var(--yellow); background: linear-gradient(135deg, #ffd54a, var(--yellow-soft));
color: #111; color: #111;
font-family: var(--font-head); font-family: var(--font-head);
font-size: 14px; font-size: 14px;
font-weight: 700;
text-decoration: none; text-decoration: none;
box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.08); box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.08);
transition: transition:
@@ -401,7 +460,7 @@
@media (hover: hover) { @media (hover: hover) {
.meet-greet-cta:hover { .meet-greet-cta:hover {
transform: translateY(-2px); transform: translateY(-2px);
background: #ffd100; background: linear-gradient(135deg, #ffdc66, #f4c94f);
box-shadow: box-shadow:
inset 0 -2px 0 rgba(0, 0, 0, 0.08), inset 0 -2px 0 rgba(0, 0, 0, 0.08),
0 12px 24px rgba(17, 20, 24, 0.12); 0 12px 24px rgba(17, 20, 24, 0.12);
@@ -434,6 +493,7 @@
.pricing-plan-grid, .pricing-plan-grid,
.pricing-plan-grid-three { .pricing-plan-grid-three {
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
max-width: none;
} }
} }
@@ -470,6 +530,7 @@
.pricing-plan-grid-three { .pricing-plan-grid-three {
grid-template-columns: 1fr; grid-template-columns: 1fr;
gap: 18px; gap: 18px;
max-width: none;
} }
.pricing-section-mobile-cta { .pricing-section-mobile-cta {
@@ -518,13 +579,17 @@
left: 16px; left: 16px;
bottom: 16px; bottom: 16px;
width: auto; width: auto;
flex-direction: column;
align-items: stretch;
gap: 14px; gap: 14px;
padding: 18px 18px 16px; padding: 18px 18px 16px;
border-radius: 28px; border-radius: 28px;
} }
.meet-greet-top {
flex-direction: column;
align-items: stretch;
gap: 12px;
}
.meet-greet-copy p { .meet-greet-copy p {
font-size: 14px; font-size: 14px;
line-height: 1.5; line-height: 1.5;
@@ -532,7 +597,7 @@
} }
.meet-greet-cta { .meet-greet-cta {
align-self: flex-start; width: 100%;
} }
} }
</style> </style>
+173 -26
View File
@@ -1,4 +1,6 @@
<script lang="ts"> <script lang="ts">
import Icon from '$lib/components/Icon.svelte';
export let plan: { export let plan: {
title: string; title: string;
price: string; price: string;
@@ -18,16 +20,39 @@
style="--mobile-order:{plan.mobileOrder};" style="--mobile-order:{plan.mobileOrder};"
> >
{#if plan.isPopular} {#if plan.isPopular}
<span class="plan-card__ribbon">Popular</span> <span class="plan-card__ribbon">
<Icon name="fas fa-star" className="plan-card__ribbon-icon" />
Popular
</span>
{/if} {/if}
<div class="plan-card__header">
<div class="plan-card__eyebrow">
<span class="plan-card__eyebrow-badge">
<Icon name={variant === 'pricing' ? 'fas fa-paw' : 'fas fa-leaf'} className="plan-card__eyebrow-icon" />
</span>
<span>{plan.isPopular ? 'Goodwalk favourite' : variant === 'pricing' ? 'Flexible routine' : 'Tailored support'}</span>
</div>
<h3>{plan.title}</h3> <h3>{plan.title}</h3>
<div class="plan-card__price">{plan.price}</div> <div class="plan-card__price">{plan.price}</div>
<p class="plan-card__period">{plan.period}</p> <p class="plan-card__period">{plan.period}</p>
</div>
<div class="plan-card__body">
<p class="plan-card__feature-label">
<Icon name="fas fa-circle-check" className="plan-card__feature-label-icon" />
What's included
</p>
<ul class="plan-card__features"> <ul class="plan-card__features">
{#each plan.features as feature} {#each plan.features as feature}
<li>{feature}</li> <li>
<Icon
name={variant === 'pricing' ? 'fas fa-check' : 'fas fa-paw'}
className="plan-card__feature-icon"
/>
<span>{feature}</span>
</li>
{/each} {/each}
</ul> </ul>
</div>
<a class="btn btn-yellow plan-card__cta" href="#newlead">Book a Meet &amp; Greet</a> <a class="btn btn-yellow plan-card__cta" href="#newlead">Book a Meet &amp; Greet</a>
</article> </article>
@@ -38,22 +63,37 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
border-radius: 28px; border-radius: 28px;
padding: 30px 26px; border: 1.5px solid rgba(17, 20, 24, 0.09);
padding: 38px 26px 30px;
overflow: visible;
transition: transition:
transform 0.18s cubic-bezier(0.22, 1, 0.36, 1), transform 0.18s cubic-bezier(0.22, 1, 0.36, 1),
box-shadow 0.22s ease, box-shadow 0.22s ease,
border-color 0.22s ease; border-color 0.22s ease,
filter 0.22s ease;
}
.plan-card::before {
content: '';
position: absolute;
inset: 0 0 auto;
height: 88px;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0));
pointer-events: none;
} }
.plan-card--popular { .plan-card--popular {
border: 2px solid var(--yellow); border: 2px solid var(--yellow);
box-shadow:
inset 0 0 0 1px rgba(242, 191, 47, 0.45),
0 14px 34px rgba(17, 20, 24, 0.06);
} }
/* ── Service variant ── */ /* ── Service variant ── */
.plan-card--service { .plan-card--service {
align-items: stretch; align-items: stretch;
height: 100%; height: 100%;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.96) 0%, rgba(247, 248, 246, 0.98) 100%); background: linear-gradient(180deg, rgba(251, 251, 251, 0.98) 0%, rgba(247, 248, 246, 1) 100%);
box-shadow: box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.045), inset 0 0 0 1px rgba(17, 20, 24, 0.045),
0 8px 40px rgba(0, 0, 0, 0.06); 0 8px 40px rgba(0, 0, 0, 0.06);
@@ -63,25 +103,80 @@
.plan-card--pricing { .plan-card--pricing {
align-items: center; align-items: center;
text-align: center; text-align: center;
background: #fff; background: linear-gradient(180deg, rgba(251, 251, 251, 0.98) 0%, rgba(247, 248, 246, 1) 100%);
box-shadow: 0 14px 34px rgba(17, 20, 24, 0.05); box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.045),
0 14px 34px rgba(17, 20, 24, 0.05);
}
.plan-card--pricing.plan-card--popular {
background:
radial-gradient(circle at top, rgba(255, 209, 0, 0.12), rgba(255, 209, 0, 0) 40%),
linear-gradient(180deg, rgba(251, 251, 251, 0.98) 0%, rgba(247, 248, 246, 1) 100%);
}
.plan-card__header,
.plan-card__body {
position: relative;
z-index: 1;
width: 100%;
} }
/* ── Ribbon ── */ /* ── Ribbon ── */
.plan-card__ribbon { .plan-card__ribbon {
display: inline-flex;
align-items: center;
gap: 6px;
position: absolute; position: absolute;
top: 0; top: 0;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -40%);
padding: 6px 12px; padding: 6px 12px;
border-radius: 999px; border-radius: 999px;
background: var(--yellow); background: linear-gradient(135deg, var(--gw-green), var(--green-mid));
color: #000; color: #fff;
font-family: var(--font-head); font-family: var(--font-head);
font-size: 11px; font-size: 11px;
font-weight: 700; font-weight: 700;
letter-spacing: 0.04em; letter-spacing: 0.04em;
text-transform: uppercase; text-transform: uppercase;
box-shadow: 0 10px 20px rgba(17, 20, 24, 0.08);
white-space: nowrap;
}
:global(.plan-card__ribbon-icon) {
color: var(--yellow);
font-size: 10px;
}
.plan-card__eyebrow {
display: inline-flex;
align-items: center;
gap: 10px;
margin-bottom: 18px;
color: var(--gw-green);
font-family: var(--font-head);
font-size: 11px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.plan-card__eyebrow-badge {
display: inline-flex;
align-items: center;
justify-content: center;
width: 34px;
height: 34px;
border-radius: 12px;
background: linear-gradient(135deg, var(--gw-green), var(--green-mid));
color: #fff;
box-shadow: 0 10px 22px rgba(33, 48, 33, 0.14);
}
:global(.plan-card__eyebrow-icon) {
color: var(--yellow);
font-size: 14px;
} }
/* ── Heading ── */ /* ── Heading ── */
@@ -90,7 +185,7 @@
font-family: var(--font-head); font-family: var(--font-head);
font-size: 22px; font-size: 22px;
line-height: 1.2; line-height: 1.2;
color: #000; color: #16181d;
} }
/* ── Price ── */ /* ── Price ── */
@@ -110,7 +205,7 @@
font-size: 52px; font-size: 52px;
line-height: 0.95; line-height: 0.95;
letter-spacing: -0.05em; letter-spacing: -0.05em;
color: #000; color: #16181d;
} }
/* ── Period ── */ /* ── Period ── */
@@ -131,9 +226,33 @@
letter-spacing: 0.08em; letter-spacing: 0.08em;
} }
.plan-card__body {
margin-top: 24px;
padding-top: 18px;
border-top: 1px solid rgba(17, 20, 24, 0.07);
}
.plan-card__feature-label {
display: inline-flex;
align-items: center;
gap: 8px;
margin: 0 0 14px;
color: #59606d;
font-family: var(--font-head);
font-size: 11px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
:global(.plan-card__feature-label-icon) {
color: var(--gw-green);
font-size: 12px;
}
/* ── Features ── */ /* ── Features ── */
.plan-card__features { .plan-card__features {
margin: 24px 0 0; margin: 0;
padding: 0; padding: 0;
list-style: none; list-style: none;
} }
@@ -144,8 +263,9 @@
/* Service: bullet style */ /* Service: bullet style */
.plan-card--service .plan-card__features li { .plan-card--service .plan-card__features li {
position: relative; display: grid;
padding-left: 24px; grid-template-columns: 18px minmax(0, 1fr);
gap: 10px;
color: #34363a; color: #34363a;
font-size: 15px; font-size: 15px;
line-height: 1.5; line-height: 1.5;
@@ -155,14 +275,10 @@
margin-top: 12px; margin-top: 12px;
} }
.plan-card--service .plan-card__features li::before { :global(.plan-card--service .plan-card__feature-icon) {
content: '•'; margin-top: 3px;
position: absolute; color: var(--yellow-soft);
left: 6px; font-size: 12px;
top: 0;
color: var(--yellow);
font-size: 20px;
line-height: 1;
} }
/* Pricing: divider style */ /* Pricing: divider style */
@@ -171,11 +287,26 @@
} }
.plan-card--pricing .plan-card__features li { .plan-card--pricing .plan-card__features li {
display: grid;
grid-template-columns: 18px minmax(0, 1fr);
gap: 10px;
padding: 15px 0; padding: 15px 0;
border-top: 1px solid rgba(17, 20, 24, 0.08); border-top: 1px solid rgba(17, 20, 24, 0.08);
color: #34363a; color: #34363a;
font-size: 16px; font-size: 16px;
line-height: 1.5; line-height: 1.5;
text-align: left;
}
.plan-card--pricing .plan-card__features li:first-child {
padding-top: 0;
border-top: none;
}
:global(.plan-card--pricing .plan-card__feature-icon) {
margin-top: 3px;
color: var(--gw-green);
font-size: 12px;
} }
/* ── CTA ── */ /* ── CTA ── */
@@ -190,6 +321,7 @@
@media (hover: hover) { @media (hover: hover) {
.plan-card--service:hover { .plan-card--service:hover {
transform: translateY(-2px); transform: translateY(-2px);
border-color: rgba(17, 20, 24, 0.14);
box-shadow: box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.055), inset 0 0 0 1px rgba(17, 20, 24, 0.055),
0 10px 40px rgba(0, 0, 0, 0.08); 0 10px 40px rgba(0, 0, 0, 0.08);
@@ -197,8 +329,16 @@
} }
.plan-card--pricing:hover { .plan-card--pricing:hover {
transform: translateY(-6px) scale(1.012); transform: translateY(-2px);
box-shadow: 0 22px 44px rgba(17, 20, 24, 0.1); border-color: rgba(17, 20, 24, 0.14);
box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.06),
0 18px 38px rgba(17, 20, 24, 0.08);
filter: brightness(1.012);
}
.plan-card--popular:hover {
border-color: var(--yellow);
} }
} }
@@ -210,7 +350,14 @@
@media (max-width: 768px) { @media (max-width: 768px) {
.plan-card { .plan-card {
order: var(--mobile-order, 0); order: var(--mobile-order, 0);
padding: 28px 22px; width: min(100%, 420px);
margin-inline: auto;
padding: 36px 22px 28px;
}
.plan-card__body {
margin-top: 22px;
padding-top: 16px;
} }
.plan-card--pricing .plan-card__price { .plan-card--pricing .plan-card__price {
+1 -1
View File
@@ -358,7 +358,7 @@
testimonials={content.testimonials} testimonials={content.testimonials}
seedKey={currentPath} seedKey={currentPath}
/> />
<BookingSection booking={pageContent.booking} /> <BookingSection booking={pageContent.booking} variant="card-stepper" />
</main> </main>
<style> <style>
+1 -1
View File
@@ -260,7 +260,7 @@
</div> </div>
</section> </section>
<BookingSection booking={content.booking} /> <BookingSection booking={content.booking} variant="card-stepper" />
</main> </main>
<style> <style>
@@ -201,13 +201,6 @@
</button> </button>
<div bind:this={stageEl} class="testimonial-stage" on:scroll={handleStageScroll}> <div bind:this={stageEl} class="testimonial-stage" on:scroll={handleStageScroll}>
<div class="testimonial-woof" aria-hidden="true">
<span class="testimonial-woof-text">WOOF</span>
<span class="testimonial-ray testimonial-ray-1"></span>
<span class="testimonial-ray testimonial-ray-2"></span>
<span class="testimonial-ray testimonial-ray-3"></span>
</div>
{#each slides as testimonial, index} {#each slides as testimonial, index}
<article class:testimonial-slide-active={index === activeIndex} class="testimonial-slide"> <article class:testimonial-slide-active={index === activeIndex} class="testimonial-slide">
<div class="testimonial-photo-wrap"> <div class="testimonial-photo-wrap">
@@ -619,54 +612,6 @@
display: none; display: none;
} }
.testimonial-woof {
position: absolute;
top: 40px;
right: 60px;
z-index: 2;
color: #2e3031;
transform: rotate(-6deg);
transform-origin: center center;
}
.testimonial-woof-text {
display: inline-block;
font-family: 'Fredoka', 'Fredoka One', var(--font-head), sans-serif;
font-size: 32px;
line-height: 1;
letter-spacing: 0.02em;
}
.testimonial-ray {
position: absolute;
border-radius: 999px;
background: #ffd100;
}
.testimonial-ray-1 {
top: -12px;
right: -48px;
width: 32px;
height: 11px;
transform: rotate(-35deg);
}
.testimonial-ray-2 {
top: 6px;
right: -60px;
width: 46px;
height: 13px;
transform: rotate(-35deg);
}
.testimonial-ray-3 {
top: 24px;
right: -50px;
width: 36px;
height: 11px;
transform: rotate(-35deg);
}
.testimonial-arrow { .testimonial-arrow {
position: absolute; position: absolute;
top: 50%; top: 50%;
@@ -715,9 +660,6 @@
font-size: 17px; font-size: 17px;
} }
.testimonial-woof {
right: 40px;
}
} }
@media (max-width: 767px) { @media (max-width: 767px) {
@@ -825,39 +767,6 @@
font-size: 20px; font-size: 20px;
} }
.testimonial-woof {
top: 16px;
right: 18px;
}
.testimonial-woof-text {
font-size: 22px;
}
.testimonial-ray {
right: -28px;
width: 9px;
}
.testimonial-ray-1 {
top: -7px;
height: 34px;
}
.testimonial-ray-2 {
top: 10px;
right: -38px;
width: 34px;
height: 9px;
}
.testimonial-ray-3 {
top: 35px;
right: -28px;
width: 27px;
height: 8px;
}
.testimonial-arrow-left, .testimonial-arrow-left,
.testimonial-arrow-right { .testimonial-arrow-right {
display: none; display: none;
@@ -0,0 +1,694 @@
<script lang="ts">
export let idPrefix: string;
export let lead = '';
export let submitLabel = 'Book a free Meet & Greet';
export let tone: 'default' | 'conversational' | 'minimal' = 'default';
export let layout: 'stacked' | 'carded' = 'stacked';
export let eyebrow = 'Free Meet & Greet';
export let title = 'Tell us about your dog';
export let subtitle =
'A guided first step so we can recommend the right walk, visit, or calmer starting point.';
let submitted = false;
let step = 1;
let ownerStepUnlocked = false;
function handleSubmit() {
if (step === 1) {
ownerStepUnlocked = true;
step = 2;
return;
}
submitted = true;
}
function goToStep(nextStep: number) {
if (nextStep === 2 && !ownerStepUnlocked) {
return;
}
step = nextStep;
}
</script>
<form
class={`vf-form vf-form--${tone} vf-form--${layout}`}
on:submit|preventDefault={handleSubmit}
novalidate
>
<div class="vf-header">
<span class="vf-eyebrow">{eyebrow}</span>
<h3 class="vf-title">{title}</h3>
<p class="vf-subtitle">{subtitle}</p>
<div class="vf-stepper" aria-label="Application steps">
<button
type="button"
class:active={step === 1}
class="vf-step"
on:click={() => goToStep(1)}
>
<span class="vf-step-number">1</span>
<span class="vf-step-label">Dog details</span>
</button>
<span class="vf-step-divider" aria-hidden="true"></span>
<button
type="button"
class:active={step === 2}
class="vf-step"
disabled={!ownerStepUnlocked}
aria-disabled={!ownerStepUnlocked}
on:click={() => goToStep(2)}
>
<span class="vf-step-number">2</span>
<span class="vf-step-label">Owner details</span>
</button>
</div>
</div>
{#if lead}
<p class="vf-lead">{lead}</p>
{/if}
{#if step === 1}
<section class="vf-group" aria-labelledby={`${idPrefix}-dog-group`}>
<div class="vf-group-head">
<p class="vf-kicker" id={`${idPrefix}-dog-group`}>Dog details</p>
<p class="vf-group-copy">
A few calm details first so we can judge fit, pace, and the right kind of outing.
</p>
</div>
<div class="vf-grid vf-grid--two">
<label class="vf-field">
<span class="vf-label">Dog name</span>
<input id={`${idPrefix}-dog-name`} name="dogName" type="text" placeholder="Maya" />
</label>
<label class="vf-field">
<span class="vf-label">Suburb / location</span>
<input
id={`${idPrefix}-location`}
name="location"
type="text"
placeholder="Mt Eden, Grey Lynn, Ponsonby…"
/>
</label>
</div>
<fieldset class="vf-choice-group">
<legend class="vf-label">What feels closest right now?</legend>
<p class="vf-helper">
Not sure is completely fine. We can sort that out at the Meet &amp; Greet.
</p>
<div class="vf-choices">
<label class="vf-choice">
<input type="radio" name={`${idPrefix}-service-fit`} value="tiny-gang" />
<span>Tiny Gang Pack Walks</span>
</label>
<label class="vf-choice">
<input type="radio" name={`${idPrefix}-service-fit`} value="one-to-one" />
<span>1:1 Walks</span>
</label>
<label class="vf-choice">
<input type="radio" name={`${idPrefix}-service-fit`} value="puppy-visits" />
<span>Puppy Visits</span>
</label>
<label class="vf-choice">
<input type="radio" name={`${idPrefix}-service-fit`} value="not-sure" checked />
<span>Not sure yet</span>
</label>
</div>
</fieldset>
<label class="vf-field vf-field--full">
<span class="vf-label">About your dog</span>
<textarea
id={`${idPrefix}-about-dog`}
name="aboutDog"
rows="5"
placeholder="Tell us about age, size, confidence, leash manners, how they feel around other dogs, and anything that helps us make the right recommendation."
></textarea>
</label>
<div class="vf-note-row" aria-label="Helpful notes">
<article class="vf-note">
<span class="vf-note-title">Nervous dogs</span>
<p>
If your dog is shy, easily overwhelmed, or still building confidence, mention it here.
That often points us toward a calmer first step.
</p>
</article>
<article class="vf-note">
<span class="vf-note-title">Tiny Gang suitability</span>
<p>
Our small-group walks work best for dogs who enjoy the right company, gentle
structure, and a routine they can settle into.
</p>
</article>
</div>
</section>
{/if}
{#if step === 2}
<section class="vf-group" aria-labelledby={`${idPrefix}-owner-group`}>
<div class="vf-group-head">
<p class="vf-kicker" id={`${idPrefix}-owner-group`}>Owner details</p>
<p class="vf-group-copy">
So Aless can reply properly and arrange a free Meet &amp; Greet without back-and-forth.
</p>
</div>
<div class="vf-grid vf-grid--three">
<label class="vf-field">
<span class="vf-label">Owner name</span>
<input id={`${idPrefix}-owner-name`} name="ownerName" type="text" placeholder="Your full name" />
</label>
<label class="vf-field">
<span class="vf-label">Email</span>
<input id={`${idPrefix}-email`} name="email" type="email" placeholder="you@example.com" />
</label>
<label class="vf-field">
<span class="vf-label">Phone</span>
<input id={`${idPrefix}-phone`} name="phone" type="tel" placeholder="021 123 4567" />
</label>
</div>
<article class="vf-owner-note">
<span class="vf-note-title">What happens next</span>
<p>
Well reply personally, talk through fit, and arrange the free Meet &amp; Greet if it
feels like the right next step.
</p>
</article>
</section>
{/if}
<div class="vf-footer">
<p class="vf-reassurance">
Free Meet &amp; Greet. No pressure. Just the right starting point for your dog.
</p>
<div class="vf-actions">
{#if step === 2}
<button type="button" class="vf-secondary" on:click={() => goToStep(1)}>Back</button>
{/if}
<button type="submit" class="vf-submit">
{step === 1 ? 'Next: owner details' : submitLabel}
</button>
</div>
</div>
{#if submitted}
<p class="vf-success" role="status">
Demo only: this variant would hand the enquiry to Aless and prompt a free Meet &amp; Greet.
</p>
{/if}
</form>
<style>
.vf-form {
display: grid;
gap: 24px;
}
.vf-form--carded {
gap: 18px;
}
.vf-header {
display: grid;
gap: 12px;
}
.vf-eyebrow {
display: inline-flex;
align-items: center;
width: fit-content;
min-height: 30px;
padding: 0 12px;
border-radius: 999px;
background: rgba(33, 48, 33, 0.07);
box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.05);
color: var(--gw-green);
font-family: var(--font-head);
font-size: 11px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.vf-title {
margin: 0;
color: #11171b;
font-family: var(--font-head);
font-size: clamp(26px, 3vw, 34px);
line-height: 1.06;
letter-spacing: -0.04em;
}
.vf-subtitle {
margin: 0;
color: #59606d;
font-size: 15px;
line-height: 1.6;
}
.vf-stepper {
display: flex;
align-items: center;
gap: 10px;
margin-top: 4px;
}
.vf-step {
display: inline-flex;
align-items: center;
gap: 10px;
min-height: 44px;
padding: 0 14px 0 10px;
border: none;
border-radius: 999px;
background: rgba(255, 255, 255, 0.84);
box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.06);
color: #50555c;
cursor: pointer;
transition:
background 0.18s ease,
color 0.18s ease,
transform 0.18s cubic-bezier(0.22, 1, 0.36, 1);
}
.vf-step.active {
background: rgba(33, 48, 33, 0.08);
color: #11171b;
}
.vf-step:disabled {
cursor: default;
opacity: 0.55;
}
.vf-step-number {
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
border-radius: 10px;
background: var(--gw-green);
color: var(--yellow);
font-family: var(--font-head);
font-size: 12px;
font-weight: 700;
}
.vf-step-label {
font-family: var(--font-head);
font-size: 12px;
font-weight: 700;
line-height: 1.2;
}
.vf-step-divider {
width: 26px;
height: 1px;
background: rgba(17, 20, 24, 0.1);
}
.vf-lead {
margin: 0;
color: #4c5056;
font-size: 15px;
line-height: 1.65;
}
.vf-group {
display: grid;
gap: 18px;
}
.vf-form--carded .vf-group {
padding: 22px;
border-radius: 24px;
background: linear-gradient(180deg, rgba(251, 251, 251, 0.98) 0%, rgba(247, 248, 246, 1) 100%);
box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.06),
0 12px 28px rgba(17, 20, 24, 0.06);
}
.vf-group-head {
display: grid;
gap: 6px;
}
.vf-kicker {
margin: 0;
color: var(--gw-green);
font-family: var(--font-head);
font-size: 11px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.vf-group-copy {
margin: 0;
color: #59606d;
font-size: 14px;
line-height: 1.55;
}
.vf-grid {
display: grid;
gap: 14px;
}
.vf-grid--two {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.vf-grid--three {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.vf-field {
display: grid;
gap: 8px;
}
.vf-field--full {
width: 100%;
}
.vf-label,
.vf-choice-group legend {
color: #16181d;
font-size: 14px;
font-weight: 700;
line-height: 1.35;
}
.vf-field input,
.vf-field textarea {
width: 100%;
border: none;
border-radius: 18px;
background: rgba(255, 255, 255, 0.96);
box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.08),
0 1px 0 rgba(255, 255, 255, 0.3);
color: #1f2421;
padding: 15px 16px;
font-size: 15px;
line-height: 1.45;
outline: none;
transition:
box-shadow 0.18s ease,
transform 0.18s cubic-bezier(0.22, 1, 0.36, 1),
background 0.18s ease;
}
.vf-field textarea {
resize: vertical;
min-height: 132px;
}
.vf-field input:focus-visible,
.vf-field textarea:focus-visible,
.vf-choice input:focus-visible + span,
.vf-step:focus-visible,
.vf-secondary:focus-visible {
box-shadow:
inset 0 0 0 2px rgba(255, 209, 0, 0.7),
0 0 0 4px rgba(255, 209, 0, 0.14);
background: #fff;
outline: none;
}
.vf-choice-group {
display: grid;
gap: 10px;
min-width: 0;
margin: 0;
padding: 0;
border: none;
}
.vf-helper {
margin: 0;
color: #687076;
font-size: 13px;
line-height: 1.5;
}
.vf-choices {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.vf-choice {
position: relative;
}
.vf-choice input {
position: absolute;
opacity: 0;
pointer-events: none;
}
.vf-choice span {
display: inline-flex;
align-items: center;
min-height: 42px;
padding: 0 14px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.9);
box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.08);
color: #2f3134;
font-size: 13px;
font-weight: 600;
line-height: 1.2;
transition:
box-shadow 0.18s ease,
background 0.18s ease,
color 0.18s ease,
transform 0.18s cubic-bezier(0.22, 1, 0.36, 1);
}
.vf-choice input:checked + span {
background: rgba(255, 209, 0, 0.18);
box-shadow: inset 0 0 0 1px rgba(255, 209, 0, 0.34);
color: #16181d;
}
.vf-note-row {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
}
.vf-note,
.vf-owner-note {
padding: 16px 16px 15px;
border-radius: 20px;
}
.vf-note {
background: rgba(33, 48, 33, 0.05);
box-shadow: inset 0 0 0 1px rgba(33, 48, 33, 0.06);
}
.vf-owner-note {
background: rgba(255, 209, 0, 0.12);
box-shadow: inset 0 0 0 1px rgba(255, 209, 0, 0.16);
}
.vf-note-title {
display: block;
margin-bottom: 6px;
color: var(--gw-green);
font-family: var(--font-head);
font-size: 11px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.vf-note p,
.vf-owner-note p {
margin: 0;
color: #4c5056;
font-size: 13px;
line-height: 1.55;
}
.vf-footer {
display: grid;
gap: 14px;
}
.vf-actions {
display: flex;
align-items: center;
gap: 12px;
}
.vf-reassurance {
margin: 0;
color: #59606d;
font-size: 13px;
line-height: 1.5;
}
.vf-secondary {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 52px;
padding: 0 18px;
border: none;
border-radius: 999px;
background: rgba(33, 48, 33, 0.07);
box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.06);
color: var(--gw-green);
font-family: var(--font-head);
font-size: 14px;
font-weight: 700;
line-height: 1.2;
cursor: pointer;
}
.vf-submit {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 52px;
width: fit-content;
padding: 0 22px;
border: none;
border-radius: 999px;
background: linear-gradient(135deg, #ffd54a, var(--yellow-soft));
box-shadow:
inset 0 -2px 0 rgba(0, 0, 0, 0.08),
0 12px 24px rgba(17, 20, 24, 0.1);
color: #111;
font-family: var(--font-head);
font-size: 14px;
font-weight: 700;
line-height: 1.2;
cursor: pointer;
transition:
transform 0.18s cubic-bezier(0.22, 1, 0.36, 1),
box-shadow 0.18s ease,
filter 0.18s ease;
}
.vf-submit:focus-visible {
outline: 3px solid rgba(255, 209, 0, 0.28);
outline-offset: 3px;
}
.vf-success {
margin: 0;
padding: 14px 16px;
border-radius: 18px;
background: rgba(33, 48, 33, 0.07);
box-shadow: inset 0 0 0 1px rgba(33, 48, 33, 0.08);
color: var(--gw-green);
font-size: 14px;
line-height: 1.55;
}
.vf-form--conversational .vf-label,
.vf-form--conversational .vf-choice-group legend {
font-family: var(--font-head);
font-size: 16px;
letter-spacing: -0.02em;
}
.vf-form--conversational .vf-field input,
.vf-form--conversational .vf-field textarea {
border-radius: 22px;
padding: 17px 18px;
font-size: 16px;
}
.vf-form--minimal .vf-group-copy,
.vf-form--minimal .vf-helper,
.vf-form--minimal .vf-reassurance,
.vf-form--minimal .vf-subtitle {
color: #6b7077;
}
.vf-form--minimal .vf-field input,
.vf-form--minimal .vf-field textarea,
.vf-form--minimal .vf-choice span {
box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.06);
}
@media (hover: hover) {
.vf-step:hover,
.vf-secondary:hover,
.vf-choice:hover span,
.vf-submit:hover {
transform: translateY(-1px);
}
.vf-submit:hover {
box-shadow:
inset 0 -2px 0 rgba(0, 0, 0, 0.08),
0 16px 28px rgba(17, 20, 24, 0.12);
filter: brightness(1.02);
}
}
@media (max-width: 768px) {
.vf-grid--two,
.vf-grid--three,
.vf-note-row {
grid-template-columns: 1fr;
}
.vf-stepper {
align-items: stretch;
gap: 8px;
}
.vf-step {
flex: 1 1 0;
min-width: 0;
}
.vf-step-divider {
display: none;
}
.vf-form {
gap: 20px;
}
.vf-form--carded .vf-group {
padding: 18px;
border-radius: 22px;
}
.vf-field input,
.vf-field textarea {
font-size: 16px;
}
.vf-actions {
flex-direction: column-reverse;
align-items: stretch;
}
.vf-secondary,
.vf-submit {
width: 100%;
}
}
</style>
+13
View File
@@ -673,6 +673,19 @@
max-width: none; max-width: none;
} }
.footer-social-cluster {
gap: 8px;
}
.footer-social-invite {
font-size: 11px;
padding-left: 2px;
}
:global(.footer-social-invite-arrow) {
font-size: 13px;
}
.footer-col-label { .footer-col-label {
margin-bottom: 12px; margin-bottom: 12px;
} }
+33
View File
@@ -545,6 +545,33 @@ footer {
max-width: 30ch; max-width: 30ch;
} }
.footer-social-cluster {
display: inline-flex;
flex-direction: column;
align-items: flex-start;
gap: 10px;
}
.footer-social-invite {
display: inline-flex;
align-items: center;
gap: 8px;
padding-left: 4px;
color: rgba(255, 255, 255, 0.82);
font-family: var(--font-head);
font-size: 12px;
font-weight: 700;
letter-spacing: 0.02em;
line-height: 1.2;
}
:global(.footer-social-invite-arrow) {
font-size: 14px;
color: var(--yellow);
transform: rotate(24deg);
transition: transform 0.18s cubic-bezier(0.22, 1, 0.36, 1);
}
.social-links a { .social-links a {
width: 44px; width: 44px;
height: 44px; height: 44px;
@@ -567,6 +594,12 @@ footer {
transform: translateY(-1px); transform: translateY(-1px);
} }
@media (hover: hover) {
.footer-social-cluster:hover :global(.footer-social-invite-arrow) {
transform: rotate(34deg) translateX(1px) translateY(1px);
}
}
.footer-col-label { .footer-col-label {
margin: 0 0 14px; margin: 0 0 14px;
font-family: var(--font-head); font-family: var(--font-head);
+1 -1
View File
@@ -138,7 +138,7 @@
<TestimonialsSection testimonials={content.testimonials} seedKey="/" /> <TestimonialsSection testimonials={content.testimonials} seedKey="/" />
<FounderStorySection founderStory={content.founderStory} /> <FounderStorySection founderStory={content.founderStory} />
<InfoSection info={content.info} /> <InfoSection info={content.info} />
<BookingSection booking={content.booking} /> <BookingSection booking={content.booking} variant="card-stepper" />
<InstagramSection instagram={content.instagram} /> <InstagramSection instagram={content.instagram} />
<Footer footer={content.footer} /> <Footer footer={content.footer} />
{/if} {/if}
@@ -0,0 +1,922 @@
<script lang="ts">
import { onMount } from 'svelte';
import Icon from '$lib/components/Icon.svelte';
import PageHeader from '$lib/components/PageHeader.svelte';
import VariantApplicationFields from '$lib/components/contact-form-variants/VariantApplicationFields.svelte';
type VariantTab = {
id: string;
index: string;
label: string;
kicker: string;
};
const variantTabs: VariantTab[] = [
{ id: 'variant-1', index: '01', label: 'Improved current', kicker: 'Familiar, lighter, clearer' },
{ id: 'variant-2', index: '02', label: 'Split hero + form', kicker: 'Story on the left, action on the right' },
{ id: 'variant-3', index: '03', label: 'Card stepper', kicker: 'Application flow with stronger rhythm' },
{ id: 'variant-4', index: '04', label: 'Conversational', kicker: 'More guided, more human' },
{ id: 'variant-5', index: '05', label: 'Trust-first', kicker: 'Reassurance before friction' },
{ id: 'variant-6', index: '06', label: 'Ultra-minimal', kicker: 'Quiet luxury version' }
];
let activeVariant = variantTabs[0].id;
onMount(() => {
const sections = Array.from(document.querySelectorAll<HTMLElement>('.variant-showcase'));
const observer = new IntersectionObserver(
(entries) => {
const visible = entries
.filter((entry) => entry.isIntersecting)
.sort((a, b) => b.intersectionRatio - a.intersectionRatio)[0];
if (visible?.target?.id) {
activeVariant = visible.target.id;
}
},
{
rootMargin: '-18% 0px -45% 0px',
threshold: [0.2, 0.35, 0.55]
}
);
sections.forEach((section) => observer.observe(section));
return () => observer.disconnect();
});
</script>
<svelte:head>
<title>Contact Form Variants | Goodwalk</title>
<meta
name="description"
content="Six conversion-focused Goodwalk contact form variants for internal review before updating the live Meet and Greet flow."
/>
</svelte:head>
<main class="variants-page">
<PageHeader
variant="green"
eyebrow="Internal review page"
title="Contact Form Variants"
subtitle="Six conversion-focused ways to frame the same Goodwalk application flow, all on one page, without touching the live contact route."
>
<div class="variants-hero-chips">
<span class="variants-hero-chip">
<Icon name="fas fa-paw" />
Premium, calm, small-dog focused
</span>
<span class="variants-hero-chip">
<Icon name="fas fa-heart" />
Free Meet &amp; Greet CTA in every version
</span>
<span class="variants-hero-chip">
<Icon name="fas fa-mobile-screen-button" />
Mobile-first comparison
</span>
</div>
</PageHeader>
<div class="variants-switcher-wrap">
<nav class="variants-switcher" aria-label="Contact form variants">
{#each variantTabs as tab}
<a
href={`#${tab.id}`}
class:active={activeVariant === tab.id}
class="variants-switcher-tab"
aria-current={activeVariant === tab.id ? 'page' : undefined}
title={tab.kicker}
>
<span class="variants-switcher-index">{tab.index}</span>
<span class="variants-switcher-label">{tab.label}</span>
</a>
{/each}
</nav>
</div>
<section id="variant-1" class="variant-showcase">
<div class="page-inner">
<div class="variant-intro">
<div>
<span class="variant-kicker">01. Improved current</span>
<h2>Keep the friendly Goodwalk feel, but lighten the weight and improve the rhythm.</h2>
</div>
<p>
This is the safest replacement direction. It still feels recognisably Goodwalk, but the hierarchy is clearer,
the trust cues breathe more, and the form reads more like an application than an enquiry box.
</p>
</div>
<article class="variant-surface variant-surface--current">
<div class="variant-surface-head">
<div class="variant-proof-row" aria-label="Application highlights">
<span class="variant-proof-pill">
<Icon name="fas fa-comment-dots" />
Reply within 24 hours
</span>
<span class="variant-proof-pill">
<Icon name="fas fa-heart" />
Nervous dogs welcome
</span>
<span class="variant-proof-pill">
<Icon name="fas fa-handshake" />
Free Meet &amp; Greet first
</span>
</div>
</div>
<VariantApplicationFields
idPrefix="variant-one"
layout="carded"
eyebrow="Current direction, modernised"
title="Book your free Meet & Greet"
subtitle="A friendlier two-step application with calmer spacing, lighter surfaces, and a clearer handoff."
lead="Start with the dog, then the owner. Enough detail for a thoughtful recommendation, without making the first step feel heavy."
submitLabel="Request a free Meet & Greet"
/>
</article>
</div>
</section>
<section id="variant-2" class="variant-showcase variant-showcase--warm">
<div class="page-inner">
<div class="variant-intro">
<div>
<span class="variant-kicker">02. Split hero + form</span>
<h2>Put the emotional reassurance and brand story beside the action.</h2>
</div>
<p>
Better when the primary objection is trust. The left panel does the calming and framing; the right panel asks
for details once the page already feels safe.
</p>
</div>
<div class="variant-split-layout">
<article class="variant-split-story">
<div class="variant-split-photo">
<img src="/images/founder-image-aless-goodwalk.jpg" alt="Aless from Goodwalk" />
</div>
<div class="variant-split-copy">
<span class="variant-story-kicker">Book with confidence</span>
<h3>Your dog starts with a real person, not a platform.</h3>
<p>
Every enquiry goes to Aless. If your dog would thrive in Tiny Gang, we will say so. If they need more space,
time, or a calmer first step, we will say that too.
</p>
<ul class="variant-story-list">
<li>Small-dog aware matching, not one-size-fits-all scheduling</li>
<li>Free Meet &amp; Greet before anything starts</li>
<li>Strong fit for tiny dogs, nervous dogs, and routine-focused owners</li>
</ul>
</div>
</article>
<article class="variant-surface variant-surface--split">
<VariantApplicationFields
idPrefix="variant-two"
eyebrow="Meet Aless first"
title="Tell us about your dog"
subtitle="The trust-building version: softer emotional framing, then a simple two-step application."
lead="Tell us who your dog is, how they tend to feel around other dogs, and what kind of support you want from the week."
submitLabel="Book a free Meet & Greet"
/>
</article>
</div>
</div>
</section>
<section id="variant-3" class="variant-showcase">
<div class="page-inner">
<div class="variant-intro">
<div>
<span class="variant-kicker">03. Card-based stepper</span>
<h2>Make the guided application structure feel deliberate and premium.</h2>
</div>
<p>
This version leans into progression and sequencing. Strong if you want the form to feel curated and higher-value
rather than like a standard contact action.
</p>
</div>
<div class="variant-stepper">
<div class="variant-step-cards" aria-label="Application steps">
<article class="variant-step-card variant-step-card--active">
<span class="variant-step-number">1</span>
<strong>Dog fit</strong>
<p>Temperament, location, and Tiny Gang suitability.</p>
</article>
<article class="variant-step-card">
<span class="variant-step-number">2</span>
<strong>Owner details</strong>
<p>Just enough to reply and arrange the Meet &amp; Greet.</p>
</article>
<article class="variant-step-card">
<span class="variant-step-number">3</span>
<strong>Warm follow-up</strong>
<p>Personal reply from Aless within 24 hours.</p>
</article>
</div>
<article class="variant-surface variant-surface--stepper">
<VariantApplicationFields
idPrefix="variant-three"
layout="carded"
eyebrow="Structured application"
title="Apply for the right Goodwalk fit"
subtitle="A more premium, card-led two-step flow for owners who like process and clarity."
lead="A more structured application flow for owners who want clarity, process, and a sense that their dog will be matched thoughtfully."
submitLabel="Start the Meet & Greet process"
/>
</article>
</div>
</div>
</section>
<section id="variant-4" class="variant-showcase variant-showcase--green">
<div class="page-inner">
<div class="variant-intro variant-intro--light">
<div>
<span class="variant-kicker">04. Conversational form</span>
<h2>Sound more like Goodwalk speaking directly to the owner.</h2>
</div>
<p>
This version is the warmest. Strongest if conversion improves when the interaction feels personal and guided,
especially for worried owners and first-time dog-walking clients.
</p>
</div>
<div class="variant-conversation-shell">
<article class="variant-conversation-note">
<span class="variant-conversation-pill">A calmer first step</span>
<p>
We are not looking for perfect answers here. Just enough context to understand your dog properly and point you
toward the right walk, visit, or Meet &amp; Greet conversation.
</p>
</article>
<article class="variant-surface variant-surface--conversation">
<VariantApplicationFields
idPrefix="variant-four"
tone="conversational"
eyebrow="A calmer conversation"
title="Lets start with your dog"
subtitle="This one feels the most personal: Goodwalk voice first, application structure underneath."
lead="Tell us about your dog as if you were introducing them to us in person."
submitLabel="Talk it through with Aless"
/>
</article>
</div>
</div>
</section>
<section id="variant-5" class="variant-showcase">
<div class="page-inner">
<div class="variant-intro">
<div>
<span class="variant-kicker">05. Trust-first form</span>
<h2>Lead with reassurance before asking for any effort.</h2>
</div>
<p>
Best when the core conversion barrier is “Can I trust you with my dog?” rather than “Do I understand the service?”
The form still matters, but the trust panel leads the page.
</p>
</div>
<div class="variant-trust-layout">
<aside class="variant-trust-panel" aria-label="Why Goodwalk feels safe">
<div class="variant-trust-panel-top">
<span class="variant-story-kicker">Why this feels easier</span>
<h3>Owners do not have to guess what kind of care their dog will get.</h3>
</div>
<div class="variant-trust-points">
<article class="variant-trust-point">
<Icon name="fas fa-user-check" />
<div>
<strong>Personal reply from Aless</strong>
<p>Not a team inbox, not an anonymous handoff.</p>
</div>
</article>
<article class="variant-trust-point">
<Icon name="fas fa-dog" />
<div>
<strong>Tiny-dog aware recommendations</strong>
<p>Especially important if your dog is small, sensitive, or easily overwhelmed.</p>
</div>
</article>
<article class="variant-trust-point">
<Icon name="fas fa-comments" />
<div>
<strong>Meet first, decide second</strong>
<p>The free Meet &amp; Greet keeps the first step low-pressure and genuinely helpful.</p>
</div>
</article>
</div>
<blockquote class="variant-trust-quote">
“You know exactly who is caring for your dog. Your dog knows who is at the door.”
</blockquote>
</aside>
<article class="variant-surface variant-surface--trust">
<VariantApplicationFields
idPrefix="variant-five"
layout="carded"
eyebrow="Trust-first application"
title="Start with a safe first step"
subtitle="Lead with reassurance, then move into a guided two-step Meet and Greet request."
lead="Tell us what kind of dog you have, what week-to-week support would help most, and whether Tiny Gang feels like the right fit."
submitLabel="Request your free Meet & Greet"
/>
</article>
</div>
</div>
</section>
<section id="variant-6" class="variant-showcase variant-showcase--minimal">
<div class="page-inner">
<div class="variant-intro">
<div>
<span class="variant-kicker">06. Ultra-minimal premium</span>
<h2>Cut almost everything back and let spacing, typography, and reassurance do the work.</h2>
</div>
<p>
The quietest option. Strong if the brand is confident enough to convert with restraint rather than explanation.
Probably best for a higher-trust audience or repeat referrals.
</p>
</div>
<article class="variant-minimal-shell">
<div class="variant-minimal-copy">
<span class="variant-story-kicker">Free Meet &amp; Greet</span>
<h3>Start with the right fit.</h3>
<p>
Tell us about your dog, your area, and the kind of support you need. We will come back with a calm next step,
not a hard sell.
</p>
</div>
<div class="variant-minimal-divider" aria-hidden="true"></div>
<VariantApplicationFields
idPrefix="variant-six"
tone="minimal"
eyebrow="Quiet premium version"
title="Book the right first meeting"
subtitle="A stripped-back two-step flow where spacing, copy, and confidence do most of the work."
lead=""
submitLabel="Book the free Meet & Greet"
/>
</article>
</div>
</section>
</main>
<style>
.variants-page {
background: var(--off-white);
}
.variants-hero-chips {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 10px;
margin-top: 28px;
}
.variants-hero-chip {
display: inline-flex;
align-items: center;
gap: 8px;
min-height: 38px;
padding: 8px 14px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.14);
color: #fff;
font-size: 13px;
font-weight: 600;
line-height: 1.2;
}
.variants-hero-chip :global(.icon) {
color: var(--yellow);
font-size: 12px;
}
.variants-switcher-wrap {
position: sticky;
top: 12px;
z-index: 25;
padding: 14px var(--space-container-x) 0;
}
.variants-switcher {
display: flex;
gap: 10px;
max-width: var(--max-w);
margin: 0 auto;
padding: 10px;
overflow-x: auto;
border-radius: 24px;
background: rgba(248, 247, 242, 0.9);
box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.06),
0 16px 30px rgba(17, 20, 24, 0.08);
backdrop-filter: blur(10px);
scrollbar-width: none;
}
.variants-switcher::-webkit-scrollbar {
display: none;
}
.variants-switcher-tab {
display: inline-flex;
align-items: center;
gap: 10px;
min-height: 44px;
padding: 0 14px;
border-radius: 999px;
color: #50555c;
font-family: var(--font-head);
font-size: 12px;
font-weight: 700;
line-height: 1.2;
white-space: nowrap;
transition:
background 0.18s ease,
color 0.18s ease,
transform 0.18s cubic-bezier(0.22, 1, 0.36, 1);
}
.variants-switcher-tab.active {
background: var(--gw-green);
color: #fff;
}
.variants-switcher-index {
color: var(--yellow-soft);
font-size: 10px;
letter-spacing: 0.08em;
}
.variant-showcase {
scroll-margin-top: 116px;
padding: 40px 0 72px;
}
.variant-showcase--warm {
background: linear-gradient(180deg, rgba(245, 239, 230, 0.7), rgba(248, 247, 242, 0));
}
.variant-showcase--green {
background: linear-gradient(180deg, rgba(33, 48, 33, 0.96), rgba(33, 48, 33, 0.92));
color: #fff;
}
.variant-showcase--minimal {
background: linear-gradient(180deg, rgba(255, 255, 255, 0.65), rgba(248, 247, 242, 0));
}
.variant-intro {
display: grid;
grid-template-columns: minmax(0, 1.1fr) minmax(280px, 0.9fr);
gap: 22px;
align-items: end;
margin-bottom: 28px;
}
.variant-intro--light h2,
.variant-intro--light p {
color: #fff;
}
.variant-kicker {
display: inline-block;
margin-bottom: 10px;
color: var(--gw-green);
font-family: var(--font-head);
font-size: 11px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.variant-showcase--green .variant-kicker {
color: var(--yellow);
}
.variant-intro h2 {
margin: 0;
color: #0f1115;
font-family: var(--font-head);
font-size: clamp(28px, 3.4vw, 44px);
line-height: 1.04;
letter-spacing: -0.04em;
text-wrap: balance;
}
.variant-intro p {
margin: 0;
color: #50555c;
font-size: 16px;
line-height: 1.65;
}
.variant-surface,
.variant-split-story,
.variant-conversation-note,
.variant-trust-panel,
.variant-minimal-shell {
border-radius: 32px;
background: linear-gradient(180deg, rgba(251, 251, 251, 0.98), rgba(247, 248, 246, 1));
box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.06),
0 22px 52px rgba(17, 20, 24, 0.1);
}
.variant-surface {
padding: 28px;
}
.variant-proof-row {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 20px;
}
.variant-proof-pill {
display: inline-flex;
align-items: center;
gap: 8px;
min-height: 38px;
padding: 8px 14px;
border-radius: 999px;
background: rgba(33, 48, 33, 0.06);
box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.05);
color: var(--gw-green);
font-size: 13px;
font-weight: 600;
line-height: 1.2;
}
.variant-proof-pill :global(.icon) {
color: var(--yellow-soft);
font-size: 12px;
}
.variant-split-layout,
.variant-trust-layout {
display: grid;
grid-template-columns: minmax(300px, 0.95fr) minmax(0, 1.05fr);
gap: 22px;
align-items: stretch;
}
.variant-split-story {
overflow: hidden;
}
.variant-split-photo {
aspect-ratio: 4 / 3;
background: #e7dcc8;
}
.variant-split-photo img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center top;
}
.variant-split-copy {
display: grid;
gap: 14px;
padding: 24px 24px 26px;
}
.variant-story-kicker {
color: var(--gw-green);
font-family: var(--font-head);
font-size: 11px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.variant-split-copy h3,
.variant-trust-panel h3,
.variant-minimal-copy h3 {
margin: 0;
color: #10161a;
font-family: var(--font-head);
font-size: clamp(24px, 2vw, 32px);
line-height: 1.08;
letter-spacing: -0.03em;
}
.variant-split-copy p,
.variant-conversation-note p,
.variant-minimal-copy p {
margin: 0;
color: #4d535a;
font-size: 15px;
line-height: 1.65;
}
.variant-story-list {
display: grid;
gap: 10px;
margin: 0;
padding: 0;
list-style: none;
}
.variant-story-list li {
position: relative;
padding-left: 20px;
color: #2f3134;
font-size: 14px;
line-height: 1.55;
}
.variant-story-list li::before {
content: '';
position: absolute;
left: 0;
top: 8px;
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--yellow-soft);
}
.variant-stepper {
display: grid;
gap: 18px;
}
.variant-step-cards {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 14px;
}
.variant-step-card {
padding: 20px;
border-radius: 26px;
background: rgba(255, 255, 255, 0.8);
box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.06),
0 12px 26px rgba(17, 20, 24, 0.05);
}
.variant-step-card--active {
background: linear-gradient(180deg, rgba(255, 209, 0, 0.18), rgba(255, 255, 255, 0.95));
}
.variant-step-number {
display: inline-flex;
align-items: center;
justify-content: center;
width: 34px;
height: 34px;
margin-bottom: 14px;
border-radius: 12px;
background: var(--gw-green);
color: var(--yellow);
font-family: var(--font-head);
font-size: 14px;
font-weight: 700;
}
.variant-step-card strong {
display: block;
margin-bottom: 6px;
color: #10161a;
font-family: var(--font-head);
font-size: 15px;
line-height: 1.25;
}
.variant-step-card p {
margin: 0;
color: #5d636a;
font-size: 13px;
line-height: 1.5;
}
.variant-conversation-shell {
display: grid;
grid-template-columns: minmax(260px, 0.72fr) minmax(0, 1.28fr);
gap: 22px;
align-items: start;
}
.variant-conversation-note {
padding: 24px;
background:
radial-gradient(circle at top right, rgba(255, 209, 0, 0.14), rgba(255, 209, 0, 0) 34%),
linear-gradient(180deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.08));
color: #fff;
}
.variant-conversation-pill {
display: inline-flex;
align-items: center;
min-height: 30px;
padding: 0 12px;
margin-bottom: 14px;
border-radius: 999px;
background: rgba(255, 209, 0, 0.15);
color: var(--yellow);
font-family: var(--font-head);
font-size: 11px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.variant-surface--conversation {
background: linear-gradient(180deg, rgba(251, 251, 251, 0.99), rgba(248, 247, 242, 1));
}
.variant-trust-panel {
display: grid;
gap: 22px;
padding: 28px;
background:
radial-gradient(circle at top right, rgba(255, 209, 0, 0.18), rgba(255, 209, 0, 0) 36%),
linear-gradient(180deg, rgba(255, 250, 240, 0.96), rgba(247, 243, 232, 0.96));
}
.variant-trust-panel-top {
display: grid;
gap: 10px;
}
.variant-trust-points {
display: grid;
gap: 14px;
}
.variant-trust-point {
display: grid;
grid-template-columns: 42px minmax(0, 1fr);
gap: 12px;
align-items: start;
}
.variant-trust-point :global(.icon) {
display: inline-flex;
align-items: center;
justify-content: center;
width: 42px;
height: 42px;
border-radius: 14px;
background: linear-gradient(135deg, var(--gw-green), var(--green-mid));
color: var(--yellow);
font-size: 16px;
}
.variant-trust-point strong {
display: block;
margin-bottom: 4px;
color: #11171b;
font-family: var(--font-head);
font-size: 14px;
line-height: 1.25;
}
.variant-trust-point p {
margin: 0;
color: #575d63;
font-size: 14px;
line-height: 1.55;
}
.variant-trust-quote {
margin: 0;
padding-top: 18px;
border-top: 1px solid rgba(17, 20, 24, 0.08);
color: #202427;
font-family: var(--font-head);
font-size: 18px;
line-height: 1.45;
letter-spacing: -0.02em;
}
.variant-minimal-shell {
max-width: 880px;
margin: 0 auto;
padding: 36px;
background: rgba(251, 251, 251, 0.92);
}
.variant-minimal-copy {
display: grid;
gap: 12px;
max-width: 42rem;
}
.variant-minimal-divider {
width: 100%;
height: 1px;
margin: 24px 0 28px;
background: rgba(17, 20, 24, 0.08);
}
@media (hover: hover) {
.variants-switcher-tab:hover {
transform: translateY(-1px);
}
}
@media (max-width: 1024px) {
.variant-intro,
.variant-split-layout,
.variant-trust-layout,
.variant-conversation-shell {
grid-template-columns: 1fr;
}
.variant-step-cards {
grid-template-columns: 1fr;
}
}
@media (max-width: 768px) {
.variants-switcher-wrap {
top: 8px;
padding: 10px var(--space-container-x-mobile) 0;
}
.variants-switcher {
border-radius: 20px;
}
.variant-showcase {
scroll-margin-top: 104px;
padding: 28px 0 56px;
}
.variants-hero-chips {
gap: 8px;
margin-top: 22px;
}
.variants-hero-chip {
font-size: 12px;
padding: 8px 12px;
}
.variant-intro {
gap: 14px;
margin-bottom: 20px;
}
.variant-intro h2 {
font-size: 28px;
}
.variant-intro p {
font-size: 15px;
line-height: 1.58;
}
.variant-surface,
.variant-split-story,
.variant-conversation-note,
.variant-trust-panel,
.variant-minimal-shell {
border-radius: 24px;
}
.variant-surface,
.variant-trust-panel,
.variant-minimal-shell {
padding: 20px;
}
.variant-split-copy {
padding: 20px;
}
.variant-proof-row {
gap: 8px;
margin-bottom: 16px;
}
.variant-proof-pill {
font-size: 12px;
}
.variant-minimal-divider {
margin: 20px 0 24px;
}
}
</style>