Files
gw-svelte/src/lib/components/ValuesSection.svelte
T
2026-05-15 01:28:10 +12:00

644 lines
16 KiB
Svelte

<script lang="ts">
import { reveal } from '$lib/actions/reveal';
import { getEnhancedImage } from '$lib/enhanced-images';
import Icon from '$lib/components/Icon.svelte';
import type { IconCard } from '$lib/types';
export let values: IconCard[];
const stakes = [
{
label: 'Without the right routine',
title: 'By the end of the day, everything feels harder than it should.',
body:
'Your dog still has energy to burn, you are carrying guilt through the workday, and home does not feel as calm as it could.',
points: [
'A dog who is restless, wired, or harder to settle at home',
'A workday shaped by guilt, logistics, and wondering how they are doing',
'Too much uncertainty around who is picking up your dog and what the walk will be like'
],
footer: 'The walk is not really the point. The evening is.'
},
{
label: 'With Goodwalk',
title: 'A good walk changes you & your dogs whole evening.',
body:
'Your dog comes home happier, the routine feels lighter, and you are not spending the day second-guessing whether they are okay.',
points: [
'A walker your dog recognises and is happy to see at the door',
'Small-group or one-on-one care that genuinely suits your dog',
'Clear updates, calmer evenings, and one less thing sitting on your mind'
],
footer: 'That is what people are really buying: peace of mind, routine, and a dog who feels cared for.'
}
];
const clientPhotos = [
{
imageUrl: '/images/dog.png',
alt: 'Two happy Goodwalk client dogs out on a walk in Auckland',
name: 'Happy clients',
detail: 'out with Goodwalk'
},
{
imageUrl: '/images/pack-walk-tiny-gang.png',
alt: 'Goodwalk Tiny Gang dogs together on a walk in Auckland',
name: 'Tiny Gang',
detail: 'small group pack walks'
},
{
imageUrl: '/images/tiny-gang-mt-albert-park.png',
alt: 'Goodwalk dogs together at Mt Albert Park in Auckland',
name: 'Mt Albert Park',
detail: 'Goodwalk regulars'
},
{
imageUrl: '/images/otis-auckland-dog-walking-review.jpg',
alt: 'Otis enjoying his Goodwalk routine in Auckland',
name: 'Otis',
detail: 'regular weekly walks'
},
{
imageUrl: '/images/wallace-auckland-dog-walking-review.jpg',
alt: 'Wallace during a Goodwalk puppy-to-pack journey',
name: 'Wallace',
detail: 'from puppy visits to pack walks'
}
];
$: clientPhotoCards = clientPhotos.map((photo) => ({
...photo,
enhanced: getEnhancedImage(photo.imageUrl)
}));
$: orderedValues = values
.map((value, index) => ({ value, index }))
.sort((a, b) => {
const aOrder = a.value.order ?? Number.POSITIVE_INFINITY;
const bOrder = b.value.order ?? Number.POSITIVE_INFINITY;
if (aOrder !== bOrder) {
return aOrder - bOrder;
}
return a.index - b.index;
})
.map(({ value }) => value);
</script>
<section id="values" use:reveal={{ delay: 30 }} class="reveal-block">
<div class="values-inner">
<div class="section-header">
<span class="eyebrow values-eyebrow">Why people come to us</span>
<h2 class="section-heading">Calmer dogs. Better routines. The Tiny Gang effect.</h2>
<p class="section-intro values-intro">
Goodwalk was created for busy owners who want reliable, relationship-led care their dog genuinely looks forward to.
</p>
</div>
<div class="values-photo-grid" aria-label="Goodwalk client dogs">
{#each clientPhotoCards as photo, index}
<figure class:values-photo-card-featured={index === 0} class="values-photo-card">
{#if photo.enhanced}
<enhanced:img
class="values-photo-image"
src={photo.enhanced}
alt={photo.alt}
loading="lazy"
decoding="async"
/>
{:else}
<img
class="values-photo-image"
src={photo.imageUrl}
alt={photo.alt}
loading="lazy"
decoding="async"
/>
{/if}
<figcaption class="values-photo-caption">
<span class="values-photo-name">{photo.name}</span>
<span class="values-photo-detail">{photo.detail}</span>
</figcaption>
</figure>
{/each}
</div>
<div class="values-bento values-contrast">
{#each stakes as stake, index}
<article class:values-contrast-cell-good={index === 1} class="values-contrast-cell">
<div class="values-contrast-head">
<span class:values-contrast-label-good={index === 1} class="values-contrast-label">
{stake.label}
</span>
<span class="values-contrast-num">0{index + 1}</span>
</div>
<h3>{stake.title}</h3>
<p class="values-contrast-body">{stake.body}</p>
<ul class="values-contrast-list">
{#each stake.points as point}
<li>
<span class="values-contrast-bullet">
<Icon
name={index === 1 ? 'fas fa-check' : 'fas fa-minus'}
className="values-contrast-glyph"
/>
</span>
<span>{point}</span>
</li>
{/each}
</ul>
<p class="values-contrast-footer">{stake.footer}</p>
</article>
{/each}
</div>
<div class="values-points-header">
<span class="eyebrow values-eyebrow">What we stand for</span>
<h3 class="values-points-title">The values behind every walk</h3>
<p class="values-points-intro">
Kind handling, small groups, proper safety training, and honest communication — not extras, just how Goodwalk works.
</p>
</div>
<div class="values-bento values-points">
{#each orderedValues as value}
<div class="values-point">
<div class="values-point-icon">
<Icon name={value.icon} className="values-point-glyph" />
</div>
<h3>{value.title}</h3>
<p>{value.body}</p>
</div>
{/each}
</div>
</div>
</section>
<style>
/* Minimalist, grid-based layout (hairline "bento" cells) with Goodwalk
brand colour carried through the icons and the "With Goodwalk" cell. */
#values {
position: relative;
color: var(--text);
}
.values-inner {
max-width: var(--max-w);
margin: 0 auto;
padding: 0 50px;
}
.values-inner .section-heading {
color: #000;
text-align: center;
}
.values-eyebrow {
width: fit-content;
padding: 6px 12px;
border-radius: 999px;
background: rgba(33, 48, 33, 0.06);
box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.07);
}
.values-intro {
max-width: 720px;
}
/* ── Client photo gallery ── */
.values-photo-grid {
display: grid;
grid-template-columns: 1.25fr 0.9fr 0.9fr;
grid-template-rows: repeat(2, clamp(170px, 18vw, 240px));
gap: 16px;
margin-top: 32px;
max-width: 1120px;
margin-left: auto;
margin-right: auto;
}
.values-photo-card {
position: relative;
overflow: hidden;
min-height: 0;
border-radius: 28px;
background: #ede4d2;
box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.05),
0 18px 34px rgba(17, 20, 24, 0.08);
}
.values-photo-card-featured {
grid-row: 1 / span 2;
}
.values-photo-image {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
@media (hover: hover) {
.values-photo-card:hover .values-photo-image {
transform: scale(1.06);
}
}
.values-photo-caption {
position: absolute;
left: 16px;
right: 16px;
bottom: 16px;
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 10px;
padding: 12px 14px;
border-radius: 18px;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.78), rgba(255, 255, 255, 0.92));
box-shadow:
inset 0 0 0 1px rgba(17, 20, 24, 0.05),
0 12px 24px rgba(17, 20, 24, 0.08);
}
.values-photo-name,
.values-photo-detail {
display: block;
}
.values-photo-name {
color: #102010;
font-family: var(--font-head);
font-size: 14px;
font-weight: 700;
}
.values-photo-detail {
color: #5a605f;
font-size: 13px;
line-height: 1.3;
text-align: right;
}
/* ── Bento container: hairline grid via 1px gaps over a line-coloured base ── */
.values-bento {
max-width: 1120px;
margin-left: auto;
margin-right: auto;
display: grid;
gap: 1px;
background: rgba(17, 20, 24, 0.1);
border: 1px solid rgba(17, 20, 24, 0.1);
border-radius: 18px;
overflow: hidden;
box-shadow: 0 14px 34px rgba(17, 20, 24, 0.06);
}
/* ── Before / after contrast ── */
.values-contrast {
grid-template-columns: repeat(2, minmax(0, 1fr));
margin-top: 36px;
}
.values-contrast-cell {
display: flex;
flex-direction: column;
padding: 38px 36px;
background: #fff;
}
.values-contrast-cell-good {
background: var(--gw-green);
}
.values-contrast-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 20px;
}
.values-contrast-label {
display: inline-flex;
align-items: center;
padding: 5px 11px;
border-radius: 999px;
background: rgba(17, 20, 24, 0.05);
color: var(--gray);
font-family: var(--font-head);
font-size: 11px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.values-contrast-label-good {
background: var(--yellow);
color: #000;
}
.values-contrast-num {
font-family: var(--font-head);
font-size: 12px;
font-weight: 700;
color: rgba(17, 20, 24, 0.22);
letter-spacing: 0.04em;
}
.values-contrast-cell h3 {
margin: 0 0 12px;
font-family: var(--font-head);
font-size: clamp(20px, 1.9vw, 25px);
font-weight: 700;
line-height: 1.22;
letter-spacing: -0.02em;
color: #0d1a0d;
}
.values-contrast-body {
margin: 0 0 20px;
color: #4c5056;
font-size: 15px;
line-height: 1.65;
}
.values-contrast-list {
display: grid;
margin: 0 0 22px;
padding: 0;
list-style: none;
}
.values-contrast-list li {
display: grid;
grid-template-columns: 20px minmax(0, 1fr);
gap: 12px;
align-items: start;
padding: 13px 0;
color: #3f4348;
font-size: 15px;
line-height: 1.5;
}
.values-contrast-list li + li {
border-top: 1px solid rgba(17, 20, 24, 0.08);
}
.values-contrast-bullet {
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
margin-top: 1px;
}
.values-contrast-list :global(.values-contrast-glyph) {
font-size: 10px;
color: var(--gray);
}
.values-contrast-cell-good .values-contrast-bullet {
border-radius: 50%;
background: var(--yellow);
}
.values-contrast-cell-good .values-contrast-list :global(.values-contrast-glyph) {
font-size: 9px;
color: var(--gw-green);
}
.values-contrast-footer {
margin: auto 0 0;
padding-top: 18px;
border-top: 1px solid rgba(17, 20, 24, 0.08);
color: var(--gw-green);
font-family: var(--font-head);
font-size: 13px;
font-weight: 700;
line-height: 1.5;
}
.values-contrast-cell-good .values-contrast-footer {
border-top-color: rgba(255, 255, 255, 0.18);
color: var(--yellow);
}
/* Light text for the gw-green "With Goodwalk" cell */
.values-contrast-cell-good h3 {
color: #fff;
}
.values-contrast-cell-good .values-contrast-num {
color: rgba(255, 255, 255, 0.4);
}
.values-contrast-cell-good .values-contrast-body {
color: rgba(255, 255, 255, 0.82);
}
.values-contrast-cell-good .values-contrast-list li {
color: rgba(255, 255, 255, 0.9);
}
.values-contrast-cell-good .values-contrast-list li + li {
border-top-color: rgba(255, 255, 255, 0.14);
}
/* ── Values points header ── */
.values-points-header {
margin-top: 52px;
text-align: center;
}
.values-points-title {
max-width: 19ch;
margin: 12px auto 0;
font-family: var(--font-head);
font-size: clamp(24px, 2.4vw, 32px);
font-weight: 700;
line-height: 1.14;
letter-spacing: -0.03em;
color: #000;
}
.values-points-intro {
max-width: 560px;
margin: 14px auto 0;
color: #4c5056;
font-size: var(--body-copy-size);
line-height: 1.65;
}
/* ── Values points ── */
.values-points {
grid-template-columns: repeat(3, minmax(0, 1fr));
margin-top: 26px;
box-shadow: var(--shadow-panel-elevated);
}
.values-point {
display: flex;
flex-direction: column;
padding: 32px 30px;
background: #fff;
transition: background 0.18s ease;
}
@media (hover: hover) {
.values-point:hover {
background: #fcfbf6;
}
}
.values-point-icon {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
margin-bottom: 18px;
border-radius: 11px;
background: var(--gw-green);
box-shadow: 0 6px 16px rgba(33, 48, 33, 0.18);
}
.values-point-icon :global(.values-point-glyph) {
font-size: 17px;
color: var(--yellow);
}
.values-point h3 {
margin: 0 0 9px;
font-family: var(--font-head);
font-size: 17px;
font-weight: 700;
line-height: 1.25;
color: #0d1a0d;
}
.values-point p {
margin: 0;
color: #4c5056;
font-size: 14px;
line-height: 1.6;
}
@media (min-width: 1600px) {
.values-photo-grid,
.values-bento {
max-width: 1180px;
}
}
/* ── Mobile ── */
@media (max-width: 768px) {
.values-inner {
padding: 0 var(--space-container-x-mobile);
}
.values-intro {
max-width: 32ch;
}
.values-eyebrow {
padding: 6px 10px;
font-size: 11px;
}
.values-photo-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
grid-template-rows: auto;
gap: 10px;
margin-top: 22px;
}
.values-photo-card,
.values-photo-card-featured {
grid-row: auto;
min-height: 178px;
border-radius: 22px;
}
.values-photo-caption {
left: 10px;
right: 10px;
bottom: 10px;
padding: 10px 11px;
border-radius: 16px;
}
.values-photo-name {
font-size: 12px;
}
.values-photo-detail {
font-size: 11px;
}
.values-bento {
border-radius: 16px;
}
.values-contrast {
grid-template-columns: 1fr;
margin-top: 26px;
}
.values-contrast-cell {
padding: 26px 22px;
}
.values-contrast-body {
font-size: var(--body-copy-size-mobile);
line-height: 1.6;
}
.values-contrast-list li {
font-size: var(--body-copy-size-mobile);
line-height: 1.45;
}
.values-points-header {
margin-top: 30px;
}
.values-points-title {
max-width: 16ch;
font-size: clamp(22px, 6.4vw, 27px);
}
.values-points-intro {
max-width: 36ch;
font-size: var(--body-lead-size-mobile);
line-height: 1.55;
}
.values-points {
grid-template-columns: 1fr;
margin-top: 20px;
}
.values-point {
padding: 26px 22px;
}
}
/* ── Reveal ── */
: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);
}
</style>