Compare commits

...

3 Commits

Author SHA1 Message Date
DanielS
36227215fc fix: add type annotation for slider index parameter
All checks were successful
Production Build & Deploy / build-and-deploy (push) Successful in 27s
2026-07-18 04:52:37 +02:00
DanielS
7bebcc066e feat: replace hero tabs with interactive template slider 2026-07-18 04:50:55 +02:00
DanielS
934a047586 style: change hero visual tabs to industry templates 2026-07-18 04:48:48 +02:00

View File

@@ -1,5 +1,18 @@
---
// src/components/HeroAndLiquidGlass.astro
const heroTemplates = [
{ id: "01", name: "Der Handwerker-Klassiker", style: "Einfach & Bodenständig", layout: "boxed", design: "Brutalismus", colors: "from-[#FDFBF7] to-[#FAF7F2] text-[#2C1A11] border-[#2C1A11]/10" },
{ id: "02", name: "Dachdecker Meister", style: "Elegant & Professionell", layout: "split", design: "Glassmorphismus", colors: "from-zinc-900 to-zinc-950 text-white border-yellow-500/20" },
{ id: "03", name: "Solar & Photovoltaik", style: "Tech & Zukunft", layout: "bento", design: "SaaS-Minimalismus", colors: "from-zinc-900 to-black text-zinc-100 border-orange-500/20" },
{ id: "04", name: "Die Kanzlei", style: "Seriös & Clean", layout: "asymmetric", design: "Glassmorphismus", colors: "from-[#0B0F19] to-[#070A13] text-white border-emerald-500/20" },
{ id: "05", name: "Bio-Hofladen", style: "Rustikal & Natur", layout: "single", design: "Neomorphismus", colors: "from-[#FAF7F2] to-[#E8DCC4] text-[#4A3B32] border-[#E8DCC4]" },
{ id: "06", name: "Sanitär & Heizung", style: "Klar & Zuverlässig", layout: "bento", design: "SaaS-Minimalismus", colors: "from-white to-slate-50 text-slate-800 border-slate-200" },
{ id: "07", name: "KFZ Schnellservice", style: "Dynamisch & Direkt", layout: "split", design: "Brutalismus", colors: "from-zinc-800 to-zinc-900 text-white border-zinc-700" },
{ id: "08", name: "Schreinerei Holzart", style: "Handwerk & Präzision", layout: "boxed", design: "SaaS-Minimalismus", colors: "from-[#F5F2EB] to-[#D9D2C5] text-[#3D3A36] border-[#D9D2C5]" },
{ id: "09", name: "Steuerberater Premium", style: "Exklusiv & Diskret", layout: "bento", design: "Glassmorphismus", colors: "from-slate-900 to-slate-950 text-slate-100 border-amber-500/20" },
{ id: "10", name: "Garten- & Landschaftsbau", style: "Frisch & Modern", layout: "asymmetric", design: "Glassmorphismus", colors: "from-[#F3F7F4] to-white text-slate-800 border-emerald-200" }
];
---
<!-- Hero-Sektion: Hybrid Liquid Glass Style & Aurora Glow -->
@@ -49,10 +62,6 @@
<!-- Textur-Noise -->
<div class="absolute inset-0 opacity-[0.02] dark:opacity-[0.01] pointer-events-none bg-[radial-gradient(#000_1px,transparent_1px)] dark:bg-[radial-gradient(#fff_1px,transparent_1px)] [background-size:8px_8px] transition-opacity duration-300"></div>
<!-- Helle innere Sphären -->
<div class="absolute -top-12 -right-12 w-32 h-32 rounded-full bg-sky-200/35 dark:bg-sky-400/10 blur-xl group-hover:scale-110 transition-transform duration-700"></div>
<div class="absolute -bottom-16 -left-16 w-40 h-40 rounded-full bg-indigo-200/25 dark:bg-indigo-500/10 blur-xl group-hover:scale-110 transition-transform duration-700"></div>
<!-- Taktile Details -->
<span class="absolute top-3 left-3 w-2 h-2 border-t border-l border-slate-300 dark:border-white/30"></span>
<span class="absolute top-3 right-3 w-2 h-2 border-t border-r border-slate-300 dark:border-white/30"></span>
@@ -60,8 +69,8 @@
<span class="absolute bottom-3 right-3 w-2 h-2 border-b border-r border-slate-300 dark:border-white/30"></span>
<!-- Header -->
<div class="flex justify-between items-center relative z-10">
<span class="text-[9px] font-mono text-slate-400 dark:text-zinc-500 tracking-widest">SYSTEM STATUS: ACTIVE</span>
<div class="relative z-10 flex justify-between items-center mb-3">
<span class="text-[9px] font-mono text-slate-400 dark:text-zinc-500 tracking-widest uppercase" id="hero-slider-counter">TEMPLATE 01 / 10</span>
<div class="flex gap-1">
<span class="w-1.5 h-1.5 rounded-full bg-slate-300 dark:bg-red-500/60"></span>
<span class="w-1.5 h-1.5 rounded-full bg-slate-300 dark:bg-yellow-500/60"></span>
@@ -69,23 +78,83 @@
</div>
</div>
<!-- Grafik -->
<div class="my-auto relative z-10 flex flex-col items-center">
<div class="w-24 h-24 rounded-full border border-sky-200 dark:border-white/10 flex items-center justify-center bg-white/60 dark:bg-white/[0.02] relative group-hover:border-sky-400/40 transition-colors duration-500 shadow-inner">
<svg class="w-8 h-8 text-sky-600 dark:text-sky-400 stroke-[1.5]" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M9.813 15.904L9 21m0 0l-.813-5.096L3 15.187m6 5.813a2.25 2.25 0 100-4.5 2.25 2.25 0 000 4.5zM19.071 5.929a10 10 0 00-14.142 0M17.657 7.343a8 8 0 00-11.314 0M16.243 8.757a6 6 0 00-8.486 0M19.071 19.071L12 12" />
</svg>
</div>
<span class="text-xs font-mono text-slate-800 dark:text-zinc-300 mt-4 tracking-wider uppercase font-bold">Lighthouse Perfekt</span>
<span class="text-[10px] text-slate-500 font-mono mt-1">Speed Index: 0.4s</span>
<!-- Dynamic Slider Content -->
<div class="my-auto relative z-10 w-full overflow-hidden h-48">
{heroTemplates.map((item, index) => (
<div id={`hero-slide-${index}`} class={`hero-slide absolute inset-0 transition-all duration-500 flex flex-col justify-between ${index === 0 ? 'opacity-100 scale-100 pointer-events-auto' : 'opacity-0 scale-95 pointer-events-none'}`}>
<div class:list={["relative w-full h-full rounded-2xl border bg-gradient-to-br p-4 flex flex-col justify-between shadow-inner", item.colors]}>
<!-- Top bar inside preview card -->
<div class="flex justify-between items-center border-b border-current/5 pb-2">
<span class="text-[9px] font-mono opacity-60 tracking-wider">TEMPLATE {item.id}</span>
<span class="text-[9px] font-mono px-1.5 py-0.5 rounded bg-current/10 uppercase font-bold">{item.layout}</span>
</div>
<!-- Mini layout representations -->
<div class="flex-grow py-3 flex gap-2 opacity-30">
{item.layout === "bento" && (
<div class="w-full grid grid-cols-3 gap-1">
<div class="col-span-2 h-5 bg-current/20 rounded"></div>
<div class="h-5 bg-current/20 rounded"></div>
<div class="h-7 bg-current/25 rounded"></div>
<div class="col-span-2 h-7 bg-current/20 rounded"></div>
</div>
)}
{item.layout === "split" && (
<div class="w-full grid grid-cols-2 gap-2">
<div class="h-14 bg-current/20 rounded"></div>
<div class="h-14 bg-current/30 rounded flex flex-col justify-end p-1"><div class="h-1.5 w-3/4 bg-current/20 rounded"></div></div>
</div>
)}
{item.layout === "boxed" && (
<div class="w-full border border-current/20 rounded p-1 flex flex-col gap-1">
<div class="h-2 bg-current/20 rounded"></div>
<div class="h-9 bg-current/20 rounded"></div>
</div>
)}
{item.layout === "asymmetric" && (
<div class="w-full flex gap-2">
<div class="w-1/3 h-14 bg-current/25 rounded"></div>
<div class="w-2/3 h-10 bg-current/15 rounded"></div>
</div>
)}
{item.layout === "single" && (
<div class="w-full flex flex-col gap-1">
<div class="h-3 bg-current/20 rounded"></div>
<div class="h-3 bg-current/20 rounded"></div>
<div class="h-6 bg-current/20 rounded"></div>
</div>
)}
</div>
<!-- Bottom info -->
<div class="flex justify-between items-end pt-2 border-t border-current/5">
<div>
<h3 class="text-xs font-bold leading-none">{item.name}</h3>
<span class="text-[9px] opacity-60 mt-1 block">{item.style}</span>
</div>
<span class="text-[9px] font-mono px-1.5 py-0.5 rounded bg-current/5 uppercase">{item.design}</span>
</div>
</div>
</div>
))}
</div>
<!-- Footer -->
<div class="relative z-10 border-t border-slate-100 dark:border-white/5 pt-4">
<div class="flex justify-between items-baseline">
<span class="text-2xl font-bold text-slate-900 dark:text-white tracking-tight">100 / 100</span>
<span class="text-[9px] font-mono text-emerald-600 dark:text-emerald-400 uppercase tracking-widest font-bold">BEST SCORE</span>
<!-- Navigation Footer -->
<div class="relative z-10 border-t border-slate-100 dark:border-white/5 pt-4 flex justify-between items-center">
<!-- Left/Right Buttons -->
<div class="flex gap-2">
<button id="hero-slider-prev" aria-label="Vorheriges Template" class="w-8 h-8 rounded-lg bg-black/5 hover:bg-black/10 dark:bg-white/5 dark:hover:bg-white/10 flex items-center justify-center text-slate-700 dark:text-white transition-colors border border-black/5 dark:border-white/5">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" class="w-2.5 h-2.5 fill-current"><path d="M9.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l192 192c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 246.6 86.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-192 192z"/></svg>
</button>
<button id="hero-slider-next" aria-label="Nächstes Template" class="w-8 h-8 rounded-lg bg-black/5 hover:bg-black/10 dark:bg-white/5 dark:hover:bg-white/10 flex items-center justify-center text-slate-700 dark:text-white transition-colors border border-black/5 dark:border-white/5">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" class="w-2.5 h-2.5 fill-current"><path d="M310.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-192 192c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L242.7 256 73.4 86.6c-12.5-12.5-12.5-32.8 0-45.3s-32.8-12.5-45.3 0l192 192z"/></svg>
</button>
</div>
<a href="/templates" class="inline-flex items-center gap-1.5 px-3 py-1.5 bg-sky-600 hover:bg-sky-700 dark:bg-sky-500/10 dark:hover:bg-sky-500/20 text-white dark:text-sky-400 font-bold text-[10px] uppercase tracking-wider rounded-lg border border-transparent dark:border-sky-500/20 transition-colors">
Alle Templates
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" class="w-2.5 h-2.5 fill-current" aria-hidden="true"><path d="M438.6 278.6c12.5-12.5 12.5-32.8 0-45.3l-160-160c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L338.8 224 32 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l306.7 0L233.4 393.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l160-160z"/></svg>
</a>
</div>
</div>
</div>
@@ -129,7 +198,7 @@
</div>
<!-- Liquid Glass Service Grid -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<!-- Card 1: Webdesign -->
<div class="relative rounded-2xl border border-white/80 dark:border-white/[0.06] bg-white/40 dark:bg-transparent p-8 backdrop-blur-xl hover:border-sky-300 dark:hover:border-sky-500/20 hover:bg-white/60 dark:hover:bg-slate-950/20 transition-all duration-300 group flex flex-col justify-between min-h-[260px] shadow-sm hover:shadow-md reveal">
@@ -182,6 +251,28 @@
<span class="text-[9px] font-mono text-slate-400 dark:text-zinc-600 mt-6 tracking-wider">Codeschreinerei</span>
</div>
<!-- Card 4: Lighthouse Perfekt -->
<div class="relative rounded-2xl border border-white/80 dark:border-white/[0.06] bg-white/40 dark:bg-transparent p-8 backdrop-blur-xl hover:border-sky-300 dark:hover:border-sky-500/20 hover:bg-white/60 dark:hover:bg-slate-950/20 transition-all duration-300 group flex flex-col justify-between min-h-[260px] shadow-sm hover:shadow-md reveal">
<span class="absolute top-3 left-3 w-1.5 h-1.5 border-t border-l border-slate-300 dark:border-zinc-700/50"></span>
<span class="absolute top-3 right-3 w-1.5 h-1.5 border-t border-r border-slate-300 dark:border-zinc-700/50"></span>
<div>
<div class="w-10 h-10 rounded bg-sky-50 border border-sky-100 dark:bg-sky-400/5 dark:border-sky-400/10 flex items-center justify-center text-sky-600 dark:text-sky-400 group-hover:border-sky-300 dark:group-hover:border-sky-400/30 transition-all duration-300 mb-6">
<svg class="w-5 h-5 text-sky-600 dark:text-sky-400 stroke-[1.5]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M9.813 15.904L9 21m0 0l-.813-5.096L3 15.187m6 5.813a2.25 2.25 0 100-4.5 2.25 2.25 0 000 4.5zM19.071 5.929a10 10 0 00-14.142 0M17.657 7.343a8 8 0 00-11.314 0M16.243 8.757a6 6 0 00-8.486 0M19.071 19.071L12 12" />
</svg>
</div>
<h3 class="text-lg font-bold text-slate-950 dark:text-white mb-2 uppercase tracking-tight transition-colors duration-300">Lighthouse Perfekt</h3>
<p class="text-slate-600 dark:text-zinc-400 text-xs leading-relaxed transition-colors duration-300">
Wir programmieren so sauber, dass wir regelmäßig die Bestnote 100/100 im Google Speed Index erzielen.
</p>
</div>
<div class="flex justify-between items-baseline mt-6 pt-4 border-t border-slate-100 dark:border-white/5">
<span class="text-lg font-bold text-slate-900 dark:text-white tracking-tight">100 / 100</span>
<span class="text-[9px] font-mono text-emerald-600 dark:text-emerald-400 uppercase tracking-widest font-bold">BEST SCORE</span>
</div>
</div>
</div>
<!-- Showcase-Link Callout -->
@@ -331,4 +422,36 @@
});
}
});
// Hero Template Slider
const slides = document.querySelectorAll('.hero-slide');
const prevBtn = document.getElementById('hero-slider-prev');
const nextBtn = document.getElementById('hero-slider-next');
const counter = document.getElementById('hero-slider-counter');
let currentIdx = 0;
const totalSlides = slides.length;
function updateSlider(newIdx: number) {
// Hide current slide
slides[currentIdx].classList.remove('opacity-100', 'scale-100', 'pointer-events-auto');
slides[currentIdx].classList.add('opacity-0', 'scale-95', 'pointer-events-none');
// Update index
currentIdx = (newIdx + totalSlides) % totalSlides;
// Show new slide
slides[currentIdx].classList.remove('opacity-0', 'scale-95', 'pointer-events-none');
slides[currentIdx].classList.add('opacity-100', 'scale-100', 'pointer-events-auto');
// Update counter text
if (counter) {
const templateNum = String(currentIdx + 1).padStart(2, '0');
counter.textContent = `TEMPLATE ${templateNum} / ${totalSlides}`;
}
}
if (prevBtn && nextBtn) {
prevBtn.addEventListener('click', () => updateSlider(currentIdx - 1));
nextBtn.addEventListener('click', () => updateSlider(currentIdx + 1));
}
</script>