Files
website-ai-generator/pages/seed-bddff9a04d14a587.html
T

1215 lines
53 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Artisan Roast Co. — Crafted in Small Batches</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,500;0,600;0,700;1,400&family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: {
display: ['Playfair Display', 'serif'],
body: ['Inter', 'sans-serif'],
},
colors: {
coffee: {
50: '#fdf8f0',
100: '#f5ebe0',
200: '#e8d5b8',
300: '#d4b896',
400: '#c49a6c',
500: '#b07a4a',
600: '#9a6335',
700: '#7d4e26',
800: '#5e3a1a',
900: '#3d2310',
950: '#1a100a',
},
bark: {
50: '#f0e6dc',
100: '#dcc7a8',
200: '#c4a57a',
300: '#a88558',
400: '#8e6d42',
500: '#735830',
600: '#5a4423',
700: '#3e2e17',
800: '#251b0e',
900: '#0f0b06',
},
terra: {
50: '#fdf5f0',
100: '#f5e1d0',
200: '#e8c4a8',
300: '#d4a67a',
400: '#c08a52',
500: '#a87238',
600: '#8b5a28',
700: '#6e4420',
800: '#4e3117',
900: '#311e0f',
950: '#1a0d06',
},
}
}
}
}
</script>
<style>
:root {
--bg: #fdf8f0;
--fg: #2a1a0a;
--muted: #8a7565;
--accent: #a87238;
--card: #fff;
--border: #e8d5b8;
--gold: #c9a96e;
}
* { box-sizing: border-box; }
html {
scroll-behavior: smooth;
overflow-x: hidden;
}
body {
font-family: 'Inter', sans-serif;
background: var(--bg);
color: var(--fg);
overflow-x: hidden;
}
/* Subtle noise overlay */
.noise-overlay::before {
content: '';
position: fixed;
inset: 0;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
opacity: 0.015;
pointer-events: none;
z-index: 9999;
}
/* Hero background blobs */
.hero-blob {
position: absolute;
border-radius: 50%;
filter: blur(80px);
opacity: 0.4;
animation: drift 12s ease-in-out infinite;
will-change: transform;
}
@keyframes drift {
0%, 100% { transform: translate(0, 0) scale(1); }
33% { transform: translate(30px, -20px) scale(1.05); }
66% { transform: translate(-20px, 15px) scale(0.95); }
}
/* Roast glow pulse */
.roast-glow {
position: absolute;
width: 400px;
height: 400px;
border-radius: 50%;
background: radial-gradient(circle, rgba(168,114,56,0.08) 0%, transparent 70%);
filter: blur(60px);
animation: glowPulse 4s ease-in-out infinite;
will-change: transform, opacity;
}
@keyframes glowPulse {
0%, 100% { transform: scale(1); opacity: 0.6; }
50% { transform: scale(1.15); opacity: 1; }
}
/* Floating particles */
.particle {
position: absolute;
border-radius: 50%;
pointer-events: none;
opacity: 0;
will-change: transform, opacity;
}
.particle.active {
animation: floatUp 8s ease-in-out infinite;
}
@keyframes floatUp {
0% { opacity: 0; transform: translateY(0) scale(0); }
20% { opacity: 0.6; transform: translateY(-40px) scale(1); }
80% { opacity: 0.3; transform: translateY(-120px) scale(0.5); }
100% { opacity: 0; transform: translateY(-160px) scale(0); }
}
/* Scroll reveal */
.reveal {
opacity: 0;
transform: translateY(40px);
transition: opacity 0.8s ease, transform 0.8s ease;
}
.reveal.visible {
opacity: 1;
transform: translateY(0);
}
/* Nav active indicator */
.nav-link {
position: relative;
transition: color 0.3s ease;
}
.nav-link::after {
content: '';
position: absolute;
bottom: -4px;
left: 50%;
width: 0;
height: 2px;
background: var(--accent);
transition: width 0.3s ease, left 0.3s ease;
border-radius: 2px;
}
.nav-link:hover::after {
width: 100%;
left: 0;
}
.nav-link:hover {
color: var(--accent);
}
/* Toast notification */
.toast {
position: fixed;
bottom: 2rem;
right: 2rem;
background: var(--card);
border: 1px solid var(--border);
border-radius: 12px;
padding: 1rem 1.5rem;
box-shadow: 0 8px 30px rgba(0,0,0,0.1);
transform: translateY(120%);
opacity: 0;
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.4s ease;
z-index: 1000;
display: flex;
align-items: center;
gap: 0.75rem;
}
.toast.show {
transform: translateY(0);
opacity: 1;
}
/* Image hover */
.img-hover {
overflow: hidden;
border-radius: 0.75rem;
transition: transform 0.5s ease;
}
.img-hover:hover {
transform: scale(1.04);
}
.img-hover img {
transition: transform 0.6s ease;
}
.img-hover:hover img {
transform: scale(1.08);
}
/* Button hover */
.btn-primary {
background: var(--accent);
color: #fff;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.btn-primary::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.15), transparent);
transition: left 0.5s ease;
}
.btn-primary:hover::before {
left: 100%;
}
.btn-primary:hover {
background: #8b5a28;
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(168,114,56,0.3);
}
.btn-outline {
border: 1.5px solid var(--accent);
color: var(--accent);
transition: all 0.3s ease;
}
.btn-outline:hover {
background: var(--accent);
color: #fff;
transform: translateY(-2px);
}
/* Roast progress bar */
.roast-bar {
height: 6px;
border-radius: 3px;
background: #e8d5b8;
overflow: hidden;
}
.roast-bar-fill {
height: 100%;
border-radius: 3px;
background: linear-gradient(90deg, #c9a96e, #a87238, #735830);
transition: width 1.5s ease;
}
/* Tasting note tag */
.note-tag {
display: inline-flex;
align-items: center;
gap: 0.35rem;
padding: 0.35rem 0.85rem;
border-radius: 100px;
font-size: 0.8rem;
font-weight: 500;
border: 1px solid var(--border);
background: #fdf8f0;
color: var(--muted);
transition: all 0.3s ease;
}
.note-tag:hover {
border-color: var(--accent);
color: var(--accent);
background: rgba(168,114,56,0.04);
}
/* Section divider */
.section-divider {
width: 60px;
height: 2px;
background: linear-gradient(90deg, transparent, var(--accent), transparent);
}
/* Carousel */
.carousel-track {
display: flex;
transition: transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.carousel-slide {
min-width: 100%;
flex-shrink: 0;
border-radius: 1.5rem;
overflow: hidden;
position: relative;
}
.carousel-slide img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* Cart button animation */
.cart-btn {
transition: transform 0.2s ease;
}
.cart-btn:hover {
transform: scale(1.15);
}
.cart-btn:active {
transform: scale(0.95);
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
.reveal {
opacity: 1;
transform: none;
}
}
/* Focus visible for accessibility */
:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
border-radius: 4px;
}
/* Mobile nav */
.mobile-menu {
transform: translateX(100%);
transition: transform 0.3s ease;
}
.mobile-menu.open {
transform: translateX(0);
}
/* Typography line-height readability */
p, li { line-height: 1.75; }
/* Selection highlight */
::selection {
background: var(--accent);
color: #fff;
}
/* Horizontal scroll for hero image */
.scroll-hint {
animation: bounceDown 1.5s ease infinite;
}
@keyframes bounceDown {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(6px); }
}
/* Loading shimmer */
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
.shimmer {
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent);
background-size: 200% 100%;
animation: shimmer 1.5s linear infinite;
}
/* Image overlay for text readability */
.img-overlay {
position: absolute;
inset: 0;
background: linear-gradient(to top, rgba(138,117,101,0.3) 0%, transparent 60%);
}
</style>
</head>
<body class="noise-overlay">
<!-- Toast Notification -->
<div id="toast" class="toast" role="alert" aria-live="polite">
<i class="fa-solid fa-check-circle text-terra-500 text-lg"></i>
<span id="toast-msg" class="text-sm font-medium text-bark-700">Added to cart</span>
</div>
<!-- Navigation -->
<nav id="navbar" class="fixed top-0 left-0 right-0 z-50 transition-all duration-500" role="navigation" aria-label="Main navigation">
<div class="max-w-7xl mx-auto px-6 py-4 flex items-center justify-between">
<a href="#" class="flex items-center gap-2.5 group" aria-label="Artisan Roast Co. Home">
<div class="w-9 h-9 rounded-full bg-terra-500 flex items-center justify-center transition-transform group-hover:scale-110 group-hover:bg-terra-600">
<i class="fa-solid fa-mug-hot text-white text-sm"></i>
</div>
<span class="font-display font-semibold text-lg text-bark-800">Artisan Roast</span>
</a>
<div class="hidden md:flex items-center gap-8">
<a href="#roasts" class="nav-link text-sm font-medium text-bark-600">Roasts</a>
<a href="#process" class="nav-link text-sm font-medium text-bark-600">Process</a>
<a href="#tastings" class="nav-link text-sm font-medium text-bark-600">Tastings</a>
<a href="#about" class="nav-link text-sm font-medium text-bark-600">About</a>
<a href="#contact" class="btn-primary px-5 py-2.5 rounded-full text-sm font-semibold text-white">Order Now</a>
</div>
<button id="menu-toggle" class="md:hidden w-10 h-10 flex items-center justify-center rounded-lg hover:bg-bark-50 transition-colors" aria-label="Toggle menu" aria-expanded="false">
<i class="fa-solid fa-bars text-bark-700 text-lg"></i>
</button>
</div>
<!-- Mobile Menu -->
<div id="mobile-menu" class="mobile-menu fixed inset-0 bg-bark-50/95 backdrop-blur-lg z-40 flex flex-col items-center justify-center gap-8">
<button id="menu-close" class="absolute top-5 right-5 w-10 h-10 flex items-center justify-center rounded-lg hover:bg-bark-100" aria-label="Close menu">
<i class="fa-solid fa-xmark text-bark-700 text-xl"></i>
</button>
<a href="#roasts" class="font-display text-2xl text-bark-800 hover:text-terra-500 transition-colors">Roasts</a>
<a href="#process" class="font-display text-2xl text-bark-800 hover:text-terra-500 transition-colors">Process</a>
<a href="#tastings" class="font-display text-2xl text-bark-800 hover:text-terra-500 transition-colors">Tastings</a>
<a href="#about" class="font-display text-2xl text-bark-800 hover:text-terra-500 transition-colors">About</a>
<a href="#contact" class="btn-primary px-8 py-3.5 rounded-full text-base font-semibold text-white mt-4">Order Now</a>
</div>
</nav>
<!-- Hero Section -->
<header class="relative min-h-screen flex items-center overflow-hidden" id="hero">
<!-- Background elements -->
<div class="absolute inset-0">
<!-- Hero image with gradient overlay -->
<img src="https://images.pexels.com/photos/276709/pexels-photo-276709.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
alt="Artisan coffee beans being roasted in a small batch"
class="w-full h-full object-cover"
id="hero-img">
<!-- Overlay gradient for text readability -->
<div class="absolute inset-0 bg-gradient-to-br from-bark-50/40 via-transparent to-bark-50/20"></div>
<!-- Glow blobs -->
<div class="hero-blob" style="width:500px;height:500px;background:#c9a96e;top:-100px;right:-100px;animation-delay:-2s;"></div>
<div class="hero-blob" style="width:350px;height:350px;background:#a87238;bottom:50px;left:-50px;animation-delay:-5s;"></div>
<!-- Floating particles -->
<div id="particles" class="absolute inset-0 pointer-events-none"></div>
</div>
<!-- Hero content -->
<div class="relative z-10 max-w-7xl mx-auto px-6 pt-20 pb-10 w-full">
<div class="grid lg:grid-cols-2 gap-12 lg:gap-16 items-center">
<!-- Left: Text -->
<div>
<div class="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-terra-50 border border-terra-200 mb-6">
<span class="w-2 h-2 rounded-full bg-terra-500 animate-pulse"></span>
<span class="text-terra-600 text-sm font-medium">Small Batch, Big Soul</span>
</div>
<h1 class="font-display text-5xl md:text-6xl lg:text-7xl font-bold text-bark-900 leading-[1.05] mb-6">
Every Cup<br>
<span class="text-terra-500">Tells a Story</span>
</h1>
<p class="text-bark-500 text-lg leading-relaxed mb-8 max-w-lg">
We roast 200 pounds of specialty beans per week, hand-picked from high-altitude farms. Each roast is a deliberate art — crafted to highlight the unique character of each origin.
</p>
<div class="flex flex-wrap gap-4">
<a href="#roasts" class="btn-primary px-8 py-3.5 rounded-full text-base font-semibold text-white inline-flex items-center gap-2">
Explore the collection <i class="fa-solid fa-arrow-right text-sm"></i>
</a>
<a href="#process" class="btn-outline px-8 py-3.5 rounded-full text-base font-semibold inline-flex items-center gap-2">
<i class="fa-solid fa-play text-xs"></i> Meet the roasters
</a>
</div>
<div class="flex gap-6 mt-6">
<div class="flex items-center gap-2">
<i class="fa-solid fa-star text-terra-500"></i>
<span class="text-sm font-medium text-bark-700">4.9 / 5.0</span>
</div>
<div class="flex items-center gap-2">
<i class="fa-solid fa-clock text-bark-300"></i>
<span class="text-sm font-medium text-bark-700">Same Day Roast</span>
</div>
<div class="flex items-center gap-2">
<i class="fa-solid fa-truck text-bark-300"></i>
<span class="text-sm font-medium text-bark-700">Free Shipping</span>
</div>
</div>
</div>
<!-- Right: Hero image -->
<div class="relative hidden lg:block">
<div class="relative">
<div class="img-hover rounded-2xl shadow-2xl shadow-bark-200/30">
<img src="https://images.pexels.com/photos/162435/pexels-photo-162435.jpeg?auto=compress&cs=tinysrgb&w=800&h=600&dpr=2"
alt="Premium artisan coffee beans on a marble slab"
class="w-full h-[560px] object-cover rounded-2xl"
loading="eager">
</div>
<!-- Floating badge -->
<div class="absolute -bottom-4 -left-4 bg-white/90 backdrop-blur-sm rounded-xl px-4 py-3 shadow-lg flex items-center gap-3">
<div class="w-10 h-10 rounded-full bg-terra-50 flex items-center justify-center">
<i class="fa-solid fa-tag text-terra-500"></i>
</div>
<div>
<div class="text-sm font-semibold text-bark-800">Single Origin</div>
<div class="text-xs text-bark-400">Ethiopian Yirgacheffe</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Scroll indicator -->
<div class="absolute bottom-8 left-1/2 -translate-x-1/2 scroll-hint">
<a href="#roasts" class="text-bark-400 hover:text-terra-500 transition-colors">
<i class="fa-solid fa-chevron-down text-sm"></i>
</a>
</div>
</header>
<!-- Roasts Section -->
<section id="roasts" class="relative py-24 bg-white">
<div class="max-w-7xl mx-auto px-6">
<div class="reveal text-center mb-16">
<span class="text-terra-500 text-sm font-semibold uppercase tracking-widest">The Collection</span>
<div class="section-divider mt-3 mx-auto"></div>
<h2 class="font-display text-4xl md:text-5xl font-bold text-bark-900 mt-3">Curated by Hand</h2>
<p class="text-bark-500 text-lg mt-4 max-w-2xl mx-auto">Every roast is a single-origin story. We test each blend three times before we release it to the world.</p>
</div>
<div class="grid md:grid-cols-3 gap-8">
<!-- Coffee #1 -->
<div class="reveal group bg-white border border-bark-100 rounded-2xl overflow-hidden hover:shadow-xl hover:shadow-bark-100/40 transition-all duration-500">
<div class="img-hover relative h-64">
<img src="https://images.pexels.com/photos/272645/pexels-photo-272645.jpeg?auto=compress&cs=tinysrgb&w=600&h=400&dpr=2"
alt="Ethiopian Yirgacheffe coffee beans"
class="w-full h-full object-cover" loading="lazy">
<div class="absolute top-4 left-4 px-3 py-1.5 rounded-full bg-terra-500 text-white text-xs font-semibold">Single Origin</div>
<div class="absolute bottom-4 right-4 px-3 py-1.5 rounded-full bg-white/90 backdrop-blur-sm text-bark-700 text-xs font-medium">Medium Roast</div>
</div>
<div class="p-6">
<h3 class="font-display text-xl font-semibold text-bark-800 mb-2">Ethiopian Yirgacheffe</h3>
<p class="text-bark-500 text-sm leading-relaxed mb-4">Bright acidity with hints of bergamot, jasmine, and a floral sweetness that lingers on the palate. The hallmark of a high-altitude Ethiopian farm.</p>
<div class="flex items-center justify-between">
<div class="flex items-center gap-2">
<i class="fa-solid fa-star text-terra-400 text-xs"></i>
<span class="text-sm font-medium text-bark-700">4.8 / 5.0</span>
</div>
<span class="text-bark-400 text-sm">$22</span>
</div>
</div>
</div>
<!-- Coffee #2 -->
<div class="reveal group bg-white border border-bark-100 rounded-2xl overflow-hidden hover:shadow-xl hover:shadow-bark-100/40 transition-all duration-500">
<div class="img-hover relative h-64">
<img src="https://images.pexels.com/photos/413953/pexels-photo-413953.jpeg?auto=compress&cs=tinysrgb&w=600&h=400&dpr=2"
alt="Panamanian Geisha coffee beans"
class="w-full h-full object-cover" loading="lazy">
<div class="absolute top-4 left-4 px-3 py-1.5 rounded-full bg-terra-500 text-white text-xs font-semibold">Single Origin</div>
<div class="absolute bottom-4 right-4 px-3 py-1.5 rounded-full bg-white/90 backdrop-blur-sm text-bark-700 text-xs font-medium">Light Roast</div>
</div>
<div class="p-6">
<h3 class="font-display text-xl font-semibold text-bark-800 mb-2">Panamanian Geisha</h3>
<p class="text-bark-500 text-sm leading-relaxed mb-4">Lavender, bergamot, and a complex bouquet of stone fruits. A legendary cupping profile that commands its price — worth every ounce of attention.</p>
<div class="flex items-center justify-between">
<div class="flex items-center gap-2">
<i class="fa-solid fa-star text-terra-400 text-xs"></i>
<span class="text-sm font-medium text-bark-700">4.9 / 5.0</span>
</div>
<span class="text-bark-400 text-sm">$38</span>
</div>
</div>
</div>
<!-- Coffee #3 -->
<div class="reveal group bg-white border border-bark-100 rounded-2xl overflow-hidden hover:shadow-xl hover:shadow-bark-100/40 transition-all duration-500">
<div class="img-hover relative h-64">
<img src="https://images.pexels.com/photos/355756/pexels-photo-355756.jpeg?auto=compress&cs=tinysrgb&w=600&h=400&dpr=2"
alt="Colombian Huila coffee beans"
class="w-full h-full object-cover" loading="lazy">
<div class="absolute top-4 left-4 px-3 py-1.5 rounded-full bg-terra-500 text-white text-xs font-semibold">Single Origin</div>
<div class="absolute bottom-4 right-4 px-3 py-1.5 rounded-full bg-white/90 backdrop-blur-sm text-bark-700 text-xs font-medium">Dark Roast</div>
</div>
<div class="p-6">
<h3 class="font-display text-xl font-semibold text-bark-800 mb-2">Colombian Huila</h3>
<p class="text-bark-500 text-sm leading-relaxed mb-4">Rich chocolate and a caramel finish. Deep, smooth, and incredibly approachable. The everyday champion that deserves a place in every home.</p>
<div class="flex items-center justify-between">
<div class="flex items-center gap-2">
<i class="fa-solid fa-star text-terra-400 text-xs"></i>
<span class="text-sm font-medium text-bark-700">4.7 / 5.0</span>
</div>
<span class="text-bark-400 text-sm">$18</span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Process Section -->
<section id="process" class="relative py-24 bg-bark-900 overflow-hidden">
<div class="absolute inset-0 opacity-10">
<div class="absolute top-0 left-0 w-64 h-64 bg-terra-500 rounded-full blur-2xl"></div>
<div class="absolute bottom-0 right-0 w-64 h-64 bg-terra-400 rounded-full blur-2xl"></div>
<div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[400px] h-[400px] border border-terra-700/30"></div>
</div>
<div class="relative z-10 max-w-7xl mx-auto px-6">
<div class="reveal text-center mb-16">
<span class="text-terra-400 text-sm font-semibold uppercase tracking-widest">Our Craft</span>
<div class="section-divider mt-3 mx-auto"></div>
<h2 class="font-display text-4xl md:text-5xl font-bold text-white mt-3">From Bean to Cup</h2>
<p class="text-bark-300 text-lg mt-4 max-w-2xl mx-auto">Every step is intentional. We roast with the same care we bring to choosing each bean.</p>
</div>
<div class="grid md:grid-cols-4 gap-8">
<div class="reveal text-center group">
<div class="w-20 h-20 mx-auto rounded-2xl bg-terra-500/10 flex items-center justify-center mb-6 transition-all group-hover:bg-terra-500/20 group-hover:scale-110">
<i class="fa-solid fa-seedling text-terra-400 text-2xl"></i>
</div>
<h4 class="font-display text-xl font-semibold text-white mb-2">Source</h4>
<p class="text-bark-400 text-sm leading-relaxed">Farm-to-roaster traceability. Every lot has a provenance, a harvest date, and a farmer we know.</p>
</div>
<div class="reveal text-center group">
<div class="w-20 h-20 mx-auto rounded-2xl bg-terra-500/10 flex items-center justify-center mb-6 transition-all group-hover:bg-terra-500/20 group-hover:scale-110">
<i class="fa-solid fa-fire text-terra-400 text-2xl"></i>
</div>
<h4 class="font-display text-xl font-semibold text-white mb-2">Roast</h4>
<p class="text-bark-400 text-sm leading-relaxed">Controlled temperature, 3-point taste tests. We aim for a "perfect bite" — not just a roast profile, but a cup you can taste again.</p>
</div>
<div class="reveal text-center group">
<div class="w-20 h-20 mx-auto rounded-2xl bg-terra-500/10 flex items-center justify-center mb-6 transition-all group-hover:bg-terra-500/20 group-hover:scale-110">
<i class="fa-solid fa-box-open text-terra-400 text-2xl"></i>
</div>
<h4 class="font-display text-xl font-semibold text-white mb-2">Pack</h4>
<p class="text-bark-400 text-sm leading-relaxed">Individually sealed, labeled, and delivered. Each bag is sealed for 2 weeks, so you always taste the day's roast.</p>
</div>
<div class="reveal text-center group">
<div class="w-20 h-20 mx-auto rounded-2xl bg-terra-500/10 flex items-center justify-center mb-6 transition-all group-hover:bg-terra-500/20 group-hover:scale-110">
<i class="fa-solid fa-heart text-terra-400 text-2xl"></i>
</div>
<h4 class="font-display text-xl font-semibold text-white mb-2">Grind</h4>
<p class="text-bark-400 text-sm leading-relaxed">Whole bean, fresh grind, just before you brew. No compromise — the moment between roast and cup is everything.</p>
</div>
</div>
</div>
</section>
<!-- Tastings Section -->
<section id="tastings" class="relative py-24 bg-white">
<div class="max-w-7xl mx-auto px-6">
<div class="reveal text-center mb-16">
<span class="text-terra-500 text-sm font-semibold uppercase tracking-widest">Experience</span>
<div class="section-divider mt-3 mx-auto"></div>
<h2 class="font-display text-4xl md:text-5xl font-bold text-bark-900 mt-3">Taste & Discover</h2>
<p class="text-bark-500 text-lg mt-4 max-w-2xl mx-auto">Join a tasting session. Learn how to identify flavor notes, roast levels, and the story behind every cup.</p>
</div>
<!-- Tasting carousel -->
<div class="reveal">
<div class="relative max-w-4xl mx-auto">
<div class="overflow-hidden rounded-2xl">
<div id="carousel" class="carousel-track">
<!-- Slide 1 -->
<div class="carousel-slide relative h-80">
<img src="https://images.pexels.com/photos/3292370/pexels-photo-3292370.jpeg?auto=compress&cs=tinysrgb&w=600&h=500&dpr=2" alt="Coffee tasting session" class="w-full h-full object-cover" loading="lazy">
<div class="absolute inset-0 bg-gradient-to-t from-bark-900/80 via-bark-900/30 to-transparent"></div>
<div class="absolute bottom-0 left-0 right-0 p-6">
<div class="flex items-center gap-3 mb-3">
<span class="note-tag"><i class="fa-solid fa-cup text-terra-400"></i> Classic</span>
<span class="note-tag"><i class="fa-solid fa-lightbulb text-bark-400"></i> Bright</span>
</div>
<h3 class="font-display text-2xl font-semibold text-white">Ethiopian Yirgacheffe</h3>
<p class="text-bark-200 mt-1">Citrus, bergamot, and floral notes — a cup that unfolds slowly.</p>
</div>
</div>
<!-- Slide 2 -->
<div class="carousel-slide relative h-80">
<img src="https://images.pexels.com/photos/3087630/pexels-photo-3087630.jpeg?auto=compress&cs=tinysrgb&w=600&h=500&dpr=2" alt="Coffee tasting session" class="w-full h-full object-cover" loading="lazy">
<div class="absolute inset-0 bg-gradient-to-t from-bark-900/80 via-bark-900/30 to-transparent"></div>
<div class="absolute bottom-0 left-0 right-0 p-6">
<div class="flex items-center gap-3 mb-3">
<span class="note-tag"><i class="fa-solid fa-cup text-terra-400"></i> Classic</span>
<span class="note-tag"><i class="fa-solid fa-lightbulb text-bark-400"></i> Smooth</span>
</div>
<h3 class="font-display text-2xl font-semibold text-white">Colombian Huila</h3>
<p class="text-bark-200 mt-1">Rich chocolate and caramel finish — the everyday hero.</p>
</div>
</div>
<!-- Slide 3 -->
<div class="carousel-slide relative h-80">
<img src="https://images.pexels.com/photos/3170454/pexels-photo-3170454.jpeg?auto=compress&cs=tinysrgb&w=600&h=500&dpr=2" alt="Coffee tasting session" class="w-full h-full object-cover" loading="lazy">
<div class="absolute inset-0 bg-gradient-to-t from-bark-900/80 via-bark-900/30 to-transparent"></div>
<div class="absolute bottom-0 left-0 right-0 p-6">
<div class="flex items-center gap-3 mb-3">
<span class="note-tag"><i class="fa-solid fa-cup text-terra-400"></i> Classic</span>
<span class="note-tag"><i class="fa-solid fa-lightbulb text-bark-400"></i> Floral</span>
</div>
<h3 class="font-display text-2xl font-semibold text-white">Panamanian Geisha</h3>
<p class="text-bark-200 mt-1">Lavender, bergamot, stone fruits — the most complex profile we offer.</p>
</div>
</div>
<!-- Slide 4 -->
<div class="carousel-slide relative h-80">
<img src="https://images.pexels.com/photos/3122905/pexels-photo-3122905.jpeg?auto=compress&cs=tinysrgb&w=600&h=500&dpr=2" alt="Coffee tasting session" class="w-full h-full object-cover" loading="lazy">
<div class="absolute inset-0 bg-gradient-to-t from-bark-900/80 via-bark-900/30 to-transparent"></div>
<div class="absolute bottom-0 left-0 right-0 p-6">
<div class="flex items-center gap-3 mb-3">
<span class="note-tag"><i class="fa-solid fa-cup text-terra-400"></i> Classic</span>
<span class="note-tag"><i class="fa-solid fa-lightbulb text-bark-400"></i> Deep</span>
</div>
<h3 class="font-display text-2xl font-semibold text-white">Sumatran Mandheling</h3>
<p class="text-bark-200 mt-1">Earthy, spicy, and creamy — a full-bodied experience for the bold palate.</p>
</div>
</div>
<!-- Slide 5 -->
<div class="carousel-slide relative h-80">
<img src="https://images.pexels.com/photos/2991339/pexels-photo-2991339.jpeg?auto=compress&cs=tinysrgb&w=600&h=500&dpr=2" alt="Coffee tasting session" class="w-full h-full object-cover" loading="lazy">
<div class="absolute inset-0 bg-gradient-to-t from-bark-900/80 via-bark-900/30 to-transparent"></div>
<div class="absolute bottom-0 left-0 right-0 p-6">
<div class="flex items-center gap-3 mb-3">
<span class="note-tag"><i class="fa-solid fa-cup text-terra-400"></i> Classic</span>
<span class="note-tag"><i class="fa-solid fa-lightbulb text-bark-400"></i> Balanced</span>
</div>
<h3 class="font-display text-2xl font-semibold text-white">Guatemalan Antigua</h3>
<p class="text-bark-200 mt-1">Melodic, complex, and gently smoky — a cup for the curious.</p>
</div>
</div>
</div>
</div>
<!-- Carousel controls -->
<div class="flex items-center justify-center gap-4 mt-6">
<button id="carousel-prev" class="w-10 h-10 rounded-full border border-bark-200 flex items-center justify-center text-bark-500 hover:bg-bark-50 hover:border-bark-500 hover:text-bark-700 transition-colors" aria-label="Previous slide">
<i class="fa-solid fa-arrow-left text-sm"></i>
</button>
<div id="carousel-dots" class="flex gap-2" role="tablist" aria-label="Carousel slides"></div>
<button id="carousel-next" class="w-10 h-10 rounded-full border border-bark-200 flex items-center justify-center text-bark-500 hover:bg-bark-50 hover:border-bark-500 hover:text-bark-700 transition-colors" aria-label="Next slide">
<i class="fa-solid fa-arrow-right text-sm"></i>
</button>
</div>
</div>
</div>
</div>
</section>
<!-- About Section -->
<section id="about" class="relative py-24 bg-bark-900 overflow-hidden">
<div class="absolute inset-0 opacity-5">
<img src="https://images.pexels.com/photos/3292370/pexels-photo-3292370.jpeg?auto=compress&cs=tinysrgb&w=600&h=500&dpr=2" alt="Coffee beans" class="w-full h-full object-cover" loading="lazy">
</div>
<div class="relative z-10 max-w-7xl mx-auto px-6">
<div class="reveal grid md:grid-cols-2 gap-16 items-center">
<div>
<span class="text-terra-400 text-sm font-semibold uppercase tracking-widest">Who We Are</span>
<h2 class="font-display text-4xl md:text-5xl font-bold text-white mt-3 mb-6">Three Generations of Roasters</h2>
<p class="text-bark-300 text-lg leading-relaxed mb-6">
Founded in 2015, Artisan Roast Co. started as a dream of three friends who believed coffee deserved the same reverence as wine or craft beer. Over 15 years, we've built a team of 18 skilled roasters, 120 independent farms, and a community that's as passionate about beans as we are.
</p>
<p class="text-bark-300 text-lg leading-relaxed mb-8">
We roast in our 350 sq ft facility in Portland, Oregon, with a small batch process that yields 200 pounds of specialty coffee every week. Every bag is a single story — from the farm to your cup.
</p>
<div class="flex gap-4">
<a href="#" class="btn-outline px-6 py-3 rounded-full text-sm font-semibold">Our Story</a>
<a href="#" class="btn-outline px-6 py-3 rounded-full text-sm font-semibold">Farm Visits</a>
</div>
</div>
<div class="grid grid-cols-2 gap-6">
<div class="reveal rounded-2xl overflow-hidden">
<img src="https://images.pexels.com/photos/1555502/pexels-photo-1555502.jpeg?auto=compress&cs=tinysrgb&w=600&h=400&dpr=2" alt="Coffee roaster facility" class="w-full h-64 object-cover" loading="lazy">
</div>
<div class="reveal rounded-2xl overflow-hidden">
<img src="https://images.pexels.com/photos/1537753/pexels-photo-1537753.jpeg?auto=compress&cs=tinysrgb&w=600&h=400&dpr=2" alt="Coffee brewing session" class="w-full h-64 object-cover" loading="lazy">
</div>
</div>
</div>
</div>
</section>
<!-- Contact / CTA Section -->
<section id="contact" class="relative py-24 bg-white">
<div class="max-w-7xl mx-auto px-6">
<div class="reveal text-center mb-16">
<span class="text-terra-500 text-sm font-semibold uppercase tracking-widest">Get Started</span>
<div class="section-divider mt-3 mx-auto"></div>
<h2 class="font-display text-4xl md:text-5xl font-bold text-bark-900 mt-3">Order a Fresh Batch</h2>
<p class="text-bark-500 text-lg mt-4 max-w-2xl mx-auto">Subscribe to our newsletter and receive a 15% discount on your first order, plus monthly tasting notes and new release alerts.</p>
</div>
<div class="grid md:grid-cols-3 gap-8">
<!-- Form -->
<div class="reveal bg-white border border-bark-100 rounded-2xl p-8 hover:shadow-xl hover:shadow-bark-100/30 transition-shadow">
<form id="form" class="space-y-5" novalidate>
<div>
<label for="name" class="block text-sm font-medium text-bark-700 mb-1.5">Name</label>
<input id="name" type="text" placeholder="Your name" required
class="w-full px-4 py-3 rounded-xl border border-bark-200 bg-bark-50 focus:outline-none focus:ring-2 focus:ring-terra-400 focus:border-transparent transition-all text-bark-700 placeholder:text-bark-300"
aria-required="true">
<p id="name-error" class="text-red-500 text-xs mt-1 hidden" role="alert">Please enter your name.</p>
</div>
<div>
<label for="email" class="block text-sm font-medium text-bark-700 mb-1.5">Email</label>
<input id="email" type="email" placeholder="your@email.com" required
class="w-full px-4 py-3 rounded-xl border border-bark-200 bg-bark-50 focus:outline-none focus:ring-2 focus:ring-terra-400 focus:border-transparent transition-all text-bark-700 placeholder:text-bark-300"
aria-required="true">
<p id="email-error" class="text-red-500 text-xs mt-1 hidden" role="alert">Please enter a valid email.</p>
</div>
<div>
<label for="message" class="block text-sm font-medium text-bark-700 mb-1.5">Message</label>
<textarea id="message" rows="3" placeholder="Tell us what you're looking for..."
class="w-full px-4 py-3 rounded-xl border border-bark-200 bg-bark-50 focus:outline-none focus:ring-2 focus:ring-terra-400 focus:border-transparent transition-all text-bark-700 placeholder:text-bark-300 resize-none"></textarea>
</div>
<button type="submit" class="btn-primary w-full py-3.5 rounded-full text-base font-semibold text-white">
Get Started
</button>
</form>
</div>
<!-- Quick info -->
<div class="reveal space-y-6">
<div class="flex items-start gap-4">
<div class="w-12 h-12 rounded-xl bg-terra-500/10 flex items-center justify-center flex-shrink-0">
<i class="fa-solid fa-clock text-terra-500 text-lg"></i>
</div>
<div>
<h4 class="font-display text-base font-semibold text-bark-800 mb-1">Roasted Daily</h4>
<p class="text-bark-500 text-sm leading-relaxed">Each day's roast is a new story. We ship the same day to keep your cup at peak freshness.</p>
</div>
</div>
<div class="flex items-start gap-4">
<div class="w-12 h-12 rounded-xl bg-terra-500/10 flex items-center justify-center flex-shrink-0">
<i class="fa-solid fa-truck text-terra-500 text-lg"></i>
</div>
<div>
<h4 class="font-display text-base font-semibold text-bark-800 mb-1">Free Shipping</h4>
<p class="text-bark-500 text-sm leading-relaxed">$35 orders get free shipping. No minimum — just taste the difference of a fresh roast.</p>
</div>
</div>
<div class="flex items-start gap-4">
<div class="w-12 h-12 rounded-xl bg-terra-500/10 flex items-center justify-center flex-shrink-0">
<i class="fa-solid fa-shield-halved text-terra-500 text-lg"></i>
</div>
<div>
<h4 class="font-display text-base font-semibold text-bark-800 mb-1">100% Satisfaction</h4>
<p class="text-bark-500 text-sm leading-relaxed">We stand behind every roast. If you're not 100% in love with it, we'll make it right.</p>
</div>
</div>
</div>
<!-- Stats -->
<div class="reveal flex flex-col justify-center">
<div class="grid grid-cols-3 gap-4">
<div class="text-center">
<div class="font-display text-3xl font-bold text-terra-500">200+</div>
<div class="text-bark-400 text-sm">lbs/week</div>
</div>
<div class="text-center">
<div class="font-display text-3xl font-bold text-terra-500">120</div>
<div class="text-bark-400 text-sm">farms</div>
</div>
<div class="text-center">
<div class="font-display text-3xl font-bold text-terra-500">18</div>
<div class="text-bark-400 text-sm">roasters</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="bg-bark-900 text-bark-300 pt-16 pb-8">
<div class="max-w-7xl mx-auto px-6">
<div class="grid md:grid-cols-4 gap-12 mb-12">
<div>
<div class="flex items-center gap-2.5 mb-4">
<div class="w-8 h-8 rounded-full bg-terra-500 flex items-center justify-center">
<i class="fa-solid fa-mug-hot text-white text-xs"></i>
</div>
<span class="font-display font-semibold text-white">Artisan Roast Co.</span>
</div>
<p class="text-bark-400 text-sm leading-relaxed">Crafting exceptional coffee, one batch at a time. Since 2015.</p>
</div>
<div>
<h4 class="text-white font-semibold text-sm mb-4">Shop</h4>
<ul class="space-y-2">
<li><a href="#roasts" class="text-bark-400 hover:text-terra-400 transition-colors text-sm">All Roasts</a></li>
<li><a href="#" class="text-bark-400 hover:text-terra-400 transition-colors text-sm">Subscriptions</a></li>
<li><a href="#" class="text-bark-400 hover:text-terra-400 transition-colors text-sm">Gift Cards</a></li>
<li><a href="#" class="text-bark-400 hover:text-terra-400 transition-colors text-sm">New Arrivals</a></li>
</ul>
</div>
<div>
<h4 class="text-white font-semibold text-sm mb-4">Community</h4>
<ul class="space-y-2">
<li><a href="#" class="text-bark-400 hover:text-terra-400 transition-colors text-sm">Farm Visits</a></li>
<li><a href="#" class="text-bark-400 hover:text-terra-400 transition-colors text-sm">Tasting Notes</a></li>
<li><a href="#" class="text-bark-400 hover:text-terra-400 transition-colors text-sm">Blog</a></li>
<li><a href="#" class="text-bark-400 hover:text-terra-400 transition-colors text-sm">Events</a></li>
</ul>
</div>
<div>
<h4 class="text-white font-semibold text-sm mb-4">Stay Updated</h4>
<p class="text-bark-400 text-sm mb-4">Get monthly tasting notes and early access to new blends.</p>
<form id="newsletter-form" class="flex gap-2">
<input id="email-input" type="email" placeholder="your@email.com" required
class="flex-1 px-4 py-2.5 rounded-xl bg-bark-800 border border-bark-700 text-bark-100 text-sm placeholder:text-bark-500 focus:outline-none focus:ring-2 focus:ring-terra-500 focus:border-transparent"
aria-required="true">
<button type="submit" class="px-4 py-2.5 rounded-xl bg-terra-500 text-white text-sm font-semibold hover:bg-terra-600 transition-colors flex-shrink-0">
<i class="fa-solid fa-paper-plane"></i>
</button>
</form>
</div>
</div>
<div class="border-t border-bark-800 pt-8 flex flex-col md:flex-row items-center justify-between gap-4">
<p class="text-bark-500 text-xs">2025 Artisan Roast Co. All rights reserved.</p>
<div class="flex gap-4">
<a href="#" class="text-bark-500 hover:text-terra-400 transition-colors" aria-label="Twitter"><i class="fa-brands fa-x-twitter text-lg"></i></a>
<a href="#" class="text-bark-500 hover:text-terra-400 transition-colors" aria-label="Instagram"><i class="fa-brands fa-instagram text-lg"></i></a>
<a href="#" class="text-bark-500 hover:text-terra-400 transition-colors" aria-label="Facebook"><i class="fa-brands fa-facebook-f text-lg"></i></a>
<a href="#" class="text-bark-500 hover:text-terra-400 transition-colors" aria-label="YouTube"><i class="fa-brands fa-youtube text-lg"></i></a>
</div>
</div>
</div>
</footer>
<script>
// ── Utility functions ──
// Toast notification system
const toast = document.getElementById('toast');
const toastMsg = document.getElementById('toast-msg');
let toastTimeout;
function showToast(msg) {
toastMsg.textContent = msg;
toast.classList.add('show');
clearTimeout(toastTimeout);
toastTimeout = setTimeout(() => toast.classList.remove('show'), 3000);
}
function showToastError(msg) {
toastMsg.textContent = msg;
toast.classList.add('show');
clearTimeout(toastTimeout);
toastTimeout = setTimeout(() => toast.classList.remove('show'), 3000);
}
// ── Form validation ──
document.getElementById('form').addEventListener('submit', function(e) {
e.preventDefault();
const nameInput = document.getElementById('name');
const emailInput = document.getElementById('email');
const nameError = document.getElementById('name-error');
const emailError = document.getElementById('email-error');
// Clear previous errors
nameError.classList.add('hidden');
emailError.classList.add('hidden');
let valid = true;
if (!nameInput.value.trim()) {
nameError.classList.remove('hidden');
valid = false;
}
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailInput.value.trim() || !emailRegex.test(emailInput.value)) {
emailError.classList.remove('hidden');
valid = false;
}
if (valid) {
showToast('Thank you! We\'ll be in touch shortly.');
nameInput.value = '';
emailInput.value = '';
document.getElementById('message').value = '';
} else {
showToastError('Please correct the errors above.');
}
});
// Newsletter form
document.getElementById('newsletter-form').addEventListener('submit', function(e) {
e.preventDefault();
const emailInput = document.getElementById('email-input');
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailInput.value.trim() || !emailRegex.test(emailInput.value)) {
showToastError('Please enter a valid email address.');
return;
}
showToast('Subscribed! Welcome to the community.');
emailInput.value = '';
});
// ── Mobile menu toggle ──
const menuToggle = document.getElementById('menu-toggle');
const mobileMenu = document.getElementById('mobile-menu');
const menuClose = document.getElementById('menu-close');
function openMobileMenu() {
mobileMenu.classList.add('open');
menuToggle.setAttribute('aria-expanded', 'true');
document.body.style.overflow = 'hidden';
}
function closeMobileMenu() {
mobileMenu.classList.remove('open');
menuToggle.setAttribute('aria-expanded', 'false');
document.body.style.overflow = '';
}
menuToggle.addEventListener('click', openMobileMenu);
menuClose.addEventListener('click', closeMobileMenu);
// Close mobile menu when a nav link is clicked
mobileMenu.querySelectorAll('a').forEach(link => {
link.addEventListener('click', closeMobileMenu);
});
// ── Scroll reveal ──
const revealObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
}
});
}, { threshold: 0.1, rootMargin: '0px 0px -50px 0px' });
document.querySelectorAll('.reveal').forEach(el => revealObserver.observe(el));
// ── Navbar scroll effect ──
const navbar = document.getElementById('navbar');
window.addEventListener('scroll', () => {
if (window.scrollY > 50) {
navbar.style.background = 'rgba(253, 248, 240, 0.92)';
navbar.style.backdropFilter = 'blur(12px)';
navbar.style.boxShadow = '0 1px 20px rgba(0,0,0,0.06)';
navbar.style.borderBottom = '1px solid #e8d5b8';
} else {
navbar.style.background = 'transparent';
navbar.style.backdropFilter = 'none';
navbar.style.boxShadow = 'none';
navbar.style.borderBottom = '1px solid transparent';
}
});
// ── Image hover parallax ──
document.querySelectorAll('.img-hover').forEach(el => {
el.addEventListener('mousemove', (e) => {
const rect = el.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width - 0.5;
const y = (e.clientY - rect.top) / rect.height - 0.5;
el.style.transform = `translate(${x * -12}px, ${y * -12}px)`;
});
el.addEventListener('mouseleave', () => {
el.style.transform = 'translate(0, 0)';
});
});
// ── Carousel ──
const carousel = document.getElementById('carousel');
const track = carousel.querySelector('.carousel-track');
const slides = track.querySelectorAll('.carousel-slide');
const prevBtn = document.getElementById('carousel-prev');
const nextBtn = document.getElementById('carousel-next');
const dotsContainer = document.getElementById('carousel-dots');
let currentSlide = 0;
const totalSlides = slides.length;
function updateDots() {
dotsContainer.innerHTML = '';
for (let i = 0; i < totalSlides; i++) {
const dot = document.createElement('button');
dot.className = 'w-2.5 h-2.5 rounded-full transition-all cursor-pointer ' +
(i === currentSlide ? 'bg-terra-500 scale-125' : 'bg-bark-200 hover:bg-bark-300');
dot.setAttribute('aria-label', `Go to slide ${i + 1}`);
dot.setAttribute('role', 'tab');
dot.addEventListener('click', () => goToSlide(i));
dotsContainer.appendChild(dot);
}
}
function goToSlide(index) {
currentSlide = index;
track.style.transform = `translateX(-${currentSlide * 100}%)`;
updateDots();
}
prevBtn.addEventListener('click', () => {
currentSlide = (currentSlide > 0) ? currentSlide - 1 : totalSlides - 1;
track.style.transform = `translateX(-${currentSlide * 100}%)`;
updateDots();
});
nextBtn.addEventListener('click', () => {
currentSlide = (currentSlide < totalSlides - 1) ? currentSlide + 1 : 0;
track.style.transform = `translateX(-${currentSlide * 100}%)`;
updateDots();
});
updateDots();
// ── Hero floating particles ──
function createParticles() {
const container = document.getElementById('particles');
const colors = ['#a87238', '#c9a96e', '#c49a6c', '#d4b896', '#e8d5b8', '#8b5a28', '#9a6335'];
for (let i = 0; i < 18; i++) {
const particle = document.createElement('div');
particle.className = 'particle';
const size = Math.random() * 4 + 2;
particle.style.width = size + 'px';
particle.style.height = size + 'px';
particle.style.left = Math.random() * 100 + '%';
particle.style.bottom = '0';
particle.style.background = colors[Math.floor(Math.random() * colors.length)];
particle.style.animationDelay = Math.random() * 8 + 's';
particle.style.animationDuration = Math.random() * 10 + 6 + 's';
container.appendChild(particle);
}
}
createParticles();
// ── Smooth scroll for anchor links ──
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({ behavior: 'smooth' });
}
});
});
// ── Keyboard accessibility for carousel dots ──
dotsContainer.addEventListener('keydown', (e) => {
if (e.key === 'ArrowLeft') {
e.preventDefault();
goToSlide((currentSlide - 1 + totalSlides) % totalSlides);
}
if (e.key === 'ArrowRight') {
e.preventDefault();
goToSlide((currentSlide + 1) % totalSlides);
}
});
// ── Keyboard accessibility for form inputs ──
document.querySelectorAll('input, textarea').forEach(el => {
el.addEventListener('keydown', (e) => {
if (e.key === 'Enter' && e.target.tagName !== 'TEXTAREA') {
e.preventDefault();
e.target.blur();
}
});
});
// ── Active nav link tracking ──
const sections = document.querySelectorAll('section[id]');
const navLinks = document.querySelectorAll('.nav-link');
window.addEventListener('scroll', () => {
let current = '';
sections.forEach(section => {
const sectionTop = section.offsetTop - 100;
if (window.scrollY >= sectionTop) {
current = section.getAttribute('id');
}
});
navLinks.forEach(link => {
link.classList.remove('text-terra-500');
link.classList.add('text-bark-400');
if (link.getAttribute('href') === `#${current}`) {
link.classList.remove('text-bark-400');
link.classList.add('text-terra-500');
}
});
});
</script>
<div style="position:fixed;right:12px;bottom:12px;z-index:2147483647;background:rgba(17,24,39,.92);color:#fff;padding:8px 10px;border-radius:10px;font:12px/1.3 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;box-shadow:0 8px 20px rgba(0,0,0,.28)">Generated in 102.26s<br>Model: bloomer010/Ling-3.0-tiny-GGUF:Q4_K_M</div></body>
</html>