4.2.3 - CTA footer, How it works

This commit is contained in:
2026-05-06 17:42:43 +12:00
parent 6d021e05ea
commit ad9df7578a
19 changed files with 621 additions and 86 deletions
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -1,4 +1,4 @@
APP_VERSION=4.2.2
APP_VERSION=4.2.3
TZ=Pacific/Auckland
POSTGRES_DB=goodwalk
+4 -4
View File
@@ -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
View File
@@ -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
View File
@@ -1,4 +1,4 @@
ARG APP_VERSION=4.2.2
ARG APP_VERSION=4.2.3
FROM python:3.12-slim
ARG APP_VERSION
+2 -2
View File
@@ -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
View File
@@ -1,6 +1,6 @@
{
"name": "goodwalk-svelte-port",
"version": "4.2.2",
"version": "4.2.3",
"private": true,
"type": "module",
"scripts": {
+64 -30
View File
@@ -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>
+5 -3
View File
@@ -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 &amp; Greet. Start here and well reply within 24 hours.</p>
<a href="/contact-us" class="footer-book-btn">
Book a Meet &amp; 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"
+259
View File
@@ -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>
+140 -8
View File
@@ -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>
+21
View File
@@ -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',
+3 -3
View File
@@ -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;
+2 -2
View File
@@ -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;
}
+30 -7
View File
@@ -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
View File
@@ -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 {
+13
View File
@@ -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;
+2
View File
@@ -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} />