updating website copy and adding new ProblemSolution.tsx

This commit is contained in:
itsamejms
2026-05-28 15:40:57 +01:00
parent b8bb2ede70
commit c5f4221c8d
8 changed files with 293 additions and 17 deletions
+50 -8
View File
@@ -4,7 +4,7 @@ const CTA = () => {
return (
<section className="py-20">
<div className="max-w-7xl mx-auto px-6">
<div className="glass rounded-[48px] p-8 md:p-20 text-center relative overflow-hidden">
<div className="glass rounded-[48px] p-8 md:p-20 text-center relative overflow-hidden border border-border-subtle">
<div className="absolute top-0 left-0 w-full h-full bg-brand/5 -z-10" />
<div className="absolute -top-24 -right-24 w-64 h-64 bg-brand/10 blur-[80px] rounded-full" />
@@ -12,18 +12,60 @@ const CTA = () => {
initial={{ opacity: 0, scale: 0.95 }}
whileInView={{ opacity: 1, scale: 1 }}
viewport={{ once: true }}
transition={{ type: "spring", stiffness: 100, damping: 20 }}
>
<h2 className="text-4xl md:text-6xl font-display font-extrabold mb-6 text-text-primary">
<h2 className="text-4xl md:text-6xl font-display font-extrabold mb-6 text-text-primary tracking-tight">
Ready to Start Your <br />
<span className="text-brand">Walking Journey?</span>
</h2>
<p className="text-text-primary/70 text-lg md:text-xl max-w-2xl mx-auto mb-10">
Join thousands of dog owners who are making every walk count. It's free to get started!
<p className="text-text-secondary text-lg md:text-xl max-w-2xl mx-auto mb-10">
Join thousands of dog owners who are making every walk count. Download the app today!
</p>
<a href="/waitlist" className="bg-brand hover:bg-brand-light text-bg-primary px-12 py-6 rounded-2xl font-extrabold text-xl transition-all transform hover:scale-105 active:scale-95 mb-6 inline-flex items-center justify-center">
Join Waitlist
</a>
{/* Download Buttons Container */}
<div className="flex flex-col sm:flex-row items-center justify-center gap-4 max-w-md mx-auto">
{/* App Store Active Link */}
<motion.a
href="https://apps.apple.com/us/app/tail-trails-club/id6758676111"
target="_blank"
rel="noopener noreferrer"
whileHover={{ scale: 1.03, y: -2 }}
whileTap={{ scale: 0.98 }}
className="w-full sm:w-auto min-w-[200px] bg-brand text-zinc-950 px-6 py-4 rounded-2xl font-bold flex items-center justify-center gap-3 transition-colors shadow-lg shadow-brand/10"
>
{/* Apple SVG Icon */}
<svg className="w-6 h-6 fill-current" viewBox="0 0 24 24">
<path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M15.97 4.17c.66-.81 1.11-1.93.99-3.06-1 .04-2.21.67-2.93 1.49-.62.69-1.16 1.84-1.01 2.96 1.12.09 2.27-.58 2.95-1.39z"/>
</svg>
<div className="text-left leading-tight">
<p className="text-[11px] uppercase opacity-80 font-medium">Download on the</p>
<p className="text-base font-extrabold -mt-0.5">App Store</p>
</div>
</motion.a>
{/* Play Store Disabled / Coming Soon Button */}
<div
className="w-full sm:w-auto min-w-[200px] bg-zinc-900 border border-zinc-800 text-zinc-400 px-6 py-4 rounded-2xl font-bold flex items-center justify-center gap-3 relative group"
title="Android version coming soon!"
>
{/* Play Store SVG Icon */}
<svg className="w-6 h-6 fill-current opacity-50" viewBox="0 0 24 24">
<path d="M5,3.14V20.86c0,0.5,0.4,0.92,0.91,0.85l9.92-9.92L5.91,2.29C5.4,2.22,5,2.64,5,3.14Z"/>
<path d="M17.23,10.37,6.83,4.41a0.39,0.39,0,0,0-.41,0L15.8,13.8Z"/>
<path d="M15.8,13.8l-9.38,9.38a0.39,0.39,0,0,0,.41,0l10.4-5.96A2.16,2.16,0,0,0,17.23,13.63,2.18,2.18,0,0,0,17.23,10.37Z"/>
</svg>
<div className="text-left leading-tight">
<p className="text-[11px] uppercase opacity-60 font-medium">Get it on</p>
<p className="text-base font-extrabold -mt-0.5 whitespace-nowrap">Google Play</p>
</div>
{/* Absolute overlay badge indicating "Coming Soon" */}
<span className="absolute -top-2.5 right-3 bg-zinc-800 text-zinc-400 text-[10px] uppercase font-black px-2 py-0.5 rounded-full tracking-wider border border-zinc-700">
Soon
</span>
</div>
</div>
</motion.div>
</div>
@@ -32,4 +74,4 @@ const CTA = () => {
);
};
export default CTA;
export default CTA;
+21 -5
View File
@@ -1,5 +1,5 @@
import { motion } from 'motion/react';
import { MapPin, Share2, Bookmark, Tag, Users, TrendingUp } from 'lucide-react';
import { MapPin, Share2, Bookmark, Tag, Users, TrendingUp, Compass, Route } from 'lucide-react';
const Features = () => {
const features = [
@@ -28,8 +28,8 @@ const Features = () => {
iconColor: "text-brand"
},
{
title: "Smart Labels",
desc: "Tag walks with helpful info like 'good for older dogs', 'off-leash friendly', or 'water access'.",
title: "Smart Marching",
desc: "You tell us about your dog. Our community tags every trail. Then we combine this information - so you can choose where to go with confidence.",
icon: Tag,
size: "md:col-span-8",
color: "bg-brand/20",
@@ -39,7 +39,7 @@ const Features = () => {
title: "Community Driven",
desc: "Connect with local dog walkers, share tips, and discover hidden gems in your area.",
icon: Users,
size: "md:col-span-6",
size: "md:col-span-8",
color: "bg-brand/20",
iconColor: "text-brand"
},
@@ -47,7 +47,23 @@ const Features = () => {
title: "Track Progress",
desc: "Monitor your walking stats over time and celebrate milestones with your four-legged companion.",
icon: TrendingUp,
size: "md:col-span-6",
size: "md:col-span-4",
color: "bg-brand/20",
iconColor: "text-brand"
},
{
title: "Discover new places",
desc: "Find trails you didn't know existed - that bring out the best in your dog.",
icon: Compass,
size: "md:col-span-5",
color: "bg-brand/20",
iconColor: "text-brand"
},
{
title: "Break the routine",
desc: "No more defaulting to the same path. Open the app. Go somewhere new.",
icon: Route,
size: "md:col-span-7",
color: "bg-brand/20",
iconColor: "text-brand"
}
+3 -3
View File
@@ -15,7 +15,7 @@ const Hero = () => {
className="text-left"
>
<div className="inline-flex items-center gap-2 bg-bg-secondary px-4 py-2 rounded-full mb-8 border border-border-subtle">
<span className="text-xs font-bold uppercase tracking-widest text-accent-secondary">Simple and effective dog walking</span>
<span className="text-xs font-bold uppercase tracking-widest text-accent-secondary">Life Unleashed</span>
</div>
<h1 className="text-6xl md:text-7xl font-display font-extrabold tracking-tight mb-8 leading-[1.05] text-text-primary">
@@ -25,12 +25,12 @@ const Hero = () => {
</h1>
<p className="text-text-primary/70 text-lg md:text-xl max-w-xl mb-12 font-medium leading-relaxed">
Record your dog walks, discover new routes, and connect with fellow dog owners. Track every tail wag, share your favorite trails, and build a community of happy pups.
Discover new trails that match your dog's needs, and turn everyday walks into real adventures.
</p>
<div className="flex flex-col sm:flex-row items-center gap-6 mb-12">
<a href="/waitlist" className="w-full sm:w-auto bg-brand hover:bg-brand-light text-bg-primary px-10 py-5 rounded-2xl font-extrabold text-lg transition-all transform hover:scale-105 active:scale-95 flex items-center justify-center gap-2">
Join Waitlist
Join the Waitlist
</a>
</div>
+170
View File
@@ -0,0 +1,170 @@
import React from 'react';
import { motion } from 'motion/react';
const ProblemSolution = () => {
// Animation variants for the parent container (triggers cascading/staggered effects)
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.2, // Time gap between card animations
},
},
};
// Animation variants for individual cards
const cardVariants = {
hidden: { opacity: 0, y: 40 },
visible: {
opacity: 1,
y: 0,
transition: { type: "spring", stiffness: 100, damping: 15 },
},
};
return (
<section id="problem-solution" className="py-20 bg-bg-secondary overflow-hidden">
<div className="max-w-7xl mx-auto px-6">
{/* Animated Header Section */}
<motion.div
initial={{ opacity: 0, y: -20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "-100px" }}
transition={{ duration: 0.6 }}
className="text-center mb-16"
>
<h2 className="text-4xl md:text-5xl font-display font-bold mb-4 text-text-primary">
Finding the Right Walk for Your Dog
</h2>
<p className="text-text-secondary font-medium max-w-3xl mx-auto">
Understanding the challenge and how TailTrails solves it
</p>
</motion.div>
{/* Grid Container coordinating the card entries */}
<motion.div
variants={containerVariants}
initial="hidden"
whileInView="visible"
viewport={{ once: true, margin: "-100px" }}
className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-stretch" // "items-stretch" forces equal height
>
{/* Problem Card */}
<motion.div
variants={cardVariants}
whileHover={{ y: -6 }} // Subtle interactive lift on hover
className="bg-bg-primary rounded-3xl border border-border-subtle p-8 shadow-lg flex flex-col justify-between"
>
<div>
<div className="mb-6 overflow-hidden rounded-xl">
<motion.img
whileHover={{ scale: 1.03 }} // Subtle zoom effect inside the card container
transition={{ duration: 0.4 }}
src="/landing/sad-dog.avif"
alt="Problem with dog-friendly places"
className="w-full h-80 object-cover"
/>
</div>
<div className="flex items-center mb-6">
<div className="w-12 h-12 rounded-xl bg-red-500/10 flex items-center justify-center mr-4 shrink-0">
<span className="text-red-500 font-bold text-lg">!</span>
</div>
<h3 className="text-2xl font-bold text-text-primary">The Problem</h3>
</div>
<p className="text-text-primary font-medium mb-4 text-lg">
Most "dog-friendly" places aren't actually right for your dog.
</p>
<ul className="mb-6 space-y-3">
<li className="flex items-start">
<span className="text-red-500 mr-3 mt-0.5 font-bold">•</span>
<span className="text-text-secondary leading-relaxed">Too busy. Too unpredictable. Too many dogs. Not enough space.</span>
</li>
<li className="flex items-start">
<span className="text-red-500 mr-3 mt-0.5 font-bold">•</span>
<span className="text-text-secondary leading-relaxed">Or the opposite; too quiet, too short, too much of the same thing.</span>
</li>
</ul>
<p className="text-text-primary font-medium mb-3">
So you either:
</p>
<ul className="mb-6 space-y-3">
<li className="flex items-start">
<span className="text-red-500 mr-3 mt-0.5 font-bold">•</span>
<span className="text-text-secondary leading-relaxed">Play it safe and stick to the same walk</span>
</li>
<li className="flex items-start">
<span className="text-red-500 mr-3 mt-0.5 font-bold">•</span>
<span className="text-text-secondary leading-relaxed">Or take a risk and hope it works out</span>
</li>
</ul>
</div>
<p className="text-red-500 font-semibold pt-4 border-t border-border-subtle/50">
Neither feels great.
</p>
</motion.div>
{/* Solution Card */}
<motion.div
variants={cardVariants}
whileHover={{ y: -6 }}
className="bg-bg-primary rounded-3xl border border-border-subtle p-8 shadow-lg flex flex-col justify-between"
>
<div>
<div className="mb-6 overflow-hidden rounded-xl">
<motion.img
whileHover={{ scale: 1.03 }}
transition={{ duration: 0.4 }}
src="/landing/happy-dog.avif"
alt="TailTrails solution"
className="w-full h-80 object-cover" // Synced height with Problem image for visual symmetry
/>
</div>
<div className="flex items-center mb-6">
<div className="w-12 h-12 rounded-xl bg-green-500/10 flex items-center justify-center mr-4 shrink-0">
<span className="text-green-500 font-bold text-lg">✓</span>
</div>
<h3 className="text-2xl font-bold text-text-primary">The Solution</h3>
</div>
<p className="text-text-primary font-medium mb-4 text-lg">
TailTrails filters the world around your dog.
</p>
<ul className="mb-6 space-y-3">
<li className="flex items-start">
<span className="text-green-500 mr-3 mt-0.5 font-bold">•</span>
<span className="text-text-secondary leading-relaxed">Every trail is tagged - environment, terrain, traffic, exposure.</span>
</li>
<li className="flex items-start">
<span className="text-green-500 mr-3 mt-0.5 font-bold">•</span>
<span className="text-text-secondary leading-relaxed">Every dog is different - energy, behaviour, needs.</span>
</li>
</ul>
<p className="text-text-primary font-medium mb-4">
We bring the two together.
</p>
</div>
<p className="text-brand font-semibold pt-4 border-t border-border-subtle/50">
So you can choose walks that bring out the best in your dog.
</p>
</motion.div>
</motion.div>
</div>
</section>
);
};
export default ProblemSolution;
+3 -1
View File
@@ -2,6 +2,7 @@ import Header from "@/components/landing/Header";
import Hero from "@/components/landing/Hero";
import Features from "@/components/landing/Features";
import HowItWorks from "@/components/landing/HowItWorks";
import ProblemSolution from "@/components/landing/ProblemSolution";
import CTA from "@/components/landing/CTA";
import Footer from "@/components/landing/Footer";
@@ -11,7 +12,8 @@ const Index = () => {
<Header />
<Hero />
<Features />
<HowItWorks />
<ProblemSolution />
{/* <HowItWorks /> */}
<CTA />
<Footer />
</main>