Initial commit

This commit is contained in:
DK
2026-02-06 16:40:23 +00:00
commit 774cb8b204
656 changed files with 77290 additions and 0 deletions

86
src/app/blog/page.tsx Normal file
View File

@@ -0,0 +1,86 @@
"use client";
import ReactLenis from "lenis/react";
import { Facebook, Instagram, Twitter } from "lucide-react";
import BlogCardThree from "@/components/sections/blog/BlogCardThree";
import FooterCard from "@/components/sections/footer/FooterCard";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import NavbarLayoutFloatingInline from "@/components/navbar/NavbarLayoutFloatingInline";
import { useBlogPosts } from "@/hooks/useBlogPosts";
export default function BlogPage() {
const { posts, isLoading } = useBlogPosts();
return (
<ThemeProvider
defaultButtonVariant="expand-hover"
defaultTextAnimation="reveal-blur"
borderRadius="sharp"
contentWidth="compact"
sizing="large"
background="aurora"
cardStyle="soft-shadow"
primaryButtonStyle="primary-glow"
secondaryButtonStyle="glass"
headingFontWeight="bold"
>
<ReactLenis root>
<div id="nav" data-section="nav">
<NavbarLayoutFloatingInline
brandName="PawsHome"
navItems={[
{ name: "Home", id: "/" },
{ name: "About", id: "about" },
{ name: "Pets", id: "products" },
{ name: "How It Works", id: "feature" },
{ name: "FAQ", id: "faq" }
]}
button={{
text: "Adopt Now", href: "#contact"
}}
/>
</div>
{isLoading ? (
<div className="w-content-width mx-auto py-20 text-center">
<p className="text-foreground">Loading posts...</p>
</div>
) : (
<div id="blog" data-section="blog">
<BlogCardThree
blogs={posts}
title="Pet Stories & Updates"
description="Discover heartwarming stories and important updates from our animal shelter community"
tag="Blog"
textboxLayout="default"
useInvertedBackground="noInvert"
animationType="slide-up"
carouselMode="buttons"
/>
</div>
)}
<div id="footer" data-section="footer">
<FooterCard
logoText="PawsHome"
copyrightText="© 2025 PawsHome Animal Shelter. Dedicated to animal welfare and adoption."
socialLinks={[
{
icon: Facebook,
href: "https://facebook.com/pawshome", ariaLabel: "Facebook"
},
{
icon: Instagram,
href: "https://instagram.com/pawshome", ariaLabel: "Instagram"
},
{
icon: Twitter,
href: "https://twitter.com/pawshome", ariaLabel: "Twitter"
}
]}
/>
</div>
</ReactLenis>
</ThemeProvider>
);
}

BIN
src/app/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

5
src/app/globals.css Normal file
View File

@@ -0,0 +1,5 @@
@import "tailwindcss";
@import "./styles/variables.css";
@import "./styles/theme.css";
@import "./styles/utilities.css";
@import "./styles/base.css";

1265
src/app/layout.tsx Normal file

File diff suppressed because it is too large Load Diff

236
src/app/page.tsx Normal file
View File

@@ -0,0 +1,236 @@
"use client"
import NavbarLayoutFloatingInline from '@/components/navbar/NavbarLayoutFloatingInline';
import HeroLogoBillboard from '@/components/sections/hero/HeroLogoBillboard';
import MetricSplitMediaAbout from '@/components/sections/about/MetricSplitMediaAbout';
import ProductCardTwo from '@/components/sections/product/ProductCardTwo';
import FeatureProcessSteps from '@/components/sections/feature/FeatureProcessSteps';
import MetricCardOne from '@/components/sections/metrics/MetricCardOne';
import TestimonialCardThirteen from '@/components/sections/testimonial/TestimonialCardThirteen';
import FaqDouble from '@/components/sections/faq/FaqDouble';
import ContactCTA from '@/components/sections/contact/ContactCTA';
import FooterCard from '@/components/sections/footer/FooterCard';
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import { Heart, Paw, Home, Award, TrendingUp, Facebook, Instagram, Twitter } from "lucide-react";
export default function PetShelterPage() {
return (
<ThemeProvider
defaultButtonVariant="expand-hover"
defaultTextAnimation="reveal-blur"
borderRadius="sharp"
contentWidth="compact"
sizing="large"
background="aurora"
cardStyle="soft-shadow"
primaryButtonStyle="primary-glow"
secondaryButtonStyle="glass"
headingFontWeight="bold"
>
<div id="nav" data-section="nav">
<NavbarLayoutFloatingInline
brandName="PawsHome"
navItems={[
{ name: "About", id: "about" },
{ name: "Pets", id: "products" },
{ name: "How It Works", id: "feature" },
{ name: "FAQ", id: "faq" }
]}
button={{ text: "Adopt Now", href: "#contact" }}
/>
</div>
<div id="hero" data-section="hero">
<HeroLogoBillboard
logoText="PawsHome"
description="Find your perfect companion. Every animal deserves a loving home. Browse adoptable pets and start your adoption journey today."
buttons={[
{ text: "Browse Pets", href: "#products" },
{ text: "Learn More", href: "#about" }
]}
background={{ variant: "aurora" }}
imageSrc="https://img.b2bpic.net/free-photo/cute-dog-playing-with-woman-shelter-adoption_23-2148682996.jpg"
imageAlt="Happy dog ready for adoption"
frameStyle="card"
/>
</div>
<div id="about" data-section="about">
<MetricSplitMediaAbout
tag="Our Mission"
tagIcon={Heart}
title="Connecting Loving Homes with Wonderful Pets"
description="PawsHome is dedicated to rescuing, caring for, and rehoming animals in need. Our compassionate team works tirelessly to ensure every pet receives proper care, veterinary attention, and socialization before finding their forever family."
metrics={[
{ value: "500+", title: "Pets Adopted" },
{ value: "98%", title: "Happy Families" }
]}
imageSrc="https://img.b2bpic.net/free-photo/smiley-woman-spending-time-with-cute-rescue-dogs-shelter_23-2148682966.jpg"
imageAlt="PawsHome shelter caring for animals"
useInvertedBackground="noInvert"
/>
</div>
<div id="products" data-section="products">
<ProductCardTwo
title="Meet Our Adoptable Friends"
description="Browse our available pets seeking their forever homes. Each profile includes age, personality, and care requirements."
products={[
{
id: "1", brand: "PawsHome", name: "Golden Retriever", price: "Adoption Fee: $150", rating: 5,
reviewCount: "142", imageSrc: "https://img.b2bpic.net/free-photo/woman-holding-adorable-dog-shelter_23-2148682978.jpg", imageAlt: "Golden Retriever puppy"
},
{
id: "2", brand: "PawsHome", name: "Tabby Cat", price: "Adoption Fee: $50", rating: 5,
reviewCount: "89", imageSrc: "https://img.b2bpic.net/free-photo/happy-couple-guys-playing-with-their-dog-backyard-grass-cheerful-old-dog_158595-6547.jpg", imageAlt: "Playful tabby kitten"
},
{
id: "3", brand: "PawsHome", name: "Holland Lop Rabbit", price: "Adoption Fee: $75", rating: 4,
reviewCount: "56", imageSrc: "https://img.b2bpic.net/free-photo/elegant-fashion-girls-summer-park_1157-21448.jpg", imageAlt: "Cute white rabbit"
}
]}
textboxLayout="default"
animationType="slide-up"
gridVariant="three-columns-all-equal-width"
useInvertedBackground="noInvert"
/>
</div>
<div id="feature" data-section="feature">
<FeatureProcessSteps
tag="How It Works"
tagIcon={Paw}
title="Simple Steps to Find Your Perfect Pet"
description="Our adoption process is designed to ensure the best match between pets and families. Follow these steps to bring home your new companion."
steps={[
{
number: "01", title: "Browse Our Pets", tag: "Explore", description: "Visit our website to view available animals with detailed profiles including photos, age, temperament, and special needs."
},
{
number: "02", title: "Meet & Greet", tag: "Connect", description: "Schedule a visit to meet your favorite pet in person. Our staff will help you understand their personality and care requirements."
},
{
number: "03", title: "Complete Application", tag: "Review", description: "Fill out our adoption application to ensure a good fit. We verify references and home compatibility for every adoption."
},
{
number: "04", title: "Welcome Home", tag: "Celebrate", description: "After approval, take your new pet home! We provide ongoing support and resources for a successful transition."
}
]}
useInvertedBackground="noInvert"
buttons={[{ text: "Start Adoption", href: "#contact" }]}
/>
</div>
<div id="metric" data-section="metric">
<MetricCardOne
title="Our Impact"
description="Making a difference in the lives of animals and families every day."
metrics={[
{
id: "1", value: "2,450", title: "Animals Rescued", description: "Pets given a second chance at life", icon: Heart
},
{
id: "2", value: "1,850", title: "Successful Adoptions", description: "Families united with their companions", icon: Home
},
{
id: "3", value: "15", title: "Years of Service", description: "Dedicated to animal welfare and care", icon: Award
},
{
id: "4", value: "99%", title: "Adoption Success", description: "Long-term happy placements", icon: TrendingUp
}
]}
gridVariant="uniform-all-items-equal"
animationType="scale-rotate"
textboxLayout="default"
useInvertedBackground="noInvert"
/>
</div>
<div id="testimonial" data-section="testimonial">
<TestimonialCardThirteen
title="Stories from Our Families"
description="Hear how adoption has transformed the lives of pets and the families who love them."
testimonials={[
{
id: "1", name: "Sarah Johnson", handle: "@sarahlovesmax", testimonial: "Max came into our lives as a shy shelter dog. Today, he's the most loving family member. Adoption was the best decision we ever made!", rating: 5,
imageSrc: "https://img.b2bpic.net/free-photo/portrait-happy-family-autumn_329181-7440.jpg", imageAlt: "Sarah with her dog Max"
},
{
id: "2", name: "Michael Chen", handle: "@mikepetsluver", testimonial: "The team at PawsHome was so helpful in finding Luna. She's brought so much joy and warmth to our home. Highly recommend!", rating: 5,
imageSrc: "https://img.b2bpic.net/free-photo/full-shot-family-with-cute-dog-outdoors_23-2148996586.jpg", imageAlt: "Michael with cat Luna"
},
{
id: "3", name: "Emma Rodriguez", handle: "@emmyandmilo", testimonial: "From day one, the staff made sure Milo was the right fit for our family. He's thriving and we couldn't imagine life without him.", rating: 5,
imageSrc: "https://img.b2bpic.net/free-photo/portrait-smiling-family-dog_329181-20491.jpg", imageAlt: "Emma with rabbit Milo"
},
{
id: "4", name: "David & Lisa Park", handle: "@parkfamily2024", testimonial: "Our kids learned so much about responsibility and compassion. Our rescue puppy Buddy is perfect for our family!", rating: 5,
imageSrc: "https://img.b2bpic.net/free-photo/positive-husband-wife-play-with-dog-man-striped-shirt-hugs-labrador-with-tenderness_197531-13723.jpg", imageAlt: "Park family with puppy Buddy"
}
]}
showRating={true}
animationType="slide-up"
textboxLayout="default"
useInvertedBackground="noInvert"
/>
</div>
<div id="faq" data-section="faq">
<FaqDouble
title="Frequently Asked Questions"
description="Find answers to common questions about pet adoption and our services."
faqs={[
{
id: "1", title: "What is the adoption fee?", content: "Adoption fees vary by animal type and age, typically ranging from $50-$200. Fees help cover veterinary care, vaccinations, and shelter operations."
},
{
id: "2", title: "Do adopted pets come with medical records?", content: "Yes! All adopted pets have been spayed/neutered, vaccinated, and microchipped. You'll receive complete medical records and care instructions."
},
{
id: "3", title: "Can I return a pet if adoption doesn't work out?", content: "We have a 30-day adjustment period. If there are issues, we'll work with you to resolve them or provide a full refund."
},
{
id: "4", title: "Do you adopt to renters?", content: "Yes, we work with renters. We only require written permission from your landlord regarding pet ownership."
},
{
id: "5", title: "What age animals are available?", content: "We have animals of all ages, from young puppies and kittens to senior pets. Senior animals make wonderful companions!"
},
{
id: "6", title: "How long does the adoption process take?", content: "Typically 1-2 weeks from application submission. This includes processing time, references check, and final approval."
}
]}
textboxLayout="default"
animationType="smooth"
useInvertedBackground="noInvert"
/>
</div>
<div id="contact" data-section="contact">
<ContactCTA
tag="Ready to Adopt?"
tagIcon={Heart}
title="Start Your Adoption Journey Today"
description="Contact us to learn more about available pets, schedule a visit, or begin the adoption process. Our friendly team is here to help!"
buttons={[
{ text: "Contact Us", href: "mailto:adopt@pawshome.org" },
{ text: "Browse Pets", href: "#products" }
]}
background={{ variant: "sparkles-gradient" }}
useInvertedBackground="noInvert"
/>
</div>
<div id="footer" data-section="footer">
<FooterCard
logoText="PawsHome"
copyrightText="© 2025 PawsHome Animal Shelter. Dedicated to animal welfare and adoption."
socialLinks={[
{ icon: Facebook, href: "https://facebook.com/pawshome", ariaLabel: "Facebook" },
{ icon: Instagram, href: "https://instagram.com/pawshome", ariaLabel: "Instagram" },
{ icon: Twitter, href: "https://twitter.com/pawshome", ariaLabel: "Twitter" }
]}
/>
</div>
</ThemeProvider>
);
}

240
src/app/shop/[id]/page.tsx Normal file
View File

@@ -0,0 +1,240 @@
"use client";
import { use, useCallback } from "react";
import { useRouter } from "next/navigation";
import ReactLenis from "lenis/react";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import NavbarLayoutFloatingInline from '@/components/navbar/NavbarLayoutFloatingInline';
import FooterCard from '@/components/sections/footer/FooterCard';
import { Facebook, Instagram, Twitter } from 'lucide-react';
import ProductDetailCard from "@/components/ecommerce/productDetail/ProductDetailCard";
import ProductCart from "@/components/ecommerce/cart/ProductCart";
import { useProductDetail } from "@/hooks/useProductDetail";
import { useCart } from "@/hooks/useCart";
import { useCheckout } from "@/hooks/useCheckout";
interface ProductPageProps {
params: Promise<{ id: string }>;
}
export default function ProductPage({ params }: ProductPageProps) {
const { id } = use(params);
const router = useRouter();
const {
product,
isLoading,
images,
meta,
variants,
quantityVariant,
selectedQuantity,
createCartItem,
} = useProductDetail(id);
const {
items: cartItems,
isOpen: cartOpen,
setIsOpen: setCartOpen,
addItem,
updateQuantity,
removeItem,
total: cartTotal,
getCheckoutItems,
} = useCart();
const { buyNow, checkout, isLoading: isCheckoutLoading } = useCheckout();
const handleAddToCart = useCallback(() => {
const item = createCartItem();
if (item) {
addItem(item);
}
}, [createCartItem, addItem]);
const handleBuyNow = useCallback(() => {
if (product) {
buyNow(product, selectedQuantity);
}
}, [product, selectedQuantity, buyNow]);
const handleCheckout = useCallback(async () => {
if (cartItems.length === 0) return;
const currentUrl = new URL(window.location.href);
currentUrl.searchParams.set("success", "true");
await checkout(getCheckoutItems(), { successUrl: currentUrl.toString() });
}, [cartItems, checkout, getCheckoutItems]);
if (isLoading) {
return (
<ThemeProvider
defaultButtonVariant="expand-hover"
defaultTextAnimation="reveal-blur"
borderRadius="sharp"
contentWidth="compact"
sizing="large"
background="aurora"
cardStyle="soft-shadow"
primaryButtonStyle="primary-glow"
secondaryButtonStyle="glass"
headingFontWeight="bold"
>
<ReactLenis root>
<div id="navbar" data-section="navbar">
<NavbarLayoutFloatingInline
brandName="PawsHome"
navItems={[
{ name: "Home", id: "/" },
{ name: "Shop", id: "/shop" }
]}
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
/>
</div>
<main className="min-h-screen flex items-center justify-center pt-20">
<p className="text-foreground">Loading product...</p>
</main>
<div id="footer" data-section="footer">
<FooterCard
logoText="PawsHome"
copyrightText="© 2025 PawsHome Animal Shelter. Dedicated to animal welfare and adoption."
socialLinks={[
{ icon: Facebook, href: "https://facebook.com/pawshome", ariaLabel: "Facebook" },
{ icon: Instagram, href: "https://instagram.com/pawshome", ariaLabel: "Instagram" },
{ icon: Twitter, href: "https://twitter.com/pawshome", ariaLabel: "Twitter" }
]}
/>
</div>
</ReactLenis>
</ThemeProvider>
);
}
if (!product) {
return (
<ThemeProvider
defaultButtonVariant="expand-hover"
defaultTextAnimation="reveal-blur"
borderRadius="sharp"
contentWidth="compact"
sizing="large"
background="aurora"
cardStyle="soft-shadow"
primaryButtonStyle="primary-glow"
secondaryButtonStyle="glass"
headingFontWeight="bold"
>
<ReactLenis root>
<div id="navbar" data-section="navbar">
<NavbarLayoutFloatingInline
brandName="PawsHome"
navItems={[
{ name: "Home", id: "/" },
{ name: "Shop", id: "/shop" }
]}
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
/>
</div>
<main className="min-h-screen flex items-center justify-center pt-20">
<div className="text-center">
<p className="text-foreground mb-4">Product not found</p>
<button
onClick={() => router.push("/shop")}
className="primary-button px-6 py-2 rounded-theme"
>
Back to Shop
</button>
</div>
</main>
<div id="footer" data-section="footer">
<FooterCard
logoText="PawsHome"
copyrightText="© 2025 PawsHome Animal Shelter. Dedicated to animal welfare and adoption."
socialLinks={[
{ icon: Facebook, href: "https://facebook.com/pawshome", ariaLabel: "Facebook" },
{ icon: Instagram, href: "https://instagram.com/pawshome", ariaLabel: "Instagram" },
{ icon: Twitter, href: "https://twitter.com/pawshome", ariaLabel: "Twitter" }
]}
/>
</div>
</ReactLenis>
</ThemeProvider>
);
}
return (
<ThemeProvider
defaultButtonVariant="expand-hover"
defaultTextAnimation="reveal-blur"
borderRadius="sharp"
contentWidth="compact"
sizing="large"
background="aurora"
cardStyle="soft-shadow"
primaryButtonStyle="primary-glow"
secondaryButtonStyle="glass"
headingFontWeight="bold"
>
<ReactLenis root>
<div id="navbar" data-section="navbar">
<NavbarLayoutFloatingInline
brandName="PawsHome"
navItems={[
{ name: "Home", id: "/" },
{ name: "Shop", id: "/shop" }
]}
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
/>
</div>
<div id="productDetailCard" data-section="productDetailCard">
<ProductDetailCard
layout="page"
name={product.name}
price={product.price}
salePrice={meta.salePrice}
rating={product.rating || 0}
description={product.description}
images={images}
variants={variants.length > 0 ? variants : undefined}
quantity={quantityVariant}
ribbon={meta.ribbon}
inventoryStatus={meta.inventoryStatus}
inventoryQuantity={meta.inventoryQuantity}
sku={meta.sku}
buttons={[
{ text: "Add To Cart", onClick: handleAddToCart },
{ text: "Buy Now", onClick: handleBuyNow },
]}
/>
</div>
<div id="productCart" data-section="productCart">
<ProductCart
isOpen={cartOpen}
onClose={() => setCartOpen(false)}
items={cartItems}
onQuantityChange={updateQuantity}
onRemove={removeItem}
total={`$${cartTotal}`}
buttons={[
{
text: isCheckoutLoading ? "Processing..." : "Check Out", onClick: handleCheckout,
},
]}
/>
</div>
<div id="footer" data-section="footer">
<FooterCard
logoText="PawsHome"
copyrightText="© 2025 PawsHome Animal Shelter. Dedicated to animal welfare and adoption."
socialLinks={[
{ icon: Facebook, href: "https://facebook.com/pawshome", ariaLabel: "Facebook" },
{ icon: Instagram, href: "https://instagram.com/pawshome", ariaLabel: "Instagram" },
{ icon: Twitter, href: "https://twitter.com/pawshome", ariaLabel: "Twitter" }
]}
/>
</div>
</ReactLenis>
</ThemeProvider>
);
}

116
src/app/shop/page.tsx Normal file
View File

@@ -0,0 +1,116 @@
"use client";
import ReactLenis from "lenis/react";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import NavbarLayoutFloatingInline from '@/components/navbar/NavbarLayoutFloatingInline';
import FooterCard from '@/components/sections/footer/FooterCard';
import { Facebook, Instagram, Twitter } from 'lucide-react';
import ProductCatalog from "@/components/ecommerce/productCatalog/ProductCatalog";
import { useProductCatalog } from "@/hooks/useProductCatalog";
import { useState } from 'react';
export default function ShopPage() {
const {
products,
isLoading,
search,
setSearch,
filters,
} = useProductCatalog({ basePath: "/shop" });
const [cartOpen, setCartOpen] = useState(false);
if (isLoading) {
return (
<ThemeProvider
defaultButtonVariant="expand-hover"
defaultTextAnimation="reveal-blur"
borderRadius="sharp"
contentWidth="compact"
sizing="large"
background="aurora"
cardStyle="soft-shadow"
primaryButtonStyle="primary-glow"
secondaryButtonStyle="glass"
headingFontWeight="bold"
>
<ReactLenis root>
<div id="navbar" data-section="navbar">
<NavbarLayoutFloatingInline
brandName="PawsHome"
navItems={[
{ name: "Home", id: "/" },
{ name: "Shop", id: "/shop" }
]}
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
/>
</div>
<main className="min-h-screen flex items-center justify-center pt-20">
<p className="text-foreground">Loading products...</p>
</main>
<div id="footer" data-section="footer">
<FooterCard
logoText="PawsHome"
copyrightText="© 2025 PawsHome Animal Shelter. Dedicated to animal welfare and adoption."
socialLinks={[
{ icon: Facebook, href: "https://facebook.com/pawshome", ariaLabel: "Facebook" },
{ icon: Instagram, href: "https://instagram.com/pawshome", ariaLabel: "Instagram" },
{ icon: Twitter, href: "https://twitter.com/pawshome", ariaLabel: "Twitter" }
]}
/>
</div>
</ReactLenis>
</ThemeProvider>
);
}
return (
<ThemeProvider
defaultButtonVariant="expand-hover"
defaultTextAnimation="reveal-blur"
borderRadius="sharp"
contentWidth="compact"
sizing="large"
background="aurora"
cardStyle="soft-shadow"
primaryButtonStyle="primary-glow"
secondaryButtonStyle="glass"
headingFontWeight="bold"
>
<ReactLenis root>
<div id="navbar" data-section="navbar">
<NavbarLayoutFloatingInline
brandName="PawsHome"
navItems={[
{ name: "Home", id: "/" },
{ name: "Shop", id: "/shop" }
]}
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
/>
</div>
<div id="productCatalog" data-section="productCatalog">
<ProductCatalog
layout="page"
products={products}
searchValue={search}
onSearchChange={setSearch}
searchPlaceholder="Search products..."
filters={filters}
emptyMessage="No products found"
/>
</div>
<div id="footer" data-section="footer">
<FooterCard
logoText="PawsHome"
copyrightText="© 2025 PawsHome Animal Shelter. Dedicated to animal welfare and adoption."
socialLinks={[
{ icon: Facebook, href: "https://facebook.com/pawshome", ariaLabel: "Facebook" },
{ icon: Instagram, href: "https://instagram.com/pawshome", ariaLabel: "Instagram" },
{ icon: Twitter, href: "https://twitter.com/pawshome", ariaLabel: "Twitter" }
]}
/>
</div>
</ReactLenis>
</ThemeProvider>
);
}

28
src/app/styles/base.css Normal file
View File

@@ -0,0 +1,28 @@
* {
scrollbar-width: thin;
scrollbar-color: rgba(255, 255, 255, 1) rgba(255, 255, 255, 0);
}
html {
overscroll-behavior: none;
overscroll-behavior-y: none;
}
body {
background-color: var(--background);
color: var(--foreground);
font-family: var(--font-lora), sans-serif;
position: relative;
min-height: 100vh;
overscroll-behavior: none;
overscroll-behavior-y: none;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: var(--font-lora), sans-serif;
}

174
src/app/styles/theme.css Normal file
View File

@@ -0,0 +1,174 @@
@theme inline {
--color-background: var(--background);
--color-card: var(--card);
--color-foreground: var(--foreground);
--color-primary-cta: var(--primary-cta);
--color-secondary-cta: var(--secondary-cta);
--color-accent: var(--accent);
--color-background-accent: var(--background-accent);
/* theme border radius */
--radius-theme: var(--theme-border-radius);
--radius-theme-capped: var(--theme-border-radius-capped);
/* text */
--text-2xs: var(--text-2xs);
--text-xs: var(--text-xs);
--text-sm: var(--text-sm);
--text-base: var(--text-base);
--text-lg: var(--text-lg);
--text-xl: var(--text-xl);
--text-2xl: var(--text-2xl);
--text-3xl: var(--text-3xl);
--text-4xl: var(--text-4xl);
--text-5xl: var(--text-5xl);
--text-6xl: var(--text-6xl);
--text-7xl: var(--text-7xl);
--text-8xl: var(--text-8xl);
--text-9xl: var(--text-9xl);
/* height */
--height-4: var(--height-4);
--height-5: var(--height-5);
--height-6: var(--height-6);
--height-7: var(--height-7);
--height-8: var(--height-8);
--height-9: var(--height-9);
--height-11: var(--height-11);
--height-12: var(--height-12);
--height-10: var(--height-10);
--height-30: var(--height-30);
--height-90: var(--height-90);
--height-100: var(--height-100);
--height-110: var(--height-110);
--height-120: var(--height-120);
--height-130: var(--height-130);
--height-140: var(--height-140);
--height-150: var(--height-150);
--height-page-padding: calc(2.25rem+var(--vw-1_5)+var(--vw-1_5));
/* width */
--width-5: var(--width-5);
--width-7_5: var(--width-7_5);
--width-10: var(--width-10);
--width-12_5: var(--width-12_5);
--width-15: var(--width-15);
--width-17: var(--width-17);
--width-17_5: var(--width-17_5);
--width-20: var(--width-20);
--width-21: var(--width-21);
--width-22_5: var(--width-22_5);
--width-25: var(--width-25);
--width-26: var(--width-26);
--width-27_5: var(--width-27_5);
--width-30: var(--width-30);
--width-32_5: var(--width-32_5);
--width-35: var(--width-35);
--width-37_5: var(--width-37_5);
--width-40: var(--width-40);
--width-42_5: var(--width-42_5);
--width-45: var(--width-45);
--width-47_5: var(--width-47_5);
--width-50: var(--width-50);
--width-52_5: var(--width-52_5);
--width-55: var(--width-55);
--width-57_5: var(--width-57_5);
--width-60: var(--width-60);
--width-62_5: var(--width-62_5);
--width-65: var(--width-65);
--width-67_5: var(--width-67_5);
--width-70: var(--width-70);
--width-72_5: var(--width-72_5);
--width-75: var(--width-75);
--width-77_5: var(--width-77_5);
--width-80: var(--width-80);
--width-82_5: var(--width-82_5);
--width-85: var(--width-85);
--width-87_5: var(--width-87_5);
--width-90: var(--width-90);
--width-92_5: var(--width-92_5);
--width-95: var(--width-95);
--width-97_5: var(--width-97_5);
--width-100: var(--width-100);
--width-content-width: var(--width-content-width);
--width-carousel-padding: var(--width-carousel-padding);
--width-carousel-padding-controls: var(--width-carousel-padding-controls);
--width-carousel-padding-expanded: var(--width-carousel-padding-expanded);
--width-carousel-padding-controls-expanded: var(--width-carousel-padding-controls-expanded);
--width-carousel-item-3: var(--width-carousel-item-3);
--width-carousel-item-4: var(--width-carousel-item-4);
--width-x-padding-mask-fade: var(--width-x-padding-mask-fade);
--width-content-width-expanded: var(--width-content-width-expanded);
/* gap */
--spacing-1: var(--vw-0_25);
--spacing-2: var(--vw-0_5);
--spacing-3: var(--vw-0_75);
--spacing-4: var(--vw-1);
--spacing-5: var(--vw-1_25);
--spacing-6: var(--vw-1_5);
--spacing-7: var(--vw-1_75);
--spacing-8: var(--vw-2);
--spacing-x-1: var(--vw-0_25);
--spacing-x-2: var(--vw-0_5);
--spacing-x-3: var(--vw-0_75);
--spacing-x-4: var(--vw-1);
--spacing-x-5: var(--vw-1_25);
--spacing-x-6: var(--vw-1_5);
/* border radius */
--radius-none: 0;
--radius-sm: var(--vw-0_5);
--radius: var(--vw-0_75);
--radius-md: var(--vw-1);
--radius-lg: var(--vw-1_25);
--radius-xl: var(--vw-1_75);
--radius-full: 999px;
/* padding */
--padding-1: var(--vw-0_25);
--padding-2: var(--vw-0_5);
--padding-2.5: var(--vw-0_625);
--padding-3: var(--vw-0_75);
--padding-4: var(--vw-1);
--padding-5: var(--vw-1_25);
--padding-6: var(--vw-1_5);
--padding-7: var(--vw-1_75);
--padding-8: var(--vw-2);
--padding-x-1: var(--vw-0_25);
--padding-x-2: var(--vw-0_5);
--padding-x-3: var(--vw-0_75);
--padding-x-4: var(--vw-1);
--padding-x-5: var(--vw-1_25);
--padding-x-6: var(--vw-1_5);
--padding-x-7: var(--vw-1_75);
--padding-x-8: var(--vw-2);
--padding-hero-page-padding-half: var(--padding-hero-page-padding-half);
--padding-hero-page-padding: var(--padding-hero-page-padding);
--padding-hero-page-padding-1_5: var(--padding-hero-page-padding-1_5);
--padding-hero-page-padding-double: var(--padding-hero-page-padding-double);
/* margin */
--margin-1: var(--vw-0_25);
--margin-2: var(--vw-0_5);
--margin-3: var(--vw-0_75);
--margin-4: var(--vw-1);
--margin-5: var(--vw-1_25);
--margin-6: var(--vw-1_5);
--margin-7: var(--vw-1_75);
--margin-8: var(--vw-2);
--margin-x-1: var(--vw-0_25);
--margin-x-2: var(--vw-0_5);
--margin-x-3: var(--vw-0_75);
--margin-x-4: var(--vw-1);
--margin-x-5: var(--vw-1_25);
--margin-x-6: var(--vw-1_5);
--margin-x-7: var(--vw-1_75);
--margin-x-8: var(--vw-2);
}

View File

@@ -0,0 +1,178 @@
@layer components {}
@layer utilities {
/* Card, primary-button, and secondary-button styles are now dynamically injected via ThemeProvider */
/* .card {
@apply backdrop-blur-sm bg-gradient-to-br from-card/80 to-card/40 shadow-sm border border-card;
}
.primary-button {
@apply bg-gradient-to-b from-primary-cta/83 to-primary-cta;
box-shadow:
color-mix(in srgb, var(--color-background) 25%, transparent) 0px 1px 1px 0px inset,
color-mix(in srgb, var(--color-primary-cta) 15%, transparent) 3px 3px 3px 0px;
}
.secondary-button {
@apply backdrop-blur-sm bg-gradient-to-br from-secondary-cta/80 to-secondary-cta shadow-sm border border-secondary-cta;
} */
.tag-card {
@apply backdrop-blur-sm bg-gradient-to-br from-card/80 to-card/40 shadow-sm border border-card;
}
.mask-fade-x {
-webkit-mask-image: linear-gradient(to right, transparent 0%, transparent calc((100vw - var(--width-content-width)) / 4), black calc((100vw - var(--width-content-width)) / 2 + 5vw), black calc(100% - (100vw - var(--width-content-width)) / 2 - 5vw), transparent calc(100% - (100vw - var(--width-content-width)) / 4), transparent 100%);
mask-image: linear-gradient(to right, transparent 0%, transparent calc((100vw - var(--width-content-width)) / 4), black calc((100vw - var(--width-content-width)) / 2 + 5vw), black calc(100% - (100vw - var(--width-content-width)) / 2 - 5vw), transparent calc(100% - (100vw - var(--width-content-width)) / 4), transparent 100%);
}
.mask-padding-x {
-webkit-mask-image: linear-gradient(to right, transparent 0%, black var(--width-x-padding-mask-fade), black calc(100% - var(--width-x-padding-mask-fade)), transparent 100%);
mask-image: linear-gradient(to right, transparent 0%, black var(--width-x-padding-mask-fade), black calc(100% - var(--width-x-padding-mask-fade)), transparent 100%);
}
.mask-fade-bottom {
-webkit-mask-image: linear-gradient(to bottom, black 0%, black 50%, transparent 100%);
mask-image: linear-gradient(to bottom, black 0%, black 50%, transparent 100%);
}
.mask-fade-y {
mask-image: linear-gradient(to bottom,
transparent 0%,
black var(--vw-1_5),
black calc(100% - var(--vw-1_5)),
transparent 100%);
}
.mask-fade-bottom-large {
-webkit-mask-image: linear-gradient(to bottom, black 0%, black 50%, transparent 75%, transparent 100%);
mask-image: linear-gradient(to bottom, black 0%, black 50%, transparent 75%, transparent 100%);
}
.mask-fade-bottom-long {
-webkit-mask-image: linear-gradient(to bottom, black 0%, black 5%, transparent 100%);
mask-image: linear-gradient(to bottom, black 0%, black 5%, transparent 100%);
}
.mask-fade-top-long {
-webkit-mask-image: linear-gradient(to top, black 0%, black 5%, transparent 100%);
mask-image: linear-gradient(to top, black 0%, black 5%, transparent 100%);
}
.mask-fade-xy {
-webkit-mask-image:
linear-gradient(to right, transparent 0%, black 20%, black 80%, transparent 100%),
linear-gradient(to bottom, transparent 0%, black 20%, black 80%, transparent 100%);
mask-image:
linear-gradient(to right, transparent 0%, black 20%, black 80%, transparent 100%),
linear-gradient(to bottom, transparent 0%, black 20%, black 80%, transparent 100%);
-webkit-mask-composite: source-in;
mask-composite: intersect;
}
/* ANIMATION */
.animation-container {
animation:
fadeInOpacity 0.8s ease-in-out forwards,
fadeInTranslate 0.6s forwards;
}
.animation-container-fade {
animation: fadeInOpacity 0.8s ease-in-out forwards;
}
@keyframes fadeInOpacity {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeInTranslate {
from {
transform: translateY(0.75vh);
}
to {
transform: translateY(0vh);
}
}
@keyframes aurora {
from {
background-position: 50% 50%, 50% 50%;
}
to {
background-position: 350% 50%, 350% 50%;
}
}
@keyframes spin-slow {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes spin-reverse {
from {
transform: rotate(0deg);
}
to {
transform: rotate(-360deg);
}
}
.animate-spin-slow {
animation: spin-slow 15s linear infinite;
}
.animate-spin-reverse {
animation: spin-reverse 10s linear infinite;
}
@keyframes marquee-vertical {
from {
transform: translateY(0);
}
to {
transform: translateY(-50%);
}
}
.animate-marquee-vertical {
animation: marquee-vertical 20s linear infinite;
}
@keyframes orbit {
from {
transform: rotate(var(--initial-position, 0deg)) translateX(var(--translate-position, 120px)) rotate(calc(-1 * var(--initial-position, 0deg)));
}
to {
transform: rotate(calc(var(--initial-position, 0deg) + 360deg)) translateX(var(--translate-position, 120px)) rotate(calc(-1 * (var(--initial-position, 0deg) + 360deg)));
}
}
@keyframes map-dot-pulse {
0%, 100% {
transform: scale(0.4);
opacity: 0.6;
}
50% {
transform: scale(1.4);
opacity: 1;
}
}
}

View File

@@ -0,0 +1,215 @@
:root {
/* Base units */
/* --vw is set by ThemeProvider */
/* --background: #f6f0e9;;
--card: #efe7dd;;
--foreground: #2b180a;;
--primary-cta: #2b180a;;
--secondary-cta: #efe7dd;;
--accent: #94877c;;
--background-accent: #afa094;; */
--background: #f6f0e9;;
--card: #efe7dd;;
--foreground: #2b180a;;
--primary-cta: #2b180a;;
--secondary-cta: #efe7dd;;
--accent: #94877c;;
--background-accent: #afa094;;
/* text sizing - set by ThemeProvider */
/* --text-2xs: clamp(0.465rem, 0.62vw, 0.62rem);
--text-xs: clamp(0.54rem, 0.72vw, 0.72rem);
--text-sm: clamp(0.615rem, 0.82vw, 0.82rem);
--text-base: clamp(0.69rem, 0.92vw, 0.92rem);
--text-lg: clamp(0.75rem, 1vw, 1rem);
--text-xl: clamp(0.825rem, 1.1vw, 1.1rem);
--text-2xl: clamp(0.975rem, 1.3vw, 1.3rem);
--text-3xl: clamp(1.2rem, 1.6vw, 1.6rem);
--text-4xl: clamp(1.5rem, 2vw, 2rem);
--text-5xl: clamp(2.025rem, 2.75vw, 2.75rem);
--text-6xl: clamp(2.475rem, 3.3vw, 3.3rem);
--text-7xl: clamp(3rem, 4vw, 4rem);
--text-8xl: clamp(3.5rem, 4.5vw, 4.5rem);
--text-9xl: clamp(5.25rem, 7vw, 7rem); */
/* Base spacing units */
--vw-0_25: calc(var(--vw) * 0.25);
--vw-0_5: calc(var(--vw) * 0.5);
--vw-0_625: calc(var(--vw) * 0.625);
--vw-0_75: calc(var(--vw) * 0.75);
--vw-1: calc(var(--vw) * 1);
--vw-1_25: calc(var(--vw) * 1.25);
--vw-1_5: calc(var(--vw) * 1.5);
--vw-1_75: calc(var(--vw) * 1.75);
--vw-2: calc(var(--vw) * 2);
--vw-2_25: calc(var(--vw) * 2.25);
--vw-2_5: calc(var(--vw) * 2.5);
--vw-2_75: calc(var(--vw) * 2.75);
--vw-3: calc(var(--vw) * 3);
/* width */
--width-5: clamp(4rem, 5vw, 6rem);
--width-7_5: clamp(5.625rem, 7.5vw, 7.5rem);
--width-10: clamp(7.5rem, 10vw, 10rem);
--width-12_5: clamp(9.375rem, 12.5vw, 12.5rem);
--width-15: clamp(11.25rem, 15vw, 15rem);
--width-17: clamp(12.75rem, 17vw, 17rem);
--width-17_5: clamp(13.125rem, 17.5vw, 17.5rem);
--width-20: clamp(15rem, 20vw, 20rem);
--width-21: clamp(15.75rem, 21vw, 21rem);
--width-22_5: clamp(16.875rem, 22.5vw, 22.5rem);
--width-25: clamp(18.75rem, 25vw, 25rem);
--width-26: clamp(19.5rem, 26vw, 26rem);
--width-27_5: clamp(20.625rem, 27.5vw, 27.5rem);
--width-30: clamp(22.5rem, 30vw, 30rem);
--width-32_5: clamp(24.375rem, 32.5vw, 32.5rem);
--width-35: clamp(26.25rem, 35vw, 35rem);
--width-37_5: clamp(28.125rem, 37.5vw, 37.5rem);
--width-40: clamp(30rem, 40vw, 40rem);
--width-42_5: clamp(31.875rem, 42.5vw, 42.5rem);
--width-45: clamp(33.75rem, 45vw, 45rem);
--width-47_5: clamp(35.625rem, 47.5vw, 47.5rem);
--width-50: clamp(37.5rem, 50vw, 50rem);
--width-52_5: clamp(39.375rem, 52.5vw, 52.5rem);
--width-55: clamp(41.25rem, 55vw, 55rem);
--width-57_5: clamp(43.125rem, 57.5vw, 57.5rem);
--width-60: clamp(45rem, 60vw, 60rem);
--width-62_5: clamp(46.875rem, 62.5vw, 62.5rem);
--width-65: clamp(48.75rem, 65vw, 65rem);
--width-67_5: clamp(50.625rem, 67.5vw, 67.5rem);
--width-70: clamp(52.5rem, 70vw, 70rem);
--width-72_5: clamp(54.375rem, 72.5vw, 72.5rem);
--width-75: clamp(56.25rem, 75vw, 75rem);
--width-77_5: clamp(58.125rem, 77.5vw, 77.5rem);
--width-80: clamp(60rem, 80vw, 80rem);
--width-82_5: clamp(61.875rem, 82.5vw, 82.5rem);
--width-85: clamp(63.75rem, 85vw, 85rem);
--width-87_5: clamp(65.625rem, 87.5vw, 87.5rem);
--width-90: clamp(67.5rem, 90vw, 90rem);
--width-92_5: clamp(69.375rem, 92.5vw, 92.5rem);
--width-95: clamp(71.25rem, 95vw, 95rem);
--width-97_5: clamp(73.125rem, 97.5vw, 97.5rem);
--width-100: clamp(75rem, 100vw, 100rem);
/* --width-content-width and --width-content-width-expanded are set by ThemeProvider */
--width-carousel-padding: calc((100vw - var(--width-content-width)) / 2 + 1px - var(--vw-1_5));
--width-carousel-padding-controls: calc((100vw - var(--width-content-width)) / 2 + 1px);
--width-carousel-padding-expanded: calc((var(--width-content-width-expanded) - var(--width-content-width)) / 2 + 1px - var(--vw-1_5));
--width-carousel-padding-controls-expanded: calc((var(--width-content-width-expanded) - var(--width-content-width)) / 2 + 1px);
--width-carousel-item-3: calc(var(--width-content-width) / 3 - var(--vw-1_5) / 3 * 2);
--width-carousel-item-4: calc(var(--width-content-width) / 4 - var(--vw-1_5) / 4 * 3);
--width-x-padding-mask-fade: clamp(1.5rem, 4vw, 4rem);
--height-4: 1rem;
--height-5: 1.25rem;
--height-6: 1.5rem;
--height-7: 1.75rem;
--height-8: 2rem;
--height-9: 2.25rem;
--height-10: 2.5rem;
--height-11: 2.75rem;
--height-12: 3rem;
--height-30: 7.5rem;
--height-90: 22.5rem;
--height-100: 25rem;
--height-110: 27.5rem;
--height-120: 30rem;
--height-130: 32.5rem;
--height-140: 35rem;
--height-150: 37.5rem;
/* hero page padding */
--padding-hero-page-padding-half: calc((var(--height-10) + var(--vw-1_5) + var(--vw-1_5) + var(--height-10)) / 2);
--padding-hero-page-padding: calc(var(--height-10) + var(--vw-1_5) + var(--vw-1_5) + var(--height-10));
--padding-hero-page-padding-1_5: calc(1.5 * (var(--height-10) + var(--vw-1_5) + var(--vw-1_5) + var(--height-10)));
--padding-hero-page-padding-double: calc(2 * (var(--height-10) + var(--vw-1_5) + var(--vw-1_5) + var(--height-10)));
}
@media (max-width: 767px) {
:root {
/* --vw and text sizing are set by ThemeProvider */
/* --vw: 3vw;
--text-2xs: 2.5vw;
--text-xs: 2.75vw;
--text-sm: 3vw;
--text-base: 3.25vw;
--text-lg: 3.5vw;
--text-xl: 4.25vw;
--text-2xl: 5vw;
--text-3xl: 6vw;
--text-4xl: 7vw;
--text-5xl: 7.5vw;
--text-6xl: 8.5vw;
--text-7xl: 10vw;
--text-8xl: 12vw;
--text-9xl: 14vw; */
--width-5: 5vw;
--width-7_5: 7.5vw;
--width-10: 10vw;
--width-12_5: 12.5vw;
--width-15: 15vw;
--width-17_5: 17.5vw;
--width-20: 20vw;
--width-22_5: 22.5vw;
--width-25: 25vw;
--width-27_5: 27.5vw;
--width-30: 30vw;
--width-32_5: 32.5vw;
--width-35: 35vw;
--width-37_5: 37.5vw;
--width-40: 40vw;
--width-42_5: 42.5vw;
--width-45: 45vw;
--width-47_5: 47.5vw;
--width-50: 50vw;
--width-52_5: 52.5vw;
--width-55: 55vw;
--width-57_5: 57.5vw;
--width-60: 60vw;
--width-62_5: 62.5vw;
--width-65: 65vw;
--width-67_5: 67.5vw;
--width-70: 70vw;
--width-72_5: 72.5vw;
--width-75: 75vw;
--width-77_5: 77.5vw;
--width-80: 80vw;
--width-82_5: 82.5vw;
--width-85: 85vw;
--width-87_5: 87.5vw;
--width-90: 90vw;
--width-92_5: 92.5vw;
--width-95: 95vw;
--width-97_5: 97.5vw;
--width-100: 100vw;
/* --width-content-width and --width-content-width-expanded are set by ThemeProvider */
--width-carousel-padding: calc((100vw - var(--width-content-width)) / 2 + 1px - var(--vw-1_5));
--width-carousel-padding-controls: calc((100vw - var(--width-content-width)) / 2 + 1px);
--width-carousel-padding-expanded: calc((var(--width-content-width-expanded) - var(--width-content-width)) / 2 + 1px - var(--vw-1_5));
--width-carousel-padding-controls-expanded: calc((var(--width-content-width-expanded) - var(--width-content-width)) / 2 + 1px);
--width-carousel-item-3: var(--width-content-width);
--width-carousel-item-4: var(--width-content-width);
--width-x-padding-mask-fade: 10vw;
--height-4: 3.5vw;
--height-5: 4.5vw;
--height-6: 5.5vw;
--height-7: 6.5vw;
--height-8: 7.5vw;
--height-9: 8.5vw;
--height-10: 9vw;
--height-11: 10vw;
--height-12: 11vw;
--height-30: 25vw;
--height-90: 81vw;
--height-100: 90vw;
--height-110: 99vw;
--height-120: 108vw;
--height-130: 117vw;
--height-140: 126vw;
--height-150: 135vw;
}
}