v4.0.6 - Simplicity focus
This commit is contained in:
@@ -27,10 +27,40 @@
|
||||
export let content: HomePageContent;
|
||||
export let ab: AbContext | undefined = undefined;
|
||||
export let pagePath = '/';
|
||||
// The booking form is swappable so variants can preview an alternate Meet &
|
||||
// Greet form on the same homepage design. Defaults to the live wizard, so the
|
||||
// homepage route renders unchanged. See /variants/meet-greet.
|
||||
export let BookingComponent: typeof BookingWizard = BookingWizard;
|
||||
|
||||
const meetGreetVariantPath = '/variants/meet-greet';
|
||||
$: isMeetGreetVariant = pagePath === meetGreetVariantPath;
|
||||
const reviewCta = content.intro.reviewCta;
|
||||
const heroImage = '/images/smiling-happy-dog-maya.webp';
|
||||
const stars = Array.from({ length: 5 });
|
||||
$: heroLead = isMeetGreetVariant
|
||||
? 'Small group walks, solo support, and puppy visits for Auckland dogs who do better with a calm, consistent routine.'
|
||||
: 'Real adventures with the Tiny Gang, in small, matched groups across Auckland. Same walker every time, so your dog comes home happy, tired, and ready to settle.';
|
||||
$: founderQuote = isMeetGreetVariant
|
||||
? "Small groups, careful matching, and the same walker each time. That's how a walk feels safe, social, and worth looking forward to."
|
||||
: "Every dog gets a walk built around them, not a one-size pack: the right small group, a walker who knows their name and their quirks, and adventures that grow with their confidence. That's how a walk becomes the best part of a dog's day.";
|
||||
$: servicesHeading = isMeetGreetVariant
|
||||
? 'Choose the setup that fits your dog.'
|
||||
: undefined;
|
||||
$: servicesIntro = isMeetGreetVariant
|
||||
? 'Pack walks for social dogs, solo walks for dogs who need more space, and puppy visits for the early routine.'
|
||||
: undefined;
|
||||
$: howItWorksContent = isMeetGreetVariant
|
||||
? {
|
||||
...content.howItWorks,
|
||||
intro: 'Start with a free Meet & Greet. We assess the fit, then build the right routine for your dog.'
|
||||
}
|
||||
: content.howItWorks;
|
||||
$: bookingContent = isMeetGreetVariant
|
||||
? {
|
||||
...content.booking,
|
||||
subtitle: 'Tell us a little about your dog. We reply within 24 hours to arrange your free Meet & Greet.'
|
||||
}
|
||||
: content.booking;
|
||||
</script>
|
||||
|
||||
<Header navigation={content.navigation} />
|
||||
@@ -40,14 +70,10 @@
|
||||
<div class="chero-copy">
|
||||
<p class="chero-eyebrow">Goodwalk · Auckland dog walking</p>
|
||||
<h1 class="chero-title">
|
||||
<span class="chero-title-lead">All we do is</span>
|
||||
<span class="chero-title-main">small & medium dogs</span>
|
||||
<span class="chero-title-lead">Specialist walks for small & medium dogs</span>
|
||||
<span class="chero-title-main">Meet the Tiny Gang.</span>
|
||||
</h1>
|
||||
<p class="chero-lead">
|
||||
Real adventures with the Tiny Gang, in small, matched groups across
|
||||
Auckland. Same walker every time, so your dog comes home happy, tired,
|
||||
and ready to settle.
|
||||
</p>
|
||||
<p class="chero-lead">{heroLead}</p>
|
||||
</div>
|
||||
|
||||
<div class="chero-media">
|
||||
@@ -107,10 +133,7 @@
|
||||
<figure class="cfounder-quote">
|
||||
<blockquote class="cfounder-blockquote">
|
||||
<p class="cfounder-text">
|
||||
Every dog gets a walk built around them, not a one-size pack: the right
|
||||
small group, a walker who knows their name and their quirks, and
|
||||
adventures that grow with their confidence. That's how a walk becomes
|
||||
the best part of a dog's day.
|
||||
{founderQuote}
|
||||
</p>
|
||||
</blockquote>
|
||||
<figcaption class="cfounder-attr">
|
||||
@@ -133,19 +156,24 @@
|
||||
</section>
|
||||
|
||||
<!-- Offer first: what can I actually book, and roughly what does it cost? -->
|
||||
<ServicesSection services={content.services} />
|
||||
<ServicesSection services={content.services} heading={servicesHeading} intro={servicesIntro} />
|
||||
|
||||
<!-- Then the process: what happens after I enquire? Lowers the unknown. -->
|
||||
<HowItWorksSection content={content.howItWorks} />
|
||||
<HowItWorksSection content={howItWorksContent} />
|
||||
|
||||
<!-- Only now the reasons to choose us. -->
|
||||
<ValuesSection values={content.values} />
|
||||
|
||||
<TestimonialsSection testimonials={content.testimonials} seedKey={pagePath} />
|
||||
<FounderStorySection founderStory={content.founderStory} />
|
||||
<InfoSection info={content.info} />
|
||||
<BookingWizard booking={content.booking} {pagePath} {ab} />
|
||||
<InstagramSection instagram={content.instagram} />
|
||||
{#if isMeetGreetVariant}
|
||||
<TestimonialsSection testimonials={content.testimonials} seedKey={pagePath} />
|
||||
<InfoSection info={content.info} />
|
||||
<svelte:component this={BookingComponent} booking={bookingContent} {pagePath} {ab} />
|
||||
{:else}
|
||||
<!-- Only now the reasons to choose us. -->
|
||||
<ValuesSection values={content.values} />
|
||||
<TestimonialsSection testimonials={content.testimonials} seedKey={pagePath} />
|
||||
<FounderStorySection founderStory={content.founderStory} />
|
||||
<InfoSection info={content.info} />
|
||||
<svelte:component this={BookingComponent} booking={bookingContent} {pagePath} {ab} />
|
||||
<InstagramSection instagram={content.instagram} />
|
||||
{/if}
|
||||
<Footer footer={content.footer} />
|
||||
|
||||
<style>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,613 +0,0 @@
|
||||
<script lang="ts">
|
||||
/*
|
||||
* Tiny Gang pack walks page — clarity redesign.
|
||||
*
|
||||
* One design system, one message. Replaces the multi-card / multi-gradient
|
||||
* ServiceLandingPage treatment (for this page) with a single green hero +
|
||||
* light body that shares the homepage's visual language. The message is said
|
||||
* once, in order: what it is -> what's different -> how joining works -> fit
|
||||
* -> proof -> price -> FAQ -> book.
|
||||
*
|
||||
* View component only: the route owns Header/Footer, SEO, and data.
|
||||
* Preview at /variants/tiny-gang. To go live, render this instead of
|
||||
* ServiceLandingPage for pack-walks in src/routes/[slug]/+page.svelte.
|
||||
*/
|
||||
import Icon from '$lib/components/ui/Icon.svelte';
|
||||
import ServiceHero from '$lib/components/sections/ServiceHero.svelte';
|
||||
import { reveal } from '$lib/actions/reveal';
|
||||
import BookingWizard from '$lib/components/sections/BookingWizard.svelte';
|
||||
import PricingPlanCard from '$lib/components/ui/PricingPlanCard.svelte';
|
||||
import TestimonialsSection from '$lib/components/sections/TestimonialsSection.svelte';
|
||||
import FaqSection from '$lib/components/sections/FaqSection.svelte';
|
||||
import { decoratePlans } from '$lib/utils/pricing';
|
||||
import type { ServicePageContent, SiteSharedContent } from '$lib/types';
|
||||
|
||||
export let content: SiteSharedContent;
|
||||
export let pageContent: ServicePageContent;
|
||||
export let currentPath = '/pack-walks';
|
||||
|
||||
// What makes Tiny Gang different. Said once here, not spread across a
|
||||
// 3-point highlight and a 6-card benefit grid that repeated each other.
|
||||
const traits = [
|
||||
{
|
||||
icon: 'fas fa-users',
|
||||
title: 'Carefully matched groups',
|
||||
body: '4 to 8 dogs, grouped by temperament, energy, and play style. Never a random pack.'
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-shield-dog',
|
||||
title: 'Small & medium dogs only',
|
||||
body: 'Pace, group size, and play style are all built for little dogs, so yours is never the odd one out.'
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-user-check',
|
||||
title: 'The same walker, every week',
|
||||
body: 'One familiar face at the door and on the walk. Your dog is known, not handed around.'
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-eye',
|
||||
title: 'Eyes on every dog',
|
||||
body: 'Small groups mean we notice the little things early, from recall to a quiet day.'
|
||||
}
|
||||
];
|
||||
|
||||
// How joining works. The process, made explicit instead of buried in a
|
||||
// paragraph and an FAQ.
|
||||
const steps = [
|
||||
{
|
||||
title: 'Free Meet & Greet',
|
||||
body: 'We come to your home, meet your dog, and talk honestly about whether the pack suits them.'
|
||||
},
|
||||
{
|
||||
title: 'Two assessment walks',
|
||||
body: 'Your dog settles in gently while we confirm the right group, pace, and handling.'
|
||||
},
|
||||
{
|
||||
title: 'Your weekly slot',
|
||||
body: 'A regular spot with the same little crew and the same walker, week in, week out.'
|
||||
}
|
||||
];
|
||||
|
||||
// Distilled pricing message. The title already says the routine and the
|
||||
// price says the cost, so each card keeps only the one or two lines that
|
||||
// actually differ. The universal "free pickup" promise is stated once under
|
||||
// the grid instead of repeated on every card.
|
||||
const planLines: Record<string, string[]> = {
|
||||
'1 Walk Per Week': [
|
||||
'A calm weekly outing',
|
||||
'Time to sniff, play, and unwind',
|
||||
'Great for dogs just starting out'
|
||||
],
|
||||
'2-3 Walks Per Week': [
|
||||
'Steady exercise and real social time',
|
||||
'A settled mid-week rhythm',
|
||||
'Our balanced routine'
|
||||
],
|
||||
'4-5 Walks Per Week': [
|
||||
'Best value per walk',
|
||||
'Maximum routine and structure',
|
||||
'For high-energy, social dogs'
|
||||
],
|
||||
'Casual Pack Walk': [
|
||||
'No weekly commitment',
|
||||
'Book only the weeks you need',
|
||||
'For dogs already in the pack'
|
||||
]
|
||||
};
|
||||
|
||||
$: pricingPlans = decoratePlans(
|
||||
pageContent.pricing.plans.map((plan) => ({
|
||||
...plan,
|
||||
features: planLines[plan.title] ?? plan.features
|
||||
}))
|
||||
);
|
||||
$: faqItems = pageContent.faq?.items?.slice(0, 6) ?? [];
|
||||
</script>
|
||||
|
||||
<main class="tg">
|
||||
<!-- Hero: the shared service-page hero (green copy left, photo bleeds
|
||||
right), identical to /dog-walking and /puppy-visits. -->
|
||||
<ServiceHero
|
||||
eyebrow={pageContent.hero.eyebrow}
|
||||
title={pageContent.hero.title}
|
||||
subtitle={pageContent.hero.subtitle}
|
||||
imageUrl={pageContent.hero.imageUrl}
|
||||
imageAlt={pageContent.hero.imageAlt}
|
||||
chips={pageContent.hero.chips ?? []}
|
||||
cta={pageContent.hero.cta}
|
||||
/>
|
||||
|
||||
<!-- What makes it different (said once) -->
|
||||
<section class="tg-section" use:reveal={{ distance: 0 }} aria-labelledby="tg-diff-heading">
|
||||
<div class="tg-inner">
|
||||
<div class="tg-head">
|
||||
<p class="tg-eyebrow">What makes Tiny Gang different</p>
|
||||
<h2 id="tg-diff-heading" class="tg-h2">Not a big anonymous pack. A small, matched crew.</h2>
|
||||
</div>
|
||||
<ul class="tg-traits">
|
||||
{#each traits as trait}
|
||||
<li class="tg-trait">
|
||||
<span class="tg-trait-icon" aria-hidden="true"><Icon name={trait.icon} /></span>
|
||||
<div>
|
||||
<h3>{trait.title}</h3>
|
||||
<p>{trait.body}</p>
|
||||
</div>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- How joining works (the process, explicit) -->
|
||||
<section class="tg-section tg-section-steps" use:reveal={{ distance: 0 }} aria-labelledby="tg-steps-heading">
|
||||
<div class="tg-inner">
|
||||
<div class="tg-head">
|
||||
<p class="tg-eyebrow">How joining works</p>
|
||||
<h2 id="tg-steps-heading" class="tg-h2">Three simple steps, no pressure.</h2>
|
||||
</div>
|
||||
<ol class="tg-steps">
|
||||
{#each steps as step, i}
|
||||
<li class="tg-step">
|
||||
<span class="tg-step-num" aria-hidden="true">{i + 1}</span>
|
||||
<h3>{step.title}</h3>
|
||||
<p>{step.body}</p>
|
||||
</li>
|
||||
{/each}
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Is it right for your dog? -->
|
||||
{#if pageContent.decision}
|
||||
<section class="tg-section" use:reveal={{ distance: 0 }} aria-labelledby="tg-fit-heading">
|
||||
<div class="tg-inner">
|
||||
<div class="tg-head">
|
||||
<p class="tg-eyebrow">Honest fit check</p>
|
||||
<h2 id="tg-fit-heading" class="tg-h2">{pageContent.decision.title ?? 'Is Tiny Gang right for your dog?'}</h2>
|
||||
</div>
|
||||
<div class="tg-fit">
|
||||
<div class="tg-fit-col">
|
||||
<h3>{pageContent.decision.fitTitle ?? 'A great fit if your dog:'}</h3>
|
||||
<ul>
|
||||
{#each pageContent.decision.fitItems as item}
|
||||
<li>
|
||||
<span class="tg-fit-mark tg-fit-mark-yes" aria-hidden="true"><Icon name="fas fa-check" /></span>
|
||||
<span>{item}</span>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tg-fit-col">
|
||||
<h3>{pageContent.decision.notFitTitle ?? 'Better on a solo walk if your dog:'}</h3>
|
||||
<ul>
|
||||
{#each pageContent.decision.notFitItems as item}
|
||||
<li>
|
||||
<span class="tg-fit-mark tg-fit-mark-no" aria-hidden="true"><Icon name="fas fa-xmark" /></span>
|
||||
<span>{item}</span>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{#if pageContent.decision.footnote}
|
||||
<p class="tg-fit-note">{pageContent.decision.footnote}</p>
|
||||
{/if}
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
||||
|
||||
<!-- Proof: owners love it -->
|
||||
<TestimonialsSection
|
||||
heading="Owners love the Tiny Gang"
|
||||
testimonials={content.testimonials}
|
||||
seedKey={currentPath}
|
||||
/>
|
||||
|
||||
<!-- Price -->
|
||||
<section class="tg-section" use:reveal={{ distance: 0 }} aria-labelledby="tg-price-heading">
|
||||
<div class="tg-inner tg-inner-wide">
|
||||
<div class="tg-head">
|
||||
<p class="tg-eyebrow">Simple weekly pricing</p>
|
||||
<h2 id="tg-price-heading" class="tg-h2">{pageContent.pricing.title}</h2>
|
||||
<p class="tg-price-tagline">The best investment you'll ever make is in your dog's happiness.</p>
|
||||
{#if pageContent.pricing.intro}
|
||||
<p class="tg-head-sub">{pageContent.pricing.intro}</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="tg-plans">
|
||||
{#each pricingPlans as plan}
|
||||
<PricingPlanCard {plan} variant="service" hideCtaOnMobile={true} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<div class="tg-price-notes">
|
||||
{#if pageContent.pricing.scarcityNote}
|
||||
<p class="tg-note tg-note-warm"><Icon name="fas fa-clock" />{pageContent.pricing.scarcityNote}</p>
|
||||
{/if}
|
||||
<p class="tg-note"><Icon name="fas fa-stopwatch" />60+ minute adventures.</p>
|
||||
<p class="tg-note"><Icon name="fas fa-car" />Free pickup & drop-off, every walk.</p>
|
||||
<p class="tg-note"><Icon name="fas fa-shield-heart" />Starts with a free Meet & Greet.</p>
|
||||
</div>
|
||||
|
||||
<a class="btn btn-yellow btn-mobile-center tg-plans-cta" href="#newlead">Book a Meet & Greet</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- FAQ -->
|
||||
{#if faqItems.length}
|
||||
<section class="tg-section" use:reveal={{ distance: 0 }}>
|
||||
<div class="tg-inner tg-inner-narrow">
|
||||
<FaqSection
|
||||
title={pageContent.faq?.title ?? 'Tiny Gang FAQs'}
|
||||
intro={pageContent.faq?.intro}
|
||||
faqs={faqItems}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
||||
|
||||
<BookingWizard booking={pageContent.booking} pagePath={currentPath} />
|
||||
</main>
|
||||
|
||||
<style>
|
||||
/* ── One system: tokens for this page ──────────────────────────────── */
|
||||
.tg {
|
||||
--tg-max: 1120px;
|
||||
--tg-narrow: 820px;
|
||||
background: var(--off-white);
|
||||
color: var(--text-heading);
|
||||
}
|
||||
|
||||
.tg-inner {
|
||||
max-width: var(--tg-max);
|
||||
margin: 0 auto;
|
||||
padding-inline: var(--space-container-x);
|
||||
}
|
||||
|
||||
.tg-inner-narrow {
|
||||
max-width: var(--tg-narrow);
|
||||
}
|
||||
|
||||
/* Pricing breaks out wider than the body so four cards have real width
|
||||
(and the full CTA never clips). */
|
||||
.tg-inner-wide {
|
||||
max-width: 1280px;
|
||||
}
|
||||
|
||||
.tg-section {
|
||||
padding-block: clamp(48px, 6vw, 84px);
|
||||
}
|
||||
|
||||
/* Alternating surface for rhythm, not a new "system": just a tint. */
|
||||
.tg-section-steps {
|
||||
background: var(--surface-panel-cream);
|
||||
border-block: 1px solid var(--border-soft);
|
||||
}
|
||||
|
||||
/* One eyebrow, one heading, everywhere. */
|
||||
.tg-eyebrow {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin: 0 0 14px;
|
||||
font-family: var(--font-body);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--gw-green);
|
||||
}
|
||||
|
||||
.tg-eyebrow::before {
|
||||
content: '';
|
||||
width: 24px;
|
||||
height: 2px;
|
||||
border-radius: 2px;
|
||||
background: var(--yellow);
|
||||
}
|
||||
|
||||
.tg-head {
|
||||
max-width: 40rem;
|
||||
margin: 0 auto clamp(28px, 4vw, 44px);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tg-h2 {
|
||||
margin: 0;
|
||||
font-family: var(--font-head);
|
||||
font-size: clamp(28px, 3.4vw, 42px);
|
||||
font-weight: 700;
|
||||
line-height: 1.08;
|
||||
letter-spacing: -0.03em;
|
||||
color: var(--text-heading);
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.tg-head-sub {
|
||||
margin: 14px auto 0;
|
||||
max-width: 36rem;
|
||||
color: var(--text-muted);
|
||||
font-size: 17px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.tg-price-tagline {
|
||||
margin: 14px auto 0;
|
||||
max-width: 32rem;
|
||||
color: var(--gw-green);
|
||||
font-family: var(--font-head);
|
||||
font-size: clamp(17px, 1.7vw, 20px);
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
letter-spacing: -0.01em;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
/* ── Traits: a clean feature list, not boxed cards ─────────────────── */
|
||||
.tg-traits {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: clamp(24px, 3vw, 40px) clamp(32px, 5vw, 64px);
|
||||
}
|
||||
|
||||
.tg-trait {
|
||||
display: grid;
|
||||
grid-template-columns: 44px minmax(0, 1fr);
|
||||
gap: 16px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.tg-trait-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 14px;
|
||||
background: var(--surface-brand);
|
||||
color: var(--yellow);
|
||||
font-size: 17px;
|
||||
}
|
||||
|
||||
.tg-trait h3 {
|
||||
margin: 2px 0 6px;
|
||||
font-family: var(--font-head);
|
||||
font-size: 19px;
|
||||
line-height: 1.2;
|
||||
color: var(--text-heading);
|
||||
}
|
||||
|
||||
.tg-trait p {
|
||||
margin: 0;
|
||||
color: var(--text-muted);
|
||||
font-size: 15px;
|
||||
line-height: 1.6;
|
||||
max-width: 38ch;
|
||||
}
|
||||
|
||||
/* ── Steps: numerals, not cards ────────────────────────────────────── */
|
||||
.tg-steps {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: clamp(24px, 4vw, 48px);
|
||||
counter-reset: tg-step;
|
||||
}
|
||||
|
||||
.tg-step {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tg-step-num {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-bottom: 16px;
|
||||
border-radius: 50%;
|
||||
background: var(--yellow);
|
||||
color: var(--gw-green);
|
||||
font-family: var(--font-head);
|
||||
font-size: 16px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.tg-step h3 {
|
||||
margin: 0 0 8px;
|
||||
font-family: var(--font-head);
|
||||
font-size: 19px;
|
||||
line-height: 1.2;
|
||||
color: var(--text-heading);
|
||||
}
|
||||
|
||||
.tg-step p {
|
||||
margin: 0;
|
||||
color: var(--text-muted);
|
||||
font-size: 15px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* ── Fit check: one card, two columns ──────────────────────────────── */
|
||||
.tg-fit {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: clamp(20px, 3vw, 32px);
|
||||
padding: clamp(24px, 3vw, 40px);
|
||||
border-radius: var(--radius-xl);
|
||||
background: var(--surface-panel);
|
||||
box-shadow:
|
||||
inset 0 0 0 1px var(--border-soft-strong),
|
||||
var(--shadow-card);
|
||||
}
|
||||
|
||||
.tg-fit-col h3 {
|
||||
margin: 0 0 16px;
|
||||
font-family: var(--font-head);
|
||||
font-size: 17px;
|
||||
line-height: 1.3;
|
||||
color: var(--text-heading);
|
||||
}
|
||||
|
||||
.tg-fit-col ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.tg-fit-col li {
|
||||
display: grid;
|
||||
grid-template-columns: 22px minmax(0, 1fr);
|
||||
gap: 12px;
|
||||
align-items: start;
|
||||
color: var(--text-heading-soft);
|
||||
font-size: 15px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.tg-fit-mark {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
margin-top: 1px;
|
||||
border-radius: 50%;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.tg-fit-mark-yes {
|
||||
background: rgba(var(--brand-rgb), 0.1);
|
||||
color: var(--gw-green);
|
||||
}
|
||||
|
||||
.tg-fit-mark-no {
|
||||
background: rgba(var(--ink-rgb), 0.06);
|
||||
color: var(--text-subtle);
|
||||
}
|
||||
|
||||
.tg-fit-note {
|
||||
margin: 22px auto 0;
|
||||
max-width: 48rem;
|
||||
color: var(--text-muted);
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ── Pricing ───────────────────────────────────────────────────────── */
|
||||
.tg-plans {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
/* Roomier, consistent cards on this page, scoped via .tg-plans so the shared
|
||||
PricingPlanCard and other pages keep their own sizing. */
|
||||
.tg-plans :global(.plan-card) {
|
||||
padding: 44px 30px 38px;
|
||||
}
|
||||
|
||||
/* The featured card carries the "Goodwalk favourite" ribbon (absolute,
|
||||
top: 16px). Give it enough head room that the ribbon sits clearly above
|
||||
the title instead of over it. */
|
||||
.tg-plans :global(.plan-card--featured) {
|
||||
padding-top: 62px;
|
||||
}
|
||||
|
||||
/* Full-width CTA: never squished, and consistent across all four cards.
|
||||
display:flex (block-level) overrides the component's inline-flex +
|
||||
align-self:center, so the button always spans the full card width. */
|
||||
.tg-plans :global(.plan-card__cta) {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
align-self: stretch;
|
||||
padding-inline: 15px;
|
||||
}
|
||||
|
||||
.tg-price-notes {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.tg-note {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin: 0;
|
||||
padding: 8px 16px;
|
||||
border-radius: var(--radius-pill);
|
||||
background: var(--surface-brand-soft);
|
||||
color: var(--gw-green);
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tg-note-warm {
|
||||
background: var(--surface-accent-muted);
|
||||
color: #5a4500;
|
||||
}
|
||||
|
||||
:global(.tg-note .icon) {
|
||||
color: var(--yellow);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
:global(.tg-note-warm .icon) {
|
||||
color: #b88800;
|
||||
}
|
||||
|
||||
.tg-plans-cta {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ── Responsive ────────────────────────────────────────────────────── */
|
||||
@media (max-width: 980px) {
|
||||
.tg-plans {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.tg-traits {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.tg-steps {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.tg-fit {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.tg-plans {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.tg-plans :global(.plan-card) {
|
||||
padding: 30px 24px 26px;
|
||||
}
|
||||
|
||||
.tg-plans :global(.plan-card--featured) {
|
||||
padding-top: 46px;
|
||||
}
|
||||
|
||||
.tg-plans-cta {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user