Refactor code structure for improved readability and maintainability

This commit is contained in:
2026-09-07 09:40:36 +02:00
parent 98052adb47
commit 359f5a4b3d
14 changed files with 6697 additions and 4 deletions
+3 -1
View File
@@ -26,4 +26,6 @@
`llama-server -hf unsloth/gemma-4-26B-A4B-it-qat-GGUF:UD-Q4_K_XL --reasoning off -fa on -ngl 99 -b 2048 -ub 2048 -c 4096 --temp 1.0 --top-p 0.95 --top-k 64 --no-mmap -t 4` -> 20 t/s `llama-server -hf unsloth/gemma-4-26B-A4B-it-qat-GGUF:UD-Q4_K_XL --reasoning off -fa on -ngl 99 -b 2048 -ub 2048 -c 4096 --temp 1.0 --top-p 0.95 --top-k 64 --no-mmap -t 4` -> 20 t/s
`llama-server -hf unsloth/gemma-4-E4B-it-GGUF:Q3_K_XL --reasoning off -fa on -ngl 99 -b 2048 -ub 2048 -c 4096 --temp 1.0 --top-p 0.95 --top-k 64 --no-mmap -t 4 --spec-type draft-mtp --spec-draft-n-max 3 --port 8081` -> 130t/s `llama-server -hf unsloth/gemma-4-E4B-it-GGUF:Q3_K_XL --reasoning off -fa on -ngl 99 -b 2048 -ub 2048 -c 4096 --temp 1.0 --top-p 0.95 --top-k 64 --no-mmap -t 4 --spec-type draft-mtp --spec-draft-n-max 3 --port 8081` -> 130t/s
`llama serve -hf bloomer010/Ling-3.0-tiny-GGUF:Q4_K_M` -> 200t/s
+990
View File
@@ -0,0 +1,990 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>VITALITY FRAME — Fitness Coaching</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,700;1,9..40,400&family=Playfair+Display:wght@400;700;900&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: {
colors: {
navy: { 50: '#f0f4f8', 100: '#d9e2ec', 200: '#bcccdc', 300: '#9fb3c8', 400: '#7a8ba3', 500: '#5c6f8a', 600: '#4a5a74', 700: '#3a4a60', 800: '#2a3648', 900: '#1a2030' },
teal: { 400: '#2dd4bf', 500: '#14b8a6', 600: '#0d9488' },
coral: { 400: '#fb7185', 500: '#f43f5e', 600: '#e11d48' },
sand: { 50: '#faf8f5', 100: '#f0ebe3', 200: '#e6d9c3', 300: '#d4c4a0', 400: '#c4a97d' }
},
fontFamily: {
display: ['Playfair Display', 'serif'],
body: ['DM Sans', 'sans-serif']
}
}
}
}
</script>
<style>
:root {
--bg: #0f1419;
--bg-card: #1a2030;
--bg-elevated: #232b3d;
--fg: #f0ebe3;
--fg-muted: #9fb3c8;
--accent: #2dd4bf;
--accent-warm: #fb7185;
--border: #2a3648;
--gold: #c4a97d;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html {
scroll-behavior: smooth;
overflow-x: hidden;
}
body {
font-family: 'DM Sans', sans-serif;
background: var(--bg);
color: var(--fg);
overflow-x: hidden;
line-height: 1.7;
}
::selection {
background: var(--accent);
color: var(--bg);
}
/* Scrollbar */
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--accent); }
/* Loading screen */
#loader {
position: fixed;
inset: 0;
z-index: 9999;
background: var(--bg);
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 1.5rem;
transition: opacity 0.6s ease, visibility 0.6s ease;
}
#loader.hidden {
opacity: 0;
visibility: hidden;
}
.loader-bar {
width: 120px;
height: 2px;
background: var(--border);
border-radius: 2px;
overflow: hidden;
}
.loader-bar-inner {
width: 0%;
height: 100%;
background: var(--accent);
border-radius: 2px;
animation: loaderSlide 1.2s ease-in-out forwards;
}
@keyframes loaderSlide {
0% { width: 0%; }
50% { width: 70%; }
100% { width: 100%; }
}
/* Hero image styling */
.hero-img-container {
position: relative;
overflow: hidden;
border-radius: 1.5rem;
}
.hero-img-container img {
transition: transform 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.hero-img-container:hover img {
transform: scale(1.04);
}
.hero-img-overlay {
position: absolute;
inset: 0;
background: linear-gradient(135deg, rgba(15,20,25,0.9) 0%, rgba(15,20,25,0.4) 50%, transparent 100%);
pointer-events: none;
}
/* Floating particles */
.particle {
position: fixed;
width: 3px;
height: 3px;
background: var(--accent);
border-radius: 50%;
opacity: 0.15;
pointer-events: none;
z-index: 0;
animation: floatParticle 14s linear infinite;
}
@keyframes floatParticle {
0% { transform: translateY(0) translateX(0); opacity: 0; }
10% { opacity: 0.15; }
90% { opacity: 0.15; }
100% { transform: translateY(-100vh) translateX(40px); opacity: 0; }
}
/* Section reveal */
.reveal {
opacity: 0;
transform: translateY(40px);
transition: opacity 0.8s ease, transform 0.8s ease;
}
.reveal.visible {
opacity: 1;
transform: translateY(0);
}
/* Card hover */
.card-lift {
transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94), box-shadow 0.4s ease;
}
.card-lift:hover {
transform: translateY(-6px);
box-shadow: 0 20px 40px rgba(0,0,0,0.4);
}
/* Button shine */
.btn-shine {
position: relative;
overflow: hidden;
}
.btn-shine::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.6s ease;
}
.btn-shine:hover::before {
left: 100%;
}
/* Pulse ring */
.pulse-ring {
animation: pulseRing 2.5s ease-out infinite;
}
@keyframes pulseRing {
0% { box-shadow: 0 0 0 0 rgba(45, 212, 191, 0.5); }
100% { box-shadow: 0 0 0 30px rgba(45, 212, 191, 0); }
}
/* Counter animation */
.counter {
font-variant-numeric: tabular-nums;
}
/* Gradient text */
.gradient-text {
background: linear-gradient(135deg, var(--accent) 0%, var(--gold) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
/* Mobile nav */
.nav-menu {
transform: translateX(100%);
transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.nav-menu.open {
transform: translateX(0);
}
/* Progress bar */
.progress-bar {
height: 6px;
background: var(--border);
border-radius: 3px;
overflow: hidden;
}
.progress-fill {
height: 100%;
border-radius: 3px;
background: var(--accent);
transition: width 1.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
/* Testimonial quote line */
.quote-line {
width: 3px;
background: var(--accent);
border-radius: 2px;
}
/* Marquee */
.marquee {
display: flex;
animation: marquee 30s linear infinite;
}
@keyframes marquee {
0% { transform: translateX(0); }
100% { transform: translateX(-50%); }
}
/* Focus visible */
*:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
border-radius: 4px;
}
/* Stagger */
.stagger-item {
opacity: 0;
transform: translateY(30px);
animation: staggerIn 0.6s ease forwards;
}
.stagger-item:nth-child(1) { animation-delay: 0.05s; }
.stagger-item:nth-child(2) { animation-delay: 0.15s; }
.stagger-item:nth-child(3) { animation-delay: 0.25s; }
.stagger-item:nth-child(4) { animation-delay: 0.35s; }
.stagger-item:nth-child(5) { animation-delay: 0.45s; }
.stagger-item:nth-child(6) { animation-delay: 0.55s; }
@keyframes staggerIn {
to { opacity: 1; transform: translateY(0); }
}
/* 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; }
.stagger-item { opacity: 1; transform: none; }
}
/* Parallax background blobs */
.bg-blob {
position: absolute;
border-radius: 50%;
filter: blur(80px);
opacity: 0.15;
pointer-events: none;
}
</style>
</head>
<body>
<!-- Loader -->
<div id="loader" aria-live="polite">
<div class="loader-bar"><div class="loader-bar-inner"></div></div>
<span class="text-sm text-teal-400 font-body tracking-widest uppercase">Loading</span>
</div>
<!-- Particles -->
<div id="particles" aria-hidden="true"></div>
<!-- Navigation -->
<nav class="fixed top-0 left-0 w-full z-50 transition-all duration-500" id="navbar" 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="font-display text-xl font-bold tracking-tight flex items-center gap-2" aria-label="VITALITY FRAME Home">
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" aria-hidden="true">
<circle cx="14" cy="14" r="13" stroke="#2dd4bf" stroke-width="2"/>
<path d="M8 14 Q14 6 20 14 Q14 22 8 14" fill="#2dd4bf" opacity="0.8"/>
<circle cx="14" cy="14" r="3" fill="#fb7185"/>
</svg>
<span class="text-sand-50">VITALITY</span>
<span class="text-sand-400 ml-1">FRAME</span>
</a>
<div class="hidden md:flex items-center gap-8">
<a href="#about" class="text-sm text-sand-300 hover:text-teal-400 transition-colors duration-300 font-medium">About</a>
<a href="#services" class="text-sm text-sand-300 hover:text-teal-400 transition-colors duration-300 font-medium">Services</a>
<a href="#testimonials" class="text-sm text-sand-300 hover:text-teal-400 transition-colors duration-300 font-medium">Stories</a>
<a href="#contact" class="text-sm text-sand-300 hover:text-teal-400 transition-colors duration-300 font-medium">Contact</a>
</div>
<button id="mobile-toggle" class="md:hidden text-sand-300 text-xl" aria-label="Toggle menu" aria-expanded="false">
<i class="fa-solid fa-bars"></i>
</button>
</div>
<!-- Mobile Menu -->
<div id="mobile-menu" class="nav-menu absolute top-full left-0 w-full bg-navy-900/95 backdrop-blur-xl border-t border-navy-700" role="menu">
<div class="px-6 py-6 flex flex-col gap-4">
<a href="#about" class="text-sand-200 hover:text-teal-400 transition-colors font-medium py-2" role="menuitem">About</a>
<a href="#services" class="text-sand-200 hover:text-teal-400 transition-colors font-medium py-2" role="menuitem">Services</a>
<a href="#testimonials" class="text-sand-200 hover:text-teal-400 transition-colors font-medium py-2" role="menuitem">Stories</a>
<a href="#contact" class="text-sand-200 hover:text-teal-400 transition-colors font-medium py-2" role="menuitem">Contact</a>
</div>
</div>
</nav>
<!-- Hero Section -->
<section class="relative min-h-screen flex items-center overflow-hidden" id="hero">
<!-- Background blobs -->
<div class="bg-blob w-96 h-96 bg-teal-500 top-20 -left-48" aria-hidden="true"></div>
<div class="bg-blob w-80 h-80 bg-coral-500 bottom-20 -right-40" aria-hidden="true"></div>
<div class="bg-blob w-64 h-64 bg-sand-500 top-1/2 left-1/2" aria-hidden="true"></div>
<div class="max-w-7xl mx-auto px-6 w-full pt-28 pb-20 relative z-10">
<div class="grid lg:grid-cols-2 gap-12 lg:gap-16 items-center">
<!-- Left Column -->
<div class="space-y-8">
<div class="flex flex-wrap items-center gap-3">
<span class="px-4 py-1.5 bg-coral-500/15 text-coral-400 text-xs font-semibold rounded-full border border-coral-500/20 uppercase tracking-widest">Transforming Lives</span>
<span class="px-4 py-1.5 bg-teal-500/15 text-teal-400 text-xs font-semibold rounded-full border border-teal-500/20 uppercase tracking-widest">Personalized Training</span>
</div>
<h1 class="font-display text-5xl md:text-7xl lg:text-8xl font-black leading-[1.05] tracking-tight">
<span class="gradient-text">Your Body</span>, <br>Your Story,
<br>Your Victory.
</h1>
<p class="text-lg md:text-xl text-sand-300 max-w-lg leading-relaxed">
I help ambitious individuals build lasting strength, reclaim confidence, and achieve the fitness results they deserve — not through suffering, but through smart, sustainable transformation.
</p>
<div class="flex flex-wrap gap-4">
<a href="#contact" class="btn-shine px-8 py-4 bg-teal-500 text-navy-900 font-bold rounded-full text-sm uppercase tracking-wide hover:bg-teal-400 transition-colors duration-300 shadow-lg shadow-teal-500/20">
Start Your Journey
</a>
<a href="#about" class="px-8 py-4 border border-sand-400/30 text-sand-100 font-semibold rounded-full text-sm uppercase tracking-wide hover:border-sand-400/50 hover:bg-sand-400/5 transition-colors duration-300">
Learn More
</a>
</div>
<div class="flex gap-12 pt-4">
<div>
<p class="text-3xl font-bold text-sand-100 counter" data-target="250">0</p>
<p class="text-xs text-sand-400 mt-1">Happy Clients</p>
</div>
<div>
<p class="text-3xl font-bold text-sand-100 counter" data-target="98">0</p>
<p class="text-xs text-sand-400 mt-1">% Satisfaction</p>
</div>
<div>
<p class="text-3xl font-bold text-sand-100 counter" data-target="12">0</p>
<p class="text-xs text-sand-400 mt-1">Years Experience</p>
</div>
</div>
</div>
<!-- Right Column — Image -->
<div class="hero-img-container relative">
<div class="aspect-[4/5] rounded-2xl overflow-hidden">
<img src="https://images.pexels.com/photos/398177/pexels-photo-398177.jpeg?auto=compress&cs=tinysrgb&w=1260&h=1500" alt="Individual in a gym performing strength training with focused expression" class="w-full h-full object-cover">
</div>
<div class="absolute -bottom-6 -left-6 bg-navy-900/90 backdrop-blur-sm p-4 rounded-2xl shadow-xl border border-navy-700">
<div class="flex items-center gap-3">
<div class="w-10 h-10 rounded-full bg-teal-500/20 flex items-center justify-center">
<i class="fa-solid fa-dumbbell text-teal-400"></i>
</div>
<div>
<p class="text-sm font-semibold">Certified Coach</p>
<p class="text-xs text-sand-400">12 years of experience</p>
</div>
</div>
</div>
<div class="absolute -top-4 -right-4 bg-coral-500/20 p-3 rounded-2xl shadow-xl border border-coral-500/30 pulse-ring">
<div class="flex items-center gap-2">
<span class="w-2 h-2 bg-coral-400 rounded-full animate-pulse"></span>
<p class="text-xs text-coral-400 font-semibold">Verified</p>
</div>
</div>
</div>
</div>
</div>
<!-- Scroll indicator -->
<div class="absolute bottom-8 left-1/2 -translate-x-1/2 flex flex-col items-center gap-2 opacity-60" aria-hidden="true">
<span class="text-xs text-sand-400 uppercase tracking-widest">Scroll</span>
<div class="w-px h-8 bg-sand-400/30"></div>
</div>
</section>
<!-- Marquee Banner -->
<div class="py-4 bg-navy-800/50 border-y border-navy-700/50 overflow-hidden" aria-hidden="true">
<div class="marquee">
<div class="flex items-center gap-8 px-4 whitespace-nowrap">
<span class="text-sm text-sand-400">Strength Building</span><span class="text-sand-700">|</span>
<span class="text-sm text-sand-400">Cardiovascular Fitness</span><span class="text-sand-700">|</span>
<span class="text-sm text-sand-400">Mental Clarity</span><span class="text-sand-700">|</span>
<span class="text-sm text-sand-400">Recovery & Balance</span><span class="text-sand-700">|</span>
<span class="text-sm text-sand-400">Sustainable Results</span><span class="text-sand-700">|</span>
<span class="text-sm text-sand-400">Nutrition Planning</span><span class="text-sand-700">|</span>
<span class="text-sm text-sand-400">Personalized Programs</span><span class="text-sand-700">|</span>
<span class="text-sm text-sand-400">Long-term Transformation</span><span class="text-sand-700">|</span>
</div>
<div class="flex items-center gap-8 px-4 whitespace-nowrap">
<span class="text-sm text-sand-400">Strength Building</span><span class="text-sand-700">|</span>
<span class="text-sm text-sand-400">Cardiovascular Fitness</span><span class="text-sand-700">|</span>
<span class="text-sm text-sand-400">Mental Clarity</span><span class="text-sand-700">|</span>
<span class="text-sm text-sand-400">Recovery & Balance</span><span class="text-sand-700">|</span>
<span class="text-sm text-sand-400">Sustainable Results</span><span class="text-sand-700">|</span>
<span class="text-sm text-sand-400">Nutrition Planning</span><span class="text-sand-700">|</span>
<span class="text-sm text-sand-400">Personalized Programs</span><span class="text-sand-700">|</span>
<span class="text-sm text-sand-400">Long-term Transformation</span><span class="text-sand-700">|</span>
</div>
</div>
</div>
<!-- About / Mission Section -->
<section id="about" class="py-24 md:py-32 relative">
<div class="max-w-7xl mx-auto px-6">
<div class="grid lg:grid-cols-2 gap-16 items-center">
<div class="reveal">
<span class="text-teal-400 text-xs font-bold uppercase tracking-widest">Our Philosophy</span>
<h2 class="font-display text-4xl md:text-5xl font-bold mt-4 mb-6 leading-tight">
Fitness Is a <span class="text-sand-100">Personal</span> Journey
</h2>
<p class="text-sand-300 text-lg leading-relaxed mb-6">
Every individual is unique. What works for someone else is not necessarily what you need. At Vitality Frame, we design training plans that align with your goals, lifestyle, and personality.
</p>
<p class="text-sand-400 leading-relaxed mb-8">
I combine evidence-based methods with hands-on coaching to help you build strength that lasts long after the gym. No shortcuts, no wasted effort — just real, sustainable transformation.
</p>
<div class="grid grid-cols-3 gap-6">
<div class="text-center p-4 bg-navy-800/40 rounded-xl border border-navy-700/50">
<div class="text-3xl font-bold text-teal-400 mb-1">12</div>
<p class="text-xs text-sand-400">Years coaching</p>
</div>
<div class="text-center p-4 bg-navy-800/40 rounded-xl border border-navy-700/50">
<div class="text-3xl font-bold text-coral-400 mb-1">4.9</div>
<p class="text-xs text-sand-400">Avg. rating</p>
</div>
<div class="text-center p-4 bg-navy-800/40 rounded-xl border border-navy-700/50">
<div class="text-3xl font-bold text-sand-400 mb-1">98%</div>
<p class="text-xs text-sand-400">Satisfaction</p>
</div>
</div>
</div>
<div class="reveal">
<div class="space-y-5">
<div class="flex gap-5 group">
<div class="w-12 h-12 rounded-xl bg-teal-500/15 flex items-center justify-center flex-shrink-0 group-hover:bg-teal-500/25 transition-colors duration-300">
<i class="fa-solid fa-bullseye text-teal-400 group-hover:text-teal-300 transition-colors duration-300"></i>
</div>
<div>
<h3 class="font-semibold text-sand-100 mb-1">Goal Alignment</h3>
<p class="text-sand-400 text-sm">Every training program is tailored to your specific objectives. No one-size-fits-all approaches — we meet you where you are.</p>
</div>
</div>
<div class="flex gap-5 group">
<div class="w-12 h-12 rounded-xl bg-coral-500/15 flex items-center justify-center flex-shrink-0 group-hover:bg-coral-500/25 transition-colors duration-300">
<i class="fa-solid fa-people-group text-coral-400 group-hover:text-coral-300 transition-colors duration-300"></i>
</div>
<div>
<h3 class="font-semibold text-sand-100 mb-1">Community Support</h3>
<p class="text-sand-400 text-sm">Access to a network of motivated individuals. Accountability, encouragement, and shared success are at the heart of every session.</p>
</div>
</div>
<div class="flex gap-5 group">
<div class="w-12 h-12 rounded-xl bg-sand-400/15 flex items-center justify-center flex-shrink-0 group-hover:bg-sand-400/25 transition-colors duration-300">
<i class="fa-solid fa-chart-line text-sand-400 group-hover:text-sand-300 transition-colors duration-300"></i>
</div>
<div>
<h3 class="font-semibold text-sand-100 mb-1">Data-Driven Results</h3>
<p class="text-sand-400 text-sm">Progress tracking, performance metrics, and adaptive programming ensure every workout moves you forward.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Services Section -->
<section id="services" class="py-24 md:py-32 bg-navy-900/50 relative">
<div class="bg-blob w-80 h-80 bg-teal-500 -top-40 right-0" aria-hidden="true"></div>
<div class="max-w-7xl mx-auto px-6">
<div class="text-center mb-16 reveal">
<span class="text-teal-400 text-xs font-bold uppercase tracking-widest">What We Offer</span>
<h2 class="font-display text-4xl md:text-5xl font-bold mt-4 text-sand-100">Programs That Match Your Life</h2>
<p class="text-sand-400 mt-4 max-w-2xl mx-auto">From foundational strength-building to advanced performance optimization, our programs are built around evidence and your personal needs.</p>
</div>
<div class="grid md:grid-cols-3 gap-6">
<div class="reveal group bg-navy-800/40 border border-navy-700/50 rounded-2xl p-8 hover:border-teal-500/30 transition-all duration-500 card-lift cursor-pointer">
<div class="w-14 h-14 rounded-xl bg-teal-500/15 flex items-center justify-center mb-6 group-hover:bg-teal-500/25 transition-colors duration-300">
<i class="fa-solid fa-dumbbell text-teal-400 text-xl"></i>
</div>
<h3 class="font-display text-2xl font-bold mb-3">Strength Foundations</h3>
<p class="text-sand-400 mb-6 leading-relaxed">Perfect for beginners. Build a solid base of compound movements, proper form, and consistent habits that last a lifetime.</p>
<ul class="space-y-3 mb-6">
<li class="flex items-center gap-2 text-sm text-sand-300"><i class="fa-solid fa-check text-teal-400 text-xs"></i> Form & technique coaching</li>
<li class="flex items-center gap-2 text-sm text-sand-300"><i class="fa-solid fa-check text-teal-400 text-xs"></i> Progressive overload plan</li>
<li class="flex items-center gap-2 text-sm text-sand-300"><i class="fa-solid fa-check text-teal-400 text-xs"></i> 12-month accountability plan</li>
</ul>
<a href="#contact" class="inline-flex items-center gap-2 text-teal-400 text-sm font-semibold hover:text-teal-300 transition-colors group">
Start Free Session <i class="fa-solid fa-arrow-right text-xs transition-transform group-hover:translate-x-1"></i>
</a>
</div>
<div class="reveal group bg-navy-800/40 border border-navy-700/50 rounded-2xl p-8 hover:border-coral-500/30 transition-all duration-500 card-lift cursor-pointer">
<div class="w-14 h-14 rounded-xl bg-coral-500/15 flex items-center justify-center mb-6 group-hover:bg-coral-500/25 transition-colors duration-300">
<i class="fa-solid fa-person-running text-coral-400 text-xl"></i>
</div>
<h3 class="font-display text-2xl font-bold mb-3">Performance Elite</h3>
<p class="text-sand-400 mb-6 leading-relaxed">For those ready to push limits. Advanced training protocols, nutrition optimization, and mental performance coaching.</p>
<ul class="space-y-3 mb-6">
<li class="flex items-center gap-2 text-sm text-sand-300"><i class="fa-solid fa-check text-coral-400 text-xs"></i> Advanced training protocols</li>
<li class="flex items-center gap-2 text-sm text-sand-300"><i class="fa-solid fa-check text-coral-400 text-xs"></i> Recovery science integration</li>
<li class="flex items-center gap-2 text-sm text-sand-300"><i class="fa-solid fa-check text-coral-400 text-xs"></i> Monthly progress reviews</li>
</ul>
<a href="#contact" class="inline-flex items-center gap-2 text-coral-400 text-sm font-semibold hover:text-coral-300 transition-colors group">
Upgrade Now <i class="fa-solid fa-arrow-right text-xs transition-transform group-hover:translate-x-1"></i>
</a>
</div>
<div class="reveal group bg-navy-800/40 border border-navy-700/50 rounded-2xl p-8 hover:border-sand-400/30 transition-all duration-500 card-lift cursor-pointer">
<div class="w-14 h-14 rounded-xl bg-sand-400/15 flex items-center justify-center mb-6 group-hover:bg-sand-400/25 transition-colors duration-300">
<i class="fa-solid fa-heart-pulse text-sand-400 text-xl"></i>
</div>
<h3 class="font-display text-2xl font-bold mb-3">Wellness Transformation</h3>
<p class="text-sand-400 mb-6 leading-relaxed">Holistic approach combining movement, nutrition, and mindset. Designed for those wanting sustainable lifestyle change, not just quick results.</p>
<ul class="space-y-3 mb-6">
<li class="flex items-center gap-2 text-sm text-sand-300"><i class="fa-solid fa-check text-sand-400 text-xs"></i> Mindset & habit building</li>
<li class="flex items-center gap-2 text-sm text-sand-300"><i class="fa-solid fa-check text-sand-400 text-xs"></i> Meal planning & prep guides</li>
<li class="flex items-center gap-2 text-sm text-sand-300"><i class="fa-solid fa-check text-sand-400 text-xs"></i> Ongoing coaching sessions</li>
</ul>
<a href="#contact" class="inline-flex items-center gap-2 text-sand-400 text-sm font-semibold hover:text-sand-200 transition-colors group">
Learn More <i class="fa-solid fa-arrow-right text-xs transition-transform group-hover:translate-x-1"></i>
</a>
</div>
</div>
</div>
</section>
<!-- Testimonials Section -->
<section id="testimonials" class="py-24 md:py-32 relative overflow-hidden">
<div class="max-w-7xl mx-auto px-6">
<div class="text-center mb-16 reveal">
<span class="text-coral-400 text-xs font-bold uppercase tracking-widest">Success Stories</span>
<h2 class="font-display text-4xl md:text-5xl font-bold mt-4 text-sand-100">Real Outcomes, Real People</h2>
</div>
<div class="grid md:grid-cols-3 gap-6">
<div class="reveal bg-navy-800/40 border border-navy-700/50 rounded-2xl p-8 hover:border-coral-500/30 transition-all duration-500 card-lift">
<div class="flex items-center gap-1 mb-4">
<i class="fa-solid fa-star text-coral-400 text-sm"></i>
<i class="fa-solid fa-star text-coral-400 text-sm"></i>
<i class="fa-solid fa-star text-coral-400 text-sm"></i>
<i class="fa-solid fa-star text-coral-400 text-sm"></i>
<i class="fa-solid fa-star text-coral-400 text-sm"></i>
</div>
<p class="text-sand-200 leading-relaxed mb-6 italic">"After years of failed attempts, this coach finally understood what I needed. The structured plan is so intuitive that I'm not even thinking about it anymore — I'm just getting results."</p>
<div class="flex items-center gap-4">
<img src="https://images.pexels.com/photos/1238955/pexels-photo-1238955.jpeg?auto=compress&cs=tinysrgb&w=120&h=120" alt="Alex Morgan" class="w-10 h-10 rounded-full object-cover">
<div>
<p class="text-sm font-semibold text-sand-100">Alex Morgan</p>
<p class="text-xs text-sand-400">Runner, 6 months</p>
</div>
</div>
</div>
<div class="reveal bg-navy-800/40 border border-navy-700/50 rounded-2xl p-8 hover:border-coral-500/30 transition-all duration-500 card-lift">
<div class="flex items-center gap-1 mb-4">
<i class="fa-solid fa-star text-coral-400 text-sm"></i>
<i class="fa-solid fa-star text-coral-400 text-sm"></i>
<i class="fa-solid fa-star text-coral-400 text-sm"></i>
<i class="fa-solid fa-star text-coral-400 text-sm"></i>
<i class="fa-solid fa-star text-coral-400 text-sm"></i>
</div>
<p class="text-sand-200 leading-relaxed mb-6 italic">"I came in with a shattered sense of self-esteem. Within 6 months, I had rebuilt my body and my confidence. This is the best decision I ever made."</p>
<div class="flex items-center gap-4">
<img src="https://images.pexels.com/photos/1079267/pexels-photo-1079267.jpeg?auto=compress&cs=tinysrgb&w=120&h=120" alt="Jordan Chen" class="w-10 h-10 rounded-full object-cover">
<div>
<p class="text-sm font-semibold text-sand-100">Jordan Chen</p>
<p class="text-xs text-sand-400">Former athlete, 12 months</p>
</div>
</div>
</div>
<div class="reveal bg-navy-800/40 border border-navy-700/50 rounded-2xl p-8 hover:border-coral-500/30 transition-all duration-500 card-lift">
<div class="flex items-center gap-1 mb-4">
<i class="fa-solid fa-star text-coral-400 text-sm"></i>
<i class="fa-solid fa-star text-coral-400 text-sm"></i>
<i class="fa-solid fa-star text-coral-400 text-sm"></i>
<i class="fa-solid fa-star text-coral-400 text-sm"></i>
<i class="fa-solid fa-star text-coral-400 text-sm"></i>
</div>
<p class="text-sand-200 leading-relaxed mb-6 italic">"The holistic approach changed everything for me. My mind and my body are finally in sync. This is more than a coaching service — it's a lifestyle."</p>
<div class="flex items-center gap-4">
<img src="https://images.pexels.com/photos/4008935/pexels-photo-4008935.jpeg?auto=compress&cs=tinysrgb&w=120&h=120" alt="Maya Okonkwo" class="w-10 h-10 rounded-full object-cover">
<div>
<p class="text-sm font-semibold text-sand-100">Maya Okonkwo</p>
<p class="text-xs text-sand-400">New parent, 9 months</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Contact Section -->
<section id="contact" class="py-24 md:py-32 relative">
<div class="max-w-7xl mx-auto px-6">
<div class="grid lg:grid-cols-2 gap-12 items-start">
<div class="reveal">
<span class="text-teal-400 text-xs font-bold uppercase tracking-widest">Get Started</span>
<h2 class="font-display text-4xl md:text-5xl font-bold mt-4 mb-6">Ready to Begin?</h2>
<p class="text-sand-300 leading-relaxed mb-8">Whether you're just starting out or looking to optimize what you already have, I'd love to hear from you. Let's start a conversation.</p>
<form id="contact-form" class="space-y-5" novalidate>
<div>
<label for="name" class="block text-sm text-sand-300 mb-1.5 font-medium">Your Name</label>
<input type="text" id="name" name="name" required autocomplete="name" class="w-full bg-navy-800 border border-navy-700 rounded-xl px-4 py-3 text-sand-100 placeholder-sand-400/40 focus:outline-none focus:border-teal-500 focus:ring-2 focus:ring-teal-500/20 transition-all duration-300" placeholder="Enter your full name">
<p class="text-xs text-coral-400 mt-1 hidden" id="name-error">Please enter your name</p>
</div>
<div>
<label for="email" class="block text-sm text-sand-300 mb-1.5 font-medium">Email Address</label>
<input type="email" id="email" name="email" required autocomplete="email" class="w-full bg-navy-800 border border-navy-700 rounded-xl px-4 py-3 text-sand-100 placeholder-sand-400/40 focus:outline-none focus:border-teal-500 focus:ring-2 focus:ring-teal-500/20 transition-all duration-300" placeholder="you@example.com">
<p class="text-xs text-coral-400 mt-1 hidden" id="email-error">Please enter a valid email address</p>
</div>
<div>
<label for="phone" class="block text-sm text-sand-300 mb-1.5 font-medium">Phone (Optional)</label>
<input type="tel" id="phone" name="phone" autocomplete="tel" class="w-full bg-navy-800 border border-navy-700 rounded-xl px-4 py-3 text-sand-100 placeholder-sand-400/40 focus:outline-none focus:border-teal-500 focus:ring-2 focus:ring-teal-500/20 transition-all duration-300" placeholder="(555) 123-4567">
</div>
<div>
<label for="message" class="block text-sm text-sand-300 mb-1.5 font-medium">What Are You Looking For?</label>
<textarea id="message" name="message" rows="4" required class="w-full bg-navy-800 border border-navy-700 rounded-xl px-4 py-3 text-sand-100 placeholder-sand-400/40 focus:outline-none focus:border-teal-500 focus:ring-2 focus:ring-teal-500/20 transition-all duration-300 resize-none" placeholder="Tell me about your fitness goals..."></textarea>
<p class="text-xs text-coral-400 mt-1 hidden" id="message-error">Please share what you're looking for</p>
</div>
<button type="submit" class="btn-shine w-full py-4 bg-teal-500 text-navy-900 font-bold rounded-xl text-sm uppercase tracking-wide hover:bg-teal-400 transition-colors duration-300 shadow-lg shadow-teal-500/20">
Send Message
</button>
</form>
</div>
<div class="space-y-6 reveal">
<div class="flex gap-5">
<div class="w-12 h-12 rounded-xl bg-teal-500/15 flex items-center justify-center flex-shrink-0">
<i class="fa-solid fa-phone text-teal-400 text-lg"></i>
</div>
<div>
<p class="text-sm text-sand-300 font-medium">Call Us</p>
<p class="text-sand-200 font-semibold">+1 (555) 123-4567</p>
<p class="text-xs text-sand-400 mt-1">MonFri, 9am6pm</p>
</div>
</div>
<div class="flex gap-5">
<div class="w-12 h-12 rounded-xl bg-coral-500/15 flex items-center justify-center flex-shrink-0">
<i class="fa-solid fa-envelope text-coral-400 text-lg"></i>
</div>
<div>
<p class="text-sm text-sand-300 font-medium">Email Us</p>
<p class="text-sand-200 font-semibold">hello@vitalityframe.com</p>
<p class="text-xs text-sand-400 mt-1">We respond within 2 hours</p>
</div>
</div>
<div class="flex gap-5">
<div class="w-12 h-12 rounded-xl bg-sand-400/15 flex items-center justify-center flex-shrink-0">
<i class="fa-solid fa-location-dot text-sand-400 text-lg"></i>
</div>
<div>
<p class="text-sm text-sand-300 font-medium">Our Office</p>
<p class="text-sand-200 font-semibold">Suite 14, 420 Wellness Blvd</p>
<p class="text-xs text-sand-400 mt-1">Downtown, Portland, OR</p>
</div>
</div>
<!-- Social Links -->
<div class="flex gap-4 pt-4">
<a href="#" class="w-10 h-10 rounded-xl bg-navy-800 border border-navy-700 flex items-center justify-center text-sand-400 hover:border-teal-500 hover:text-teal-400 hover:bg-teal-500/10 transition-all duration-300" aria-label="Instagram">
<i class="fa-brands fa-instagram"></i>
</a>
<a href="#" class="w-10 h-10 rounded-xl bg-navy-800 border border-navy-700 flex items-center justify-center text-sand-400 hover:border-teal-500 hover:text-teal-400 hover:bg-teal-500/10 transition-all duration-300" aria-label="Twitter / X">
<i class="fa-brands fa-x-twitter"></i>
</a>
<a href="#" class="w-10 h-10 rounded-xl bg-navy-800 border border-navy-700 flex items-center justify-center text-sand-400 hover:border-teal-500 hover:text-teal-400 hover:bg-teal-500/10 transition-all duration-300" aria-label="YouTube">
<i class="fa-brands fa-youtube"></i>
</a>
<a href="#" class="w-10 h-10 rounded-xl bg-navy-800 border border-navy-700 flex items-center justify-center text-sand-400 hover:border-teal-500 hover:text-teal-400 hover:bg-teal-500/10 transition-all duration-300" aria-label="LinkedIn">
<i class="fa-brands fa-linkedin-in"></i>
</a>
</div>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="bg-navy-900 border-t border-navy-700/50 py-16">
<div class="max-w-7xl mx-auto px-6">
<div class="grid md:grid-cols-4 gap-12 mb-12">
<div>
<p class="font-display text-2xl font-bold text-sand-100 mb-3">VITALITY</p>
<p class="text-sand-400 text-sm leading-relaxed">Transforming lives through personalized fitness. We help you build strength, confidence, and lasting habits.</p>
</div>
<div>
<p class="font-semibold text-sand-200 mb-4">Programs</p>
<ul class="space-y-2">
<li><a href="#services" class="text-sm text-sand-400 hover:text-teal-400 transition-colors">Strength Foundations</a></li>
<li><a href="#services" class="text-sm text-sand-400 hover:text-teal-400 transition-colors">Performance Elite</a></li>
<li><a href="#services" class="text-sm text-sand-400 hover:text-teal-400 transition-colors">Wellness Transformation</a></li>
<li><a href="#contact" class="text-sm text-sand-400 hover:text-teal-400 transition-colors">Custom Plans</a></li>
</ul>
</div>
<div>
<p class="font-semibold text-sand-200 mb-4">Company</p>
<ul class="space-y-2">
<li><a href="#about" class="text-sm text-sand-400 hover:text-teal-400 transition-colors">About Us</a></li>
<li><a href="#contact" class="text-sm text-sand-400 hover:text-teal-400 transition-colors">Contact</a></li>
<li><a href="#" class="text-sm text-sand-400 hover:text-teal-400 transition-colors">Blog</a></li>
<li><a href="#" class="text-sm text-sand-400 hover:text-teal-400 transition-colors">Careers</a></li>
</ul>
</div>
<div>
<p class="font-semibold text-sand-200 mb-4">Stay Connected</p>
<p class="text-sand-400 text-sm mb-4">Weekly insights, training tips, and exclusive content.</p>
<form id="newsletter-form" class="flex gap-2" novalidate>
<input type="email" id="newsletter-email" required placeholder="Your email" class="flex-1 bg-navy-800 border border-navy-700 rounded-lg px-3 py-2 text-sm text-sand-100 placeholder-sand-400/40 focus:outline-none focus:border-teal-500 transition-all">
<button type="submit" class="px-4 py-2 bg-teal-500 text-navy-900 font-semibold text-sm rounded-lg hover:bg-teal-400 transition-colors">
<i class="fa-solid fa-paper-plane"></i>
</button>
</form>
</div>
</div>
<div class="border-t border-navy-700/50 pt-8 flex flex-col md:flex-row items-center justify-between gap-4">
<p class="text-xs text-sand-400">&copy; 2025 Vitality Frame. All rights reserved.</p>
<div class="flex gap-6">
<a href="#" class="text-xs text-sand-400 hover:text-teal-400 transition-colors">Privacy Policy</a>
<a href="#" class="text-xs text-sand-400 hover:text-teal-400 transition-colors">Terms of Service</a>
<a href="#" class="text-xs text-sand-400 hover:text-teal-400 transition-colors">Cookie Settings</a>
</div>
</div>
</div>
</footer>
<!-- Toast notification -->
<div id="toast" class="fixed top-6 right-6 z-[100] bg-navy-800 border border-teal-500/30 rounded-xl px-6 py-4 shadow-2xl translate-x-[120%] transition-transform duration-500" role="alert" aria-live="polite">
<p class="text-sm text-sand-200 font-medium" id="toast-message">Message sent successfully!</p>
</div>
<script>
// ── Loader ──
window.addEventListener('load', () => {
setTimeout(() => {
document.getElementById('loader').classList.add('hidden');
}, 1400);
});
// ── Particles ──
(function createParticles() {
const container = document.getElementById('particles');
for (let i = 0; i < 20; i++) {
const p = document.createElement('div');
p.className = 'particle';
p.style.left = Math.random() * 100 + '%';
p.style.top = Math.random() * 100 + '%';
p.style.animationDuration = (8 + Math.random() * 12) + 's';
p.style.animationDelay = (Math.random() * 10) + 's';
p.style.opacity = (0.05 + Math.random() * 0.1).toString();
p.style.width = (2 + Math.random() * 3) + 'px';
p.style.height = p.style.width;
p.setAttribute('aria-hidden', 'true');
container.appendChild(p);
}
})();
// ── Navbar scroll effect ──
const navbar = document.getElementById('navbar');
window.addEventListener('scroll', () => {
if (window.scrollY > 80) {
navbar.classList.add('bg-navy-900/90', 'backdrop-blur-xl', 'border-b', 'border-navy-700/50');
} else {
navbar.classList.remove('bg-navy-900/90', 'backdrop-blur-xl', 'border-b', 'border-navy-700/50');
}
});
// ── Mobile menu ──
const mobileToggle = document.getElementById('mobile-toggle');
const mobileMenu = document.getElementById('mobile-menu');
let mobileOpen = false;
mobileToggle.addEventListener('click', () => {
mobileOpen = !mobileOpen;
mobileMenu.classList.toggle('open');
mobileToggle.setAttribute('aria-expanded', mobileOpen);
mobileToggle.innerHTML = mobileOpen
? '<i class="fa-solid fa-xmark"></i>'
: '<i class="fa-solid fa-bars"></i>';
});
// Close mobile menu on link click
mobileMenu.querySelectorAll('a').forEach(a => {
a.addEventListener('click', () => {
mobileOpen = false;
mobileMenu.classList.remove('open');
mobileToggle.setAttribute('aria-expanded', 'false');
mobileToggle.innerHTML = '<i class="fa-solid fa-bars"></i>';
});
});
// ── Reveal on scroll ──
const observer = new IntersectionObserver((entries) => {
entries.forEach(e => {
if (e.isIntersecting) {
e.target.classList.add('visible');
}
});
}, { threshold: 0.1, rootMargin: '0px 0px -50px 0px' });
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
// ── Counter animation ──
const counterEls = document.querySelectorAll('.counter');
const counterObserver = new IntersectionObserver((entries) => {
entries.forEach(e => {
if (e.isIntersecting) {
const el = e.target;
const target = parseInt(el.dataset.target);
const duration = 2000;
const start = performance.now();
const tick = (now) => {
const elapsed = now - start;
const progress = Math.min(elapsed / duration, 1);
const eased = 1 - Math.pow(1 - progress, 3);
const current = Math.round(eased * target);
el.textContent = current.toLocaleString();
if (progress < 1) requestAnimationFrame(tick);
};
requestAnimationFrame(tick);
}
});
}, { threshold: 0.5 });
counterEls.forEach(el => counterObserver.observe(el));
// ── Contact form ──
const contactForm = document.getElementById('contact-form');
const newsletterForm = document.getElementById('newsletter-form');
function showToast(msg) {
const toast = document.getElementById('toast');
const msgEl = document.getElementById('toast-message');
msgEl.textContent = msg;
toast.style.transform = 'translateX(0)';
setTimeout(() => {
toast.style.transform = 'translateX(120%)';
}, 4000);
}
function validateEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
contactForm.addEventListener('submit', (e) => {
e.preventDefault();
const name = document.getElementById('name');
const email = document.getElementById('email');
const message = document.getElementById('message');
let valid = true;
if (!name.value.trim() || name.value.trim().length < 2) {
document.getElementById('name-error').classList.remove('hidden');
valid = false;
} else {
document.getElementById('name-error').classList.add('hidden');
}
if (!validateEmail(email.value.trim())) {
document.getElementById('email-error').classList.remove('hidden');
valid = false;
} else {
document.getElementById('email-error').classList.add('hidden');
}
if (!message.value.trim() || message.value.trim().length < 10) {
document.getElementById('message-error').classList.remove('hidden');
valid = false;
} else {
document.getElementById('message-error').classList.add('hidden');
}
if (valid) {
showToast('Message sent! We will reach out within 2 hours.');
contactForm.reset();
}
});
newsletterForm.addEventListener('submit', (e) => {
e.preventDefault();
const email = document.getElementById('newsletter-email');
if (validateEmail(email.value.trim())) {
showToast('Subscribed! Welcome to the Vitality community.');
email.value = '';
} else {
showToast('Please enter a valid email address.');
}
});
// ── Smooth scroll for anchor links ──
document.querySelectorAll('a[href^="#"]').forEach(a => {
a.addEventListener('click', (e) => {
e.preventDefault();
const target = document.querySelector(a.getAttribute('href'));
if (target) {
const offset = 80;
const top = target.getBoundingClientRect().top + window.scrollY - offset;
window.scrollTo({ top, behavior: 'smooth' });
}
});
});
// ── Keyboard accessibility for mobile menu ──
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && mobileOpen) {
mobileOpen = false;
mobileMenu.classList.remove('open');
mobileToggle.setAttribute('aria-expanded', 'false');
mobileToggle.innerHTML = '<i class="fa-solid fa-bars"></i>';
}
});
// ── Intersection observer for counter ──
// (Already handled above, but we add a fallback)
const observerOptions = { threshold: 0.3 };
const counterObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const el = entry.target;
const target = parseInt(el.dataset.target);
const duration = 2000;
const start = performance.now();
const animate = (now) => {
const elapsed = now - start;
const progress = Math.min(elapsed / duration, 1);
const eased = 1 - Math.pow(1 - progress, 3);
el.textContent = Math.round(eased * target).toLocaleString();
if (progress < 1) requestAnimationFrame(animate);
};
requestAnimationFrame(animate);
counterObserver.unobserve(entry.target);
}
});
}, { threshold: 0.5 });
counterObserver.observe(document.querySelector('.counter'));
</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 89.27s<br>Model: bloomer010/Ling-3.0-tiny-GGUF:Q4_K_M</div></body>
</html>
```
+945
View File
@@ -0,0 +1,945 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lena Voss — Architect Portfolio</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;600;700;900&family=DM+Sans:wght@300;400;500;600&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: {
display: ['Playfair Display', 'serif'],
body: ['DM Sans', 'sans-serif'],
},
colors: {
bg: '#1A1A1A',
fg: '#F5F0EB',
muted: '#8A8580',
accent: '#C47B5A',
card: '#2A2A2A',
border: '#3A3A3A',
warm: '#D4C4B0',
sand: '#E8DCC8',
}
}
}
}
</script>
<style>
:root {
--bg: #1A1A1A;
--fg: #F5F0EB;
--muted: #8A8580;
--accent: #C47B5A;
--card: #2A2A2A;
--border: #3A3A3A;
--warm: #D4C4B0;
--sand: #E8DCC8;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
font-family: 'DM Sans', sans-serif;
background: var(--bg);
color: var(--fg);
overflow-x: hidden;
-webkit-font-smoothing: antialiased;
}
.font-display { font-family: 'Playfair Display', serif; }
/* Custom cursor */
.cursor-dot {
width: 8px;
height: 8px;
background: var(--accent);
border-radius: 50%;
position: fixed;
top: 0;
left: 0;
z-index: 9999;
pointer-events: none;
transition: transform 0.1s ease;
mix-blend-mode: difference;
}
.cursor-dot.hover {
transform: scale(2);
background: var(--accent);
opacity: 0.4;
}
/* Scroll reveal */
.reveal {
opacity: 0;
transform: translateY(40px);
transition: opacity 0.8s ease, transform 0.8s ease;
}
.reveal.visible {
opacity: 1;
transform: translateY(0);
}
.reveal-delay-1 { transition-delay: 0.1s; }
.reveal-delay-2 { transition-delay: 0.2s; }
.reveal-delay-3 { transition-delay: 0.3s; }
.reveal-delay-4 { transition-delay: 0.4s; }
/* Hero image styling */
.hero-image-wrapper {
position: relative;
overflow: hidden;
border-radius: 0 0 40px 40px;
}
.hero-image-wrapper::after {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(135deg, rgba(26,26,26,0.85) 0%, rgba(26,26,26,0.4) 50%, rgba(26,26,26,0.3) 100%);
pointer-events: none;
}
.hero-image-wrapper img {
filter: sepia(0.05) contrast(1.02);
transition: filter 1.2s ease;
}
.hero-image-wrapper:hover img {
filter: sepia(0) contrast(1.03);
}
/* Project card */
.project-card {
position: relative;
overflow: hidden;
border-radius: 12px;
background: var(--card);
border: 1px solid var(--border);
transition: transform 0.5s ease, border-color 0.4s ease;
}
.project-card:hover {
transform: translateY(-6px);
border-color: var(--accent);
}
.project-card img {
transition: transform 0.7s ease;
}
.project-card:hover img {
transform: scale(1.06);
}
.project-overlay {
position: absolute;
inset: 0;
background: linear-gradient(0deg, rgba(26,26,26,0.95) 0%, rgba(26,26,26,0.3) 50%, transparent 100%);
display: flex;
flex-direction: column;
justify-content: flex-end;
padding: 1.5rem;
opacity: 0;
transition: opacity 0.4s ease;
}
.project-card:hover .project-overlay {
opacity: 1;
}
/* Nav link underline */
.nav-link {
position: relative;
padding-bottom: 2px;
}
.nav-link::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 1px;
background: var(--accent);
transition: width 0.3s ease;
}
.nav-link:hover::after {
width: 100%;
}
/* CTA button */
.btn-primary {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.85rem 2rem;
background: var(--accent);
color: var(--bg);
font-weight: 600;
font-size: 0.9rem;
letter-spacing: 0.02em;
border: none;
border-radius: 2px;
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
}
.btn-primary:hover {
background: #D4A27A;
transform: translateY(-2px);
box-shadow: 0 8px 24px rgba(196,123,90,0.3);
}
.btn-primary:active {
transform: translateY(0);
}
.btn-secondary {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.85rem 2rem;
background: transparent;
color: var(--fg);
font-weight: 500;
font-size: 0.9rem;
border: 1px solid var(--border);
border-radius: 2px;
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
}
.btn-secondary:hover {
border-color: var(--accent);
color: var(--accent);
transform: translateY(-2px);
}
.btn-secondary:active {
transform: translateY(0);
}
/* Section divider */
.section-divider {
height: 1px;
background: linear-gradient(90deg, transparent, var(--border), transparent);
}
/* Typing cursor */
.typing-cursor::after {
content: '|';
animation: blink 1s step-end infinite;
color: var(--accent);
}
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
/* Floating particles */
.particle {
position: absolute;
width: 3px;
height: 3px;
background: var(--accent);
border-radius: 50%;
opacity: 0.15;
pointer-events: none;
animation: float 8s ease-in-out infinite;
}
@keyframes float {
0%, 100% { transform: translateY(0) translateX(0); }
50% { transform: translateY(-20px) translateX(10px); }
}
/* Image overlay effect on hero */
.hero-overlay-gradient {
background: linear-gradient(180deg, transparent 0%, rgba(26,26,26,0.7) 50%, rgba(26,26,26,0.95) 100%);
height: 100%;
}
/* Image grid */
.img-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1px;
background: var(--border);
}
.img-grid > div {
position: relative;
overflow: hidden;
}
.img-grid > div:first-child {
grid-column: span 2;
}
.img-grid > div img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.7s ease;
}
.img-grid > div:hover img {
transform: scale(1.05);
}
/* Timeline */
.timeline-line {
position: absolute;
left: 18px;
top: 0;
bottom: 0;
width: 1px;
background: var(--border);
}
.timeline-dot {
width: 12px;
height: 12px;
background: var(--accent);
border-radius: 50%;
border: 2px solid var(--bg);
box-shadow: 0 0 0 3px var(--accent);
}
/* Noise texture overlay */
.noise-overlay {
position: fixed;
inset: 0;
pointer-events: none;
z-index: 9998;
opacity: 0.03;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
background-size: 256px;
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
.reveal {
opacity: 1;
transform: none;
transition: none;
}
.particle {
animation: none;
}
.project-card:hover {
transform: none;
}
}
/* Mobile adjustments */
@media (max-width: 768px) {
.cursor-dot {
display: none;
}
.img-grid > div:first-child {
grid-column: span 1;
}
}
/* Smooth scrolling for nav */
#main-content {
scroll-behavior: smooth;
}
/* Focus visible */
:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
/* Animated counter */
.counter {
display: inline-block;
}
/* Loading screen */
.loading-screen {
position: fixed;
inset: 0;
background: var(--bg);
display: flex;
align-items: center;
justify-content: center;
z-index: 10000;
transition: opacity 0.6s ease, visibility 0.6s ease;
}
.loading-screen.hidden {
opacity: 0;
visibility: hidden;
}
.loading-spinner {
width: 40px;
height: 40px;
border: 2px solid var(--border);
border-top-color: var(--accent);
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
</style>
</head>
<body class="bg-bg text-fg font-body">
<!-- Loading Screen -->
<div class="loading-screen" id="loadingScreen">
<div class="flex flex-col items-center gap-4">
<div class="loading-spinner"></div>
<span class="text-muted text-sm tracking-widest uppercase">Loading</span>
</div>
</div>
<!-- Custom Cursor -->
<div class="cursor-dot" id="cursorDot"></div>
<!-- Noise texture background -->
<div class="noise-overlay"></div>
<!-- Floating particles container -->
<div id="particles" class="fixed inset-0 pointer-events-none z-0"></div>
<!-- Navigation -->
<nav id="navbar" class="fixed top-0 left-0 right-0 z-50 transition-all duration-500">
<div class="max-w-7xl mx-auto px-6 py-4 flex items-center justify-between">
<a href="#" class="font-display text-xl font-bold tracking-tight text-fg" aria-label="Home">
<span class="text-accent">L</span>ena Voss
</a>
<div class="hidden md:flex items-center gap-8">
<a href="#work" class="nav-link text-sm text-muted hover:text-fg transition-colors">Work</a>
<a href="#about" class="nav-link text-sm text-muted hover:text-fg transition-colors">About</a>
<a href="#contact" class="nav-link text-sm text-muted hover:text-fg transition-colors">Contact</a>
</div>
<button id="mobileMenuBtn" class="md:hidden text-fg text-xl p-2" aria-label="Toggle menu" aria-expanded="false">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</button>
</div>
<!-- Mobile menu -->
<div id="mobileMenu" class="md:hidden hidden bg-card border-t border-border">
<div class="px-6 py-4 flex flex-col gap-4">
<a href="#work" class="text-sm text-muted hover:text-fg transition-colors py-2">Work</a>
<a href="#about" class="text-sm text-muted hover:text-fg transition-colors py-2">About</a>
<a href="#contact" class="text-sm text-muted hover:text-fg transition-colors py-2">Contact</a>
</div>
</div>
</nav>
<!-- Main Content -->
<main id="main-content">
<!-- Hero Section -->
<section class="relative min-h-screen flex items-center overflow-hidden">
<div class="absolute inset-0">
<img src="https://images.pexels.com/photos/312524/pexels-photo-312524.jpeg?auto=compress&cs=tinysrgb&w=1920" alt="Architecture in a modern cityscape" class="w-full h-full object-cover" style="filter: sepia(0.03) contrast(1.04);">
<div class="absolute inset-0 hero-overlay-gradient"></div>
</div>
<div class="relative z-10 max-w-7xl mx-auto px-6 pt-24 pb-16 w-full">
<div class="max-w-3xl">
<div class="mb-6">
<span class="text-accent text-xs tracking-[0.3em] uppercase font-medium">Studio • Built by Hand</span>
</div>
<h1 class="font-display text-5xl sm:text-6xl lg:text-7xl font-bold leading-[1.05] mb-6">
Designing<br>
<span class="text-accent">Spaces</span>
of Meaning
</h1>
<p class="text-muted text-lg max-w-xl mb-10 leading-relaxed">
I craft buildings that resonate with the human experience — where form meets function, and every line tells a story of place and purpose.
</p>
<div class="flex flex-wrap gap-4">
<a href="#work" class="btn-primary">
Explore Work
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
<a href="#about" class="btn-secondary">
About Me
</a>
</div>
</div>
</div>
</section>
<!-- Stats Bar -->
<section class="relative z-10 -mt-16">
<div class="max-w-7xl mx-auto px-6">
<div class="flex flex-wrap gap-8 justify-center text-center bg-card border border-border rounded-2xl p-8">
<div>
<div class="text-3xl font-bold text-accent">12</div>
<div class="text-muted text-sm">Projects Completed</div>
</div>
<div class="w-px bg-border"></div>
<div>
<div class="text-3xl font-bold text-accent">8</div>
<div class="text-muted text-sm">Years of Experience</div>
</div>
<div class="w-px bg-border"></div>
<div>
<div class="text-3xl font-bold text-accent">40+</div>
<div class="text-muted text-sm">Awards & Recognitions</div>
</div>
</div>
</div>
</section>
<!-- Work Section -->
<section id="work" class="py-24 relative">
<div class="max-w-7xl mx-auto px-6">
<div class="text-center mb-16 reveal">
<span class="text-accent text-xs tracking-[0.3em] uppercase font-medium">Selected Work</span>
<h2 class="font-display text-4xl sm:text-5xl font-bold mt-3">Projects</h2>
<p class="text-muted mt-4 max-w-md mx-auto">A curated selection of built works that blend craft with contemporary design principles.</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- Project 1 -->
<div class="project-card reveal">
<img src="https://images.pexels.com/photos/313590/pexels-photo-313590.jpeg?auto=compress&cs=tinysrgb&w=800" alt="Modern residential design with open plan and natural light" class="w-full h-80 object-cover">
<div class="project-overlay">
<div>
<h3 class="font-display text-xl font-bold text-fg">The Oakridge Residence</h3>
<p class="text-muted text-sm mt-1">Residential · Chicago, IL</p>
</div>
<div class="flex gap-3 mt-3">
<a href="#" class="text-accent text-sm font-medium hover:underline">View →</a>
<a href="#" class="text-muted text-sm font-medium hover:underline">Details</a>
</div>
</div>
</div>
<!-- Project 2 -->
<div class="project-card reveal">
<img src="https://images.pexels.com/photos/312524/pexels-photo-312524.jpeg?auto=compress&cs=tinysrgb&w=800" alt="Contemporary office building with glass facades and green rooftop" class="w-full h-80 object-cover">
<div class="project-overlay">
<div>
<h3 class="font-display text-xl font-bold text-fg">The Meridian Gallery</h3>
<p class="text-muted text-sm mt-1">Commercial · New York, NY</p>
</div>
<div class="flex gap-3 mt-3">
<a href="#" class="text-accent text-sm font-medium hover:underline">View →</a>
<a href="#" class="text-muted text-sm font-medium hover:underline">Details</a>
</div>
</div>
</div>
<!-- Project 3 -->
<div class="project-card reveal">
<img src="https://images.pexels.com/photos/313590/pexels-photo-313590.jpeg?auto=compress&cs=tinysrgb&w=800" alt="Civic building with modernist glass and courtyard design" class="w-full h-80 object-cover">
<div class="project-overlay">
<div>
<h3 class="font-display text-xl font-bold text-fg">The Alden Civic Center</h3>
<p class="text-muted text-sm mt-1">Public · Portland, OR</p>
</div>
<div class="flex gap-3 mt-3">
<a href="#" class="text-accent text-sm font-medium hover:underline">View →</a>
<a href="#" class="text-muted text-sm font-medium hover:underline">Details</a>
</div>
</div>
</div>
<!-- Project 4 -->
<div class="project-card reveal">
<img src="https://images.pexels.com/photos/312524/pexels-photo-312524.jpeg?auto=compress&cs=tinysrgb&w=800" alt="Luxury home with minimalist interior and natural materials" class="w-full h-80 object-cover">
<div class="project-overlay">
<div>
<h3 class="font-display text-xl font-bold text-fg">The Meridian Residence</h3>
<p class="text-muted text-sm mt-1">Residential · Denver, CO</p>
</div>
<div class="flex gap-3 mt-3">
<a href="#" class="text-accent text-sm font-medium hover:underline">View →</a>
<a href="#" class="text-muted text-sm font-medium hover:underline">Details</a>
</div>
</div>
</div>
<!-- Project 5 -->
<div class="project-card reveal">
<img src="https://images.pexels.com/photos/312524/pexels-photo-312524.jpeg?auto=compress&cs=tinysrgb&w=800" alt="Restaurant and cultural space with warm wood interior" class="w-full h-80 object-cover">
<div class="project-overlay">
<div>
<h3 class="font-display text-xl font-bold text-fg">The Willow Dining Pavilion</h3>
<p class="text-muted text-sm mt-1">Restaurant · Austin, TX</p>
</div>
<div class="flex gap-3 mt-3">
<a href="#" class="text-accent text-sm font-medium hover:underline">View →</a>
<a href="#" class="text-muted text-sm font-medium hover:underline">Details</a>
</div>
</div>
</div>
<!-- Project 6 -->
<div class="project-card reveal">
<img src="https://images.pexels.com/photos/312524/pexels-photo-312524.jpeg?auto=compress&cs=tinysrgb&w=800" alt="Mixed-use development with sustainable materials and open sky" class="w-full h-80 object-cover">
<div class="project-overlay">
<div>
<h3 class="font-display text-xl font-bold text-fg">The Meridian Arts Hub</h3>
<p class="text-muted text-sm mt-1">Mixed-use · London, UK</p>
</div>
<div class="flex gap-3 mt-3">
<a href="#" class="text-accent text-sm font-medium hover:underline">View →</a>
<a href="#" class="text-muted text-sm font-medium hover:underline">Details</a>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- About Section -->
<section id="about" class="py-24 relative bg-card">
<div class="max-w-7xl mx-auto px-6">
<div class="grid lg:grid-cols-2 gap-16 items-center">
<div class="reveal">
<span class="text-accent text-xs tracking-[0.3em] uppercase font-medium">About Me</span>
<h2 class="font-display text-4xl font-bold mt-3 mb-6">Crafting spaces that matter</h2>
<p class="text-muted leading-relaxed mb-6">
I draw from a foundation of materiality, craftsmanship, and deep listening to place. Every project begins with a question: what does this site want to become?
</p>
<p class="text-muted leading-relaxed mb-8">
Over two decades of experience, I have worked across residential, commercial, and public architecture — always with the conviction that good design is a form of generosity.
</p>
<div class="flex flex-wrap gap-4">
<a href="#" class="btn-primary">
Portfolio
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
<a href="#" class="btn-secondary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
<polyline points="15 3 21 3 21 9"></polyline>
<line x1="10" y1="14" x2="21" y2="3"></line>
</svg>
Contact
</a>
</div>
</div>
<div class="reveal reveal-delay-2">
<div class="grid grid-cols-2 gap-6">
<div class="bg-card border border-border rounded-xl p-6 text-center">
<div class="text-5xl font-bold text-accent mb-1">15</div>
<div class="text-muted text-sm">Projects Completed</div>
</div>
<div class="bg-card border border-border rounded-xl p-6 text-center">
<div class="text-5xl font-bold text-accent mb-1">12</div>
<div class="text-muted text-sm">Awards Won</div>
</div>
<div class="bg-card border border-border rounded-xl p-6 text-center">
<div class="text-5xl font-bold text-accent mb-1">9</div>
<div class="text-muted text-sm">Cities Worked</div>
</div>
<div class="bg-card border border-border rounded-xl p-6 text-center">
<div class="text-5xl font-bold text-accent mb-1">6</div>
<div class="text-muted text-sm">Years Active</div>
</div>
</div>
<div class="mt-10">
<h3 class="font-display text-xl font-bold mb-4">Design Philosophy</h3>
<div class="space-y-4 text-muted leading-relaxed">
<p>I believe architecture should be a conversation between the built and the natural world. Every material has a story, and every space carries a memory.</p>
<p>My process begins with deep observation — understanding how a site breathes, where people gather, and what they need before I ever lift a tool.</p>
<p>Design is not about imposing a vision on a place. It is about listening, then speaking.</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Services Section -->
<section class="py-24 relative">
<div class="max-w-7xl mx-auto px-6">
<div class="text-center mb-16 reveal">
<span class="text-accent text-xs tracking-[0.3em] uppercase font-medium">Approach</span>
<h2 class="font-display text-4xl sm:text-5xl font-bold mt-3">How I work</h2>
</div>
<div class="grid md:grid-cols-3 gap-8">
<div class="reveal reveal-delay-1">
<div class="bg-card border border-border rounded-2xl p-8 relative overflow-hidden">
<div class="absolute top-0 right-0 w-16 h-16 bg-accent/10 rounded-bl-[12px]"></div>
<div class="w-12 h-12 bg-accent/20 rounded-xl flex items-center justify-center mb-6">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path>
<path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path>
</svg>
</div>
<h3 class="font-display text-xl font-bold mb-3">Process</h3>
<p class="text-muted text-sm leading-relaxed">I follow a structured approach — from concept to construction — ensuring every decision is deliberate and informed by the project's context.</p>
</div>
</div>
<div class="reveal reveal-delay-2">
<div class="bg-card border border-border rounded-2xl p-8 relative overflow-hidden">
<div class="absolute top-0 right-0 w-16 h-16 bg-accent/10 rounded-bl-[12px]"></div>
<div class="w-12 h-12 bg-accent/20 rounded-xl flex items-center justify-center mb-6">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
<line x1="3" y1="9" x2="21" y2="9"></line>
<line x1="9" y1="21" x2="21" y2="21"></line>
<line x1="3" y1="15" x2="21" y2="15"></line>
</svg>
</div>
<h3 class="font-display text-xl font-bold mb-3">Collaboration</h3>
<p class="text-muted text-sm leading-relaxed">I work closely with clients, consultants, and the local community to create spaces that are not only beautiful but also functional and inclusive.</p>
</div>
</div>
<div class="reveal reveal-delay-3">
<div class="bg-card border border-border rounded-2xl p-8 relative overflow-hidden">
<div class="absolute top-0 right-0 w-16 h-16 bg-accent/10 rounded-bl-[12px]"></div>
<div class="w-12 h-12 bg-accent/20 rounded-xl flex items-center justify-center mb-6">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
</svg>
</div>
<h3 class="font-display text-xl font-bold mb-3">Sustainability</h3>
<p class="text-muted text-sm leading-relaxed">Every design prioritizes material efficiency, passive climate strategies, and long-term durability — because the best buildings endure.</p>
</div>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="py-24 relative overflow-hidden">
<div class="absolute inset-0">
<img src="https://images.pexels.com/photos/312524/pexels-photo-312524.jpeg?auto=compress&cs=tinysrgb&w=1920" alt="Architect at work with a design model" class="w-full h-full object-cover opacity-30" style="filter: sepia(0.08) contrast(1.05);">
</div>
<div class="relative z-10 max-w-4xl mx-auto px-6 text-center">
<h2 class="font-display text-4xl sm:text-5xl font-bold mb-4">Let's build something<br>worth remembering</h2>
<p class="text-muted text-lg max-w-lg mx-auto mb-8">I'm currently seeking projects that challenge and inspire. Send me a message and let's start a conversation.</p>
<div class="flex flex-wrap justify-center gap-4">
<a href="mailto:hello@lelavoss.com" class="btn-primary">
Start a Conversation
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
</div>
</div>
</section>
</main>
<!-- Footer -->
<footer class="bg-card border-t border-border py-12">
<div class="max-w-7xl mx-auto px-6">
<div class="flex flex-col md:flex-row items-center justify-between gap-6">
<div class="font-display text-lg font-bold text-fg">
<span class="text-accent">L</span>ena Voss
</div>
<p class="text-muted text-sm">© 2025 Lena Voss Architecture. All rights reserved.</p>
<div class="flex gap-6">
<a href="#" class="text-muted hover:text-accent transition-colors" aria-label="Twitter">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.4 2.2.1 4.4-.6 6-2C3 15.5.5 12 3 5c1.7 4.2 4.5 6.9 7 6.9c1.3 0 2.7-.1 4-0.3 1.3 1.9 3.3 3.2 6.5 3.2C17.5 10 21 9 22 4z"></path>
</svg>
</a>
<a href="#" class="text-muted hover:text-accent transition-colors" aria-label="Instagram">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="2" y="2" width="20" height="20" rx="5" ry="5"></rect>
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.2" y1="4.2" x2="5.4" y2="5.4"></line>
<line x1="18.6" y1="18.6" x2="19.8" y2="19.8"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.2" y1="19.8" x2="5.4" y2="18.6"></line>
<line x1="18.6" y1="5.4" x2="19.8" y2="4.2"></line>
</svg>
</a>
<a href="#" class="text-muted hover:text-accent transition-colors" aria-label="Email">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
<polyline points="22,6 12,13 2,6"></polyline>
</svg>
</a>
</div>
</div>
</div>
</footer>
<script>
// --- Loading screen ---
window.addEventListener('load', () => {
setTimeout(() => {
document.getElementById('loadingScreen').classList.add('hidden');
}, 800);
});
// --- Custom cursor ---
const cursorDot = document.getElementById('cursorDot');
let mouseX = 0, mouseY = 0;
let cursorX = 0, cursorY = 0;
document.addEventListener('mousemove', (e) => {
mouseX = e.clientX;
mouseY = e.clientY;
});
function animateCursor() {
cursorX += (mouseX - cursorX) * 0.15;
cursorY += (mouseY - cursorY) * 0.15;
cursorDot.style.left = cursorX + 'px';
cursorDot.style.top = cursorY + 'px';
requestAnimationFrame(animateCursor);
}
animateCursor();
// --- Scroll reveal ---
const revealObserver = new IntersectionObserver((entries) => {
entries.forEach((entry, index) => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
// Stagger reveal delays
const delay = entry.target.closest('.reveal')?.dataset?.delay || 0;
setTimeout(() => {
entry.target.classList.add('visible');
}, index * 100);
}
});
}, { threshold: 0.15, rootMargin: '0px 0px -50px 0px' });
document.querySelectorAll('.reveal').forEach(el => {
revealObserver.observe(el);
});
// --- Navigation ---
const navbar = document.getElementById('navbar');
const mobileMenuBtn = document.getElementById('mobileMenuBtn');
const mobileMenu = document.getElementById('mobileMenu');
let mobileMenuOpen = false;
window.addEventListener('scroll', () => {
if (window.scrollY > 80) {
navbar.style.background = 'rgba(26, 26, 26, 0.95)';
navbar.style.backdropFilter = 'blur(12px)';
navbar.style.borderBottom = '1px solid var(--border)';
} else {
navbar.style.background = 'transparent';
navbar.style.backdropFilter = 'none';
navbar.style.borderBottom = 'none';
}
});
mobileMenuBtn.addEventListener('click', () => {
mobileMenuOpen = !mobileMenuOpen;
mobileMenu.classList.toggle('hidden', !mobileMenuOpen);
mobileMenuBtn.setAttribute('aria-expanded', mobileMenuOpen);
});
// Close mobile menu on link click
mobileMenu.querySelectorAll('a').forEach(link => {
link.addEventListener('click', () => {
mobileMenuOpen = false;
mobileMenu.classList.add('hidden');
mobileMenuBtn.setAttribute('aria-expanded', 'false');
});
});
// --- Floating particles ---
(function createParticles() {
const container = document.getElementById('particles');
for (let i = 0; i < 30; i++) {
const particle = document.createElement('div');
particle.className = 'particle';
particle.style.left = Math.random() * 100 + '%';
particle.style.top = Math.random() * 100 + '%';
particle.style.animationDelay = Math.random() * 8 + 's';
particle.style.animationDuration = (6 + Math.random() * 6) + 's';
particle.style.width = (2 + Math.random() * 3) + 'px';
particle.style.height = particle.style.width;
container.appendChild(particle);
}
})();
// --- 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', block: 'start' });
}
});
});
// --- Parallax on hero image ---
(function() {
const heroImg = document.querySelector('.hero-image-wrapper img');
window.addEventListener('scroll', () => {
const scrollY = window.scrollY;
const heroSection = document.querySelector('section');
if (heroSection) {
const rect = heroSection.getBoundingClientRect();
const imageTop = rect.top;
if (scrollY > imageTop) {
heroImg.style.transform = `translateY(${Math.min(scrollY * 0.3, 50)}px)`;
heroImg.style.opacity = Math.max(1 - scrollY * 0.001, 0.7);
}
}
});
})();
// --- Active nav link highlighting ---
const sections = document.querySelectorAll('section[id]');
const navLinks = document.querySelectorAll('nav a[href^="#"]');
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-accent');
if (link.getAttribute('href') === '#' + current) {
link.classList.add('text-accent');
}
});
});
</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 63.86s<br>Model: bloomer010/Ling-3.0-tiny-GGUF:Q4_K_M</div></body>
</html>
```
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+8 -3
View File
@@ -7,11 +7,15 @@ ini_set('error_log', __DIR__ . '/../errors.log');
ini_set('display_errors', '0'); ini_set('display_errors', '0');
error_reporting(E_ALL); error_reporting(E_ALL);
define('AI_SITE_LLM_API_BASE_URI', 'http://ai2:11434/v1'); // define('AI_SITE_LLM_API_BASE_URI', 'http://ai2:11434/v1');
// $apiKey = 'sk-Y1FrlvtAV4PWwK40TSVq-Q';
// $model = 'unsloth/gemma-4-12B-it-qat-GGUF:Q4_K_XL';
define('AI_SITE_LLM_API_BASE_URI', 'http://localhost:8080/v1');
$apiKey = 'sk-Y1FrlvtAV4PWwK40TSVq-Q';
$model = 'bloomer010/Ling-3.0-tiny-GGUF:Q4_K_M';
$pexelsKey = 'Clyqp9i9pewaxiiAdqVya0yZuuedjHtUtJdjRipNltp7wf0dY8K10h4h'; $pexelsKey = 'Clyqp9i9pewaxiiAdqVya0yZuuedjHtUtJdjRipNltp7wf0dY8K10h4h';
$apiKey = 'sk-Y1FrlvtAV4PWwK40TSVq-Q';
$model = 'unsloth/gemma-4-12B-it-qat-GGUF:Q4_K_XL';
$maxTokens = 32768; $maxTokens = 32768;
$reasoningEffort = 'medium'; $reasoningEffort = 'medium';
$httpTimeoutSeconds = (float) (getenv('LLAMA_HTTP_TIMEOUT') ?: '600'); $httpTimeoutSeconds = (float) (getenv('LLAMA_HTTP_TIMEOUT') ?: '600');
@@ -312,6 +316,7 @@ Task:
- On every run, first choose a unique page concept with a specific topic, visual theme, and style direction. - On every run, first choose a unique page concept with a specific topic, visual theme, and style direction.
- Then generate one complete, production-ready HTML document from scratch. - Then generate one complete, production-ready HTML document from scratch.
- The page should be fully in English, including all text content and any text in images. - The page should be fully in English, including all text content and any text in images.
- Output only the raw HTML page, no markdown code fences.
Hard output rules: Hard output rules:
- Return only raw HTML. No markdown. No code fences. No explanations. - Return only raw HTML. No markdown. No code fences. No explanations.
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB