4.2.3 - CTA footer, How it works
This commit is contained in:
+1
-1
@@ -73,7 +73,7 @@ mkdir -p /docker/goodwalk-svelte
|
||||
It is created from [deploy.env.template](deploy.env.template). Current template contents:
|
||||
|
||||
```env
|
||||
APP_VERSION=4.2.2
|
||||
APP_VERSION=4.2.3
|
||||
ENABLE_GENERAL_ENQUIRIES=false
|
||||
TZ=Pacific/Auckland
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
ARG APP_VERSION=4.2.2
|
||||
ARG APP_VERSION=4.2.3
|
||||
|
||||
FROM node:22-alpine AS builder
|
||||
ARG APP_VERSION
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
APP_VERSION=4.2.2
|
||||
APP_VERSION=4.2.3
|
||||
TZ=Pacific/Auckland
|
||||
|
||||
POSTGRES_DB=goodwalk
|
||||
|
||||
@@ -3,10 +3,10 @@ services:
|
||||
build:
|
||||
context: .
|
||||
args:
|
||||
APP_VERSION: ${APP_VERSION:-4.2.2}
|
||||
APP_VERSION: ${APP_VERSION:-4.2.3}
|
||||
container_name: goodwalk_svelte_app
|
||||
environment:
|
||||
APP_VERSION: ${APP_VERSION:-4.2.2}
|
||||
APP_VERSION: ${APP_VERSION:-4.2.3}
|
||||
DATABASE_URL: postgresql://${POSTGRES_USER:-goodwalk}:${POSTGRES_PASSWORD_URLENCODED:-goodwalk}@db:5432/${POSTGRES_DB:-goodwalk}
|
||||
NODE_ENV: production
|
||||
PORT: 3000
|
||||
@@ -25,10 +25,10 @@ services:
|
||||
build:
|
||||
context: ./mail-api
|
||||
args:
|
||||
APP_VERSION: ${APP_VERSION:-4.2.2}
|
||||
APP_VERSION: ${APP_VERSION:-4.2.3}
|
||||
container_name: goodwalk_svelte_mail_api
|
||||
environment:
|
||||
APP_VERSION: ${APP_VERSION:-4.2.2}
|
||||
APP_VERSION: ${APP_VERSION:-4.2.3}
|
||||
RESEND_API_KEY: ${RESEND_API_KEY}
|
||||
OWNER_EMAIL: ${OWNER_EMAIL}
|
||||
OWNER_BCC: ${OWNER_BCC:-}
|
||||
|
||||
+4
-4
@@ -3,9 +3,9 @@ services:
|
||||
build:
|
||||
context: .
|
||||
args:
|
||||
APP_VERSION: ${APP_VERSION:-4.2.2}
|
||||
APP_VERSION: ${APP_VERSION:-4.2.3}
|
||||
environment:
|
||||
APP_VERSION: ${APP_VERSION:-4.2.2}
|
||||
APP_VERSION: ${APP_VERSION:-4.2.3}
|
||||
DATABASE_URL: postgresql://${POSTGRES_USER:-goodwalk}:${POSTGRES_PASSWORD:-goodwalk}@db:5432/${POSTGRES_DB:-goodwalk}
|
||||
NODE_ENV: production
|
||||
PORT: ${APP_PORT:-3000}
|
||||
@@ -19,9 +19,9 @@ services:
|
||||
build:
|
||||
context: ./mail-api
|
||||
args:
|
||||
APP_VERSION: ${APP_VERSION:-4.2.2}
|
||||
APP_VERSION: ${APP_VERSION:-4.2.3}
|
||||
environment:
|
||||
APP_VERSION: ${APP_VERSION:-4.2.2}
|
||||
APP_VERSION: ${APP_VERSION:-4.2.3}
|
||||
RESEND_API_KEY: ${RESEND_API_KEY}
|
||||
OWNER_EMAIL: ${OWNER_EMAIL}
|
||||
OWNER_BCC: ${OWNER_BCC:-}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
ARG APP_VERSION=4.2.2
|
||||
ARG APP_VERSION=4.2.3
|
||||
|
||||
FROM python:3.12-slim
|
||||
ARG APP_VERSION
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "goodwalk-svelte-port",
|
||||
"version": "4.2.2",
|
||||
"version": "4.2.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "goodwalk-svelte-port",
|
||||
"version": "4.2.2",
|
||||
"version": "4.2.3",
|
||||
"dependencies": {
|
||||
"canvas-confetti": "^1.9.4",
|
||||
"pg": "^8.13.1"
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "goodwalk-svelte-port",
|
||||
"version": "4.2.2",
|
||||
"version": "4.2.3",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
+64
-30
@@ -9,51 +9,21 @@
|
||||
<link rel="apple-touch-icon" href="/images/goodwalk-favicon-192.png" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous" />
|
||||
<link
|
||||
rel="preload"
|
||||
as="style"
|
||||
href="https://fonts.googleapis.com/css2?family=Fredoka+One&family=Readex+Pro:wght@400;500;600;700&family=Unbounded:wght@400;600;700;800&display=swap"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Fredoka+One&family=Readex+Pro:wght@400;500;600;700&family=Unbounded:wght@400;600;700;800&display=swap"
|
||||
rel="stylesheet"
|
||||
media="print"
|
||||
onload="this.media='all'"
|
||||
/>
|
||||
<noscript>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Fredoka+One&family=Readex+Pro:wght@400;500;600;700&family=Unbounded:wght@400;600;700;800&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</noscript>
|
||||
<link
|
||||
rel="preconnect"
|
||||
href="https://cdnjs.cloudflare.com"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
as="style"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
|
||||
media="print"
|
||||
onload="this.media='all'"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
<noscript>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
</noscript>
|
||||
<!-- Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-K7TLSFJVP1"></script>
|
||||
<script>
|
||||
@@ -62,9 +32,73 @@
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-K7TLSFJVP1');
|
||||
</script>
|
||||
<style>
|
||||
.no-js-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 24px;
|
||||
background: rgba(17, 20, 24, 0.58);
|
||||
}
|
||||
|
||||
.no-js-card {
|
||||
width: min(100%, 560px);
|
||||
padding: 32px 28px;
|
||||
border-radius: 24px;
|
||||
background: #fff;
|
||||
box-shadow: 0 24px 60px rgba(17, 20, 24, 0.2);
|
||||
text-align: left;
|
||||
font-family: 'Readex Pro', system-ui, sans-serif;
|
||||
color: #213021;
|
||||
}
|
||||
|
||||
.no-js-kicker {
|
||||
display: inline-block;
|
||||
margin-bottom: 14px;
|
||||
padding: 6px 10px;
|
||||
border-radius: 999px;
|
||||
background: #f3ecd9;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
color: #213021;
|
||||
}
|
||||
|
||||
.no-js-card h1 {
|
||||
margin: 0 0 12px;
|
||||
font-family: 'Unbounded', system-ui, sans-serif;
|
||||
font-size: clamp(28px, 4vw, 38px);
|
||||
line-height: 1.05;
|
||||
letter-spacing: -0.04em;
|
||||
color: #213021;
|
||||
}
|
||||
|
||||
.no-js-card p {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
line-height: 1.65;
|
||||
color: #4c5056;
|
||||
}
|
||||
</style>
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<noscript>
|
||||
<div class="no-js-overlay" role="alertdialog" aria-labelledby="no-js-title" aria-describedby="no-js-copy">
|
||||
<div class="no-js-card">
|
||||
<span class="no-js-kicker">JavaScript Required</span>
|
||||
<h1 id="no-js-title">Please enable JavaScript to use this site.</h1>
|
||||
<p id="no-js-copy">
|
||||
Goodwalk relies on JavaScript for key parts of the site, including the booking and contact forms.
|
||||
Please turn JavaScript back on in your browser settings and reload the page.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</noscript>
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -72,13 +72,15 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="footer-action">
|
||||
<div class="footer-action footer-panel footer-panel-accent">
|
||||
<p class="footer-col-label">Get Started</p>
|
||||
<h3 class="footer-action-title">Ready when you are</h3>
|
||||
<p class="footer-action-copy">Questions, pricing, or your first Meet & Greet. Start here and we’ll reply within 24 hours.</p>
|
||||
<a href="/contact-us" class="footer-book-btn">
|
||||
Book a Meet & Greet
|
||||
Contact Us
|
||||
<Icon name="fas fa-arrow-right" />
|
||||
</a>
|
||||
<p class="footer-book-note">Free, no-obligation introduction</p>
|
||||
<p class="footer-book-note">Friendly, no-pressure first step</p>
|
||||
<a
|
||||
href="https://g.page/r/CUsvrWPhkYrAEB0/"
|
||||
target="_blank"
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
<script lang="ts">
|
||||
import { reveal } from '$lib/actions/reveal';
|
||||
import Icon from '$lib/components/Icon.svelte';
|
||||
import type { HowItWorksContent } from '$lib/types';
|
||||
|
||||
export let content: HowItWorksContent;
|
||||
</script>
|
||||
|
||||
<section id="how-it-works" use:reveal={{ delay: 30 }} class="reveal-block">
|
||||
<div class="how-it-works-inner">
|
||||
<div class="how-it-works-header">
|
||||
<h2 class="section-heading">{content.title}</h2>
|
||||
{#if content.intro}
|
||||
<p class="how-it-works-intro">{content.intro}</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="how-it-works-flow" aria-label="How it works">
|
||||
{#each content.steps as step, index}
|
||||
<article class="how-it-works-step">
|
||||
<div class="how-it-works-badge" aria-hidden="true">
|
||||
<span class="how-it-works-count">0{index + 1}</span>
|
||||
</div>
|
||||
{#if step.icon}
|
||||
<div class="how-it-works-icon-bubble">
|
||||
<Icon name={step.icon} className="how-it-works-icon" />
|
||||
</div>
|
||||
{/if}
|
||||
<h3>{step.title}</h3>
|
||||
<p>{step.body}</p>
|
||||
</article>
|
||||
|
||||
{#if index < content.steps.length - 1}
|
||||
<div class="how-it-works-connector" aria-hidden="true">
|
||||
<span class="how-it-works-connector-line"></span>
|
||||
<div class="how-it-works-connector-bubble">
|
||||
<Icon name="fas fa-paw" className="how-it-works-connector-icon" />
|
||||
</div>
|
||||
<span class="how-it-works-connector-line"></span>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
:global(.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);
|
||||
}
|
||||
|
||||
:global(.reveal-visible.reveal-block) {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
#how-it-works {
|
||||
background: #fff;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.how-it-works-inner {
|
||||
max-width: var(--max-w);
|
||||
margin: 0 auto;
|
||||
padding: 0 50px;
|
||||
}
|
||||
|
||||
.how-it-works-header {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.how-it-works-intro {
|
||||
max-width: 640px;
|
||||
margin: 14px auto 0;
|
||||
color: #4c5056;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.how-it-works-flow {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto minmax(0, 1fr);
|
||||
gap: 18px;
|
||||
align-items: stretch;
|
||||
margin-top: 34px;
|
||||
}
|
||||
|
||||
.how-it-works-step {
|
||||
position: relative;
|
||||
padding: 26px 24px;
|
||||
border-radius: 28px;
|
||||
background:
|
||||
radial-gradient(circle at top center, rgba(255, 209, 0, 0.18), transparent 36%),
|
||||
linear-gradient(180deg, #fffaf0 0%, #f8f4ea 100%);
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(17, 20, 24, 0.05),
|
||||
0 14px 28px rgba(17, 20, 24, 0.04);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.how-it-works-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-bottom: 14px;
|
||||
padding: 8px 12px;
|
||||
border-radius: 999px;
|
||||
background: #fff;
|
||||
box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.06);
|
||||
}
|
||||
|
||||
.how-it-works-count {
|
||||
color: var(--green);
|
||||
font-family: var(--font-head);
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.how-it-works-icon-bubble {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
margin: 0 auto 16px;
|
||||
border-radius: 50%;
|
||||
background: var(--green);
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(255, 255, 255, 0.08),
|
||||
0 16px 28px rgba(33, 48, 33, 0.16);
|
||||
}
|
||||
|
||||
:global(.how-it-works-icon.icon) {
|
||||
color: #fff;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.how-it-works-step h3 {
|
||||
margin: 0 0 10px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.how-it-works-step p {
|
||||
margin: 0;
|
||||
color: #4c5056;
|
||||
font-size: 15px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.how-it-works-connector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
min-width: 90px;
|
||||
}
|
||||
|
||||
.how-it-works-connector-line {
|
||||
width: 24px;
|
||||
height: 2px;
|
||||
border-radius: 999px;
|
||||
background: rgba(33, 48, 33, 0.22);
|
||||
}
|
||||
|
||||
.how-it-works-connector-bubble {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(180deg, #254129 0%, #213021 100%);
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(255, 255, 255, 0.08),
|
||||
0 14px 24px rgba(33, 48, 33, 0.14);
|
||||
}
|
||||
|
||||
:global(.how-it-works-connector-icon.icon) {
|
||||
color: var(--green);
|
||||
color: #ffd54a;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
#how-it-works {
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.how-it-works-inner {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.how-it-works-intro {
|
||||
font-size: 15px;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.how-it-works-flow {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 14px;
|
||||
margin-top: 26px;
|
||||
}
|
||||
|
||||
.how-it-works-step {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
grid-template-areas:
|
||||
'icon title badge'
|
||||
'body body body';
|
||||
column-gap: 14px;
|
||||
row-gap: 10px;
|
||||
padding: 20px 18px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.how-it-works-badge {
|
||||
grid-area: badge;
|
||||
justify-self: end;
|
||||
align-self: start;
|
||||
margin-bottom: 0;
|
||||
padding: 7px 10px;
|
||||
}
|
||||
|
||||
.how-it-works-icon-bubble {
|
||||
grid-area: icon;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
margin: 0;
|
||||
align-self: start;
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(255, 255, 255, 0.08),
|
||||
0 12px 22px rgba(33, 48, 33, 0.14);
|
||||
}
|
||||
|
||||
.how-it-works-step h3 {
|
||||
grid-area: title;
|
||||
align-self: center;
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.how-it-works-step p {
|
||||
grid-area: body;
|
||||
margin-top: 2px;
|
||||
font-size: 14px;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.how-it-works-connector {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -3,20 +3,38 @@
|
||||
import type { InfoContent } from '$lib/types';
|
||||
|
||||
export let info: InfoContent;
|
||||
|
||||
$: suburbChips = info.suburbs
|
||||
.split(',')
|
||||
.map((suburb) => suburb.trim())
|
||||
.filter(Boolean);
|
||||
</script>
|
||||
|
||||
<section id="info">
|
||||
<div class="info-inner">
|
||||
<div class="info-block">
|
||||
<h2><Icon name="fas fa-location-dot" /> {info.title}</h2>
|
||||
<p>{info.intro}</p>
|
||||
<p class="info-copy">{info.suburbs}</p>
|
||||
<p class="info-copy">
|
||||
{info.nearbyText}
|
||||
<a href={info.nearbyCta.href}>{info.nearbyCta.label}</a>
|
||||
</p>
|
||||
<h3>{info.hoursLabel}</h3>
|
||||
<p>{info.hours}</p>
|
||||
<p class="info-lead">{info.intro}</p>
|
||||
<p class="info-support">Regular walks across the inner-west and nearby suburbs.</p>
|
||||
|
||||
<div class="info-suburb-chips" aria-label="Suburbs we cover">
|
||||
{#each suburbChips as suburb}
|
||||
<span class="info-suburb-chip">{suburb}</span>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<div class="info-nearby-card">
|
||||
<div class="info-nearby-copy">
|
||||
<span class="info-nearby-kicker">Nearby but not listed?</span>
|
||||
<p>{info.nearbyText} There's a good chance we can still help.</p>
|
||||
</div>
|
||||
<a class="info-nearby-cta" href={info.nearbyCta.href}>{info.nearbyCta.label}</a>
|
||||
</div>
|
||||
|
||||
<div class="info-hours-card">
|
||||
<h3>{info.hoursLabel}</h3>
|
||||
<p>{info.hours}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-block">
|
||||
@@ -32,3 +50,117 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.info-lead {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.info-support {
|
||||
margin: 0 0 22px;
|
||||
color: #5f6369;
|
||||
}
|
||||
|
||||
.info-suburb-chips {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-bottom: 26px;
|
||||
}
|
||||
|
||||
.info-suburb-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 40px;
|
||||
padding: 8px 14px;
|
||||
border-radius: 999px;
|
||||
background: #fff;
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(17, 20, 24, 0.06),
|
||||
0 10px 24px rgba(17, 20, 24, 0.04);
|
||||
color: #213021;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.info-nearby-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 18px;
|
||||
margin-bottom: 22px;
|
||||
padding: 22px 24px;
|
||||
border-radius: 24px;
|
||||
background: linear-gradient(180deg, #fffaf0 0%, #f8f1e3 100%);
|
||||
box-shadow: 0 14px 30px rgba(17, 20, 24, 0.05);
|
||||
}
|
||||
|
||||
.info-nearby-copy p {
|
||||
margin: 6px 0 0;
|
||||
color: #4c5056;
|
||||
}
|
||||
|
||||
.info-nearby-kicker {
|
||||
display: inline-block;
|
||||
color: var(--green);
|
||||
font-family: var(--font-head);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.info-nearby-cta {
|
||||
flex: 0 0 auto;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 48px;
|
||||
padding: 12px 18px;
|
||||
border-radius: 999px;
|
||||
background: var(--green);
|
||||
color: #fff;
|
||||
font-family: var(--font-head);
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.info-hours-card {
|
||||
padding-top: 18px;
|
||||
border-top: 1px dashed rgba(33, 48, 33, 0.18);
|
||||
}
|
||||
|
||||
.info-hours-card h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.info-hours-card p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.info-suburb-chips {
|
||||
gap: 8px;
|
||||
margin-bottom: 22px;
|
||||
}
|
||||
|
||||
.info-suburb-chip {
|
||||
min-height: 36px;
|
||||
padding: 8px 12px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.info-nearby-card {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding: 20px 18px;
|
||||
}
|
||||
|
||||
.info-nearby-cta {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -83,6 +83,27 @@ export const homepageContent: HomePageContent = {
|
||||
href: '/puppy-visits'
|
||||
}
|
||||
],
|
||||
howItWorks: {
|
||||
title: 'How it works',
|
||||
//intro: 'A simple onboarding flow designed to make sure the fit is right for both you and your dog.',
|
||||
steps: [
|
||||
{
|
||||
title: 'Meet & Greet',
|
||||
body: 'We meet you and your dog first, talk through routine, temperament, and what support you need.',
|
||||
icon: 'fas fa-handshake'
|
||||
},
|
||||
{
|
||||
title: 'Two assessment walks',
|
||||
body: 'We ease your dog in with two assessment walks so we can check confidence, handling, and group fit.',
|
||||
icon: 'fas fa-clipboard-check'
|
||||
},
|
||||
{
|
||||
title: 'Happy dogs, happy humans',
|
||||
body: 'Once approved, your dog joins regular walks and comes home tired, settled, and ready for a nap.',
|
||||
icon: 'fas fa-heart'
|
||||
}
|
||||
]
|
||||
},
|
||||
values: [
|
||||
{
|
||||
icon: 'fas fa-heart',
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
padding: 14px 32px;
|
||||
font-size: 15px;
|
||||
gap: 10px;
|
||||
padding: 13px 28px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
border-radius: 40px;
|
||||
cursor: pointer;
|
||||
|
||||
@@ -385,8 +385,8 @@ nav {
|
||||
|
||||
.footer-inner {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1.4fr 2fr;
|
||||
gap: 60px;
|
||||
grid-template-columns: 1.25fr 0.95fr 1.15fr;
|
||||
gap: 24px;
|
||||
margin-bottom: 48px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
@@ -254,12 +254,13 @@
|
||||
flex: 1 1 0;
|
||||
width: 0;
|
||||
min-width: 0;
|
||||
padding: 15px 12px;
|
||||
font-size: 13.5px;
|
||||
padding: 14px 10px;
|
||||
font-size: 12.5px;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
border-radius: 999px;
|
||||
line-height: 1.25;
|
||||
line-height: 1.15;
|
||||
letter-spacing: -0.01em;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
@@ -552,13 +553,31 @@
|
||||
}
|
||||
|
||||
.footer-inner {
|
||||
gap: 36px;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.footer-action {
|
||||
order: -1;
|
||||
}
|
||||
|
||||
.footer-panel {
|
||||
padding: 22px 18px;
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
.footer-nav {
|
||||
columns: 1;
|
||||
}
|
||||
|
||||
.footer-action-title {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.footer-action-copy {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.footer-book-note {
|
||||
text-align: left;
|
||||
}
|
||||
@@ -567,6 +586,10 @@
|
||||
padding: 11px 0;
|
||||
}
|
||||
|
||||
.footer-contact {
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.footer-bottom {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
@@ -610,8 +633,8 @@
|
||||
flex: 1 1 0;
|
||||
width: 0;
|
||||
margin-right: 0 !important;
|
||||
padding: 14px 10px;
|
||||
font-size: 13px;
|
||||
line-height: 1.2;
|
||||
padding: 13px 9px;
|
||||
font-size: 12px;
|
||||
line-height: 1.1;
|
||||
}
|
||||
}
|
||||
|
||||
+67
-18
@@ -526,34 +526,60 @@ footer {
|
||||
|
||||
.footer-logo {
|
||||
display: block;
|
||||
height: 22px;
|
||||
height: 24px;
|
||||
width: auto;
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.footer-panel {
|
||||
min-height: 100%;
|
||||
padding: 28px 26px;
|
||||
border-radius: 28px;
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(255, 255, 255, 0.08),
|
||||
0 18px 34px rgba(0, 0, 0, 0.08);
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
|
||||
.footer-panel-accent {
|
||||
background:
|
||||
radial-gradient(circle at top right, rgba(255, 209, 71, 0.22), transparent 38%),
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.11) 0%, rgba(255, 255, 255, 0.06) 100%);
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(255, 255, 255, 0.1),
|
||||
0 20px 40px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.footer-brand p {
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
opacity: 0.65;
|
||||
line-height: 1.7;
|
||||
opacity: 0.76;
|
||||
margin-bottom: 24px;
|
||||
white-space: pre-line;
|
||||
max-width: 34ch;
|
||||
}
|
||||
|
||||
.social-links a {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 16px;
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
transition: background 0.2s, color 0.2s;
|
||||
transition:
|
||||
background 0.2s,
|
||||
color 0.2s,
|
||||
transform 0.16s cubic-bezier(0.22, 1, 0.36, 1);
|
||||
}
|
||||
|
||||
.social-links a:hover {
|
||||
background: var(--yellow);
|
||||
color: #000;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.footer-col-label {
|
||||
@@ -568,15 +594,18 @@ footer {
|
||||
|
||||
.footer-nav {
|
||||
list-style: none;
|
||||
columns: 2;
|
||||
column-gap: 24px;
|
||||
}
|
||||
|
||||
.footer-nav li {
|
||||
margin: 0;
|
||||
break-inside: avoid;
|
||||
}
|
||||
|
||||
.footer-nav a {
|
||||
display: block;
|
||||
padding: 8px 0;
|
||||
padding: 9px 0;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
opacity: 0.75;
|
||||
@@ -587,13 +616,29 @@ footer {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.footer-action-title {
|
||||
margin: 0 0 10px;
|
||||
color: #fff;
|
||||
font-size: 28px;
|
||||
line-height: 1;
|
||||
letter-spacing: -0.04em;
|
||||
}
|
||||
|
||||
.footer-action-copy {
|
||||
margin: 0 0 22px;
|
||||
max-width: 34ch;
|
||||
color: rgba(255, 255, 255, 0.78);
|
||||
font-size: 14px;
|
||||
line-height: 1.65;
|
||||
}
|
||||
|
||||
.footer-book-btn {
|
||||
display: flex;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
padding: 15px 22px;
|
||||
padding: 16px 22px;
|
||||
border-radius: 999px;
|
||||
background: var(--yellow);
|
||||
color: #000;
|
||||
@@ -611,14 +656,16 @@ footer {
|
||||
.footer-book-note {
|
||||
margin: 0 0 20px;
|
||||
font-size: 13px;
|
||||
opacity: 0.5;
|
||||
text-align: center;
|
||||
opacity: 0.68;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.footer-reviews {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
padding: 9px 16px;
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, 0.07);
|
||||
@@ -640,8 +687,7 @@ footer {
|
||||
}
|
||||
|
||||
.footer-contact {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
margin-top: 16px;
|
||||
padding-top: 16px;
|
||||
@@ -652,6 +698,8 @@ footer {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
min-height: 42px;
|
||||
padding: 0 2px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
opacity: 0.7;
|
||||
@@ -674,14 +722,15 @@ footer {
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||
padding-top: 24px;
|
||||
padding-top: 28px;
|
||||
font-size: 13px;
|
||||
opacity: 0.5;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.footer-legal {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.footer-legal a {
|
||||
|
||||
@@ -74,6 +74,18 @@ export interface TestimonialContent {
|
||||
imageUrl?: string;
|
||||
}
|
||||
|
||||
export interface ProcessStep {
|
||||
title: string;
|
||||
body: string;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
export interface HowItWorksContent {
|
||||
title: string;
|
||||
intro?: string;
|
||||
steps: ProcessStep[];
|
||||
}
|
||||
|
||||
export interface BookingContent {
|
||||
title: string;
|
||||
subtitle: string;
|
||||
@@ -219,6 +231,7 @@ export interface HomePageContent {
|
||||
intro: IntroContent;
|
||||
promise: PromiseContent;
|
||||
services: IconCard[];
|
||||
howItWorks: HowItWorksContent;
|
||||
values: IconCard[];
|
||||
testimonials: TestimonialContent[];
|
||||
booking: BookingContent;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import Footer from '$lib/components/Footer.svelte';
|
||||
import Header from '$lib/components/Header.svelte';
|
||||
import HeroSection from '$lib/components/HeroSection.svelte';
|
||||
import HowItWorksSection from '$lib/components/HowItWorksSection.svelte';
|
||||
import InfoSection from '$lib/components/InfoSection.svelte';
|
||||
import InstagramSection from '$lib/components/InstagramSection.svelte';
|
||||
import BookingSection from '$lib/components/BookingSection.svelte';
|
||||
@@ -139,6 +140,7 @@
|
||||
<HeroSection hero={data.content.hero} reviewCta={data.content.intro.reviewCta} />
|
||||
<PromiseSection promise={data.content.promise} />
|
||||
<ServicesSection services={data.content.services} />
|
||||
<HowItWorksSection content={data.content.howItWorks} />
|
||||
<TestimonialsSection testimonials={data.content.testimonials} />
|
||||
<ValuesSection values={data.content.values} />
|
||||
<BookingSection booking={data.content.booking} />
|
||||
|
||||
Reference in New Issue
Block a user