first commit

This commit is contained in:
2026-09-29 10:27:27 -04:00
commit a863b400fb
92 changed files with 23514 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
import React from 'react';
import { Route, Routes, BrowserRouter as Router } from 'react-router-dom';
import ScrollToTop from './components/ScrollToTop.jsx';
import HomePage from './pages/HomePage.jsx';
import PrivacyPage from './pages/PrivacyPage.jsx';
import TermsPage from './pages/TermsPage.jsx';
function App() {
return (
<Router>
<ScrollToTop />
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/privacy" element={<PrivacyPage />} />
<Route path="/terms" element={<TermsPage />} />
</Routes>
</Router>
);
}
export default App;
+21
View File
@@ -0,0 +1,21 @@
import { useLocation } from 'react-router-dom';
import { useLayoutEffect } from 'react';
const ScrollToTop = () => {
const { pathname, hash } = useLocation();
useLayoutEffect(() => {
if (hash) {
const target = document.getElementById(decodeURIComponent(hash.slice(1)));
if (target) {
target.scrollIntoView({ behavior: 'instant' });
return;
}
}
window.scrollTo({ top: 0, left: 0, behavior: 'instant' });
}, [pathname, hash]);
return null;
}
export default ScrollToTop;
+121
View File
@@ -0,0 +1,121 @@
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;500;600;700;800&family=DM+Sans:wght@400;500;600;700&display=swap');
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 98%;
--foreground: 220 20% 15%;
--primary: 220 30% 20%;
--primary-foreground: 0 0% 98%;
--secondary: 45 85% 55%;
--secondary-foreground: 220 20% 15%;
--muted: 220 15% 92%;
--muted-foreground: 220 10% 40%;
--accent: 45 85% 55%;
--accent-foreground: 220 20% 15%;
--card: 0 0% 100%;
--card-foreground: 220 20% 15%;
--popover: 0 0% 100%;
--popover-foreground: 220 20% 15%;
--border: 220 15% 85%;
--input: 220 15% 85%;
--ring: 45 85% 55%;
--radius: 0.5rem;
--destructive: 0 84% 60%;
--destructive-foreground: 0 0% 98%;
--sidebar-background: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
.dark {
--background: 220 25% 10%;
--foreground: 0 0% 95%;
--primary: 220 30% 25%;
--primary-foreground: 0 0% 98%;
--secondary: 45 85% 55%;
--secondary-foreground: 220 20% 15%;
--muted: 220 15% 18%;
--muted-foreground: 220 10% 65%;
--accent: 45 85% 55%;
--accent-foreground: 220 20% 15%;
--card: 220 20% 15%;
--card-foreground: 0 0% 95%;
--popover: 220 20% 15%;
--popover-foreground: 0 0% 95%;
--border: 220 15% 25%;
--input: 220 15% 25%;
--ring: 45 85% 55%;
--destructive: 0 84% 60%;
--destructive-foreground: 0 0% 98%;
--sidebar-background: 240 5.9% 10%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 224.3 76.3% 48%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
* {
border-color: hsl(var(--border));
}
html {
scroll-behavior: smooth;
}
body {
font-family: "DM Sans", sans-serif;
background-color: hsl(var(--background));
color: hsl(var(--foreground));
overflow-x: clip;
line-height: 1.625;
font-variant-numeric: tabular-nums;
}
h1, h2, h3, h4, h5, h6 {
font-family: "Playfair Display", serif;
text-wrap: balance;
line-height: 1.2;
letter-spacing: -0.02em;
}
h1 {
font-size: clamp(2.5rem, 5vw, 4.5rem);
font-weight: 700;
}
h2 {
font-size: clamp(2rem, 4vw, 3rem);
font-weight: 600;
}
h3 {
font-size: clamp(1.5rem, 3vw, 2rem);
font-weight: 600;
}
p {
max-width: 65ch;
}
}
@layer utilities {
.transition-smooth {
transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1);
}
.transition-fast {
transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
}
+8
View File
@@ -0,0 +1,8 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from '@/App';
import '@/index.css';
ReactDOM.createRoot(document.getElementById('root')).render(
<App />
);
+113
View File
@@ -0,0 +1,113 @@
import React from 'react';
import { Helmet } from 'react-helmet';
import { motion, useReducedMotion } from 'framer-motion';
import { ArrowRight, ArrowUpRight } from 'lucide-react';
import { Link } from 'react-router-dom';
const principles = [
{ number: '01', title: 'Precision', description: 'Give your work the attention and intention it deserves.' },
{ number: '02', title: 'Dedication', description: 'Make progress through consistent, purposeful practice.' },
{ number: '03', title: 'Guidance', description: 'Find a clearer path forward with an expert perspective.' },
];
const HomePage = () => {
const reducedMotion = useReducedMotion();
const enter = reducedMotion ? undefined : { opacity: 0, y: 30 };
const settle = { opacity: 1, y: 0 };
return (
<>
<Helmet>
<title>Mazzei Mastery - Master Your Craft</title>
<meta name="description" content="Mazzei Mastery provides expert guidance and resources to help you master your craft with precision and excellence." />
</Helmet>
<div className="min-h-screen flex flex-col">
<main>
<section id="home" className="relative min-h-[100dvh] flex items-center justify-center overflow-hidden py-28 pb-32">
<div className="absolute inset-0 z-0" aria-hidden="true">
<img
src="https://images.unsplash.com/photo-1699424031801-a51372e0975c?w=1920&q=80&auto=format"
alt=""
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-b from-black/70 via-black/60 to-black/80" />
</div>
<div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<motion.div initial={enter} animate={settle} transition={{ duration: 0.8, ease: 'easeOut' }}>
<h1 className="text-white mb-6 font-bold">Mazzei Mastery</h1>
</motion.div>
<motion.p
initial={enter}
animate={settle}
transition={{ duration: 0.8, delay: reducedMotion ? 0 : 0.2, ease: 'easeOut' }}
className="text-xl md:text-2xl lg:text-3xl text-white/90 mb-12 mx-auto max-w-3xl font-light leading-relaxed"
>
Master your craft with precision, dedication, and expert guidance
</motion.p>
<motion.div initial={enter} animate={settle} transition={{ duration: 0.8, delay: reducedMotion ? 0 : 0.4, ease: 'easeOut' }}>
<a
href="#approach"
className="group relative inline-flex min-h-12 items-center justify-center gap-3 bg-[hsl(45,85%,55%)] text-[hsl(220,20%,15%)] px-8 py-4 rounded-xl text-lg font-semibold transition-all duration-300 hover:bg-[hsl(45,85%,60%)] hover:shadow-2xl hover:shadow-[hsl(45,85%,55%)]/30 hover:scale-105 active:scale-[0.98] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(45,85%,55%)] focus-visible:ring-offset-2 focus-visible:ring-offset-black"
>
<span>Begin your journey</span>
<ArrowRight aria-hidden="true" className="w-5 h-5 transition-transform duration-300 group-hover:translate-x-1" />
</a>
</motion.div>
</div>
<a href="#approach" aria-label="Explore the approach" className="absolute bottom-7 left-1/2 -translate-x-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white">
<span className="w-6 h-10 border-2 border-white/40 rounded-full flex items-start justify-center p-2" aria-hidden="true">
<motion.span animate={reducedMotion ? undefined : { y: [0, 12, 0] }} transition={reducedMotion ? undefined : { duration: 1.5, repeat: Infinity, ease: 'easeInOut' }} className="w-1.5 h-1.5 bg-white/70 rounded-full" />
</span>
</a>
</section>
<section id="approach" aria-labelledby="approach-heading" className="bg-[hsl(220,30%,20%)] text-white py-20 sm:py-28">
<div className="max-w-5xl mx-auto px-5 sm:px-8">
<div className="flex items-center gap-5 text-[hsl(45,85%,55%)] text-xs font-semibold uppercase tracking-[0.2em] mb-7">
<span>The approach</span><span className="h-px flex-1 bg-white/20" />
</div>
<h2 id="approach-heading" className="max-w-3xl text-3xl sm:text-4xl md:text-5xl font-semibold leading-tight mb-12">Mastery is built with intention.</h2>
<div className="border-t border-white/20">
{principles.map(({ number, title, description }) => (
<div key={number} className="grid gap-2 sm:gap-6 sm:grid-cols-[3rem_1fr_1.2fr] items-baseline py-6 sm:py-8 border-b border-white/20">
<span className="text-[hsl(45,85%,55%)] text-sm tabular-nums">{number}</span>
<h3 className="text-2xl sm:text-3xl">{title}</h3>
<p className="text-white/70 text-base sm:text-lg">{description}</p>
</div>
))}
</div>
<a href="#home" className="mt-10 inline-flex min-h-11 items-center gap-2 text-sm text-[hsl(45,85%,55%)] hover:text-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white rounded-sm">
Back to top <ArrowUpRight className="w-4 h-4" aria-hidden="true" />
</a>
</div>
</section>
</main>
<footer className="relative z-10 bg-[hsl(220,30%,20%)] text-white py-12 border-t border-white/10">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex flex-col md:flex-row items-center justify-between gap-6">
<div className="text-center md:text-left">
<span className="text-2xl font-bold font-['Playfair_Display']">Mazzei Mastery</span>
<p className="text-white/70 mt-2 text-sm">Master your craft with excellence</p>
</div>
<nav aria-label="Footer navigation" className="flex flex-col sm:flex-row items-center gap-3 sm:gap-6 text-sm">
<Link to="/privacy" className="inline-flex min-h-11 items-center text-white/70 hover:text-white transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white rounded-sm">Privacy Policy</Link>
<Link to="/terms" className="inline-flex min-h-11 items-center text-white/70 hover:text-white transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white rounded-sm">Terms of Service</Link>
</nav>
</div>
<div className="mt-8 pt-8 border-t border-white/10 text-center">
<p className="text-white/60 text-sm mx-auto">© {new Date().getFullYear()} Mazzei Mastery. All rights reserved.</p>
</div>
</div>
</footer>
</div>
</>
);
};
export default HomePage;
+27
View File
@@ -0,0 +1,27 @@
import React from 'react';
import { Helmet } from 'react-helmet';
import { Link } from 'react-router-dom';
import { ArrowLeft } from 'lucide-react';
const PrivacyPage = () => (
<>
<Helmet>
<title>Privacy Policy | Mazzei Mastery</title>
<meta name="description" content="Privacy information for the Mazzei Mastery website." />
</Helmet>
<main className="min-h-[100dvh] bg-[hsl(220,30%,20%)] text-white px-5 py-12 sm:py-20">
<div className="max-w-2xl mx-auto">
<Link to="/" className="inline-flex min-h-11 items-center gap-2 text-[hsl(45,85%,55%)] hover:text-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white rounded-sm"><ArrowLeft className="w-4 h-4" aria-hidden="true" /> Back to home</Link>
<p className="mt-14 mb-4 text-xs font-semibold uppercase tracking-[0.2em] text-[hsl(45,85%,55%)]">Mazzei Mastery</p>
<h1 className="text-white mb-8">Privacy Policy</h1>
<div className="space-y-7 text-white/75 leading-relaxed">
<p>This website is currently an informational landing page. It does not offer accounts, contact forms, or checkout, and it does not ask you to submit personal information through the page.</p>
<p>Like other websites, the hosting service may process technical information needed to deliver the site, such as your IP address and browser request data. Your browser may also request the fonts and background image shown on this page from their respective providers.</p>
<p>If the site adds features that collect personal information in the future, this notice should be updated to explain those features before they are used.</p>
</div>
</div>
</main>
</>
);
export default PrivacyPage;
+27
View File
@@ -0,0 +1,27 @@
import React from 'react';
import { Helmet } from 'react-helmet';
import { Link } from 'react-router-dom';
import { ArrowLeft } from 'lucide-react';
const TermsPage = () => (
<>
<Helmet>
<title>Terms of Service | Mazzei Mastery</title>
<meta name="description" content="Terms of use for the Mazzei Mastery website." />
</Helmet>
<main className="min-h-[100dvh] bg-[hsl(220,30%,20%)] text-white px-5 py-12 sm:py-20">
<div className="max-w-2xl mx-auto">
<Link to="/" className="inline-flex min-h-11 items-center gap-2 text-[hsl(45,85%,55%)] hover:text-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white rounded-sm"><ArrowLeft className="w-4 h-4" aria-hidden="true" /> Back to home</Link>
<p className="mt-14 mb-4 text-xs font-semibold uppercase tracking-[0.2em] text-[hsl(45,85%,55%)]">Mazzei Mastery</p>
<h1 className="text-white mb-8">Terms of Service</h1>
<div className="space-y-7 text-white/75 leading-relaxed">
<p>This website provides general information about Mazzei Mastery. Browsing the site does not create a client relationship or a commitment to provide services.</p>
<p>The content is provided for informational purposes. Please do not reproduce or redistribute the site’s content without permission.</p>
<p>The site and its content may change over time. Any future services, purchases, or accounts may have additional terms that will be provided when those features become available.</p>
</div>
</div>
</main>
</>
);
export default TermsPage;