wip
Some checks failed
Build & Deploy / deploy (push) Failing after 17s

This commit is contained in:
2026-01-17 16:06:16 +01:00
parent f64cb71170
commit e6651761f3
20 changed files with 453 additions and 350 deletions

View File

@@ -43,10 +43,10 @@ export default function Header() {
];
const headerClass = cn(
"fixed top-0 left-0 right-0 z-50 transition-all duration-500",
"fixed top-0 left-0 right-0 z-50 transition-all duration-500 safe-area-p",
{
"bg-transparent py-8": isHomePage && !isScrolled,
"bg-primary py-4 shadow-2xl": !isHomePage || isScrolled,
"bg-transparent py-4 md:py-8": isHomePage && !isScrolled,
"bg-primary py-3 md:py-4 shadow-2xl": !isHomePage || isScrolled,
}
);
@@ -56,20 +56,20 @@ export default function Header() {
return (
<>
<header className={headerClass}>
<div className="container mx-auto px-6 md:px-12 lg:px-16 max-w-7xl flex items-center justify-between">
<Link href={`/${currentLocale}`} className="flex-shrink-0 group">
<div className="container mx-auto px-4 md:px-12 lg:px-16 max-w-7xl flex items-center justify-between">
<Link href={`/${currentLocale}`} className="flex-shrink-0 group touch-target">
<Image
src={logoSrc}
alt="KLZ Cables"
width={120}
height={120}
className="h-14 w-auto transition-all duration-500 group-hover:scale-110"
className="h-10 md:h-14 w-auto transition-all duration-500 group-hover:scale-110"
priority
unoptimized
/>
</Link>
<div className="flex items-center gap-12">
<div className="flex items-center gap-4 md:gap-12">
<nav className="hidden lg:flex items-center space-x-10">
{menuItems.map((item) => (
<Link
@@ -90,14 +90,14 @@ export default function Header() {
<div className="flex items-center space-x-4 text-sm font-extrabold tracking-widest uppercase">
<Link
href={getPathForLocale('en')}
className={`hover:text-accent transition-colors flex items-center gap-2 ${currentLocale === 'en' ? 'text-accent' : 'opacity-60'}`}
className={`hover:text-accent transition-colors flex items-center gap-2 touch-target ${currentLocale === 'en' ? 'text-accent' : 'opacity-60'}`}
>
EN
</Link>
<div className="w-px h-4 bg-current opacity-20" />
<Link
href={getPathForLocale('de')}
className={`hover:text-accent transition-colors flex items-center gap-2 ${currentLocale === 'de' ? 'text-accent' : 'opacity-60'}`}
className={`hover:text-accent transition-colors flex items-center gap-2 touch-target ${currentLocale === 'de' ? 'text-accent' : 'opacity-60'}`}
>
DE
</Link>
@@ -114,8 +114,8 @@ export default function Header() {
</div>
{/* Mobile Menu Button */}
<button className={cn("lg:hidden p-2 rounded-xl bg-white/10 backdrop-blur-md border border-white/20", textColorClass)}>
<svg className="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<button className={cn("lg:hidden touch-target p-2 rounded-xl bg-white/10 backdrop-blur-md border border-white/20", textColorClass)}>
<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>

48
components/Reveal.tsx Normal file
View File

@@ -0,0 +1,48 @@
'use client';
import React, { useEffect, useRef, useState } from 'react';
import { cn } from '@/components/ui';
interface RevealProps {
children: React.ReactNode;
className?: string;
threshold?: number;
delay?: number;
}
export default function Reveal({ children, className, threshold = 0.1, delay = 0 }: RevealProps) {
const [isVisible, setIsVisible] = useState(false);
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true);
observer.unobserve(entry.target);
}
},
{ threshold }
);
if (ref.current) {
observer.observe(ref.current);
}
return () => {
if (ref.current) {
observer.unobserve(ref.current);
}
};
}, [threshold]);
return (
<div
ref={ref}
className={cn('reveal-on-scroll', isVisible && 'is-visible', className)}
style={{ transitionDelay: `${delay}ms` }}
>
{children}
</div>
);
}

View File

@@ -8,34 +8,37 @@ export default function Hero() {
const t = useTranslations('Home.hero');
return (
<section className="relative h-[90vh] flex items-center justify-center overflow-hidden bg-primary-dark">
<section className="relative h-[70vh] md:h-[90vh] flex items-center justify-center overflow-hidden bg-primary-dark">
<HeroIllustration />
<Container className="relative z-10 text-left text-white w-full">
<div className="max-w-5xl animate-slide-up">
<h1 className="text-5xl md:text-7xl lg:text-8xl font-extrabold mb-8 tracking-tight leading-[1.05]">
<h1 className="text-4xl md:text-7xl lg:text-8xl font-extrabold mb-4 md:mb-8 tracking-tight leading-[1.05] max-w-[15ch] md:max-w-none">
{t.rich('title', {
green: (chunks) => (
<span className="relative inline-block">
<span className="relative z-10 text-accent italic">{chunks}</span>
<Scribble variant="circle" className="w-[140%] h-[140%] -top-[20%] -left-[20%] text-accent/30" />
<Scribble variant="circle" className="w-[140%] h-[140%] -top-[20%] -left-[20%] text-accent/30 hidden md:block" />
</span>
)
})}
</h1>
<div className="mt-12 flex flex-wrap gap-6">
<Button href="/contact" variant="accent" size="xl" className="group">
<p className="text-lg md:text-2xl text-white/70 leading-relaxed max-w-2xl mb-8 md:mb-12 line-clamp-2 md:line-clamp-none">
{t('subtitle')}
</p>
<div className="flex flex-col md:flex-row gap-3 md:gap-6">
<Button href="/contact" variant="accent" size="lg" className="group w-full md:w-auto md:h-16 md:px-10 md:text-xl">
{t('cta')}
<span className="ml-3 transition-transform group-hover:translate-x-1">&rarr;</span>
</Button>
<Button href="/products" variant="white" size="xl" className="group">
<Button href="/products" variant="ghost" size="lg" className="group w-full md:w-auto text-white hover:bg-white/10 md:bg-white md:text-primary md:hover:bg-neutral-light md:h-16 md:px-10 md:text-xl">
{t('exploreProducts')}
</Button>
</div>
</div>
</Container>
<div className="absolute bottom-10 left-1/2 -translate-x-1/2 animate-bounce">
<div className="absolute bottom-6 md:bottom-10 left-1/2 -translate-x-1/2 animate-bounce hidden sm:block">
<div className="w-6 h-10 border-2 border-white/30 rounded-full flex justify-center p-1">
<div className="w-1 h-2 bg-white rounded-full" />
</div>

View File

@@ -166,7 +166,7 @@ export default function HeroIllustration() {
<div className="absolute inset-0 z-0 overflow-hidden bg-primary">
<svg
viewBox="-400 -200 1800 1100"
className="w-full h-full"
className="w-full h-full opacity-40 md:opacity-100 scale-150 md:scale-100 translate-x-1/4 md:translate-x-0"
preserveAspectRatio="xMidYMid slice"
fill="none"
xmlns="http://www.w3.org/2000/svg"

View File

@@ -43,26 +43,27 @@ export default function ProductCategories() {
<Section className="bg-neutral-light 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-[500px] lg:h-[650px] overflow-hidden border-r border-white/10 last:border-r-0">
<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-10 flex flex-col justify-end text-white">
<div className="mb-6 transform transition-all duration-500 group-hover:-translate-y-4">
<div className="w-16 h-16 bg-white/10 backdrop-blur-md rounded-xl flex items-center justify-center mb-6 border border-white/20">
<img src={category.icon} alt="" className="w-10 h-10 brightness-0 invert" />
<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">
<img src={category.icon} alt="" className="w-8 h-8 md:w-10 md:h-10 brightness-0 invert" />
</div>
<h3 className="text-3xl font-bold mb-4 leading-tight">{category.title}</h3>
<p className="text-white/80 text-lg line-clamp-3 opacity-0 group-hover:opacity-100 transition-all duration-500 max-h-0 group-hover:max-h-32">
<h3 className="text-2xl md:text-3xl font-bold mb-2 md:mb-4 leading-tight">{category.title}</h3>
<p className="text-white/80 text-base md:text-lg 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-sm opacity-0 group-hover:opacity-100 transition-all duration-500 delay-100">
<div className="flex items-center text-accent font-bold tracking-wider uppercase text-xs md:text-sm 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>
</div>
</div>

View File

@@ -15,22 +15,22 @@ export default async function RecentPosts({ locale }: RecentPostsProps) {
if (recentPosts.length === 0) return null;
return (
<Section className="bg-neutral py-24">
<Section className="bg-neutral py-16 md:py-24">
<Container>
<div className="flex flex-col md:flex-row items-end justify-between mb-16 gap-6">
<div className="flex flex-col md:flex-row items-start md:items-end justify-between mb-12 md:mb-16 gap-6">
<Heading level={2} subtitle="Insights" className="mb-0">
{locale === 'de' ? 'Aktuelle Blogbeiträge' : 'Recent Blog Posts'}
</Heading>
<Link href={`/${locale}/blog`} className="group flex items-center text-primary font-bold text-lg">
<Link href={`/${locale}/blog`} className="group flex items-center text-primary font-bold text-lg touch-target">
{locale === 'de' ? 'Alle Beiträge ansehen' : 'View all posts'}
<span className="ml-2 transition-transform group-hover:translate-x-2">&rarr;</span>
</Link>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-10">
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 md:gap-10">
{recentPosts.map((post) => (
<Link key={post.slug} href={`/${locale}/blog/${post.slug}`} className="group block">
<Card className="h-full flex flex-col border-none shadow-lg hover:shadow-2xl transition-all duration-500">
<Card className="h-full flex flex-col border-none shadow-lg hover:shadow-2xl transition-all duration-500 rounded-3xl">
{post.frontmatter.featuredImage && (
<div className="relative h-64 overflow-hidden">
<img
@@ -38,7 +38,7 @@ export default async function RecentPosts({ locale }: RecentPostsProps) {
alt={post.frontmatter.title}
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
/>
<div className="absolute inset-0 bg-gradient-to-t from-primary-dark/60 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
<div className="absolute inset-0 image-overlay-gradient opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
{post.frontmatter.category && (
<Badge variant="accent" className="absolute top-4 left-4 shadow-md">
{post.frontmatter.category}
@@ -46,16 +46,16 @@ export default async function RecentPosts({ locale }: RecentPostsProps) {
)}
</div>
)}
<div className="p-8 flex flex-col flex-grow">
<div className="text-sm font-medium text-text-light mb-4 flex items-center gap-2">
<span className="w-8 h-px bg-neutral-medium" />
<div className="p-6 md:p-8 flex flex-col flex-grow">
<div className="text-xs md:text-sm font-medium text-text-light mb-3 md:mb-4 flex items-center gap-2">
<span className="w-6 md:w-8 h-px bg-neutral-medium" />
{new Date(post.frontmatter.date).toLocaleDateString(locale, {
year: 'numeric',
month: 'long',
day: 'numeric'
})}
</div>
<h3 className="text-2xl font-bold text-primary group-hover:text-accent-dark transition-colors line-clamp-2 mb-6 leading-tight">
<h3 className="text-xl md:text-2xl font-bold text-primary group-hover:text-accent-dark transition-colors line-clamp-2 mb-4 md:mb-6 leading-tight">
{post.frontmatter.title}
</h3>
<div className="mt-auto flex items-center text-primary font-bold group-hover:underline decoration-2 underline-offset-4">

View File

@@ -8,33 +8,33 @@ export default function WhatWeDo() {
return (
<Section className="bg-white text-neutral-dark">
<Container>
<div className="grid grid-cols-1 lg:grid-cols-12 gap-16 lg:gap-24">
<div className="lg:col-span-4">
<div className="sticky top-32">
<div className="sticky-narrative-container">
<div className="sticky-narrative-sidebar">
<div className="lg:sticky lg:top-32">
<Heading level={2} subtitle="Our Expertise">
{t('title')}
</Heading>
<p className="text-xl text-text-secondary leading-relaxed">
<p className="text-lg md:text-xl text-text-secondary leading-relaxed">
{t('subtitle')}
</p>
<div className="mt-12 p-8 bg-primary-light rounded-2xl border border-primary/10">
<p className="text-primary font-bold text-lg italic">
<div className="mt-8 md:mt-12 p-6 md:p-8 bg-primary-light rounded-2xl border border-primary/10">
<p className="text-primary font-bold text-base md:text-lg italic">
"{t('quote')}"
</p>
</div>
</div>
</div>
<div className="lg:col-span-8 grid grid-cols-1 md:grid-cols-2 gap-x-12 gap-y-20">
<div className="sticky-narrative-content grid grid-cols-1 md:grid-cols-2 gap-x-8 md:gap-x-12 gap-y-12 md:gap-y-20">
{[0, 1, 2, 3].map((idx) => (
<div key={idx} className="group">
<div className="flex items-center gap-4 mb-6">
<span className="flex items-center justify-center w-12 h-12 rounded-full bg-primary text-white font-bold text-lg shadow-lg shadow-primary/20 group-hover:scale-110 transition-transform">
<div className="flex items-center gap-4 mb-4 md:mb-6">
<span className="flex items-center justify-center w-10 h-10 md:w-12 md:h-12 rounded-full bg-primary text-white font-bold text-base md:text-lg shadow-lg shadow-primary/20 group-hover:scale-110 transition-transform">
{idx + 1}
</span>
<div className="h-px flex-grow bg-neutral-medium" />
</div>
<h3 className="text-2xl font-bold mb-4 text-primary group-hover:text-accent-dark transition-colors">{t(`items.${idx}.title`)}</h3>
<p className="text-text-secondary text-lg leading-relaxed">{t(`items.${idx}.description`)}</p>
<h3 className="text-xl md:text-2xl font-bold mb-3 md:mb-4 text-primary group-hover:text-accent-dark transition-colors">{t(`items.${idx}.title`)}</h3>
<p className="text-text-secondary text-base md:text-lg leading-relaxed">{t(`items.${idx}.description`)}</p>
</div>
))}
</div>

View File

@@ -51,7 +51,7 @@ export function Button({ className, variant = 'primary', size = 'md', href, ...p
export function Section({ className, children, ...props }: React.HTMLAttributes<HTMLElement>) {
return (
<section className={cn('py-20 md:py-28 lg:py-36 overflow-hidden', className)} {...props}>
<section className={cn('py-16 md:py-28 lg:py-36 overflow-hidden content-visibility-auto', className)} {...props}>
{children}
</section>
);
@@ -59,7 +59,7 @@ export function Section({ className, children, ...props }: React.HTMLAttributes<
export function Container({ className, children, ...props }: React.HTMLAttributes<HTMLDivElement>) {
return (
<div className={cn('container mx-auto px-6 md:px-12 lg:px-16 max-w-7xl', className)} {...props}>
<div className={cn('container mx-auto px-4 md:px-12 lg:px-16 max-w-7xl', className)} {...props}>
{children}
</div>
);
@@ -81,8 +81,8 @@ export function Heading({
const Tag = `h${level}` as any;
const sizes = {
1: 'text-5xl md:text-6xl lg:text-7xl font-extrabold leading-[1.1]',
2: 'text-4xl md:text-5xl lg:text-6xl font-bold leading-tight',
1: 'text-4xl md:text-6xl lg:text-7xl xl:text-8xl font-extrabold leading-[1.1]',
2: 'text-3xl md:text-5xl lg:text-6xl font-bold leading-tight',
3: 'text-2xl md:text-3xl lg:text-4xl font-bold',
4: 'text-xl md:text-2xl font-bold',
};
@@ -94,9 +94,9 @@ export function Heading({
};
return (
<div className={cn('mb-12 md:mb-16', alignments[align], className)}>
<div className={cn('mb-8 md:mb-16', alignments[align], className)}>
{subtitle && (
<span className="inline-block text-accent font-bold tracking-widest uppercase text-sm mb-4 animate-fade-in">
<span className="inline-block text-accent font-bold tracking-widest uppercase text-xs md:text-sm mb-3 md:mb-4 animate-fade-in">
{subtitle}
</span>
)}