feat: add template marquee and fix gdpr google fonts request
All checks were successful
Production Build & Deploy / build-and-deploy (push) Successful in 28s

This commit is contained in:
DanielS
2026-07-18 04:37:41 +02:00
parent ad2f7c32a1
commit 11e836fc30
6 changed files with 366 additions and 225 deletions

20
package-lock.json generated
View File

@@ -10,6 +10,8 @@
"dependencies": { "dependencies": {
"@astrojs/react": "^3.6.3", "@astrojs/react": "^3.6.3",
"@astrojs/tailwind": "^5.1.4", "@astrojs/tailwind": "^5.1.4",
"@fontsource/inter": "^5.2.8",
"@fontsource/space-grotesk": "^5.2.10",
"@types/react": "^19.2.17", "@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"astro": "^4.16.0", "astro": "^4.16.0",
@@ -575,6 +577,24 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/@fontsource/inter": {
"version": "5.2.8",
"resolved": "https://registry.npmjs.org/@fontsource/inter/-/inter-5.2.8.tgz",
"integrity": "sha512-P6r5WnJoKiNVV+zvW2xM13gNdFhAEpQ9dQJHt3naLvfg+LkF2ldgSLiF4T41lf1SQCM9QmkqPTn4TH568IRagg==",
"license": "OFL-1.1",
"funding": {
"url": "https://github.com/sponsors/ayuhito"
}
},
"node_modules/@fontsource/space-grotesk": {
"version": "5.2.10",
"resolved": "https://registry.npmjs.org/@fontsource/space-grotesk/-/space-grotesk-5.2.10.tgz",
"integrity": "sha512-XNXEbT74OIITPqw2H6HXwPDp85fy43uxfBwFR5PU+9sLnjuLj12KlhVM9nZVN6q6dlKjkuN8JisW/OBxwxgUew==",
"license": "OFL-1.1",
"funding": {
"url": "https://github.com/sponsors/ayuhito"
}
},
"node_modules/@img/sharp-darwin-arm64": { "node_modules/@img/sharp-darwin-arm64": {
"version": "0.33.5", "version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz",

View File

@@ -14,6 +14,8 @@
"dependencies": { "dependencies": {
"@astrojs/react": "^3.6.3", "@astrojs/react": "^3.6.3",
"@astrojs/tailwind": "^5.1.4", "@astrojs/tailwind": "^5.1.4",
"@fontsource/inter": "^5.2.8",
"@fontsource/space-grotesk": "^5.2.10",
"@types/react": "^19.2.17", "@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"astro": "^4.16.0", "astro": "^4.16.0",

View File

@@ -0,0 +1,145 @@
---
// src/components/TemplateMarquee.astro
const templates = [
{ id: "01", name: "Der Handwerker-Klassiker", style: "Einfach & Bodenständig", layout: "boxed", design: "Brutalismus", colors: "from-[#FDFBF7] to-[#FAF7F2] text-[#2C1A11]" },
{ 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]" },
{ 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]" }
];
// Double list for infinite wrap animation
const rowData = [...templates, ...templates];
---
<section class="py-12 bg-slate-50 dark:bg-[#070A13] overflow-hidden relative border-t border-slate-200 dark:border-white/5 transition-colors duration-300">
<!-- Subtle background glow -->
<div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[80%] h-[60%] bg-sky-500/5 dark:bg-sky-500/[0.02] blur-[120px] rounded-full pointer-events-none"></div>
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 mb-8 relative z-10">
<div class="max-w-3xl">
<h2 class="text-2xl sm:text-3xl font-extrabold text-slate-900 dark:text-white tracking-tight uppercase">
Unsere Design-Vorlagen
</h2>
<p class="text-slate-600 dark:text-zinc-400 text-xs sm:text-sm mt-2">
Entdecken Sie vorkonfigurierte Layouts. Vollständig anpassbar und optimiert.
</p>
</div>
</div>
<!-- Single Marquee row container -->
<div class="relative z-10 w-full overflow-hidden">
<div class="marquee-wrapper">
<div class="marquee-track marquee-left">
{rowData.map((item, index) => (
<div class="marquee-item group relative w-72 sm:w-80 h-44 rounded-2xl border border-white/80 dark:border-white/[0.06] bg-gradient-to-br backdrop-blur-xl transition-all duration-300 hover:-translate-y-1.5 hover:border-sky-300 dark:hover:border-sky-500/30 shadow-sm hover:shadow-xl p-4 flex flex-col justify-between overflow-hidden cursor-pointer select-none" class:list={[item.colors]}>
<!-- Top bar -->
<div class="flex justify-between items-center border-b border-black/5 dark:border-white/5 pb-2">
<span class="text-[9px] font-mono opacity-60 tracking-wider">TEMPLATE {item.id}</span>
<div class="flex gap-1">
<span class="w-1.5 h-1.5 rounded-full bg-black/10 dark:bg-white/10"></span>
<span class="w-1.5 h-1.5 rounded-full bg-black/10 dark:bg-white/10"></span>
<span class="w-1.5 h-1.5 rounded-full bg-black/10 dark:bg-white/10"></span>
</div>
</div>
<!-- Mini layout representations -->
<div class="flex-grow py-3 flex gap-2">
{item.layout === "bento" && (
<div class="w-full grid grid-cols-3 gap-1 opacity-40">
<div class="col-span-2 h-7 bg-current/10 rounded"></div>
<div class="h-7 bg-current/10 rounded"></div>
<div class="h-10 bg-current/10 rounded"></div>
<div class="col-span-2 h-10 bg-current/10 rounded"></div>
</div>
)}
{item.layout === "split" && (
<div class="w-full grid grid-cols-2 gap-2 opacity-40">
<div class="h-16 bg-current/10 rounded"></div>
<div class="h-16 bg-current/20 rounded flex flex-col justify-end p-1"><div class="h-2 w-3/4 bg-current/20 rounded"></div></div>
</div>
)}
{item.layout === "boxed" && (
<div class="w-full border border-current/10 rounded p-1 opacity-40 flex flex-col gap-1">
<div class="h-3 bg-current/10 rounded"></div>
<div class="h-10 bg-current/10 rounded"></div>
</div>
)}
{item.layout === "asymmetric" && (
<div class="w-full flex gap-2 opacity-40">
<div class="w-1/3 h-16 bg-current/10 rounded"></div>
<div class="w-2/3 h-12 bg-current/15 rounded"></div>
</div>
)}
{item.layout === "single" && (
<div class="w-full flex flex-col gap-1.5 opacity-40">
<div class="h-4 bg-current/10 rounded"></div>
<div class="h-4 bg-current/10 rounded"></div>
<div class="h-8 bg-current/10 rounded"></div>
</div>
)}
</div>
<!-- Bottom info -->
<div class="flex justify-between items-end pt-2 border-t border-black/5 dark:border-white/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-black/5 dark:bg-white/5 uppercase">{item.design}</span>
</div>
<!-- Hover Preview Overlay Button -->
<div class="absolute inset-0 bg-slate-900/60 dark:bg-black/75 backdrop-blur-sm opacity-0 group-hover:opacity-100 flex items-center justify-center transition-all duration-300 z-20">
<a href="/templates" class="px-4 py-2 bg-sky-500 hover:bg-sky-400 text-white font-bold text-xs uppercase tracking-wider rounded shadow-md transform translate-y-4 group-hover:translate-y-0 transition-all duration-300">
Vorschau
</a>
</div>
</div>
))}
</div>
</div>
</div>
</section>
<style>
.marquee-wrapper {
display: flex;
width: 100%;
overflow: hidden;
user-select: none;
mask-image: linear-gradient(to right, transparent 0%, black 10%, black 90%, transparent 100%);
}
.marquee-track {
display: flex;
flex-shrink: 0;
gap: 1.5rem;
min-width: 100%;
padding: 0.5rem 0.75rem;
will-change: transform;
transform: translateZ(0);
}
.marquee-left {
animation: scroll-left 45s linear infinite;
}
/* Hover to pause animation */
.marquee-wrapper:hover .marquee-track {
animation-play-state: paused;
}
@keyframes scroll-left {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-50%);
}
}
</style>

View File

@@ -1,4 +1,14 @@
--- ---
import '@fontsource/inter/300.css';
import '@fontsource/inter/400.css';
import '@fontsource/inter/500.css';
import '@fontsource/inter/600.css';
import '@fontsource/inter/700.css';
import '@fontsource/space-grotesk/400.css';
import '@fontsource/space-grotesk/500.css';
import '@fontsource/space-grotesk/600.css';
import '@fontsource/space-grotesk/700.css';
interface Props { interface Props {
title: string; title: string;
description?: string; description?: string;
@@ -16,11 +26,6 @@ const { title, description = "Professionelles Webdesign & moderne Websites für
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<title>{title}</title> <title>{title}</title>
<!-- Google Fonts -->
<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=Inter:wght@300;400;500;600;700&family=Space+Grotesk:wght@400;500;600;700&display=swap" rel="stylesheet">
<!-- Inline script to set dark/light mode before page renders --> <!-- Inline script to set dark/light mode before page renders -->
<script is:inline> <script is:inline>
(function() { (function() {

View File

@@ -3,6 +3,7 @@ import Layout from '../layouts/Layout.astro';
import Navbar from '../components/Navbar.astro'; import Navbar from '../components/Navbar.astro';
import Footer from '../components/Footer.astro'; import Footer from '../components/Footer.astro';
import HeroAndLiquidGlass from '../components/HeroAndLiquidGlass.astro'; import HeroAndLiquidGlass from '../components/HeroAndLiquidGlass.astro';
import TemplateMarquee from '../components/TemplateMarquee.astro';
--- ---
<Layout title="N&D i-t SOLUTIONS | Webdesign & Entwicklung"> <Layout title="N&D i-t SOLUTIONS | Webdesign & Entwicklung">
@@ -12,6 +13,9 @@ import HeroAndLiquidGlass from '../components/HeroAndLiquidGlass.astro';
{/* Clean, modular Hero and Liquid Glass section */} {/* Clean, modular Hero and Liquid Glass section */}
<HeroAndLiquidGlass /> <HeroAndLiquidGlass />
<!-- Infinite Template Marquee Ticker -->
<TemplateMarquee />
<!-- Contact section (separate, clean layout) --> <!-- Contact section (separate, clean layout) -->
<section id="contact" class="py-20 bg-slate-50 dark:bg-[#0B0F19] relative border-t border-slate-200 dark:border-white/5 transition-colors duration-300"> <section id="contact" class="py-20 bg-slate-50 dark:bg-[#0B0F19] relative border-t border-slate-200 dark:border-white/5 transition-colors duration-300">
<div class="absolute inset-0 opacity-[0.015] pointer-events-none bg-[radial-gradient(#000_1px,transparent_1px)] dark:bg-[radial-gradient(#fff_1px,transparent_1px)] [background-size:16px_16px] transition-opacity duration-300"></div> <div class="absolute inset-0 opacity-[0.015] pointer-events-none bg-[radial-gradient(#000_1px,transparent_1px)] dark:bg-[radial-gradient(#fff_1px,transparent_1px)] [background-size:16px_16px] transition-opacity duration-300"></div>

View File

@@ -1,8 +1,8 @@
--- ---
import Layout from '../layouts/Layout.astro'; import Layout from "../layouts/Layout.astro";
import Navbar from '../components/Navbar.astro'; import Navbar from "../components/Navbar.astro";
import Footer from '../components/Footer.astro'; import Footer from "../components/Footer.astro";
import { FaArrowLeft, FaDesktop } from 'react-icons/fa'; import { FaArrowLeft, FaEye, FaDesktop } from "react-icons/fa";
// List of 20 design templates showcasing maximum diversity in color, structure, and style // List of 20 design templates showcasing maximum diversity in color, structure, and style
const templates = [ const templates = [
@@ -12,13 +12,12 @@ const templates = [
style: "Einfach & Bodenständig", style: "Einfach & Bodenständig",
layout: "Boxed Layout", layout: "Boxed Layout",
design: "Brutalismus", design: "Brutalismus",
colorScheme: "Sand & Terrakotta", colorScheme: "Warm & Earthy (Sand & Terrakotta)",
bgClass: "bg-[#FDFBF7] text-[#2C1A11] border-[#2C1A11]/20", bgClass: "bg-[#FDFBF7] text-[#2C1A11] border-[#2C1A11]/20",
theme: "light", theme: "light",
accentColor: "bg-[#D97706]", accentColor: "bg-[#D97706]",
badgeClass: "bg-[#D97706]/10 text-[#D97706]", badgeClass: "bg-[#D97706]/10 text-[#D97706]",
layoutPreview: "boxed", layoutPreview: "boxed",
category: "handwerk"
}, },
{ {
id: "02", id: "02",
@@ -26,13 +25,12 @@ const templates = [
style: "Elegant & Professionell", style: "Elegant & Professionell",
layout: "Split-Screen", layout: "Split-Screen",
design: "Glassmorphismus", design: "Glassmorphismus",
colorScheme: "Anthrazit & Gold", colorScheme: "Deep Dark (Anthrazit & Gold)",
bgClass: "bg-[#18181B] text-white border-yellow-500/20", bgClass: "bg-[#18181B] text-white border-yellow-500/20",
theme: "dark", theme: "dark",
accentColor: "bg-yellow-500", accentColor: "bg-yellow-500",
badgeClass: "bg-yellow-500/10 text-yellow-400", badgeClass: "bg-yellow-500/10 text-yellow-400",
layoutPreview: "split", layoutPreview: "split",
category: "handwerk"
}, },
{ {
id: "03", id: "03",
@@ -40,13 +38,12 @@ const templates = [
style: "Tech & Zukunft", style: "Tech & Zukunft",
layout: "Bento-Grid", layout: "Bento-Grid",
design: "SaaS-Minimalismus", design: "SaaS-Minimalismus",
colorScheme: "Grau & Neon-Orange", colorScheme: "Tech-Vibrant (Grau & Neon-Orange)",
bgClass: "bg-zinc-900 text-zinc-100 border-orange-500/20", bgClass: "bg-zinc-900 text-zinc-100 border-orange-500/20",
theme: "dark", theme: "dark",
accentColor: "bg-orange-500", accentColor: "bg-orange-500",
badgeClass: "bg-orange-500/10 text-orange-400", badgeClass: "bg-orange-500/10 text-orange-400",
layoutPreview: "bento", layoutPreview: "bento",
category: "dienstleister"
}, },
{ {
id: "04", id: "04",
@@ -54,13 +51,12 @@ const templates = [
style: "Seriös & Clean", style: "Seriös & Clean",
layout: "Asymmetrisch", layout: "Asymmetrisch",
design: "Glassmorphismus", design: "Glassmorphismus",
colorScheme: "Anthrazit & Smaragd-Grün", colorScheme: "Deep Dark (Anthrazit & Smaragd-Grün)",
bgClass: "bg-[#0B0F19] text-white border-emerald-500/20", bgClass: "bg-[#0B0F19] text-white border-emerald-500/20",
theme: "dark", theme: "dark",
accentColor: "bg-emerald-500", accentColor: "bg-emerald-500",
badgeClass: "bg-emerald-500/10 text-emerald-400", badgeClass: "bg-emerald-500/10 text-emerald-400",
layoutPreview: "asymmetric", layoutPreview: "asymmetric",
category: "dienstleister"
}, },
{ {
id: "05", id: "05",
@@ -74,7 +70,6 @@ const templates = [
accentColor: "bg-[#C2410C]", accentColor: "bg-[#C2410C]",
badgeClass: "bg-[#C2410C]/10 text-[#C2410C]", badgeClass: "bg-[#C2410C]/10 text-[#C2410C]",
layoutPreview: "single", layoutPreview: "single",
category: "gastro"
}, },
{ {
id: "06", id: "06",
@@ -82,13 +77,12 @@ const templates = [
style: "Klar & Zuverlässig", style: "Klar & Zuverlässig",
layout: "Bento-Grid", layout: "Bento-Grid",
design: "SaaS-Minimalismus", design: "SaaS-Minimalismus",
colorScheme: "Weiß & Navy-Blau", colorScheme: "Clean Light (Weiß & Navy-Blau)",
bgClass: "bg-white text-slate-800 border-slate-200", bgClass: "bg-white text-slate-800 border-slate-200",
theme: "light", theme: "light",
accentColor: "bg-blue-800", accentColor: "bg-blue-800",
badgeClass: "bg-blue-800/10 text-blue-800", badgeClass: "bg-blue-800/10 text-blue-800",
layoutPreview: "bento", layoutPreview: "bento",
category: "handwerk"
}, },
{ {
id: "07", id: "07",
@@ -96,13 +90,12 @@ const templates = [
style: "Dynamisch & Direkt", style: "Dynamisch & Direkt",
layout: "Split-Screen", layout: "Split-Screen",
design: "Brutalismus", design: "Brutalismus",
colorScheme: "Grau & Neon-Orange", colorScheme: "Tech-Vibrant (Grau & Neon-Orange)",
bgClass: "bg-zinc-800 text-white border-zinc-700", bgClass: "bg-zinc-800 text-white border-zinc-700",
theme: "dark", theme: "dark",
accentColor: "bg-orange-600", accentColor: "bg-orange-600",
badgeClass: "bg-orange-600/15 text-orange-400", badgeClass: "bg-orange-600/15 text-orange-400",
layoutPreview: "split", layoutPreview: "split",
category: "handwerk"
}, },
{ {
id: "08", id: "08",
@@ -110,13 +103,12 @@ const templates = [
style: "Handwerk & Präzision", style: "Handwerk & Präzision",
layout: "Boxed Layout", layout: "Boxed Layout",
design: "SaaS-Minimalismus", design: "SaaS-Minimalismus",
colorScheme: "Sand-Töne", colorScheme: "Warm & Earthy (Sand-Töne)",
bgClass: "bg-[#F5F2EB] text-[#3D3A36] border-[#D9D2C5]", bgClass: "bg-[#F5F2EB] text-[#3D3A36] border-[#D9D2C5]",
theme: "light", theme: "light",
accentColor: "bg-[#8B5A2B]", accentColor: "bg-[#8B5A2B]",
badgeClass: "bg-[#8B5A2B]/10 text-[#8B5A2B]", badgeClass: "bg-[#8B5A2B]/10 text-[#8B5A2B]",
layoutPreview: "boxed", layoutPreview: "boxed",
category: "handwerk"
}, },
{ {
id: "09", id: "09",
@@ -124,13 +116,12 @@ const templates = [
style: "Exklusiv & Diskret", style: "Exklusiv & Diskret",
layout: "Bento-Grid", layout: "Bento-Grid",
design: "Glassmorphismus", design: "Glassmorphismus",
colorScheme: "Anthrazit & Gold", colorScheme: "Deep Dark (Anthrazit & Gold)",
bgClass: "bg-slate-900 text-slate-100 border-amber-500/20", bgClass: "bg-slate-900 text-slate-100 border-amber-500/20",
theme: "dark", theme: "dark",
accentColor: "bg-amber-500", accentColor: "bg-amber-500",
badgeClass: "bg-amber-500/10 text-amber-400", badgeClass: "bg-amber-500/10 text-amber-400",
layoutPreview: "bento", layoutPreview: "bento",
category: "dienstleister"
}, },
{ {
id: "10", id: "10",
@@ -138,13 +129,12 @@ const templates = [
style: "Frisch & Modern", style: "Frisch & Modern",
layout: "Asymmetrisch", layout: "Asymmetrisch",
design: "Glassmorphismus", design: "Glassmorphismus",
colorScheme: "Weiß & Salbei-Grün", colorScheme: "Clean Light (Weiß & Salbei-Grün)",
bgClass: "bg-[#F3F7F4] text-slate-800 border-emerald-200", bgClass: "bg-[#F3F7F4] text-slate-800 border-emerald-200",
theme: "light", theme: "light",
accentColor: "bg-emerald-700", accentColor: "bg-emerald-700",
badgeClass: "bg-emerald-700/10 text-emerald-800", badgeClass: "bg-emerald-700/10 text-emerald-800",
layoutPreview: "asymmetric", layoutPreview: "asymmetric",
category: "handwerk"
}, },
{ {
id: "11", id: "11",
@@ -152,13 +142,12 @@ const templates = [
style: "Clean & Vertrauensvoll", style: "Clean & Vertrauensvoll",
layout: "Minimalistisch 1-spaltig", layout: "Minimalistisch 1-spaltig",
design: "SaaS-Minimalismus", design: "SaaS-Minimalismus",
colorScheme: "Weiß & Navy-Blau", colorScheme: "Clean Light (Weiß & Navy-Blau)",
bgClass: "bg-slate-50 text-slate-800 border-slate-200", bgClass: "bg-slate-50 text-slate-800 border-slate-200",
theme: "light", theme: "light",
accentColor: "bg-[#1E3A8A]", accentColor: "bg-[#1E3A8A]",
badgeClass: "bg-[#1E3A8A]/10 text-[#1E3A8A]", badgeClass: "bg-[#1E3A8A]/10 text-[#1E3A8A]",
layoutPreview: "single", layoutPreview: "single",
category: "dienstleister"
}, },
{ {
id: "12", id: "12",
@@ -166,13 +155,12 @@ const templates = [
style: "Gemütlich & Lecker", style: "Gemütlich & Lecker",
layout: "Boxed Layout", layout: "Boxed Layout",
design: "Neomorphismus", design: "Neomorphismus",
colorScheme: "Terrakotta", colorScheme: "Warm & Earthy (Terrakotta)",
bgClass: "bg-[#FDF9F3] text-[#5C3E21] border-[#EADCC9]", bgClass: "bg-[#FDF9F3] text-[#5C3E21] border-[#EADCC9]",
theme: "light", theme: "light",
accentColor: "bg-[#B45309]", accentColor: "bg-[#B45309]",
badgeClass: "bg-[#B45309]/10 text-[#B45309]", badgeClass: "bg-[#B45309]/10 text-[#B45309]",
layoutPreview: "boxed", layoutPreview: "boxed",
category: "gastro"
}, },
{ {
id: "13", id: "13",
@@ -180,13 +168,12 @@ const templates = [
style: "Präzise & Leistungsstark", style: "Präzise & Leistungsstark",
layout: "Split-Screen", layout: "Split-Screen",
design: "Brutalismus", design: "Brutalismus",
colorScheme: "Grau & Electric-Purple", colorScheme: "Tech-Vibrant (Grau & Electric-Purple)",
bgClass: "bg-neutral-900 text-neutral-100 border-purple-500/20", bgClass: "bg-neutral-900 text-neutral-100 border-purple-500/20",
theme: "dark", theme: "dark",
accentColor: "bg-purple-600", accentColor: "bg-purple-600",
badgeClass: "bg-purple-600/10 text-purple-400", badgeClass: "bg-purple-600/10 text-purple-400",
layoutPreview: "split", layoutPreview: "split",
category: "handwerk"
}, },
{ {
id: "14", id: "14",
@@ -194,13 +181,12 @@ const templates = [
style: "Stark & Motivierend", style: "Stark & Motivierend",
layout: "Asymmetrisch", layout: "Asymmetrisch",
design: "Brutalismus", design: "Brutalismus",
colorScheme: "Schwarz & Neon-Orange", colorScheme: "Deep Dark (Schwarz & Neon-Orange)",
bgClass: "bg-black text-white border-orange-500/20", bgClass: "bg-black text-white border-orange-500/20",
theme: "dark", theme: "dark",
accentColor: "bg-orange-500", accentColor: "bg-orange-500",
badgeClass: "bg-orange-500/10 text-orange-500", badgeClass: "bg-orange-500/10 text-orange-500",
layoutPreview: "asymmetric", layoutPreview: "asymmetric",
category: "dienstleister"
}, },
{ {
id: "15", id: "15",
@@ -208,13 +194,12 @@ const templates = [
style: "Minimalismus & Ästhetik", style: "Minimalismus & Ästhetik",
layout: "Split-Screen", layout: "Split-Screen",
design: "SaaS-Minimalismus", design: "SaaS-Minimalismus",
colorScheme: "Weiß & Navy-Blau", colorScheme: "Clean Light (Weiß & Navy-Blau)",
bgClass: "bg-white text-zinc-900 border-zinc-200", bgClass: "bg-white text-zinc-900 border-zinc-200",
theme: "light", theme: "light",
accentColor: "bg-zinc-900", accentColor: "bg-zinc-900",
badgeClass: "bg-zinc-950/10 text-zinc-900", badgeClass: "bg-zinc-950/10 text-zinc-900",
layoutPreview: "split", layoutPreview: "split",
category: "dienstleister"
}, },
{ {
id: "16", id: "16",
@@ -222,13 +207,12 @@ const templates = [
style: "Achtsam & Gesund", style: "Achtsam & Gesund",
layout: "Minimalistisch 1-spaltig", layout: "Minimalistisch 1-spaltig",
design: "Glassmorphismus", design: "Glassmorphismus",
colorScheme: "Weiß & Salbei-Grün", colorScheme: "Clean Light (Weiß & Salbei-Grün)",
bgClass: "bg-[#F7FAFC] text-slate-800 border-emerald-100", bgClass: "bg-[#F7FAFC] text-slate-800 border-emerald-100",
theme: "light", theme: "light",
accentColor: "bg-emerald-600", accentColor: "bg-emerald-600",
badgeClass: "bg-emerald-600/10 text-emerald-700", badgeClass: "bg-emerald-600/10 text-emerald-700",
layoutPreview: "single", layoutPreview: "single",
category: "dienstleister"
}, },
{ {
id: "17", id: "17",
@@ -236,13 +220,12 @@ const templates = [
style: "Hart & Präzise", style: "Hart & Präzise",
layout: "Boxed Layout", layout: "Boxed Layout",
design: "Brutalismus", design: "Brutalismus",
colorScheme: "Anthrazit & Smaragd-Grün", colorScheme: "Deep Dark (Anthrazit & Smaragd-Grün)",
bgClass: "bg-stone-900 text-stone-100 border-emerald-500/20", bgClass: "bg-stone-900 text-stone-100 border-emerald-500/20",
theme: "dark", theme: "dark",
accentColor: "bg-emerald-600", accentColor: "bg-emerald-600",
badgeClass: "bg-emerald-600/10 text-emerald-400", badgeClass: "bg-emerald-600/10 text-emerald-400",
layoutPreview: "boxed", layoutPreview: "boxed",
category: "handwerk"
}, },
{ {
id: "18", id: "18",
@@ -250,13 +233,12 @@ const templates = [
style: "Rustikal & Einladend", style: "Rustikal & Einladend",
layout: "Bento-Grid", layout: "Bento-Grid",
design: "Neomorphismus", design: "Neomorphismus",
colorScheme: "Sand-Töne", colorScheme: "Warm & Earthy (Sand-Töne)",
bgClass: "bg-[#FAF6F0] text-[#543D2B] border-[#EFEAE2]", bgClass: "bg-[#FAF6F0] text-[#543D2B] border-[#EFEAE2]",
theme: "light", theme: "light",
accentColor: "bg-[#A75D5D]", accentColor: "bg-[#A75D5D]",
badgeClass: "bg-[#A75D5D]/10 text-[#A75D5D]", badgeClass: "bg-[#A75D5D]/10 text-[#A75D5D]",
layoutPreview: "bento", layoutPreview: "bento",
category: "gastro"
}, },
{ {
id: "19", id: "19",
@@ -264,13 +246,12 @@ const templates = [
style: "Sauber & Strukturiert", style: "Sauber & Strukturiert",
layout: "Bento-Grid", layout: "Bento-Grid",
design: "SaaS-Minimalismus", design: "SaaS-Minimalismus",
colorScheme: "Grau & Electric-Purple", colorScheme: "Tech-Vibrant (Grau & Electric-Purple)",
bgClass: "bg-[#1C1B22] text-zinc-100 border-indigo-500/20", bgClass: "bg-[#1C1B22] text-zinc-100 border-indigo-500/20",
theme: "dark", theme: "dark",
accentColor: "bg-indigo-500", accentColor: "bg-indigo-500",
badgeClass: "bg-indigo-500/10 text-indigo-400", badgeClass: "bg-indigo-500/10 text-indigo-400",
layoutPreview: "bento", layoutPreview: "bento",
category: "dienstleister"
}, },
{ {
id: "20", id: "20",
@@ -278,229 +259,213 @@ const templates = [
style: "Kreativ & Präzise", style: "Kreativ & Präzise",
layout: "Asymmetrisch", layout: "Asymmetrisch",
design: "Glassmorphismus", design: "Glassmorphismus",
colorScheme: "Grau & Neon-Orange", colorScheme: "Tech-Vibrant (Grau & Neon-Orange)",
bgClass: "bg-[#1E1E2E] text-zinc-100 border-orange-500/20", bgClass: "bg-[#1E1E2E] text-zinc-100 border-orange-500/20",
theme: "dark", theme: "dark",
accentColor: "bg-orange-500", accentColor: "bg-orange-500",
badgeClass: "bg-orange-500/10 text-orange-400", badgeClass: "bg-orange-500/10 text-orange-400",
layoutPreview: "asymmetric", layoutPreview: "asymmetric",
category: "handwerk" },
}
];
const categories = [
{ id: "all", name: "Alle Branchen" },
{ id: "handwerk", name: "Handwerk & Bau" },
{ id: "dienstleister", name: "Dienstleister & Praxis" },
{ id: "gastro", name: "Gastronomie & Handel" }
]; ];
--- ---
<Layout title="Template-Katalog | N&D i-t SOLUTIONS"> <Layout title="Template-Katalog | N&D i-t SOLUTIONS">
<Navbar /> <Navbar />
<main class="relative min-h-screen bg-slate-50 dark:bg-brand-darkBg text-slate-800 dark:text-white pt-28 pb-20 px-4 sm:px-6 lg:px-8 overflow-hidden transition-colors duration-300"> <main
class="relative min-h-screen bg-brand-darkBg text-white pt-28 pb-20 px-4 sm:px-6 lg:px-8 overflow-hidden tactile-grid-bg"
<!-- Background Glow (Aurora Effect) --> >
<div class="absolute top-1/4 left-1/2 -translate-x-1/2 w-[600px] h-[600px] bg-sky-500/[0.03] blur-[150px] pointer-events-none rounded-full transition-colors duration-300"></div> <!-- Background Glow (Aurora Effect - kept extremely subtle) -->
<div
class="absolute top-1/4 left-1/2 -translate-x-1/2 w-[600px] h-[600px] bg-sky-500/[0.02] blur-[150px] pointer-events-none rounded-full"
>
</div>
<div
class="absolute top-2/3 left-1/3 w-[400px] h-[400px] bg-blue-600/[0.02] blur-[120px] pointer-events-none rounded-full"
>
</div>
<div class="max-w-7xl mx-auto relative z-10"> <div class="max-w-7xl mx-auto relative z-10">
<!-- Back Link --> <!-- Back Link -->
<a href="/" class="inline-flex items-center gap-2 text-slate-500 dark:text-zinc-400 hover:text-brand-arcticBlue text-xs uppercase tracking-wider font-semibold mb-8 group transition-colors"> <a
<FaArrowLeft class="w-3 h-3 group-hover:-translate-x-1 transition-transform" /> href="/"
class="inline-flex items-center gap-2 text-zinc-400 hover:text-brand-arcticBlue text-xs uppercase tracking-wider font-semibold mb-8 group transition-colors"
>
<FaArrowLeft
class="w-3 h-3 group-hover:-translate-x-1 transition-transform"
/>
Zurück zur Startseite Zurück zur Startseite
</a> </a>
<!-- Header Section --> <!-- Header Section -->
<div class="max-w-3xl mb-12"> <div class="max-w-3xl mb-16">
<h1 class="text-4xl sm:text-6xl font-bold tracking-tight mb-4 text-slate-900 dark:text-white uppercase"> <h1 class="text-4xl sm:text-6xl font-bold tracking-tight mb-4">
Die perfekte Struktur für <span class="text-brand-arcticBlue">jeden Betrieb.</span> Die perfekte Struktur für <span class="text-brand-arcticBlue"
>jeden Betrieb.</span
>
</h1> </h1>
<p class="text-slate-600 dark:text-zinc-400 text-sm sm:text-base leading-relaxed"> <p class="text-zinc-400 text-sm sm:text-base leading-relaxed">
Egal ob klassische Schreinerei, moderne Anwaltskanzlei oder lokaler Handwerker: Wir passen das Design perfekt an Ihren Stil an. Hier sind 20 beispielhafte Bento-Kombinationen, Farbwelten und Layout-Konzepte. Egal ob klassische Schreinerei, moderne Anwaltskanzlei oder lokaler
Handwerker: Wir passen das Design perfekt an Ihren Stil an. Hier sind
20 beispielhafte Bento-Kombinationen, Farbwelten und Layout-Konzepte.
</p> </p>
</div> </div>
<!-- Gewerke Filter (Barrierefrei, 44px min-h) -->
<div class="flex flex-wrap gap-2.5 mb-10">
{categories.map((cat, idx) => (
<button
data-filter={cat.id}
class={`filter-btn px-5 py-2.5 rounded-xl text-xs font-bold uppercase tracking-wider border transition-all duration-300 min-h-[44px] focus:outline-none focus:ring-2 focus:ring-sky-500 ${
idx === 0
? "bg-brand-arcticBlue border-brand-arcticBlue text-zinc-950"
: "border-slate-200 dark:border-zinc-700/50 bg-white/40 dark:bg-slate-900/40 text-slate-600 dark:text-zinc-400 hover:border-brand-arcticBlue hover:text-brand-arcticBlue dark:hover:text-white"
}`}
>
{cat.name}
</button>
))}
</div>
<!-- Grid System Container (20 Bento-Kacheln) --> <!-- Grid System Container (20 Bento-Kacheln) -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6" id="templates-grid"> <div
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6"
{templates.map((tpl) => ( >
<a href={`/templates/${tpl.id}`} data-category={tpl.category} class={`template-card group relative rounded-2xl p-6 border transition-all duration-500 flex flex-col justify-between h-[340px] ${tpl.bgClass} ${tpl.theme === 'dark' ? 'hover:border-white/20' : 'hover:border-black/20'} shadow-sm dark:shadow-lg cursor-pointer block tactile-noise origin-center`}> {
templates.map((tpl) => (
{/* Precision Blueprint Corner Markers */} <a
<span class="absolute top-2 left-2 w-1.5 h-1.5 border-t border-l border-current/25"></span> href={`/templates/${tpl.id}`}
<span class="absolute top-2 right-2 w-1.5 h-1.5 border-t border-r border-current/25"></span> class={`group relative rounded-2xl p-6 border transition-all duration-300 hover:scale-[1.01] flex flex-col justify-between h-[340px] ${tpl.bgClass} ${tpl.theme === "dark" ? "hover:border-white/20" : "hover:border-black/20"} shadow-lg cursor-pointer block tactile-noise`}
<span class="absolute bottom-2 left-2 w-1.5 h-1.5 border-b border-l border-current/25"></span> >
<span class="absolute bottom-2 right-2 w-1.5 h-1.5 border-b border-r border-current/25"></span> {/* Precision Blueprint Corner Markers */}
<span class="absolute top-2 left-2 w-1.5 h-1.5 border-t border-l border-current/25" />
<span class="absolute top-2 right-2 w-1.5 h-1.5 border-t border-r border-current/25" />
<span class="absolute bottom-2 left-2 w-1.5 h-1.5 border-b border-l border-current/25" />
<span class="absolute bottom-2 right-2 w-1.5 h-1.5 border-b border-r border-current/25" />
{/* Overlay glow for modern style */} {/* Overlay glow for modern style */}
<div class="absolute inset-0 bg-white/[0.01] dark:bg-white/[0.02] rounded-2xl pointer-events-none opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div> <div class="absolute inset-0 bg-white/[0.01] dark:bg-white/[0.02] rounded-2xl pointer-events-none opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
<div> <div>
{/* Badge & ID & Status Indicator */} {/* Badge & ID & Status Indicator */}
<div class="flex items-center justify-between mb-4"> <div class="flex items-center justify-between mb-4">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<span class={`text-[10px] font-mono font-bold uppercase px-2 py-0.5 rounded ${tpl.badgeClass}`}> <span
{tpl.style} class={`text-[10px] font-mono font-bold uppercase px-2 py-0.5 rounded ${tpl.badgeClass}`}
</span> >
<span class="relative flex h-2 w-2" title="Vorschau aktiv"> {tpl.style}
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span> </span>
<span class="relative inline-flex rounded-full h-2 w-2 bg-emerald-500"></span> <span class="relative flex h-2 w-2" title="Vorschau aktiv">
</span> <span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75" />
<span class="relative inline-flex rounded-full h-2 w-2 bg-emerald-500" />
</span>
</div>
<span class="text-xs font-mono opacity-40">#{tpl.id}</span>
</div> </div>
<span class="text-xs font-mono opacity-40">#{tpl.id}</span>
</div>
{/* Title & Description */} {/* Title & Description */}
<h3 class="text-lg font-bold tracking-tight mb-2 line-clamp-2 leading-snug"> <h3 class="text-lg font-bold tracking-tight mb-2 line-clamp-2 leading-snug">
{tpl.name} {tpl.name}
</h3> </h3>
<div class="space-y-1 mt-3">
<div class="flex items-center gap-1.5 text-[11px] opacity-70">
<span class="font-bold">Stil:</span> {tpl.design}
</div>
<div class="flex items-center gap-1.5 text-[11px] opacity-70">
<span class="font-bold">Farbe:</span> {tpl.colorScheme}
</div>
</div>
</div>
{/* Visual Mini-Layout Preview Component inside card */} <div class="space-y-1 mt-3">
<div class="my-4 h-16 w-full rounded border border-black/[0.06] dark:border-white/[0.06] bg-black/5 dark:bg-white/5 p-1.5 flex gap-1 justify-center items-stretch relative overflow-hidden"> <div class="flex items-center gap-1.5 text-[11px] opacity-70">
<span class="font-bold">Stil:</span> {tpl.design}
{tpl.layoutPreview === "bento" && ( </div>
<div class="w-full grid grid-cols-3 gap-1"> <div class="flex items-center gap-1.5 text-[11px] opacity-70">
<div class={`col-span-2 rounded ${tpl.accentColor} opacity-70`}></div> <span class="font-bold">Farbe:</span> {tpl.colorScheme}
<div class="rounded bg-black/10 dark:bg-white/10"></div>
<div class="rounded bg-black/10 dark:bg-white/10"></div>
<div class="col-span-2 rounded bg-black/10 dark:bg-white/10"></div>
</div>
)}
{tpl.layoutPreview === "split" && (
<div class="w-full flex gap-1">
<div class={`w-1/2 rounded ${tpl.accentColor} opacity-70`}></div>
<div class="w-1/2 rounded bg-black/10 dark:bg-white/10"></div>
</div>
)}
{tpl.layoutPreview === "boxed" && (
<div class="w-full flex justify-center items-center p-2">
<div class="w-full h-full rounded border border-black/20 dark:border-white/20 p-1 flex gap-1">
<div class={`w-1/3 rounded ${tpl.accentColor} opacity-70`}></div>
<div class="w-2/3 rounded bg-black/10 dark:bg-white/10"></div>
</div> </div>
</div> </div>
)}
{tpl.layoutPreview === "asymmetric" && (
<div class="w-full grid grid-cols-4 gap-1">
<div class="rounded bg-black/10 dark:bg-white/10"></div>
<div class={`col-span-2 rounded ${tpl.accentColor} opacity-70`}></div>
<div class="rounded bg-black/10 dark:bg-white/10"></div>
</div>
)}
{tpl.layoutPreview === "single" && (
<div class="w-full flex flex-col gap-1 justify-center">
<div class={`h-3 w-3/4 mx-auto rounded ${tpl.accentColor} opacity-70`}></div>
<div class="h-2 w-1/2 mx-auto rounded bg-black/10 dark:bg-white/10"></div>
<div class="h-2 w-2/3 mx-auto rounded bg-black/10 dark:bg-white/10"></div>
</div>
)}
</div>
{/* CTA action bottom */}
<div class="flex items-center justify-between pt-3 border-t border-black/[0.06] dark:border-white/[0.06]">
<span class="text-[10px] font-mono opacity-50 uppercase">{tpl.layout}</span>
<div class="flex items-center gap-1.5 text-xs font-semibold group-hover:translate-x-0.5 transition-transform">
<span>Vorschau</span>
<FaDesktop class="w-3 h-3 opacity-60" />
</div> </div>
</div>
</a> {/* Visual Mini-Layout Preview Component inside card (Bento Content-Mix) */}
))} <div class="my-4 h-16 w-full rounded border border-black/[0.06] dark:border-white/[0.06] bg-black/5 dark:bg-white/5 p-1.5 flex gap-1 justify-center items-stretch relative overflow-hidden">
{tpl.layoutPreview === "bento" && (
<div class="w-full grid grid-cols-3 gap-1">
<div
class={`col-span-2 rounded ${tpl.accentColor} opacity-70`}
/>
<div class="rounded bg-black/10 dark:bg-white/10" />
<div class="rounded bg-black/10 dark:bg-white/10" />
<div class="col-span-2 rounded bg-black/10 dark:bg-white/10" />
</div>
)}
{tpl.layoutPreview === "split" && (
<div class="w-full flex gap-1">
<div
class={`w-1/2 rounded ${tpl.accentColor} opacity-70`}
/>
<div class="w-1/2 rounded bg-black/10 dark:bg-white/10" />
</div>
)}
{tpl.layoutPreview === "boxed" && (
<div class="w-full flex justify-center items-center p-2">
<div class="w-full h-full rounded border border-black/20 dark:border-white/20 p-1 flex gap-1">
<div
class={`w-1/3 rounded ${tpl.accentColor} opacity-70`}
/>
<div class="w-2/3 rounded bg-black/10 dark:bg-white/10" />
</div>
</div>
)}
{tpl.layoutPreview === "asymmetric" && (
<div class="w-full grid grid-cols-4 gap-1">
<div class="rounded bg-black/10 dark:bg-white/10" />
<div
class={`col-span-2 rounded ${tpl.accentColor} opacity-70`}
/>
<div class="rounded bg-black/10 dark:bg-white/10" />
</div>
)}
{tpl.layoutPreview === "single" && (
<div class="w-full flex flex-col gap-1 justify-center">
<div
class={`h-3 w-3/4 mx-auto rounded ${tpl.accentColor} opacity-70`}
/>
<div class="h-2 w-1/2 mx-auto rounded bg-black/10 dark:bg-white/10" />
<div class="h-2 w-2/3 mx-auto rounded bg-black/10 dark:bg-white/10" />
</div>
)}
</div>
{/* CTA action bottom */}
<div class="flex items-center justify-between pt-3 border-t border-black/[0.06] dark:border-white/[0.06]">
<span class="text-[10px] font-mono opacity-50 uppercase">
{tpl.layout}
</span>
<div class="flex items-center gap-1.5 text-xs font-semibold group-hover:translate-x-0.5 transition-transform">
<span>Vorschau</span>
<FaDesktop class="w-3 h-3 opacity-60" />
</div>
</div>
</a>
))
}
</div> </div>
<!-- Bottom Info Callout --> <!-- Bottom Info Callout -->
<div class="mt-20 p-8 rounded-2xl bg-white/40 dark:bg-brand-darkCard/40 border border-slate-200 dark:border-brand-darkBorder relative overflow-hidden group shadow-sm dark:shadow-none transition-colors duration-300"> <div
<div class="absolute inset-0 bg-gradient-to-r from-brand-arcticBlue/5 to-transparent pointer-events-none"></div> class="mt-20 p-8 rounded-2xl bg-brand-darkCard/40 border border-brand-darkBorder relative overflow-hidden group"
<div class="relative z-10 flex flex-col md:flex-row items-start md:items-center justify-between gap-6"> >
<div
class="absolute inset-0 bg-gradient-to-r from-brand-arcticBlue/5 to-transparent pointer-events-none"
>
</div>
<div
class="relative z-10 flex flex-col md:flex-row items-start md:items-center justify-between gap-6"
>
<div> <div>
<h3 class="text-xl font-bold mb-2">Ihr Wunsch-Design ist nicht dabei?</h3> <h3 class="text-xl font-bold mb-2">
<p class="text-slate-600 dark:text-zinc-400 text-xs sm:text-sm max-w-2xl leading-relaxed"> Ihr Wunsch-Design ist nicht dabei?
Kein Problem. Jedes Layout wird von uns individuell im Code programmiert. Wir nutzen keine starren Fertig-Systeme. Teilen Sie uns einfach Ihre Vorstellungen mit, und wir setzen sie passgenau um. </h3>
<p
class="text-zinc-400 text-xs sm:text-sm max-w-2xl leading-relaxed"
>
Kein Problem. Jedes Layout wird von uns individuell im Code
programmiert. Wir nutzen keine starren Fertig-Systeme. Teilen Sie
uns einfach Ihre Vorstellungen mit, und wir setzen sie passgenau
um.
</p> </p>
</div> </div>
<a href="/#contact" class="inline-flex items-center gap-2 px-5 py-2.5 bg-brand-arcticBlue text-zinc-950 font-semibold text-xs tracking-wider uppercase rounded hover:bg-white transition-all duration-200 shrink-0"> <a
href="/#contact"
class="inline-flex items-center gap-2 px-5 py-2.5 bg-brand-arcticBlue text-zinc-950 font-semibold text-xs tracking-wider uppercase rounded hover:bg-white transition-all duration-200 shrink-0"
>
Design besprechen Design besprechen
<FaDesktop class="w-3 h-3" /> <FaDesktop class="w-3 h-3" />
</a> </a>
</div> </div>
</div> </div>
</div> </div>
</main> </main>
<Footer /> <Footer />
</Layout> </Layout>
<script>
const filterButtons = document.querySelectorAll('.filter-btn');
const cards = document.querySelectorAll('.template-card');
filterButtons.forEach(btn => {
btn.addEventListener('click', () => {
// 1. Button-Styles zurücksetzen & aktiven Button stylen
filterButtons.forEach(b => {
b.classList.remove('bg-brand-arcticBlue', 'border-brand-arcticBlue', 'text-zinc-950');
b.classList.add('border-slate-200', 'dark:border-zinc-700/50', 'bg-white/40', 'dark:bg-slate-900/40', 'text-slate-600', 'dark:text-zinc-400');
});
btn.classList.add('bg-brand-arcticBlue', 'border-brand-arcticBlue', 'text-zinc-950');
btn.classList.remove('border-slate-200', 'dark:border-zinc-700/50', 'bg-white/40', 'dark:bg-slate-900/40', 'text-slate-600', 'dark:text-zinc-400');
const filterValue = btn.getAttribute('data-filter');
cards.forEach(card => {
const cardCategory = card.getAttribute('data-category');
if (filterValue === 'all' || filterValue === cardCategory) {
card.classList.remove('hidden');
// Verzögerung für weiche CSS transition
setTimeout(() => {
card.classList.remove('opacity-0', 'scale-95');
card.classList.add('opacity-100', 'scale-100');
}, 10);
} else {
card.classList.remove('opacity-100', 'scale-100');
card.classList.add('opacity-0', 'scale-95');
// Nach Transition-Ende hidden setzen
setTimeout(() => {
card.classList.add('hidden');
}, 300);
}
});
});
});
</script>