perf: site-wide performance optimizations including image delivery and hero overhaul

This commit is contained in:
2026-02-11 18:47:13 +01:00
parent 407edc15f9
commit 24181a48c1
13 changed files with 300 additions and 1105 deletions

View File

@@ -66,7 +66,8 @@ export default async function BlogIndex({ params }: BlogIndexProps) {
alt={featuredPost.frontmatter.title}
fill
className="absolute inset-0 w-full h-full object-cover scale-105 animate-slow-zoom opacity-40 md:opacity-60"
unoptimized
sizes="100vw"
priority
/>
<div className="absolute inset-0 image-overlay-gradient" />
</>
@@ -153,7 +154,7 @@ export default async function BlogIndex({ params }: BlogIndexProps) {
alt={post.frontmatter.title}
fill
className="w-full h-full object-cover transition-transform duration-1000 group-hover:scale-110"
unoptimized
sizes="(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw"
/>
<div className="absolute inset-0 image-overlay-gradient opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
{post.frontmatter.category && (

View File

@@ -243,6 +243,7 @@ export default async function ProductPage({ params }: ProductPageProps) {
alt={product.frontmatter.title}
fill
className="object-contain p-8 transition-transform duration-700 group-hover:scale-110 z-10"
sizes="(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw"
/>
{/* Subtle reflection/shadow effect */}
<div className="absolute bottom-4 left-1/2 -translate-x-1/2 w-2/3 h-4 bg-black/5 blur-xl rounded-full" />

View File

@@ -143,8 +143,7 @@ export default async function ProductsPage({ params }: ProductsPageProps) {
alt={category.title}
fill
className="object-cover transition-transform duration-1000 group-hover:scale-105"
sizes="(max-width: 768px) 100vw, 50vw"
unoptimized
sizes="(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw"
/>
<div className="absolute inset-0 image-overlay-gradient opacity-80 group-hover:opacity-90 transition-opacity duration-500" />

View File

@@ -94,6 +94,7 @@ export default async function TeamPage({ params }: TeamPageProps) {
alt="KLZ Team"
fill
className="object-cover scale-105 animate-slow-zoom opacity-30 md:opacity-40"
sizes="100vw"
priority
/>
<div className="absolute inset-0 bg-gradient-to-b from-primary-dark/80 via-primary-dark/40 to-primary-dark/80" />

View File

@@ -12,29 +12,33 @@ export default function Footer() {
return (
<footer className="bg-primary text-white py-24 relative overflow-hidden">
<div className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-white/20 to-transparent" />
<Container>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-12 gap-16 mb-20">
{/* Brand Column */}
<div className="lg:col-span-4 space-y-8">
<Link href={`/${locale}`} className="inline-block group">
<Image
src="/logo-white.svg"
alt={t('products')}
width={150}
height={40}
<Image
src="/logo-white.svg"
alt={t('products')}
width={150}
height={40}
className="h-10 w-auto transition-transform duration-500 group-hover:scale-110"
unoptimized
/>
</Link>
<p className="text-white/60 text-base md:text-lg leading-relaxed max-w-sm">
{t('tagline')}
</p>
<div className="flex gap-4">
<a href="https://www.linkedin.com/company/klz-vertriebs-gmbh/" target="_blank" rel="noopener noreferrer" className="w-12 h-12 rounded-full bg-white/5 flex items-center justify-center text-white hover:bg-accent hover:text-primary-dark transition-all duration-300 border border-white/10">
<a
href="https://www.linkedin.com/company/klz-vertriebs-gmbh/"
target="_blank"
rel="noopener noreferrer"
className="w-12 h-12 rounded-full bg-white/5 flex items-center justify-center text-white hover:bg-accent hover:text-primary-dark transition-all duration-300 border border-white/10"
>
<span className="sr-only">LinkedIn</span>
<svg className="w-5 h-5 fill-current" viewBox="0 0 24 24">
<path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z"/>
<path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" />
</svg>
</a>
</div>
@@ -42,52 +46,113 @@ export default function Footer() {
{/* Links Columns */}
<div className="lg:col-span-2">
<h4 className="text-accent font-bold uppercase tracking-widest text-xs md:text-sm mb-8">{t('legal')}</h4>
<h4 className="text-accent font-bold uppercase tracking-widest text-xs md:text-sm mb-8">
{t('legal')}
</h4>
<ul className="space-y-4 text-white/70 list-none m-0 p-0">
<li><Link href={`/${locale}/${t('legalNoticeSlug')}`} className="text-white/70 hover:text-accent transition-all duration-300 hover:translate-x-1 inline-block">{t('legalNotice')}</Link></li>
<li><Link href={`/${locale}/${t('privacyPolicySlug')}`} className="text-white/70 hover:text-accent transition-all duration-300 hover:translate-x-1 inline-block">{t('privacyPolicy')}</Link></li>
<li><Link href={`/${locale}/${t('termsSlug')}`} className="text-white/70 hover:text-accent transition-all duration-300 hover:translate-x-1 inline-block">{t('terms')}</Link></li>
<li>
<Link
href={`/${locale}/${t('legalNoticeSlug')}`}
className="text-white/70 hover:text-accent transition-all duration-300 hover:translate-x-1 inline-block"
>
{t('legalNotice')}
</Link>
</li>
<li>
<Link
href={`/${locale}/${t('privacyPolicySlug')}`}
className="text-white/70 hover:text-accent transition-all duration-300 hover:translate-x-1 inline-block"
>
{t('privacyPolicy')}
</Link>
</li>
<li>
<Link
href={`/${locale}/${t('termsSlug')}`}
className="text-white/70 hover:text-accent transition-all duration-300 hover:translate-x-1 inline-block"
>
{t('terms')}
</Link>
</li>
</ul>
</div>
<div className="lg:col-span-2">
<h4 className="text-accent font-bold uppercase tracking-widest text-xs md:text-sm mb-8">{t('company')}</h4>
<h4 className="text-accent font-bold uppercase tracking-widest text-xs md:text-sm mb-8">
{t('company')}
</h4>
<ul className="space-y-4 text-white/70 list-none m-0 p-0">
<li><Link href={`/${locale}/team`} className="text-white/70 hover:text-accent transition-all duration-300 hover:translate-x-1 inline-block">{navT('team')}</Link></li>
<li><Link href={`/${locale}/products`} className="text-white/70 hover:text-accent transition-all duration-300 hover:translate-x-1 inline-block">{navT('products')}</Link></li>
<li><Link href={`/${locale}/blog`} className="text-white/70 hover:text-accent transition-all duration-300 hover:translate-x-1 inline-block">{navT('blog')}</Link></li>
<li><Link href={`/${locale}/contact`} className="text-white/70 hover:text-accent transition-all duration-300 hover:translate-x-1 inline-block">{navT('contact')}</Link></li>
<li>
<Link
href={`/${locale}/team`}
className="text-white/70 hover:text-accent transition-all duration-300 hover:translate-x-1 inline-block"
>
{navT('team')}
</Link>
</li>
<li>
<Link
href={`/${locale}/products`}
className="text-white/70 hover:text-accent transition-all duration-300 hover:translate-x-1 inline-block"
>
{navT('products')}
</Link>
</li>
<li>
<Link
href={`/${locale}/blog`}
className="text-white/70 hover:text-accent transition-all duration-300 hover:translate-x-1 inline-block"
>
{navT('blog')}
</Link>
</li>
<li>
<Link
href={`/${locale}/contact`}
className="text-white/70 hover:text-accent transition-all duration-300 hover:translate-x-1 inline-block"
>
{navT('contact')}
</Link>
</li>
</ul>
</div>
{/* Recent Posts Column */}
<div className="lg:col-span-4">
<h4 className="text-accent font-bold uppercase tracking-widest text-xs md:text-sm mb-8">{t('recentPosts')}</h4>
<h4 className="text-accent font-bold uppercase tracking-widest text-xs md:text-sm mb-8">
{t('recentPosts')}
</h4>
<ul className="space-y-6 list-none m-0 p-0">
{[
{
title: locale === 'de'
? "Windparkbau im Fokus: drei typische Kabelherausforderungen"
: "Focus on wind farm construction: three typical cable challenges",
slug: locale === 'de'
? "windparkbau-im-fokus-drei-typische-kabelherausforderungen"
: "focus-on-wind-farm-construction-three-typical-cable-challenges"
title:
locale === 'de'
? 'Windparkbau im Fokus: drei typische Kabelherausforderungen'
: 'Focus on wind farm construction: three typical cable challenges',
slug:
locale === 'de'
? 'windparkbau-im-fokus-drei-typische-kabelherausforderungen'
: 'focus-on-wind-farm-construction-three-typical-cable-challenges',
},
{
title: locale === 'de'
? "Warum das N2XS(F)2Y das ideale Kabel für Ihr Energieprojekt ist"
: "Why the N2XS(F)2Y is the ideal cable for your energy project",
slug: locale === 'de'
? "n2xsf2y-mittelspannungskabel-energieprojekt"
: "why-the-n2xsf2y-is-the-ideal-cable-for-your-energy-project"
}
title:
locale === 'de'
? 'Warum das N2XS(F)2Y das ideale Kabel für Ihr Energieprojekt ist'
: 'Why the N2XS(F)2Y is the ideal cable for your energy project',
slug:
locale === 'de'
? 'n2xsf2y-mittelspannungskabel-energieprojekt'
: 'why-the-n2xsf2y-is-the-ideal-cable-for-your-energy-project',
},
].map((post, i) => (
<li key={i}>
<Link href={`/${locale}/blog/${post.slug}`} className="group block text-white/80">
<p className="text-white/80 font-bold group-hover:text-accent transition-colors leading-snug mb-2 text-base md:text-base">
{post.title}
</p>
<span className="text-xs text-white/40 uppercase tracking-widest">{t('readArticle')} &rarr;</span>
<span className="text-xs text-white/40 uppercase tracking-widest">
{t('readArticle')} &rarr;
</span>
</Link>
</li>
))}
@@ -98,8 +163,12 @@ export default function Footer() {
<div className="pt-12 border-t border-white/10 flex flex-col md:flex-row justify-between items-center gap-8 text-white/40 text-xs md:text-sm font-medium">
<p>{t('copyright', { year: currentYear })}</p>
<div className="flex gap-8">
<Link href="/en" locale="en" className="hover:text-white transition-colors">English</Link>
<Link href="/de" locale="de" className="hover:text-white transition-colors">Deutsch</Link>
<Link href="/en" locale="en" className="hover:text-white transition-colors">
English
</Link>
<Link href="/de" locale="de" className="hover:text-white transition-colors">
Deutsch
</Link>
</div>
</div>
</Container>

View File

@@ -87,7 +87,6 @@ export default function Header() {
height={120}
className="h-10 md:h-14 w-auto transition-all duration-500 group-hover:scale-110"
priority
unoptimized
/>
</Link>
</motion.div>

View File

@@ -9,17 +9,17 @@ export default function Experience() {
return (
<Section className="relative py-32 md:py-48 overflow-hidden text-white">
<div className="absolute inset-0 z-0">
<Image
src="/uploads/2024/12/1694273920124-copy-2.webp"
alt={t('subtitle')}
<Image
src="/uploads/2024/12/1694273920124-copy-2.webp"
alt={t('subtitle')}
fill
className="object-cover object-center scale-105 animate-slow-zoom"
unoptimized
sizes="100vw"
/>
<div className="absolute inset-0 bg-primary/80 mix-blend-multiply" />
<div className="absolute inset-0 bg-gradient-to-r from-primary via-primary/40 to-transparent" />
</div>
<Container className="relative z-10">
<div className="max-w-3xl">
<Heading level={2} subtitle={t('subtitle')} className="text-white">
@@ -29,19 +29,25 @@ export default function Experience() {
<p className="border-l-4 border-accent pl-8 py-2 bg-white/5 backdrop-blur-sm rounded-r-xl">
{t('p1')}
</p>
<p className="pl-9">
{t('p2')}
</p>
<p className="pl-9">{t('p2')}</p>
</div>
<div className="mt-16 grid grid-cols-1 md:grid-cols-2 gap-12">
<div className="animate-fade-in">
<div className="text-2xl md:text-3xl font-extrabold text-accent mb-4">{t('certifiedQuality')}</div>
<div className="text-base md:text-lg font-bold uppercase tracking-widest text-white/60">{t('vdeApproved')}</div>
<div className="text-2xl md:text-3xl font-extrabold text-accent mb-4">
{t('certifiedQuality')}
</div>
<div className="text-base md:text-lg font-bold uppercase tracking-widest text-white/60">
{t('vdeApproved')}
</div>
</div>
<div className="animate-fade-in" style={{ animationDelay: '100ms' }}>
<div className="text-2xl md:text-3xl font-extrabold text-accent mb-4">{t('fullSpectrum')}</div>
<div className="text-base md:text-lg font-bold uppercase tracking-widest text-white/60">{t('solutionsRange')}</div>
<div className="text-2xl md:text-3xl font-extrabold text-accent mb-4">
{t('fullSpectrum')}
</div>
<div className="text-base md:text-lg font-bold uppercase tracking-widest text-white/60">
{t('solutionsRange')}
</div>
</div>
</div>
</div>

View File

@@ -46,7 +46,7 @@ export default function GallerySection() {
alt={`${t('alt')} ${idx + 1}`}
fill
className="object-cover transition-transform duration-1000 group-hover:scale-110"
unoptimized
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
<div className="absolute inset-0 bg-primary-dark/20 group-hover:bg-transparent transition-all duration-500" />
<div className="absolute inset-0 border-0 group-hover:border-[16px] border-white/10 transition-all duration-500 pointer-events-none" />

View File

@@ -4,7 +4,8 @@ import Scribble from '@/components/Scribble';
import { Button, Container, Heading, Section } from '@/components/ui';
import { motion } from 'framer-motion';
import { useTranslations } from 'next-intl';
import HeroIllustration from './HeroIllustration';
import dynamic from 'next/dynamic';
const HeroIllustration = dynamic(() => import('./HeroIllustration'), { ssr: false });
export default function Hero() {
const t = useTranslations('Home.hero');
@@ -19,7 +20,10 @@ export default function Hero() {
variants={containerVariants}
>
<motion.div variants={headingVariants}>
<Heading level={1} className="text-center md:text-left mb-6 md:mb-8 md:max-w-none text-white text-4xl sm:text-5xl md:text-7xl font-extrabold [text-shadow:_-2px_-2px_0_#002b49,_2px_-2px_0_#002b49,_-2px_2px_0_#002b49,_2px_2px_0_#002b49,_-2px_0_0_#002b49,_2px_0_0_#002b49,_0_-2px_0_#002b49,_0_2px_0_#002b49]">
<Heading
level={1}
className="text-center md:text-left mb-6 md:mb-8 md:max-w-none text-white text-4xl sm:text-5xl md:text-7xl font-extrabold [text-shadow:_-2px_-2px_0_#002b49,_2px_-2px_0_#002b49,_-2px_2px_0_#002b49,_2px_2px_0_#002b49,_-2px_0_0_#002b49,_2px_0_0_#002b49,_0_-2px_0_#002b49,_0_2px_0_#002b49]"
>
{t.rich('title', {
green: (chunks) => (
<span className="relative inline-block">
@@ -36,7 +40,7 @@ export default function Hero() {
<Scribble variant="circle" />
</motion.div>
</span>
)
),
})}
</Heading>
</motion.div>
@@ -50,13 +54,23 @@ export default function Hero() {
variants={buttonContainerVariants}
>
<motion.div variants={buttonVariants}>
<Button href="/contact" variant="accent" size="lg" className="group w-full sm:w-auto h-14 md:h-16 px-8 md:px-10 text-base md:text-lg">
<Button
href="/contact"
variant="accent"
size="lg"
className="group w-full sm:w-auto h-14 md:h-16 px-8 md:px-10 text-base md:text-lg"
>
{t('cta')}
<span className="transition-transform group-hover/btn:translate-x-1">&rarr;</span>
</Button>
</motion.div>
<motion.div variants={buttonVariants}>
<Button href="/products" variant="white" size="lg" className="group w-full sm:w-auto h-14 md:h-16 px-8 md:px-10 text-base md:text-lg md:bg-white md:text-primary md:hover:bg-neutral-light md:border-none">
<Button
href="/products"
variant="white"
size="lg"
className="group w-full sm:w-auto h-14 md:h-16 px-8 md:px-10 text-base md:text-lg md:bg-white md:text-primary md:hover:bg-neutral-light md:border-none"
>
{t('exploreProducts')}
</Button>
</motion.div>
@@ -77,7 +91,7 @@ export default function Hero() {
className="absolute bottom-6 md:bottom-10 left-1/2 -translate-x-1/2 hidden sm:block"
initial={{ opacity: 0, y: 16 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 1, ease: "easeOut", delay: 3 }}
transition={{ duration: 1, ease: 'easeOut', delay: 3 }}
>
<div className="w-6 h-10 border-2 border-white/30 rounded-full flex justify-center p-1">
<motion.div
@@ -86,7 +100,7 @@ export default function Hero() {
transition={{
duration: 1.5,
repeat: Infinity,
ease: "easeInOut"
ease: 'easeInOut',
}}
/>
</div>
@@ -101,9 +115,9 @@ const containerVariants = {
opacity: 1,
transition: {
staggerChildren: 0.12,
delayChildren: 0.4
}
}
delayChildren: 0.4,
},
},
} as const;
const headingVariants = {
@@ -112,8 +126,8 @@ const headingVariants = {
opacity: 1,
y: 0,
scale: 1,
transition: { duration: 1.2, ease: [0.25, 0.46, 0.45, 0.94] }
}
transition: { duration: 1.2, ease: [0.25, 0.46, 0.45, 0.94] },
},
} as const;
const accentVariants = {
@@ -122,8 +136,8 @@ const accentVariants = {
opacity: 1,
scale: 1,
rotate: 0,
transition: { duration: 0.8, ease: [0.25, 0.46, 0.45, 0.94] }
}
transition: { duration: 0.8, ease: [0.25, 0.46, 0.45, 0.94] },
},
} as const;
const scribbleVariants = {
@@ -132,8 +146,8 @@ const scribbleVariants = {
opacity: 1,
scale: 1,
rotate: 0,
transition: { duration: 1, type: "spring", stiffness: 300, damping: 20 }
}
transition: { duration: 1, type: 'spring', stiffness: 300, damping: 20 },
},
} as const;
const subtitleVariants = {
@@ -142,8 +156,8 @@ const subtitleVariants = {
opacity: 1,
y: 0,
scale: 1,
transition: { duration: 1, ease: [0.25, 0.46, 0.45, 0.94] }
}
transition: { duration: 1, ease: [0.25, 0.46, 0.45, 0.94] },
},
} as const;
const buttonContainerVariants = {
@@ -152,9 +166,9 @@ const buttonContainerVariants = {
opacity: 1,
transition: {
staggerChildren: 0.15,
delayChildren: 0.4
}
}
delayChildren: 0.4,
},
},
} as const;
const buttonVariants = {
@@ -163,6 +177,6 @@ const buttonVariants = {
opacity: 1,
y: 0,
scale: 1,
transition: { type: "spring", stiffness: 400, damping: 20 }
}
transition: { type: 'spring', stiffness: 400, damping: 20 },
},
} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -11,43 +11,53 @@ export default function MeetTheTeam() {
return (
<Section className="relative py-32 md:py-48 overflow-hidden">
<div className="absolute inset-0 z-0">
<Image
src="/uploads/2024/12/DSC08036-Large.webp"
alt={t('subtitle')}
<Image
src="/uploads/2024/12/DSC08036-Large.webp"
alt={t('subtitle')}
fill
className="object-cover scale-105 animate-slow-zoom"
unoptimized
sizes="100vw"
/>
<div className="absolute inset-0 bg-primary/70 mix-blend-multiply" />
<div className="absolute inset-0 bg-gradient-to-t from-primary via-primary/20 to-transparent" />
</div>
<Container className="relative z-10">
<div className="max-w-3xl text-white animate-slide-up">
<Heading level={2} subtitle={t('subtitle')} className="text-white mb-8">
<span className="text-white">{t('title')}</span>
</Heading>
<div className="relative mb-12">
<div className="absolute -left-8 top-0 bottom-0 w-1 bg-accent rounded-full" />
<p className="text-xl md:text-2xl leading-relaxed font-medium italic text-white/90 pl-8">
"{t('description')}"
</p>
</div>
<div className="flex flex-wrap gap-8 items-center">
<Button href={`/${locale}/team`} variant="accent" size="xl" className="group">
{t('cta')}
<span className="ml-3 transition-transform group-hover:translate-x-2">&rarr;</span>
</Button>
<div className="flex items-center gap-4">
<div className="flex -space-x-4">
<div className="w-14 h-14 rounded-full border-4 border-primary overflow-hidden relative">
<Image src="/uploads/2024/12/DSC07768-Large.webp" alt={teamT('michael.name')} fill className="object-cover" />
<Image
src="/uploads/2024/12/DSC07768-Large.webp"
alt={teamT('michael.name')}
fill
className="object-cover"
/>
</div>
<div className="w-14 h-14 rounded-full border-4 border-primary overflow-hidden relative">
<Image src="/uploads/2024/12/DSC07963-Large.webp" alt={teamT('klaus.name')} fill className="object-cover" />
<Image
src="/uploads/2024/12/DSC07963-Large.webp"
alt={teamT('klaus.name')}
fill
className="object-cover"
/>
</div>
</div>
<span className="text-white/60 font-bold text-xs md:text-sm uppercase tracking-widest">

View File

@@ -9,62 +9,74 @@ export default function ProductCategories() {
const locale = useLocale();
const categories = [
{
title: t('categories.lowVoltage.title'),
{
title: t('categories.lowVoltage.title'),
desc: t('categories.lowVoltage.description'),
img: '/uploads/2024/11/low-voltage-category.webp',
icon: '/uploads/2024/11/Low-Voltage.svg',
href: `/${locale}/products/low-voltage-cables`
href: `/${locale}/products/low-voltage-cables`,
},
{
title: t('categories.mediumVoltage.title'),
{
title: t('categories.mediumVoltage.title'),
desc: t('categories.mediumVoltage.description'),
img: '/uploads/2024/11/medium-voltage-category.webp',
icon: '/uploads/2024/11/Medium-Voltage.svg',
href: `/${locale}/products/medium-voltage-cables`
href: `/${locale}/products/medium-voltage-cables`,
},
{
title: t('categories.highVoltage.title'),
{
title: t('categories.highVoltage.title'),
desc: t('categories.highVoltage.description'),
img: '/uploads/2024/11/high-voltage-category.webp',
icon: '/uploads/2024/11/High-Voltage.svg',
href: `/${locale}/products/high-voltage-cables`
href: `/${locale}/products/high-voltage-cables`,
},
{
title: t('categories.solar.title'),
{
title: t('categories.solar.title'),
desc: t('categories.solar.description'),
img: '/uploads/2024/11/solar-category.webp',
icon: '/uploads/2024/11/Solar.svg',
href: `/${locale}/products/solar-cables`
}
href: `/${locale}/products/solar-cables`,
},
];
return (
<Section className="bg-neutral-light py-0 md:py-0 lg:py-0 -mt-px">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4">
{categories.map((category, idx) => (
<Link key={idx} href={category.href} className="group block relative h-[400px] md:h-[500px] lg:h-[650px] overflow-hidden border-b md:border-b-0 md:border-r border-white/10 last:border-0">
<Image
src={category.img}
<Link
key={idx}
href={category.href}
className="group block relative h-[400px] md:h-[500px] lg:h-[650px] overflow-hidden border-b md:border-b-0 md:border-r border-white/10 last:border-0"
>
<Image
src={category.img}
alt={category.title}
fill
className="object-cover transition-transform duration-1000 group-hover:scale-110"
sizes="(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 25vw"
unoptimized
/>
<div className="absolute inset-0 bg-primary-dark/40 group-hover:bg-primary-dark/60 transition-all duration-500" />
<div className="absolute inset-0 p-8 md:p-10 flex flex-col justify-end text-white">
<div className="mb-4 md:mb-6 transform transition-all duration-500 group-hover:-translate-y-4">
<div className="w-12 h-12 md:w-16 md:h-16 bg-white/10 backdrop-blur-md rounded-xl flex items-center justify-center mb-4 md:mb-6 border border-white/20">
<Image src={category.icon} alt="" width={40} height={40} className="w-8 h-8 md:w-10 md:h-10 brightness-0 invert" unoptimized />
<Image
src={category.icon}
alt=""
width={40}
height={40}
className="w-8 h-8 md:w-10 md:h-10 brightness-0 invert"
/>
</div>
<h3 className="text-xl md:text-2xl font-bold mb-2 md:mb-4 leading-tight">{category.title}</h3>
<h3 className="text-xl md:text-2xl font-bold mb-2 md:mb-4 leading-tight">
{category.title}
</h3>
<p className="text-white/80 text-sm md:text-base line-clamp-3 opacity-100 md:opacity-0 group-hover:opacity-100 transition-all duration-500 max-h-24 md:max-h-0 group-hover:max-h-32">
{category.desc}
</p>
</div>
<div className="flex items-center text-accent font-bold tracking-wider uppercase text-xs md:text-xs opacity-100 md:opacity-0 group-hover:opacity-100 transition-all duration-500 delay-100">
{t('exploreCategory')} <span className="ml-2 transition-transform group-hover:translate-x-2">&rarr;</span>
{t('exploreCategory')}{' '}
<span className="ml-2 transition-transform group-hover:translate-x-2">&rarr;</span>
</div>
</div>
</Link>

View File

@@ -43,7 +43,7 @@ export default async function RecentPosts({ locale }: RecentPostsProps) {
alt={post.frontmatter.title}
fill
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
unoptimized
sizes="(max-width: 768px) 100vw, 33vw"
/>
<div className="absolute inset-0 image-overlay-gradient opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
{post.frontmatter.category && (