feat: Add Section layout component and refactor page.tsx with updated styling and new Button variants.
This commit is contained in:
99
app/page.tsx
99
app/page.tsx
@@ -3,6 +3,7 @@ import { Button } from "@/components/ui/Button";
|
|||||||
import { SectionHeading } from "@/components/ui/SectionHeading";
|
import { SectionHeading } from "@/components/ui/SectionHeading";
|
||||||
import { Card } from "@/components/ui/Card";
|
import { Card } from "@/components/ui/Card";
|
||||||
import { FadeIn } from "@/components/ui/FadeIn";
|
import { FadeIn } from "@/components/ui/FadeIn";
|
||||||
|
import { Section } from "@/components/layout/Section";
|
||||||
import { Dumbbell, Users, Clock, Heart } from "lucide-react";
|
import { Dumbbell, Users, Clock, Heart } from "lucide-react";
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
@@ -67,48 +68,41 @@ export default function HomePage() {
|
|||||||
return (
|
return (
|
||||||
<main>
|
<main>
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<section className="relative flex items-center min-h-screen bg-primary text-secondary">
|
<Section className="flex items-center min-h-[90vh] bg-primary text-secondary">
|
||||||
<Container className="py-32 md:py-40">
|
<Container className="py-20 md:py-32">
|
||||||
<FadeIn>
|
<FadeIn>
|
||||||
<p className="text-sm uppercase tracking-[0.2em] text-secondary/60 mb-6">
|
<p className="text-sm uppercase tracking-[0.2em] opacity-80 mb-6">
|
||||||
Fitnessstudio in Reutte, Tirol
|
Fitnessstudio in Reutte, Tirol
|
||||||
</p>
|
</p>
|
||||||
</FadeIn>
|
</FadeIn>
|
||||||
<FadeIn delay={0.1}>
|
<FadeIn delay={0.1}>
|
||||||
<h1
|
<h1 className="font-bold max-w-4xl text-5xl md:text-6xl lg:text-[5rem] leading-[1.1] tracking-tight mb-6">
|
||||||
className="font-bold max-w-3xl"
|
|
||||||
style={{
|
|
||||||
fontSize: "clamp(var(--text-4xl), 5vw, var(--text-6xl))",
|
|
||||||
lineHeight: "1.1",
|
|
||||||
letterSpacing: "var(--text-5xl-letter-spacing)",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Dein Weg zu mehr
|
Dein Weg zu mehr
|
||||||
<br />
|
<br />
|
||||||
Fitness beginnt hier.
|
Fitness beginnt hier.
|
||||||
</h1>
|
</h1>
|
||||||
</FadeIn>
|
</FadeIn>
|
||||||
<FadeIn delay={0.2}>
|
<FadeIn delay={0.2}>
|
||||||
<p className="mt-6 max-w-xl text-secondary/70" style={{ fontSize: "var(--text-lg)" }}>
|
<p className="mt-6 max-w-xl text-lg md:text-xl text-secondary/80 leading-relaxed">
|
||||||
Individuelle Trainingspläne, persönliche Betreuung und eine
|
Individuelle Trainingspläne, persönliche Betreuung und eine
|
||||||
motivierende Community. Willkommen bei Sportbox Reutte.
|
motivierende Community. Willkommen bei Sportbox Reutte.
|
||||||
</p>
|
</p>
|
||||||
</FadeIn>
|
</FadeIn>
|
||||||
<FadeIn delay={0.3}>
|
<FadeIn delay={0.3}>
|
||||||
<div className="mt-10 flex flex-col sm:flex-row gap-4">
|
<div className="mt-10 flex flex-col sm:flex-row gap-4">
|
||||||
<Button href="/leistungen#kontakt" variant="secondary" className="border-secondary text-secondary hover:bg-secondary hover:text-primary">
|
<Button href="/leistungen#kontakt" variant="outline-white">
|
||||||
Jetzt Termin buchen
|
Jetzt Termin buchen
|
||||||
</Button>
|
</Button>
|
||||||
<Button href="/über-uns" variant="ghost" className="text-secondary/80 hover:text-secondary">
|
<Button href="/über-uns" variant="ghost-white">
|
||||||
Mehr über uns erfahren
|
Mehr über uns erfahren
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</FadeIn>
|
</FadeIn>
|
||||||
</Container>
|
</Container>
|
||||||
</section>
|
</Section>
|
||||||
|
|
||||||
{/* Features Section */}
|
{/* Features Section */}
|
||||||
<section className="py-[var(--spacing-section)] md:py-[var(--spacing-4xl)]">
|
<Section>
|
||||||
<Container>
|
<Container>
|
||||||
<FadeIn>
|
<FadeIn>
|
||||||
<SectionHeading
|
<SectionHeading
|
||||||
@@ -116,52 +110,45 @@ export default function HomePage() {
|
|||||||
subtitle="Wir bieten mehr als nur ein Fitnessstudio – wir sind Ihr Partner auf dem Weg zu einem gesünderen Leben."
|
subtitle="Wir bieten mehr als nur ein Fitnessstudio – wir sind Ihr Partner auf dem Weg zu einem gesünderen Leben."
|
||||||
/>
|
/>
|
||||||
</FadeIn>
|
</FadeIn>
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||||
{FEATURES.map((feature, index) => (
|
{FEATURES.map((feature, index) => (
|
||||||
<FadeIn key={feature.title} delay={index * 0.1}>
|
<FadeIn key={feature.title} delay={index * 0.1}>
|
||||||
<Card className="text-center h-full">
|
{/* Simplified Card usage since it might be just a div in this specialized case or reuse Card */}
|
||||||
|
<Card className="text-center h-full p-6 bg-background border border-border shadow-sm">
|
||||||
<feature.icon
|
<feature.icon
|
||||||
size={32}
|
size={32}
|
||||||
className="mx-auto mb-4 text-primary"
|
className="mx-auto mb-4 text-primary"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
<h3 className="text-base font-bold mb-2">{feature.title}</h3>
|
<h3 className="text-lg font-bold mb-2">{feature.title}</h3>
|
||||||
<p className="text-sm text-muted">{feature.description}</p>
|
<p className="text-sm text-muted leading-relaxed">{feature.description}</p>
|
||||||
</Card>
|
</Card>
|
||||||
</FadeIn>
|
</FadeIn>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
</section>
|
</Section>
|
||||||
|
|
||||||
{/* About Teaser Section */}
|
{/* About Teaser Section */}
|
||||||
<section className="py-[var(--spacing-section)] md:py-[var(--spacing-4xl)] bg-neutral">
|
<Section className="bg-neutral">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-20 items-center">
|
||||||
<FadeIn>
|
<FadeIn>
|
||||||
<div
|
<div
|
||||||
className="aspect-[4/3] bg-accent/40 flex items-center justify-center"
|
className="aspect-[4/3] bg-accent/40 flex items-center justify-center rounded-2xl overflow-hidden shadow-lg"
|
||||||
style={{ borderRadius: "var(--radius-md)" }}
|
|
||||||
>
|
>
|
||||||
<p className="text-muted text-sm">PLACEHOLDER: Studio-Bild</p>
|
<div className="text-muted text-sm font-medium">PLACEHOLDER: Studio-Bild</div>
|
||||||
</div>
|
</div>
|
||||||
</FadeIn>
|
</FadeIn>
|
||||||
<FadeIn delay={0.15}>
|
<FadeIn delay={0.15}>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm uppercase tracking-[0.2em] text-muted mb-4">
|
<p className="text-sm uppercase tracking-[0.2em] text-muted mb-4 font-semibold">
|
||||||
Über uns
|
Über uns
|
||||||
</p>
|
</p>
|
||||||
<h2
|
<h2 className="text-3xl md:text-4xl font-bold mb-6 tracking-tight">
|
||||||
className="font-bold mb-6"
|
|
||||||
style={{
|
|
||||||
fontSize: "var(--text-3xl)",
|
|
||||||
lineHeight: "var(--text-3xl-line-height)",
|
|
||||||
letterSpacing: "var(--text-3xl-letter-spacing)",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Mehr als nur Training – eine Gemeinschaft.
|
Mehr als nur Training – eine Gemeinschaft.
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-muted mb-6 leading-relaxed">
|
<p className="text-muted mb-8 leading-relaxed text-lg">
|
||||||
Bei Sportbox Reutte stehen Sie im Mittelpunkt. Unser erfahrenes
|
Bei Sportbox Reutte stehen Sie im Mittelpunkt. Unser erfahrenes
|
||||||
Team begleitet Sie auf Ihrem individuellen Weg – ob Einsteiger
|
Team begleitet Sie auf Ihrem individuellen Weg – ob Einsteiger
|
||||||
oder Fortgeschrittener. Gemeinsam erreichen wir Ihre Ziele.
|
oder Fortgeschrittener. Gemeinsam erreichen wir Ihre Ziele.
|
||||||
@@ -173,10 +160,10 @@ export default function HomePage() {
|
|||||||
</FadeIn>
|
</FadeIn>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
</section>
|
</Section>
|
||||||
|
|
||||||
{/* Services Preview Section */}
|
{/* Services Preview Section */}
|
||||||
<section className="py-[var(--spacing-section)] md:py-[var(--spacing-4xl)]">
|
<Section>
|
||||||
<Container>
|
<Container>
|
||||||
<FadeIn>
|
<FadeIn>
|
||||||
<SectionHeading
|
<SectionHeading
|
||||||
@@ -184,49 +171,45 @@ export default function HomePage() {
|
|||||||
subtitle="Entdecken Sie unser vielfältiges Angebot für Ihre persönlichen Fitnessziele."
|
subtitle="Entdecken Sie unser vielfältiges Angebot für Ihre persönlichen Fitnessziele."
|
||||||
/>
|
/>
|
||||||
</FadeIn>
|
</FadeIn>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||||
{SERVICES_PREVIEW.map((service, index) => (
|
{SERVICES_PREVIEW.map((service, index) => (
|
||||||
<FadeIn key={service.title} delay={index * 0.1}>
|
<FadeIn key={service.title} delay={index * 0.1}>
|
||||||
<Card className="h-full">
|
<Card className="h-full flex flex-col p-8 bg-background border border-border shadow-sm hover:shadow-md transition-shadow">
|
||||||
<h3 className="text-lg font-bold mb-3">{service.title}</h3>
|
<h3 className="text-xl font-bold mb-3">{service.title}</h3>
|
||||||
<p className="text-sm text-muted mb-4">{service.description}</p>
|
<p className="text-sm text-muted mb-6 flex-grow leading-relaxed">{service.description}</p>
|
||||||
<Button href="/leistungen" variant="ghost" className="text-sm">
|
<div className="mt-auto">
|
||||||
Mehr erfahren
|
<Button href="/leistungen" variant="ghost" className="px-0 hover:bg-transparent">
|
||||||
|
Mehr erfahren →
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</FadeIn>
|
</FadeIn>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
</section>
|
</Section>
|
||||||
|
|
||||||
{/* CTA Section */}
|
{/* CTA Section */}
|
||||||
<section className="py-[var(--spacing-section)] md:py-[var(--spacing-4xl)] bg-primary text-secondary">
|
<Section className="bg-primary text-secondary text-center">
|
||||||
<Container className="text-center">
|
<Container>
|
||||||
<FadeIn>
|
<FadeIn>
|
||||||
<h2
|
<h2 className="text-3xl md:text-4xl font-bold mb-6 tracking-tight">
|
||||||
className="font-bold mb-4"
|
|
||||||
style={{
|
|
||||||
fontSize: "var(--text-3xl)",
|
|
||||||
lineHeight: "var(--text-3xl-line-height)",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Bereit für den ersten Schritt?
|
Bereit für den ersten Schritt?
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-secondary/70 mb-8 max-w-lg mx-auto">
|
<p className="text-secondary/80 mb-10 max-w-xl mx-auto text-lg">
|
||||||
Vereinbaren Sie jetzt einen unverbindlichen Termin und lernen Sie
|
Vereinbaren Sie jetzt einen unverbindlichen Termin und lernen Sie
|
||||||
Sportbox Reutte kennen.
|
Sportbox Reutte kennen.
|
||||||
</p>
|
</p>
|
||||||
<Button
|
<Button
|
||||||
href="/leistungen#kontakt"
|
href="/leistungen#kontakt"
|
||||||
variant="secondary"
|
variant="outline-white"
|
||||||
className="border-secondary text-secondary hover:bg-secondary hover:text-primary"
|
className="px-8 py-4 text-base"
|
||||||
>
|
>
|
||||||
Jetzt Termin buchen
|
Jetzt Termin buchen
|
||||||
</Button>
|
</Button>
|
||||||
</FadeIn>
|
</FadeIn>
|
||||||
</Container>
|
</Container>
|
||||||
</section>
|
</Section>
|
||||||
|
|
||||||
{/* JSON-LD Structured Data */}
|
{/* JSON-LD Structured Data */}
|
||||||
<script
|
<script
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import Link from "next/link";
|
|||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import { Menu, X } from "lucide-react";
|
import { Menu, X } from "lucide-react";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
|
import { Container } from "@/components/ui/Container";
|
||||||
|
import { Button } from "@/components/ui/Button";
|
||||||
|
|
||||||
const NAV_ITEMS = [
|
const NAV_ITEMS = [
|
||||||
{ href: "/", label: "Startseite" },
|
{ href: "/", label: "Startseite" },
|
||||||
@@ -20,8 +22,8 @@ export function Header() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="fixed top-0 left-0 right-0 z-50 bg-background/95 backdrop-blur-sm border-b border-border">
|
<header className="fixed top-0 left-0 right-0 z-50 bg-background/95 backdrop-blur-sm border-b border-border">
|
||||||
<div className="mx-auto flex items-center justify-between px-[var(--spacing-container-padding)] py-4" style={{ maxWidth: "var(--spacing-container)" }}>
|
<Container className="flex items-center justify-between py-4">
|
||||||
<Link href="/" className="text-xl font-bold tracking-tight" aria-label="Sportbox Reutte – Zur Startseite">
|
<Link href="/" className="text-xl font-bold tracking-tight text-primary" aria-label="Sportbox Reutte – Zur Startseite">
|
||||||
SPORTBOX
|
SPORTBOX
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
@@ -30,24 +32,24 @@ export function Header() {
|
|||||||
<Link
|
<Link
|
||||||
key={item.href}
|
key={item.href}
|
||||||
href={item.href}
|
href={item.href}
|
||||||
className={`text-sm tracking-wide transition-colors hover:text-muted ${
|
className={`text-sm tracking-wide transition-colors hover:text-muted ${pathname === item.href ? "font-bold text-primary" : "font-normal text-muted-foreground/80"
|
||||||
pathname === item.href ? "font-bold" : "font-normal"
|
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{item.label}
|
{item.label}
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
<Link
|
<Button
|
||||||
href="/leistungen#kontakt"
|
href="/leistungen#kontakt"
|
||||||
className="bg-primary text-secondary px-5 py-2.5 text-sm font-medium transition-opacity hover:opacity-80"
|
variant="primary"
|
||||||
|
className="py-2.5 px-5 text-sm"
|
||||||
>
|
>
|
||||||
Jetzt Termin buchen
|
Jetzt Termin buchen
|
||||||
</Link>
|
</Button>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="lg:hidden p-2 -mr-2"
|
className="lg:hidden p-2 -mr-2 text-primary"
|
||||||
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
||||||
aria-expanded={mobileMenuOpen}
|
aria-expanded={mobileMenuOpen}
|
||||||
aria-controls="mobile-menu"
|
aria-controls="mobile-menu"
|
||||||
@@ -55,7 +57,7 @@ export function Header() {
|
|||||||
>
|
>
|
||||||
{mobileMenuOpen ? <X size={24} /> : <Menu size={24} />}
|
{mobileMenuOpen ? <X size={24} /> : <Menu size={24} />}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</Container>
|
||||||
|
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{mobileMenuOpen && (
|
{mobileMenuOpen && (
|
||||||
@@ -74,20 +76,22 @@ export function Header() {
|
|||||||
key={item.href}
|
key={item.href}
|
||||||
href={item.href}
|
href={item.href}
|
||||||
onClick={() => setMobileMenuOpen(false)}
|
onClick={() => setMobileMenuOpen(false)}
|
||||||
className={`py-3 text-base transition-colors hover:text-muted ${
|
className={`py-3 text-base transition-colors hover:text-muted ${pathname === item.href ? "font-bold text-primary" : "font-normal text-muted-foreground"
|
||||||
pathname === item.href ? "font-bold" : "font-normal"
|
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{item.label}
|
{item.label}
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
<Link
|
<div className="mt-4">
|
||||||
|
<Button
|
||||||
href="/leistungen#kontakt"
|
href="/leistungen#kontakt"
|
||||||
onClick={() => setMobileMenuOpen(false)}
|
onClick={() => setMobileMenuOpen(false)}
|
||||||
className="mt-2 bg-primary text-secondary px-5 py-3 text-center text-sm font-medium transition-opacity hover:opacity-80"
|
variant="primary"
|
||||||
|
className="w-full justify-center"
|
||||||
>
|
>
|
||||||
Jetzt Termin buchen
|
Jetzt Termin buchen
|
||||||
</Link>
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</motion.nav>
|
</motion.nav>
|
||||||
)}
|
)}
|
||||||
|
|||||||
22
components/layout/Section.tsx
Normal file
22
components/layout/Section.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
interface SectionProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
className?: string;
|
||||||
|
id?: string;
|
||||||
|
as?: "section" | "div";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Section({
|
||||||
|
children,
|
||||||
|
className = "",
|
||||||
|
id,
|
||||||
|
as: Component = "section",
|
||||||
|
}: SectionProps) {
|
||||||
|
return (
|
||||||
|
<Component
|
||||||
|
id={id}
|
||||||
|
className={`py-[var(--spacing-section)] relative ${className}`}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Component>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { JSX } from "react";
|
||||||
|
|
||||||
interface ButtonProps {
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||||
children: React.ReactNode;
|
|
||||||
href?: string;
|
href?: string;
|
||||||
variant?: "primary" | "secondary" | "ghost";
|
variant?: "primary" | "secondary" | "ghost" | "outline-white" | "ghost-white";
|
||||||
className?: string;
|
className?: string;
|
||||||
type?: "button" | "submit" | "reset";
|
|
||||||
onClick?: () => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Button({
|
export function Button({
|
||||||
@@ -15,30 +13,32 @@ export function Button({
|
|||||||
variant = "primary",
|
variant = "primary",
|
||||||
className = "",
|
className = "",
|
||||||
type = "button",
|
type = "button",
|
||||||
onClick,
|
...props
|
||||||
}: ButtonProps) {
|
}: ButtonProps) {
|
||||||
const base =
|
const base =
|
||||||
"inline-flex items-center justify-center px-6 py-3 text-sm font-medium transition-all duration-200 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary";
|
"inline-flex items-center justify-center px-6 py-3 text-sm font-medium transition-all duration-200 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:opacity-50 disabled:pointer-events-none cursor-pointer";
|
||||||
|
|
||||||
const variants = {
|
const variants = {
|
||||||
primary: "bg-primary text-secondary hover:opacity-80",
|
primary: "bg-primary text-secondary hover:opacity-90 border border-transparent",
|
||||||
secondary:
|
secondary: "bg-transparent border border-primary text-primary hover:bg-primary hover:text-secondary",
|
||||||
"border border-primary text-primary hover:bg-primary hover:text-secondary",
|
ghost: "text-primary hover:bg-neutral/50",
|
||||||
ghost: "text-primary underline-offset-4 hover:underline",
|
"outline-white": "border border-secondary text-secondary hover:bg-secondary hover:text-primary",
|
||||||
|
"ghost-white": "text-secondary hover:bg-secondary/10",
|
||||||
};
|
};
|
||||||
|
|
||||||
const classes = `${base} ${variants[variant]} ${className}`;
|
const selectedVariant = variants[variant] || variants.primary;
|
||||||
|
const combinedClasses = `${base} ${selectedVariant} ${className}`;
|
||||||
|
|
||||||
if (href) {
|
if (href) {
|
||||||
return (
|
return (
|
||||||
<Link href={href} className={classes}>
|
<Link href={href} className={combinedClasses}>
|
||||||
{children}
|
{children}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button type={type} className={classes} onClick={onClick}>
|
<button type={type} className={combinedClasses} {...props}>
|
||||||
{children}
|
{children}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ export function Container({
|
|||||||
}: ContainerProps) {
|
}: ContainerProps) {
|
||||||
return (
|
return (
|
||||||
<Component
|
<Component
|
||||||
className={`mx-auto px-[var(--spacing-container-padding)] ${className}`}
|
className={`mx-auto w-full max-w-[var(--spacing-container)] px-[var(--spacing-container-padding)] ${className}`}
|
||||||
style={{ maxWidth: "var(--spacing-container)" }}
|
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Component>
|
</Component>
|
||||||
|
|||||||
@@ -10,52 +10,59 @@
|
|||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
/* Colors */
|
/* Colors */
|
||||||
--color-primary: #000000;
|
--color-primary: var(--color-primary);
|
||||||
--color-secondary: #FFFFFF;
|
--color-secondary: var(--color-secondary);
|
||||||
--color-accent: #d6d6d6;
|
--color-accent: var(--color-accent);
|
||||||
--color-neutral: #F5F5F5;
|
--color-neutral: var(--color-neutral);
|
||||||
--color-background: #FFFFFF;
|
--color-background: var(--color-background);
|
||||||
--color-foreground: #000000;
|
--color-foreground: var(--color-foreground);
|
||||||
--color-muted: #B0B0B0;
|
--color-muted: var(--color-muted);
|
||||||
--color-muted-foreground: #ffffff;
|
--color-muted-foreground: var(--color-muted-foreground);
|
||||||
--color-border: #E0E0E0;
|
--color-border: var(--color-border);
|
||||||
--color-success: #4CAF50;
|
--color-success: var(--color-success);
|
||||||
--color-warning: #FF9800;
|
--color-warning: var(--color-warning);
|
||||||
--color-error: #F44336;
|
--color-error: var(--color-error);
|
||||||
|
|
||||||
/* Fonts */
|
/* Fonts */
|
||||||
--font-heading: 'Inter', sans-serif;
|
--font-heading: var(--font-heading);
|
||||||
--font-body: 'Inter', sans-serif;
|
--font-body: var(--font-body);
|
||||||
|
|
||||||
/* Typography Scale – override Tailwind defaults to match design tokens */
|
/* Typography Scale */
|
||||||
--text-xl: 1.5rem;
|
--text-xs: var(--text-xs);
|
||||||
--text-xl--line-height: 2rem;
|
--text-xs--line-height: var(--text-xs-line-height);
|
||||||
--text-2xl: 1.75rem;
|
--text-sm: var(--text-sm);
|
||||||
--text-2xl--line-height: 2.25rem;
|
--text-sm--line-height: var(--text-sm-line-height);
|
||||||
--text-3xl: 2rem;
|
--text-base: var(--text-base);
|
||||||
--text-3xl--line-height: 2.5rem;
|
--text-base--line-height: var(--text-base-line-height);
|
||||||
--text-4xl: 2.5rem;
|
--text-lg: var(--text-lg);
|
||||||
--text-4xl--line-height: 2.75rem;
|
--text-lg--line-height: var(--text-lg-line-height);
|
||||||
--text-5xl: 3rem;
|
--text-xl: var(--text-xl);
|
||||||
--text-5xl--line-height: 1.1;
|
--text-xl--line-height: var(--text-xl-line-height);
|
||||||
--text-6xl: 3.75rem;
|
--text-2xl: var(--text-2xl);
|
||||||
--text-6xl--line-height: 1.1;
|
--text-2xl--line-height: var(--text-2xl-line-height);
|
||||||
|
--text-3xl: var(--text-3xl);
|
||||||
|
--text-3xl--line-height: var(--text-3xl-line-height);
|
||||||
|
--text-4xl: var(--text-4xl);
|
||||||
|
--text-4xl--line-height: var(--text-4xl-line-height);
|
||||||
|
--text-5xl: var(--text-5xl);
|
||||||
|
--text-5xl--line-height: var(--text-5xl-line-height);
|
||||||
|
--text-6xl: var(--text-6xl);
|
||||||
|
--text-6xl--line-height: var(--text-6xl-line-height);
|
||||||
|
|
||||||
|
/* Spacing */
|
||||||
|
--spacing-container: var(--spacing-container);
|
||||||
|
--spacing-container-padding: var(--spacing-container-padding);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Font Override (connect next/font to CSS vars) ──── */
|
/* ── Base Layer ────────────────────────────────────── */
|
||||||
/* --font-inter is injected by next/font/google on <html> */
|
|
||||||
|
|
||||||
html {
|
@layer base {
|
||||||
--font-heading: var(--font-inter, 'Inter', sans-serif);
|
|
||||||
--font-body: var(--font-inter, 'Inter', sans-serif);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Base Resets ───────────────────────────────────── */
|
*,
|
||||||
|
*::before,
|
||||||
*, *::before, *::after {
|
*::after {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin: 0;
|
border-color: var(--color-border);
|
||||||
padding: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
@@ -73,27 +80,68 @@ body {
|
|||||||
font-size: var(--text-base);
|
font-size: var(--text-base);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Headings ─────────────────────────────────────── */
|
h1,
|
||||||
|
h2,
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
font-family: var(--font-heading);
|
font-family: var(--font-heading);
|
||||||
font-weight: var(--font-heading-weight);
|
font-weight: var(--font-heading-weight);
|
||||||
|
color: var(--color-primary);
|
||||||
|
line-height: 1.2;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
/* reasonable default */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Links ───────────────────────────────────────── */
|
h1 {
|
||||||
|
font-size: var(--text-4xl);
|
||||||
|
letter-spacing: -0.025em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: var(--text-3xl);
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: var(--text-2xl);
|
||||||
|
letter-spacing: -0.015em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: var(--text-xl);
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-size: var(--text-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
font-size: var(--text-base);
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
max-width: 65ch;
|
||||||
|
/* readability */
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
transition: opacity 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Images ──────────────────────────────────────── */
|
img,
|
||||||
|
video,
|
||||||
img, video, svg {
|
svg {
|
||||||
display: block;
|
display: block;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Focus ───────────────────────────────────────── */
|
/* ── Focus ───────────────────────────────────────── */
|
||||||
|
|
||||||
@@ -108,15 +156,3 @@ img, video, svg {
|
|||||||
background-color: var(--color-primary);
|
background-color: var(--color-primary);
|
||||||
color: var(--color-background);
|
color: var(--color-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Reduced Motion ─────────────────────────────── */
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
|
||||||
*,
|
|
||||||
*::before,
|
|
||||||
*::after {
|
|
||||||
animation-duration: 0.01ms !important;
|
|
||||||
transition-duration: 0.01ms !important;
|
|
||||||
scroll-behavior: auto !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user