Onboarding / Deployment Scripts / Marketing updates

This commit is contained in:
2026-05-11 21:02:24 +12:00
parent a90dfb7c66
commit 955a563d14
110 changed files with 9803 additions and 937 deletions
+481 -106
View File
@@ -1,68 +1,164 @@
<script lang="ts">
import { accordion } from '$lib/actions/accordion';
import { reveal } from '$lib/actions/reveal';
import ServicesSection from '$lib/components/ServicesSection.svelte';
import { getImageMetadata } from '$lib/image-metadata';
import type { AboutPageContent, SiteSharedContent } from '$lib/types';
import Icon from '$lib/components/Icon.svelte';
import { getEnhancedImage } from '$lib/enhanced-images';
import type { AboutPageContent } from '$lib/types';
export let content: SiteSharedContent;
export let pageContent: AboutPageContent;
$: standardSections = pageContent.sections.filter((s) => s.accent !== 'founder');
$: founderSection = pageContent.sections.find((s) => s.accent === 'founder') ?? null;
const founderHeadingLead = 'Meet Aless,';
const founderHeadingHighlight = 'the heart of Goodwalk';
</script>
<main class="about-page">
<!-- ── Hero ── -->
<section class="about-hero">
<div class="about-inner">
<span class="about-hero-eyebrow">About Goodwalk</span>
<h1>{pageContent.title}</h1>
<p class="about-hero-desc">Small dog specialists serving Auckland Central. A team your dog knows by name.</p>
<div class="about-hero-chips">
<a
href="https://g.page/r/CUsvrWPhkYrAEB0/"
target="_blank"
rel="noopener"
class="about-hero-chip about-hero-chip-link"
>
<span class="about-chip-stars" aria-hidden="true">★★★★★</span>
30+ five-star Google reviews
</a>
<span class="about-hero-chip">Auckland Central</span>
<span class="about-hero-chip">Small dog specialists</span>
</div>
</div>
</section>
{#each pageContent.sections as section}
<!-- ── Standard sections (Who we are, Our impact) ── -->
{#each standardSections as section}
{@const enhanced = getEnhancedImage(section.imageUrl)}
<section
use:reveal
class:about-section-gradient={section.accent === 'gradient'}
class="about-section reveal-block"
class:about-section-gradient={section.accent === 'gradient'}
>
<div class:about-section-reverse={section.reverse} class="about-inner about-section-grid">
<div class="about-inner about-section-grid" class:about-section-reverse={section.reverse}>
<div class="about-copy">
{#if section.eyebrow}
<span class="about-eyebrow">{section.eyebrow}</span>
{/if}
<h2>{section.title}</h2>
{#each section.body as paragraph}
<p>{paragraph}</p>
{/each}
</div>
<div class="about-media">
<img
src={section.imageUrl}
alt={section.imageAlt}
width={getImageMetadata(section.imageUrl)?.width}
height={getImageMetadata(section.imageUrl)?.height}
loading="lazy"
decoding="async"
/>
{#if enhanced}
<enhanced:img src={enhanced} alt={section.imageAlt} loading="lazy" decoding="async" />
{:else}
<img src={section.imageUrl} alt={section.imageAlt} loading="lazy" decoding="async" />
{/if}
</div>
</div>
</section>
{/each}
<ServicesSection services={content.services} heading={pageContent.servicesTitle} />
<!-- ── Founder section ── -->
{#if founderSection}
{@const founderEnhanced = getEnhancedImage(founderSection.imageUrl)}
<section use:reveal={{ delay: 50 }} class="about-founder reveal-block">
<div class="about-inner about-founder-grid">
<div class="about-founder-media">
{#if founderEnhanced}
<enhanced:img
src={founderEnhanced}
alt={founderSection.imageAlt}
loading="lazy"
decoding="async"
/>
{:else}
<img
src={founderSection.imageUrl}
alt={founderSection.imageAlt}
loading="lazy"
decoding="async"
/>
{/if}
</div>
<div class="about-founder-copy">
{#if founderSection.eyebrow}
<span class="about-eyebrow">{founderSection.eyebrow}</span>
{/if}
<h2 class="about-founder-heading">
<span class="about-founder-heading-desktop">
<span class="about-founder-title-main">{founderHeadingLead}</span>
<br />
<span class="about-founder-title-highlight">{founderHeadingHighlight}</span>
</span>
<span class="about-founder-heading-mobile">
<span class="about-founder-title-main">{founderHeadingLead}</span>
<span class="about-founder-title-highlight">{founderHeadingHighlight}</span>
</span>
</h2>
{#each founderSection.body as paragraph}
<p>{paragraph}</p>
{/each}
<a href="/contact-us" class="btn btn-green btn-mobile-center">Book a free Meet &amp; Greet</a>
</div>
</div>
</section>
{/if}
<section use:reveal={{ delay: 70 }} class="about-contact reveal-block">
<!-- ── FAQs ── -->
{#if pageContent.faqs && pageContent.faqs.length}
<section use:reveal={{ delay: 30 }} class="about-faq reveal-block">
<div class="about-inner">
<div class="about-faq-header">
<span class="about-eyebrow">FAQ</span>
<h2>{pageContent.faqTitle ?? 'Common questions'}</h2>
</div>
<div use:accordion class="faq about-faq-list">
{#each pageContent.faqs as item}
<details>
<summary>{item.question}</summary>
<p>{item.answer}</p>
</details>
{/each}
</div>
</div>
</section>
{/if}
<!-- ── Contact CTA ── -->
<section use:reveal={{ delay: 50 }} class="about-contact reveal-block">
<div class="about-inner">
<div class="about-contact-card">
<span class="about-contact-eyebrow">Get in touch</span>
<h2>{pageContent.contact.title}</h2>
<div class="about-contact-grid">
<p class="about-contact-desc">Questions, pricing, or your first Meet &amp; Greet — start here and we'll reply within 24 hours.</p>
<a class="btn btn-yellow btn-mobile-center about-contact-btn" href={pageContent.contact.cta.href}>
{pageContent.contact.cta.label}
</a>
<div class="about-contact-links">
<a class="about-contact-link" href={`mailto:${pageContent.contact.email}`}>
<Icon name="fas fa-envelope" />
{pageContent.contact.email}
</a>
<a class="btn btn-yellow" href={pageContent.contact.cta.href}>
{pageContent.contact.cta.label}
</a>
<a class="about-contact-link" href={`tel:${pageContent.contact.phone.replace(/[^0-9+]/g, '')}`}>
<a
class="about-contact-link"
href={`tel:${pageContent.contact.phone.replace(/[^0-9+]/g, '')}`}
>
<Icon name="fas fa-phone" />
{pageContent.contact.phone}
</a>
</div>
</div>
</div>
</section>
</main>
<style>
@@ -76,47 +172,112 @@
padding: 0 50px;
}
/* ── Shared eyebrow ── */
.about-eyebrow,
.about-hero-eyebrow,
.about-contact-eyebrow {
display: inline-block;
margin-bottom: 14px;
padding: 7px 12px;
border-radius: 999px;
font-size: 12px;
font-weight: 800;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.about-eyebrow {
background: rgba(33, 48, 33, 0.08);
color: var(--gw-green);
box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.05);
}
.about-hero-eyebrow,
.about-contact-eyebrow {
background: rgba(255, 255, 255, 0.14);
color: #fff;
}
/* ── Hero ── */
.about-hero {
padding: 72px 0 40px;
}
.about-hero h1,
.about-copy h2,
.about-contact-card h2 {
margin: 0;
font-family: var(--font-head);
font-size: clamp(34px, 4vw, 56px);
line-height: 1.05;
letter-spacing: -0.04em;
color: #000;
}
.about-hero h1 {
background: var(--gw-green);
color: #fff;
padding: 80px 0 72px;
text-align: center;
}
.about-hero h1 {
margin: 0 0 16px;
font-family: var(--font-head);
font-size: clamp(40px, 5vw, 68px);
font-weight: 800;
line-height: 1.02;
letter-spacing: -0.04em;
color: #fff;
}
.about-hero-desc {
max-width: 480px;
margin: 0 auto 28px;
color: rgba(255, 255, 255, 0.82);
font-size: 17px;
line-height: 1.55;
}
.about-hero-chips {
display: flex;
justify-content: center;
gap: 10px;
flex-wrap: wrap;
}
.about-hero-chip {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 9px 18px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.14);
color: #fff;
font-family: var(--font-head);
font-size: 14px;
font-weight: 700;
line-height: 1.2;
letter-spacing: 0.01em;
}
.about-hero-chip-link {
text-decoration: none;
transition: background 0.18s ease;
}
.about-hero-chip-link:hover {
background: rgba(255, 255, 255, 0.18);
}
.about-chip-stars {
color: var(--yellow);
letter-spacing: 1px;
font-size: 13px;
}
/* ── Standard sections ── */
.about-section {
padding: 0 0 88px;
padding: 88px 0;
}
.about-section-gradient {
margin: 0 24px 88px;
padding: 40px 0;
border-radius: 28px;
background: linear-gradient(180deg, #f5efe6 0%, #f9f6ef 100%);
}
.about-section-grid {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: 44px;
gap: 60px;
align-items: center;
}
.about-section-reverse {
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
}
.about-section-reverse .about-copy {
order: 2;
}
@@ -126,29 +287,227 @@
}
.about-copy h2 {
margin: 0 0 16px;
font-family: var(--font-head);
font-size: clamp(28px, 3vw, 40px);
font-weight: 800;
line-height: 1.08;
letter-spacing: -0.03em;
color: #0d1a0d;
}
.about-copy p {
margin: 18px 0 0;
margin: 12px 0 0;
color: #34363a;
font-size: 17px;
line-height: 1.75;
}
.about-media {
aspect-ratio: 4 / 3;
overflow: hidden;
border-radius: 28px;
box-shadow: 0 16px 48px rgba(17, 20, 24, 0.1);
}
.about-media img {
display: block;
width: 100%;
max-width: 460px;
aspect-ratio: 4 / 3;
height: auto;
margin-left: auto;
margin-right: auto;
border-radius: 28px;
height: 100%;
object-fit: cover;
box-shadow: 0 16px 40px rgba(17, 20, 24, 0.08);
object-position: center top;
}
/* ── Founder section ── */
.about-founder {
padding: 88px 0;
background: #fff;
}
.about-founder-grid {
display: grid;
grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
gap: 64px;
align-items: center;
}
.about-founder-media img {
display: block;
width: 100%;
max-width: 400px;
height: auto;
border-radius: 28px;
object-fit: cover;
box-shadow: 0 24px 56px rgba(17, 20, 24, 0.12);
margin: 0 auto;
}
.about-founder-copy h2 {
margin: 0 0 16px;
font-family: var(--font-head);
font-size: clamp(30px, 3.5vw, 44px);
font-weight: 800;
line-height: 1.06;
letter-spacing: -0.03em;
text-wrap: balance;
color: #0d1a0d;
}
.about-founder-heading-desktop {
display: block;
}
.about-founder-heading-mobile {
display: none;
}
.about-founder-heading-mobile .about-founder-title-main,
.about-founder-heading-mobile .about-founder-title-highlight {
display: block;
}
.about-founder-title-main {
color: #0d1a0d;
}
.about-founder-title-highlight {
position: relative;
display: inline-block;
color: #0d1a0d;
}
.about-founder-title-highlight::after {
content: '';
position: absolute;
left: 0;
right: -6px;
bottom: -16px;
height: 24px;
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 34' fill='none'%3E%3Cpath d='M4 24C67 10 131 4 198 5c43 1 82 6 118 18' stroke='%23192419' stroke-width='8' stroke-linecap='round'/%3E%3C/svg%3E")
center/contain no-repeat;
transform-origin: left center;
animation: about-founder-underline-draw 0.9s cubic-bezier(0.22, 1, 0.36, 1) 0.2s both;
}
@keyframes about-founder-underline-draw {
0% {
opacity: 0;
transform: scaleX(0.2) translateY(6px) rotate(-1.5deg);
}
65% {
opacity: 1;
transform: scaleX(1.04) translateY(0) rotate(0deg);
}
100% {
opacity: 1;
transform: scaleX(1) translateY(0) rotate(0deg);
}
}
.about-founder-copy p {
margin: 14px 0 0;
color: #34363a;
font-size: 17px;
line-height: 1.75;
}
.about-founder-copy .btn {
display: flex;
width: fit-content;
margin: 28px auto 0;
}
/* ── FAQs ── */
.about-faq {
padding: 80px 0;
background: var(--off-white);
}
.about-faq-header {
text-align: center;
margin-bottom: 40px;
}
.about-faq-header h2 {
margin: 0;
font-family: var(--font-head);
font-size: clamp(28px, 3vw, 40px);
font-weight: 800;
line-height: 1.08;
letter-spacing: -0.03em;
color: #0d1a0d;
}
.about-faq-list {
max-width: 720px;
margin: 0 auto;
display: flex;
flex-direction: column;
gap: 10px;
}
/* ── Contact CTA ── */
.about-contact {
padding: 0 0 88px;
}
.about-contact-card {
background: var(--gw-green);
color: #fff;
border-radius: 28px;
padding: 56px 48px;
text-align: center;
box-shadow: 0 20px 48px rgba(33, 48, 33, 0.18);
}
.about-contact-card h2 {
margin: 0 0 10px;
font-family: var(--font-head);
font-size: clamp(28px, 3vw, 42px);
font-weight: 800;
line-height: 1.08;
letter-spacing: -0.03em;
color: #fff;
}
.about-contact-desc {
max-width: 440px;
margin: 0 auto 28px;
color: rgba(255, 255, 255, 0.75);
font-size: 16px;
line-height: 1.6;
}
.about-contact-btn {
display: inline-flex;
}
.about-contact-links {
display: flex;
justify-content: center;
gap: 32px;
flex-wrap: wrap;
margin-top: 22px;
}
.about-contact-link {
display: inline-flex;
align-items: center;
gap: 8px;
color: rgba(255, 255, 255, 0.72);
font-size: 15px;
font-weight: 500;
text-decoration: none;
transition: color 0.18s ease;
}
.about-contact-link:hover {
color: #fff;
}
/* ── Reveal ── */
:global(.reveal-ready.reveal-block) {
opacity: 0;
transform: translate3d(0, var(--reveal-distance, 24px), 0);
@@ -163,41 +522,12 @@
transform: translate3d(0, 0, 0);
}
.about-contact {
padding: 0 0 88px;
}
.about-contact-card {
border-radius: 28px;
background: #fff;
padding: 42px 48px;
box-shadow: 0 14px 34px rgba(17, 20, 24, 0.05);
text-align: center;
}
.about-contact-card h2 {
font-size: clamp(28px, 3vw, 42px);
}
.about-contact-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 20px;
align-items: center;
margin-top: 28px;
}
.about-contact-link {
color: #34363a;
font-size: 20px;
font-weight: 600;
text-decoration: none;
}
/* ── Tablet ── */
@media (max-width: 1024px) {
.about-section-grid,
.about-section-reverse {
.about-founder-grid {
grid-template-columns: 1fr;
gap: 36px;
}
.about-section-reverse .about-copy,
@@ -205,38 +535,44 @@
order: initial;
}
.about-contact-grid {
grid-template-columns: 1fr;
.about-founder-media img {
max-width: 420px;
}
}
/* ── Mobile ── */
@media (max-width: 768px) {
.about-inner {
padding: 0 24px;
}
.about-hero {
padding: 56px 0 24px;
padding: 56px 0 48px;
}
.about-section,
.about-contact {
padding-bottom: 64px;
.about-hero h1 {
font-size: 38px;
}
.about-section-gradient {
margin: 0 12px 64px;
padding: 28px 0;
border-radius: 28px;
.about-hero-desc {
font-size: 15px;
}
.about-hero-chip {
font-size: 13px;
padding: 8px 14px;
}
.about-section {
padding: 60px 0;
}
.about-section-grid {
gap: 24px;
gap: 28px;
}
.about-copy h2,
.about-contact-card h2 {
font-size: 30px;
.about-copy h2 {
font-size: 28px;
}
.about-copy p {
@@ -244,16 +580,55 @@
line-height: 1.7;
}
.about-founder {
padding: 60px 0;
}
.about-founder-grid {
gap: 28px;
}
.about-founder-copy h2 {
font-size: 26px;
line-height: 1.02;
}
.about-founder-heading-desktop {
display: none;
}
.about-founder-heading-mobile {
display: block;
}
.about-founder-copy p {
font-size: 16px;
line-height: 1.7;
}
.about-faq {
padding: 60px 0;
}
.about-contact {
padding-bottom: 60px;
}
.about-contact-card {
padding: 30px 24px;
padding: 36px 24px;
border-radius: 24px;
}
.about-contact-grid {
margin-top: 22px;
.about-contact-links {
flex-direction: column;
align-items: center;
gap: 14px;
}
}
.about-contact-link {
font-size: 18px;
@media (prefers-reduced-motion: reduce) {
.about-founder-title-highlight::after {
animation: none;
}
}
</style>