+ {#each orderedValues as value, index}
+
-
@@ -117,21 +215,27 @@
@media (max-width: 768px) {
.values-shell {
- margin-top: 32px;
+ margin-top: 24px;
+ overflow: hidden;
}
.values-grid {
+ display: grid;
grid-auto-flow: column;
- grid-auto-columns: minmax(272px, 84vw);
+ grid-auto-columns: calc(100% - 64px);
grid-template-columns: none;
- gap: 14px;
+ align-items: stretch;
+ gap: 10px;
+ margin-top: 0;
+ border-top: none;
overflow-x: auto;
overscroll-behavior-x: contain;
- scroll-snap-type: x proximity;
- scroll-padding-left: 24px;
- padding: 0 24px 8px 0;
+ scroll-snap-type: x mandatory;
+ scroll-padding-left: 8px;
+ padding: 0 14px 8px 8px;
scrollbar-width: none;
-webkit-overflow-scrolling: touch;
+ touch-action: pan-x pinch-zoom;
}
.values-grid::-webkit-scrollbar {
@@ -140,9 +244,10 @@
.values-mobile-controls {
display: flex;
- justify-content: flex-end;
- gap: 12px;
- margin-top: 16px;
+ align-items: center;
+ justify-content: space-between;
+ gap: 14px;
+ margin-top: 12px;
}
.values-mobile-button {
@@ -158,19 +263,116 @@
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
-webkit-tap-highlight-color: transparent;
touch-action: manipulation;
+ transition:
+ background 0.18s ease,
+ opacity 0.18s ease,
+ transform 0.18s ease;
+ }
+
+ .values-mobile-button:disabled {
+ opacity: 0.35;
+ }
+
+ .values-mobile-pager {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ min-width: 0;
+ flex: 1;
+ }
+
+ .values-mobile-dot {
+ width: 9px;
+ height: 9px;
+ padding: 0;
+ border: none;
+ border-radius: 999px;
+ background: rgba(255, 255, 255, 0.28);
+ transition:
+ width 0.22s ease,
+ background 0.22s ease,
+ transform 0.22s ease;
+ }
+
+ .values-mobile-dot.active {
+ width: 28px;
+ background: var(--yellow);
}
.value-card {
- min-height: 100%;
- padding: 24px 22px;
- border: 1px solid rgba(255, 255, 255, 0.1);
+ display: flex;
+ min-height: clamp(230px, 42svh, 320px);
+ width: 100%;
+ min-width: 0;
+ box-sizing: border-box;
+ padding: 20px 18px 22px;
+ border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 24px;
- background: rgba(255, 255, 255, 0.05);
+ background:
+ linear-gradient(180deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.07));
+ box-shadow:
+ inset 0 1px 0 rgba(255, 255, 255, 0.08),
+ 0 6px 16px rgba(0, 0, 0, 0.06);
scroll-snap-align: start;
+ scroll-snap-stop: always;
+ flex-direction: column;
+ justify-content: flex-start;
+ gap: 14px;
+ transition:
+ background 0.24s ease,
+ box-shadow 0.24s ease,
+ border-color 0.24s ease;
+ touch-action: pan-x;
+ user-select: none;
+ -webkit-user-select: none;
+ }
+
+ .value-card.active {
+ background:
+ linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.09));
+ border-color: rgba(255, 255, 255, 0.16);
+ box-shadow:
+ inset 0 1px 0 rgba(255, 255, 255, 0.08),
+ 0 10px 22px rgba(0, 0, 0, 0.08);
}
.value-card:nth-child(odd) {
- border-right: 1px solid rgba(255, 255, 255, 0.1);
+ border-right: none;
+ }
+
+ .value-card:last-child {
+ margin-right: 2px;
+ }
+
+ .value-icon-wrap {
+ width: 56px;
+ height: 56px;
+ border-radius: 18px;
+ margin-top: 0;
+ background: rgba(255, 255, 255, 0.1);
+ }
+
+ .value-card .value-card-icon {
+ font-size: 23px;
+ }
+
+ .value-text {
+ max-width: 30ch;
+ min-width: 0;
+ margin-top: 0;
+ }
+
+ .value-text h3 {
+ margin-bottom: 8px;
+ font-size: 21px;
+ line-height: 1.08;
+ }
+
+ .value-card p {
+ font-size: 14px;
+ line-height: 1.55;
+ opacity: 0.9;
}
.values-eyebrow {
diff --git a/src/lib/content/homepage.ts b/src/lib/content/homepage.ts
index eba383e..2f1954b 100644
--- a/src/lib/content/homepage.ts
+++ b/src/lib/content/homepage.ts
@@ -53,14 +53,15 @@ export const homepageContent: HomePageContent = {
external: true
}
},
- promise: {
- title: 'Meet Aless,',
- subtitle: 'the heart of Goodwalk',
+ founderStory: {
+ title: 'Not just dog walking.',
+ subtitle: 'Built around trust.',
body: [
- 'Goodwalk was built for owners who want more than a basic walk. Alessandra leads the business with a calm, hands-on approach shaped by years of experience, a love of small dogs, and a real focus on trust, routine, and safety.',
- "From house keys to nervous first walks, we take the responsibility seriously. You'll know who is walking your dog, your dog will know who is at the door, and you'll get a reliable team that treats your dog like family. Ready to join the"
+ 'Most dog walking companies sell walks. Goodwalk was built for owners who want a calmer, more personal experience for their dog, especially small dogs who thrive on routine, familiarity, and gentle handling.',
+ 'That means familiar walkers, safe group dynamics, reliable communication, and a team your dog genuinely builds a relationship with. We know we are not just collecting dogs for a walk. We are being trusted with part of your family and access to your home.',
+ 'You know exactly who is caring for your dog. Your dog knows who is at the door. And you come home to a calmer, happier dog. Ready to'
],
- emphasis: 'TINY GANG?',
+ emphasis: 'join the Tiny Gang?',
cta: { label: 'Book a free Meet & Greet', href: '/contact-us', variant: 'green' },
imageUrl: '/images/goodwalk-dog-walker-alessandra.png',
imageAlt: 'Alessandra from Goodwalk with a dog in Auckland'
diff --git a/src/lib/styles/base.css b/src/lib/styles/base.css
index 00439aa..c5c3d3d 100644
--- a/src/lib/styles/base.css
+++ b/src/lib/styles/base.css
@@ -84,3 +84,18 @@ textarea {
transform: none;
}
}
+
+/* use:reveal action — applied via Svelte action on section elements */
+.reveal-ready.reveal-block {
+ opacity: 0;
+ transform: translate3d(0, var(--reveal-distance, 24px), 0);
+ transition:
+ opacity 0.55s ease,
+ transform 0.7s cubic-bezier(0.2, 0.8, 0.2, 1);
+ transition-delay: var(--reveal-delay, 0ms);
+}
+
+.reveal-visible.reveal-block {
+ opacity: 1;
+ transform: translate3d(0, 0, 0);
+}
diff --git a/src/lib/styles/layout.css b/src/lib/styles/layout.css
index 4eb6a18..c4e47d7 100644
--- a/src/lib/styles/layout.css
+++ b/src/lib/styles/layout.css
@@ -91,11 +91,18 @@ nav,
margin: 0 auto;
}
+/* Shared inner wrapper for page-level sections */
+.page-inner {
+ max-width: var(--max-w);
+ margin: 0 auto;
+ padding: 0 var(--space-container-x);
+}
+
nav {
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: center;
- padding: 16px 50px;
+ padding: 16px var(--space-container-x);
}
.nav-links {
diff --git a/src/lib/styles/responsive.css b/src/lib/styles/responsive.css
index e450006..cd69d8a 100644
--- a/src/lib/styles/responsive.css
+++ b/src/lib/styles/responsive.css
@@ -1,8 +1,8 @@
@media (max-width: 1024px) {
nav,
.mobile-menu {
- padding-left: 30px;
- padding-right: 30px;
+ padding-left: var(--space-container-x-tablet);
+ padding-right: var(--space-container-x-tablet);
}
.promise-inner,
@@ -11,13 +11,13 @@
.testimonials-inner,
.info-inner,
.form-inner {
- padding-left: 30px;
- padding-right: 30px;
+ padding-left: var(--space-container-x-tablet);
+ padding-right: var(--space-container-x-tablet);
}
footer {
- padding-left: 30px;
- padding-right: 30px;
+ padding-left: var(--space-container-x-tablet);
+ padding-right: var(--space-container-x-tablet);
}
.hero-text h1 {
@@ -483,7 +483,7 @@
.promise-inner {
flex-direction: column;
- padding: 0 24px;
+ padding: 0 var(--space-container-x-mobile);
}
.promise-text {
@@ -494,7 +494,7 @@
order: 2;
flex: none;
width: 100%;
- max-width: 320px;
+ max-width: 360px;
margin: 0 auto;
}
@@ -700,7 +700,11 @@
.testimonials-inner,
.info-inner,
.form-inner {
- padding: 0 24px;
+ padding: 0 var(--space-container-x-mobile);
+ }
+
+ .page-inner {
+ padding: 0 var(--space-container-x-mobile);
}
.section-heading {
@@ -708,7 +712,7 @@
}
footer {
- padding: 40px 24px 24px;
+ padding: 40px var(--space-container-x-mobile) var(--space-container-x-mobile);
}
.footer-inner {
@@ -820,4 +824,9 @@
:root {
--sh-copy-left-pad: clamp(420px, 22vw, 550px);
}
+
+ .hero-img img {
+ width: 54%;
+ object-position: center 8%;
+ }
}
diff --git a/src/lib/styles/sections.css b/src/lib/styles/sections.css
index 0132a13..716efed 100644
--- a/src/lib/styles/sections.css
+++ b/src/lib/styles/sections.css
@@ -1,19 +1,19 @@
/* Featured sections — more breathing room */
#promise,
#services {
- padding: 96px 0;
+ padding: var(--space-section-featured-y) 0;
}
/* Supporting sections */
#values,
#testimonials,
#info {
- padding: 72px 0;
+ padding: var(--space-section-support-y) 0;
}
/* Booking / lead form — neutral */
#newlead {
- padding: 80px 0;
+ padding: var(--space-section-form-y) 0;
}
#hero {
@@ -53,7 +53,7 @@
width: 100%;
max-width: 700px;
margin: 0 auto;
- padding: 0 50px 32px;
+ padding: 0 var(--space-container-x) var(--space-hero-inner-bottom);
gap: 0;
}
diff --git a/src/lib/styles/variables.css b/src/lib/styles/variables.css
index 0c36e9e..a9da6e6 100644
--- a/src/lib/styles/variables.css
+++ b/src/lib/styles/variables.css
@@ -1,4 +1,20 @@
:root {
+ /* Spacing scale */
+ --space-1: 4px;
+ --space-2: 8px;
+ --space-3: 12px;
+ --space-4: 16px;
+ --space-5: 20px;
+ --space-6: 24px;
+ --space-7: 32px;
+ --space-8: 40px;
+ --space-9: 48px;
+ --space-10: 56px;
+ --space-11: 64px;
+ --space-12: 72px;
+ --space-13: 80px;
+ --space-14: 96px;
+
/* Brand greens */
--gw-green: #213021;
--green-mid: #2d4230; /* hover states, subtle accents */
@@ -17,12 +33,30 @@
/* Layout */
--max-w: 1280px;
+ --space-container-x: var(--space-9);
+ --space-container-x-tablet: 30px;
+ --space-container-x-mobile: var(--space-6);
+ --space-section-featured-y: var(--space-14);
+ --space-section-support-y: var(--space-12);
+ --space-section-form-y: var(--space-13);
+ --space-section-page-y: var(--space-13);
+ --space-section-mobile-y: var(--space-11);
+ --space-hero-inner-bottom: var(--space-7);
/* Typography */
--font-body: 'Readex Pro', sans-serif;
--font-head: 'Unbounded', sans-serif;
}
+@media (max-width: 768px) {
+ :root {
+ --space-section-featured-y: var(--space-section-mobile-y);
+ --space-section-support-y: var(--space-section-mobile-y);
+ --space-section-form-y: var(--space-section-mobile-y);
+ --space-section-page-y: var(--space-section-mobile-y);
+ }
+}
+
@media (min-width: 1800px) {
:root {
--max-w: 1408px;
diff --git a/src/lib/types.ts b/src/lib/types.ts
index 6788091..88e3586 100644
--- a/src/lib/types.ts
+++ b/src/lib/types.ts
@@ -57,7 +57,7 @@ export interface IntroContent {
reviewCta: CallToAction;
}
-export interface PromiseContent {
+export interface FounderStoryContent {
title: string;
subtitle: string;
body: string[];
@@ -290,7 +290,7 @@ export interface HomePageContent {
navigation: NavigationContent;
hero: HeroContent;
intro: IntroContent;
- promise: PromiseContent;
+ founderStory: FounderStoryContent;
services: IconCard[];
howItWorks: HowItWorksContent;
values: IconCard[];
diff --git a/src/lib/utils/pricing.ts b/src/lib/utils/pricing.ts
new file mode 100644
index 0000000..ac51c5a
--- /dev/null
+++ b/src/lib/utils/pricing.ts
@@ -0,0 +1,19 @@
+export function numericPrice(price: string): number {
+ const value = Number(price.replace(/[^0-9.]/g, ''));
+ return Number.isFinite(value) ? value : Number.POSITIVE_INFINITY;
+}
+
+export function decoratePlans
(plans: T[]) {
+ const sorted = [...plans]
+ .map((plan, index) => ({ plan, index, value: numericPrice(plan.price) }))
+ .sort((a, b) => a.value - b.value || a.index - b.index);
+
+ const cheapestIndex = sorted[0]?.index ?? -1;
+ const mobileOrder = new Map(sorted.map((entry, order) => [entry.index, order]));
+
+ return plans.map((plan, index) => ({
+ ...plan,
+ isPopular: index === cheapestIndex,
+ mobileOrder: mobileOrder.get(index) ?? index
+ }));
+}
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index 40798e0..1e3a27c 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -7,7 +7,7 @@
import InfoSection from '$lib/components/InfoSection.svelte';
import InstagramSection from '$lib/components/InstagramSection.svelte';
import BookingSection from '$lib/components/BookingSection.svelte';
- import PromiseSection from '$lib/components/PromiseSection.svelte';
+ import FounderStorySection from '$lib/components/FounderStorySection.svelte';
import ServicesSection from '$lib/components/ServicesSection.svelte';
import TestimonialsSection from '$lib/components/TestimonialsSection.svelte';
import ValuesSection from '$lib/components/ValuesSection.svelte';
@@ -130,7 +130,7 @@
-
+