This commit is contained in:
2026-01-17 16:17:07 +01:00
parent e6651761f3
commit d4e4142381
12 changed files with 260 additions and 190 deletions

View File

@@ -37,23 +37,36 @@ export default async function StandardPage({ params: { locale, slug } }: PagePro
<Section className="bg-white -mt-8 md:-mt-12 relative z-20 rounded-t-[32px] md:rounded-t-[60px] shadow-2xl py-12 md:py-28">
<Container>
<div className="sticky-narrative-container">
{/* Sticky Narrative Sidebar */}
{/* Sticky Narrative Sidebar - Mobile Optimized */}
<div className="sticky-narrative-sidebar mb-8 lg:mb-0">
<div className="lg:sticky lg:top-32 space-y-4 md:space-y-8">
<div className="p-6 md:p-8 bg-neutral-light rounded-2xl md:rounded-3xl border border-neutral-medium">
<h3 className="text-lg md:text-xl font-bold text-primary mb-3 md:mb-4">Quick Navigation</h3>
{/* Mobile-only chip/stepper feel */}
<div className="flex lg:hidden overflow-x-auto pb-4 gap-3 no-scrollbar -mx-4 px-4">
<Badge variant="primary" className="whitespace-nowrap px-4 py-2 rounded-full shadow-sm">Overview</Badge>
<Badge variant="neutral" className="whitespace-nowrap px-4 py-2 rounded-full shadow-sm opacity-60">Details</Badge>
<Badge variant="neutral" className="whitespace-nowrap px-4 py-2 rounded-full shadow-sm opacity-60">Support</Badge>
</div>
<div className="p-6 md:p-8 bg-neutral-light rounded-2xl md:rounded-3xl border border-neutral-medium shadow-sm">
<h3 className="text-lg md:text-xl font-bold text-primary mb-3 md:mb-4 flex items-center gap-2">
<span className="w-1.5 h-6 bg-accent rounded-full" />
Quick Navigation
</h3>
<nav className="space-y-3 md:space-y-4">
<div className="h-1 w-10 md:w-12 bg-accent rounded-full" />
<p className="text-sm md:text-base text-text-secondary leading-relaxed">
Explore the details of {pageData.frontmatter.title}. KLZ provides comprehensive information on all our services and corporate policies.
</p>
</nav>
</div>
<div className="p-6 md:p-8 bg-primary-dark rounded-2xl md:rounded-3xl text-white">
<h3 className="text-lg md:text-xl font-bold mb-3 md:mb-4">Need Help?</h3>
<p className="text-sm md:text-base text-white/70 mb-4 md:mb-6">Our support team is available for any questions regarding this topic.</p>
<a href={`/${locale}/contact`} className="text-accent font-bold hover:underline touch-target">Contact Us &rarr;</a>
<div className="p-6 md:p-8 bg-primary-dark rounded-2xl md:rounded-3xl text-white shadow-xl relative overflow-hidden group">
<div className="absolute top-0 right-0 w-24 h-full bg-accent/5 -skew-x-12 translate-x-1/2 transition-transform group-hover:translate-x-1/3" />
<h3 className="text-lg md:text-xl font-bold mb-3 md:mb-4 relative z-10">Need Help?</h3>
<p className="text-sm md:text-base text-white/70 mb-4 md:mb-6 relative z-10">Our support team is available for any questions regarding this topic.</p>
<a href={`/${locale}/contact`} className="inline-flex items-center text-accent font-bold hover:underline touch-target relative z-10 group/link">
Contact Us
<span className="ml-2 transition-transform group-hover/link:translate-x-1">&rarr;</span>
</a>
</div>
</div>
</div>

View File

@@ -10,7 +10,6 @@ interface BlogPostProps {
}
import Link from 'next/link';
import Image from 'next/image';
import VisualLinkPreview from '@/components/blog/VisualLinkPreview';
import Callout from '@/components/blog/Callout';
import HighlightBox from '@/components/blog/HighlightBox';
@@ -20,6 +19,7 @@ import ChatBubble from '@/components/blog/ChatBubble';
import SplitHeading from '@/components/blog/SplitHeading';
import PostNavigation from '@/components/blog/PostNavigation';
import PowerCTA from '@/components/blog/PowerCTA';
import ShareButton from '@/components/blog/ShareButton';
const components = {
VisualLinkPreview,
@@ -187,6 +187,14 @@ export default async function BlogPost({ params: { locale, slug } }: BlogPostPro
</time>
<span className="w-1.5 h-1.5 bg-primary rounded-full" />
<span>KLZ Cables</span>
<div className="ml-auto hidden md:block">
<ShareButton
title={post.frontmatter.title}
text={post.frontmatter.excerpt || ''}
url={`https://klz-cables.com/${locale}/blog/${slug}`}
locale={locale}
/>
</div>
</div>
</div>
</div>
@@ -195,6 +203,15 @@ export default async function BlogPost({ params: { locale, slug } }: BlogPostPro
{/* Content */}
<div className="container mx-auto px-4 py-16 md:py-24 max-w-3xl">
{/* Mobile Share Button */}
<div className="md:hidden mb-8 flex justify-end">
<ShareButton
title={post.frontmatter.title}
text={post.frontmatter.excerpt || ''}
url={`https://klz-cables.com/${locale}/blog/${slug}`}
locale={locale}
/>
</div>
{/* If no featured image, show header here */}
{!post.frontmatter.featuredImage && (
<header className="mb-16 text-center">

View File

@@ -101,8 +101,12 @@ export default function ContactPage() {
<input
type="text"
id="name"
name="name"
autoComplete="name"
enterKeyHint="next"
className="w-full px-4 md:px-6 py-2.5 md:py-4 bg-neutral rounded-xl md:rounded-2xl border-2 border-transparent focus:border-primary focus:bg-white transition-all outline-none text-sm md:text-lg"
placeholder="Your Name"
required
/>
</div>
<div className="space-y-1 md:space-y-2">
@@ -110,21 +114,29 @@ export default function ContactPage() {
<input
type="email"
id="email"
name="email"
autoComplete="email"
inputMode="email"
enterKeyHint="next"
className="w-full px-4 md:px-6 py-2.5 md:py-4 bg-neutral rounded-xl md:rounded-2xl border-2 border-transparent focus:border-primary focus:bg-white transition-all outline-none text-sm md:text-lg"
placeholder="your@email.com"
required
/>
</div>
<div className="md:col-span-2 space-y-1 md:space-y-2">
<label htmlFor="message" className="text-[10px] md:text-xs font-extrabold text-primary uppercase tracking-widest">{t('form.message')}</label>
<textarea
id="message"
name="message"
rows={4}
enterKeyHint="send"
className="w-full px-4 md:px-6 py-2.5 md:py-4 bg-neutral rounded-xl md:rounded-2xl border-2 border-transparent focus:border-primary focus:bg-white transition-all outline-none text-sm md:text-lg resize-none"
placeholder="How can we help you?"
required
></textarea>
</div>
<div className="md:col-span-2 pt-2 md:pt-4">
<Button type="submit" size="lg" className="w-full shadow-xl shadow-primary/20 md:h-16 md:px-10 md:text-xl">
<Button type="submit" size="lg" className="w-full shadow-xl shadow-primary/20 md:h-16 md:px-10 md:text-xl active:scale-[0.98] transition-transform">
{t('form.submit')}
</Button>
</div>

View File

@@ -12,8 +12,6 @@ import CTA from '@/components/home/CTA';
import Reveal from '@/components/Reveal';
export default function HomePage({ params: { locale } }: { params: { locale: string } }) {
const t = useTranslations('Index');
return (
<div className="flex flex-col min-h-screen">
<Hero />

View File

@@ -9,7 +9,6 @@ import Link from 'next/link';
import Image from 'next/image';
import { getTranslations } from 'next-intl/server';
import { Section, Container, Heading, Badge, Button } from '@/components/ui';
import ProductsIllustration from '@/components/products/ProductsIllustration';
import Scribble from '@/components/Scribble';
interface ProductPageProps {
@@ -68,8 +67,7 @@ export default async function ProductPage({ params }: ProductPageProps) {
return (
<div className="flex flex-col min-h-screen bg-white">
<section className="relative min-h-[50vh] flex items-center pt-32 pb-20 overflow-hidden bg-primary-dark">
<ProductsIllustration />
<Container className="relative z-10">
<Container className="relative z-10">
<div className="max-w-4xl animate-slide-up">
<nav className="flex items-center mb-8 text-white/40 text-sm font-bold uppercase tracking-widest">
<Link href={`/${locale}/products`} className="hover:text-accent transition-colors">{t('title')}</Link>
@@ -154,8 +152,7 @@ export default async function ProductPage({ params }: ProductPageProps) {
<div className="flex flex-col min-h-screen bg-neutral-light">
{/* Product Hero */}
<section className="relative pt-40 pb-32 overflow-hidden bg-primary-dark">
<ProductsIllustration />
<Container className="relative z-10">
<Container className="relative z-10">
<div className="max-w-5xl animate-slide-up">
<nav className="flex items-center mb-8 text-white/40 text-sm font-bold uppercase tracking-widest">
<Link href={`/${locale}/products`} className="hover:text-accent transition-colors">{t('title')}</Link>

View File

@@ -1,9 +1,9 @@
import Link from 'next/link';
import Image from 'next/image';
import { useTranslations } from 'next-intl';
import { Section, Container, Heading, Card, Badge, Button } from '@/components/ui';
import ProductsIllustration from '@/components/products/ProductsIllustration';
import { Section, Container, Card, Badge, Button } from '@/components/ui';
import Scribble from '@/components/Scribble';
import Reveal from '@/components/Reveal';
interface ProductsPageProps {
params: {
@@ -49,7 +49,6 @@ export default function ProductsPage({ params }: ProductsPageProps) {
<div className="flex flex-col min-h-screen bg-neutral-light">
{/* Hero Section */}
<section className="relative min-h-[50vh] md:min-h-[70vh] flex items-center pt-32 pb-20 md:pt-40 md:pb-32 overflow-hidden bg-primary-dark">
<ProductsIllustration />
<Container className="relative z-10">
<div className="max-w-4xl animate-slide-up">
<Badge variant="accent" className="mb-4 md:mb-8 bg-white/10 text-white border border-white/20 backdrop-blur-md px-3 py-1 md:px-4 md:py-1.5">
@@ -82,48 +81,51 @@ export default function ProductsPage({ params }: ProductsPageProps) {
<Container>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 md:gap-8 lg:gap-12">
{categories.map((category, idx) => (
<Link key={idx} href={category.href} className="group block">
<Card className="h-full border-none shadow-sm hover:shadow-2xl transition-all duration-500 rounded-[24px] md:rounded-[48px] overflow-hidden bg-white">
<div className="relative h-[200px] md:h-[400px] overflow-hidden">
<Image
src={category.img}
alt={category.title}
fill
className="object-cover transition-transform duration-1000 group-hover:scale-105"
sizes="(max-width: 768px) 100vw, 50vw"
/>
<div className="absolute inset-0 image-overlay-gradient opacity-80 group-hover:opacity-90 transition-opacity duration-500" />
<div className="absolute top-3 right-3 md:top-8 md:right-8 w-10 h-10 md:w-20 md:h-20 bg-white/10 backdrop-blur-md rounded-xl md:rounded-[24px] flex items-center justify-center border border-white/20 shadow-2xl transition-all duration-500 group-hover:scale-110 group-hover:bg-white/20">
<img src={category.icon} alt="" className="w-6 h-6 md:w-12 md:h-12 brightness-0 invert opacity-80" />
</div>
<Reveal key={idx} delay={idx * 100}>
<Link key={idx} href={category.href} className="group block">
<Card className="h-full border-none shadow-sm hover:shadow-2xl transition-all duration-500 rounded-[24px] md:rounded-[48px] overflow-hidden bg-white active:scale-[0.98]">
<div className="relative h-[200px] md:h-[400px] overflow-hidden">
<Image
src={category.img}
alt={category.title}
fill
className="object-cover transition-transform duration-1000 group-hover:scale-105"
sizes="(max-width: 768px) 100vw, 50vw"
unoptimized
/>
<div className="absolute inset-0 image-overlay-gradient opacity-80 group-hover:opacity-90 transition-opacity duration-500" />
<div className="absolute top-3 right-3 md:top-8 md:right-8 w-10 h-10 md:w-20 md:h-20 bg-white/10 backdrop-blur-md rounded-xl md:rounded-[24px] flex items-center justify-center border border-white/20 shadow-2xl transition-all duration-500 group-hover:scale-110 group-hover:bg-white/20">
<img src={category.icon} alt="" className="w-6 h-6 md:w-12 md:h-12 brightness-0 invert opacity-80" />
</div>
<div className="absolute bottom-4 left-4 md:bottom-10 md:left-10 right-4 md:right-10">
<Badge variant="accent" className="mb-2 md:mb-4 shadow-lg bg-accent text-primary-dark border-none text-[10px] md:text-xs">
{t('categoryLabel')}
</Badge>
<h2 className="text-xl md:text-4xl font-bold text-white leading-tight transition-transform duration-500 group-hover:translate-x-1">
{category.title}
</h2>
</div>
</div>
<div className="p-5 md:p-10">
<p className="text-text-secondary text-sm md:text-lg leading-relaxed mb-4 md:mb-8 line-clamp-2 md:line-clamp-none">
{category.desc}
</p>
<div className="flex items-center text-primary font-bold text-base md:text-lg group-hover:text-accent-dark transition-colors">
<span className="border-b-2 border-primary/10 group-hover:border-accent-dark transition-colors pb-1">
{t('viewProducts')}
</span>
<div className="ml-3 md:ml-4 w-8 h-8 md:w-10 md:h-10 rounded-full bg-primary-light flex items-center justify-center text-primary group-hover:bg-accent group-hover:text-primary-dark transition-all duration-300 shadow-sm">
<svg className="w-4 h-4 md:w-5 md:h-5 transition-transform group-hover:translate-x-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
</svg>
<div className="absolute bottom-4 left-4 md:bottom-10 md:left-10 right-4 md:right-10">
<Badge variant="accent" className="mb-2 md:mb-4 shadow-lg bg-accent text-primary-dark border-none text-[10px] md:text-xs">
{t('categoryLabel')}
</Badge>
<h2 className="text-xl md:text-4xl font-bold text-white leading-tight transition-transform duration-500 group-hover:translate-x-1">
{category.title}
</h2>
</div>
</div>
</div>
</Card>
</Link>
<div className="p-5 md:p-10">
<p className="text-text-secondary text-sm md:text-lg leading-relaxed mb-4 md:mb-8 line-clamp-2 md:line-clamp-none">
{category.desc}
</p>
<div className="flex items-center text-primary font-bold text-base md:text-lg group-hover:text-accent-dark transition-colors">
<span className="border-b-2 border-primary/10 group-hover:border-accent-dark transition-colors pb-1">
{t('viewProducts')}
</span>
<div className="ml-3 md:ml-4 w-8 h-8 md:w-10 md:h-10 rounded-full bg-primary-light flex items-center justify-center text-primary group-hover:bg-accent group-hover:text-primary-dark transition-all duration-300 shadow-sm">
<svg className="w-4 h-4 md:w-5 md:h-5 transition-transform group-hover:translate-x-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
</svg>
</div>
</div>
</div>
</Card>
</Link>
</Reveal>
))}
</div>
</Container>

View File

@@ -1,6 +1,7 @@
import { useTranslations } from 'next-intl';
import { Section, Container, Heading, Card, Badge, Button } from '@/components/ui';
import { Section, Container, Heading, Badge, Button } from '@/components/ui';
import Image from 'next/image';
import Reveal from '@/components/Reveal';
export default function TeamPage() {
const t = useTranslations('Team');
@@ -34,9 +35,9 @@ export default function TeamPage() {
{/* Michael Bodemer Section - Sticky Narrative Split Layout */}
<section className="relative bg-white overflow-hidden">
<div className="flex flex-col lg:flex-row">
<div className="w-full lg:w-1/2 p-6 md:p-24 lg:p-32 flex flex-col justify-center bg-primary-dark text-white relative">
<Reveal className="w-full lg:w-1/2 p-6 md:p-24 lg:p-32 flex flex-col justify-center bg-primary-dark text-white relative order-2 lg:order-1">
<div className="absolute top-0 right-0 w-32 h-full bg-accent/5 -skew-x-12 translate-x-1/2" />
<div className="relative z-10 animate-fade-in">
<div className="relative z-10">
<Badge variant="accent" className="mb-4 md:mb-8">Managing Director</Badge>
<Heading level={2} className="text-white mb-6 md:mb-10 text-3xl md:text-6xl">
<span className="text-white">{t('michael.name')}</span>
@@ -47,21 +48,21 @@ export default function TeamPage() {
"{t('michael.quote')}"
</p>
</div>
<p className="text-base md:text-xl leading-relaxed text-white/70 mb-6 md:mb-12 max-w-xl line-clamp-4 md:line-clamp-none">
<p className="text-base md:text-xl leading-relaxed text-white/70 mb-6 md:mb-12 max-w-xl">
{t('michael.description')}
</p>
<Button
href="https://www.linkedin.com/in/michael-bodemer-33b493122/"
variant="accent"
size="lg"
className="group w-full md:w-auto md:h-16 md:px-10 md:text-xl"
className="group w-full md:w-auto md:h-16 md:px-10 md:text-xl active:scale-95 transition-transform"
>
{t('michael.linkedin')}
<span className="ml-3 transition-transform group-hover:translate-x-2">&rarr;</span>
</Button>
</div>
</div>
<div className="w-full lg:w-1/2 relative min-h-[300px] md:min-h-[600px] lg:min-h-screen overflow-hidden">
</Reveal>
<div className="w-full lg:w-1/2 relative min-h-[400px] md:min-h-[600px] lg:min-h-screen overflow-hidden order-1 lg:order-2">
<Image
src="/uploads/2024/12/DSC07768-Large.webp"
alt={t('michael.name')}
@@ -69,7 +70,7 @@ export default function TeamPage() {
className="object-cover scale-105 hover:scale-100 transition-transform duration-1000"
sizes="(max-width: 1024px) 100vw, 50vw"
/>
<div className="absolute inset-0 bg-gradient-to-r from-primary-dark/20 to-transparent" />
<div className="absolute inset-0 bg-gradient-to-t from-primary-dark/60 lg:bg-gradient-to-r lg:from-primary-dark/20 to-transparent" />
</div>
</div>
</section>
@@ -118,7 +119,7 @@ export default function TeamPage() {
{/* Klaus Mintel Section - Reversed Split Layout */}
<section className="relative bg-white overflow-hidden">
<div className="flex flex-col lg:flex-row">
<div className="w-full lg:w-1/2 relative min-h-[300px] md:min-h-[600px] lg:min-h-screen overflow-hidden order-2 lg:order-1">
<div className="w-full lg:w-1/2 relative min-h-[400px] md:min-h-[600px] lg:min-h-screen overflow-hidden order-1">
<Image
src="/uploads/2024/12/DSC07963-Large.webp"
alt={t('klaus.name')}
@@ -126,11 +127,11 @@ export default function TeamPage() {
className="object-cover scale-105 hover:scale-100 transition-transform duration-1000"
sizes="(max-width: 1024px) 100vw, 50vw"
/>
<div className="absolute inset-0 bg-gradient-to-l from-primary-dark/20 to-transparent" />
<div className="absolute inset-0 bg-gradient-to-t from-white/60 lg:bg-gradient-to-l lg:from-primary-dark/20 to-transparent" />
</div>
<div className="w-full lg:w-1/2 p-6 md:p-24 lg:p-32 flex flex-col justify-center bg-neutral-light text-primary relative order-1 lg:order-2">
<Reveal className="w-full lg:w-1/2 p-6 md:p-24 lg:p-32 flex flex-col justify-center bg-neutral-light text-primary relative order-2">
<div className="absolute top-0 left-0 w-32 h-full bg-primary/5 skew-x-12 -translate-x-1/2" />
<div className="relative z-10 animate-fade-in">
<div className="relative z-10">
<Badge variant="primary" className="mb-4 md:mb-8">Founder & Visionary</Badge>
<Heading level={2} className="text-primary mb-6 md:mb-10 text-3xl md:text-6xl">
{t('klaus.name')}
@@ -141,20 +142,20 @@ export default function TeamPage() {
"{t('klaus.quote')}"
</p>
</div>
<p className="text-base md:text-xl leading-relaxed text-text-secondary mb-6 md:mb-12 max-w-xl line-clamp-4 md:line-clamp-none">
<p className="text-base md:text-xl leading-relaxed text-text-secondary mb-6 md:mb-12 max-w-xl">
{t('klaus.description')}
</p>
<Button
href="https://www.linkedin.com/in/klaus-mintel-b80a8b193/"
variant="primary"
size="lg"
className="group w-full md:w-auto md:h-16 md:px-10 md:text-xl"
className="group w-full md:w-auto md:h-16 md:px-10 md:text-xl active:scale-95 transition-transform"
>
{t('klaus.linkedin')}
<span className="ml-3 transition-transform group-hover:translate-x-2">&rarr;</span>
</Button>
</div>
</div>
</Reveal>
</div>
</section>
@@ -170,16 +171,25 @@ export default function TeamPage() {
<p className="text-base md:text-xl text-text-secondary leading-relaxed">
Our core principles guide every decision we make and every cable we deliver.
</p>
{/* Mobile-only progress indicator */}
<div className="flex lg:hidden mt-8 gap-2">
{[0, 1, 2, 3, 4, 5].map((i) => (
<div key={i} className="h-1.5 flex-1 bg-neutral-medium rounded-full overflow-hidden">
<div className="h-full bg-accent w-0 group-active:w-full transition-all duration-500" />
</div>
))}
</div>
</div>
</div>
<div className="sticky-narrative-content grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-10">
{[0, 1, 2, 3, 4, 5].map((idx) => (
<div key={idx} className="p-6 md:p-10 bg-neutral-light rounded-2xl md:rounded-[40px] border border-transparent hover:border-accent hover:bg-white hover:shadow-2xl transition-all duration-500 group">
<div key={idx} className="p-6 md:p-10 bg-neutral-light rounded-2xl md:rounded-[40px] border border-transparent hover:border-accent hover:bg-white hover:shadow-2xl transition-all duration-500 group active:scale-[0.98] touch-target-none">
<div className="w-10 h-10 md:w-16 md:h-16 bg-white rounded-xl md:rounded-2xl flex items-center justify-center mb-4 md:mb-8 shadow-sm group-hover:bg-accent transition-colors duration-500">
<span className="text-primary font-extrabold text-lg md:text-2xl group-hover:text-primary-dark">0{idx + 1}</span>
</div>
<h3 className="text-lg md:text-2xl font-bold mb-2 md:mb-4 text-primary">{t(`manifesto.items.${idx}.title`)}</h3>
<p className="text-sm md:text-lg text-text-secondary leading-relaxed line-clamp-3 md:line-clamp-none">{t(`manifesto.items.${idx}.description`)}</p>
<p className="text-sm md:text-lg text-text-secondary leading-relaxed">{t(`manifesto.items.${idx}.description`)}</p>
</div>
))}
</div>

View File

@@ -12,6 +12,7 @@ export default function Header() {
const t = useTranslations('Navigation');
const pathname = usePathname();
const [isScrolled, setIsScrolled] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
// Extract locale from pathname
const currentLocale = pathname.split('/')[1] || 'en';
@@ -27,6 +28,20 @@ export default function Header() {
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
// Close mobile menu on route change
useEffect(() => {
setIsMobileMenuOpen(false);
}, [pathname]);
// Prevent scroll when mobile menu is open
useEffect(() => {
if (isMobileMenuOpen) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = 'unset';
}
}, [isMobileMenuOpen]);
// Function to get path for a different locale
const getPathForLocale = (newLocale: string) => {
@@ -45,8 +60,8 @@ export default function Header() {
const headerClass = cn(
"fixed top-0 left-0 right-0 z-50 transition-all duration-500 safe-area-p",
{
"bg-transparent py-4 md:py-8": isHomePage && !isScrolled,
"bg-primary py-3 md:py-4 shadow-2xl": !isHomePage || isScrolled,
"bg-transparent py-4 md:py-8": isHomePage && !isScrolled && !isMobileMenuOpen,
"bg-primary py-3 md:py-4 shadow-2xl": !isHomePage || isScrolled || isMobileMenuOpen,
}
);
@@ -114,15 +129,79 @@ export default function Header() {
</div>
{/* Mobile Menu Button */}
<button className={cn("lg:hidden touch-target p-2 rounded-xl bg-white/10 backdrop-blur-md border border-white/20", textColorClass)}>
<button
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
className={cn("lg:hidden touch-target p-2 rounded-xl bg-white/10 backdrop-blur-md border border-white/20 z-50", textColorClass)}
aria-label="Toggle Menu"
>
<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" />
{isMobileMenuOpen ? (
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
) : (
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
)}
</svg>
</button>
</div>
</div>
{/* Mobile Menu Overlay */}
<div className={cn(
"fixed inset-0 bg-primary-dark z-40 lg:hidden transition-all duration-500 ease-in-out flex flex-col",
isMobileMenuOpen ? "opacity-100 translate-y-0" : "opacity-0 -translate-y-full pointer-events-none"
)}>
<div className="flex-grow flex flex-col justify-center items-center p-8 space-y-8">
{menuItems.map((item, idx) => (
<Link
key={item.href}
href={`/${currentLocale}${item.href === '/' ? '' : item.href}`}
className={cn(
"text-3xl font-extrabold text-white hover:text-accent transition-all transform",
isMobileMenuOpen ? "translate-y-0 opacity-100" : "translate-y-10 opacity-0"
)}
style={{ transitionDelay: `${idx * 100}ms` }}
>
{item.label}
</Link>
))}
<div className={cn(
"pt-8 border-t border-white/10 w-full flex flex-col items-center space-y-8 transition-all duration-500 delay-500",
isMobileMenuOpen ? "translate-y-0 opacity-100" : "translate-y-10 opacity-0"
)}>
<div className="flex items-center space-x-8 text-xl font-extrabold tracking-widest uppercase text-white">
<Link
href={getPathForLocale('en')}
className={`hover:text-accent transition-colors ${currentLocale === 'en' ? 'text-accent' : 'opacity-60'}`}
>
EN
</Link>
<div className="w-px h-6 bg-white/20" />
<Link
href={getPathForLocale('de')}
className={`hover:text-accent transition-colors ${currentLocale === 'de' ? 'text-accent' : 'opacity-60'}`}
>
DE
</Link>
</div>
<Button
href={`/${currentLocale}/contact`}
variant="accent"
size="lg"
className="w-full max-w-xs py-6 text-xl shadow-2xl"
>
{t('contact')}
</Button>
</div>
</div>
{/* Bottom Branding */}
<div className="p-12 flex justify-center opacity-20">
<Image src="/logo-white.svg" alt="KLZ" width={80} height={80} unoptimized />
</div>
</div>
</header>
{/* Removed spacer div that caused white gap */}
</>
);
}

View File

@@ -0,0 +1,49 @@
'use client';
import React from 'react';
import { Button } from '@/components/ui';
interface ShareButtonProps {
title: string;
text: string;
url: string;
locale: string;
}
export default function ShareButton({ title, text, url, locale }: ShareButtonProps) {
const handleShare = async () => {
if (navigator.share) {
try {
await navigator.share({
title,
text,
url,
});
} catch (error) {
console.error('Error sharing:', error);
}
} else {
// Fallback to copy link
try {
await navigator.clipboard.writeText(url);
alert(locale === 'de' ? 'Link kopiert!' : 'Link copied!');
} catch (error) {
console.error('Error copying link:', error);
}
}
};
return (
<Button
onClick={handleShare}
variant="outline"
size="sm"
className="flex items-center gap-2 rounded-full px-6"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 100 5.368 3 3 0 000-5.368z" />
</svg>
{locale === 'de' ? 'Teilen' : 'Share'}
</Button>
);
}

View File

@@ -1,7 +1,5 @@
import React from 'react';
import { useTranslations } from 'next-intl';
import Scribble from '@/components/Scribble';
import { Section } from '../../components/ui';
import { useTranslations } from 'next-intl';
export default function VideoSection() {
const t = useTranslations('Home.video');
@@ -29,11 +27,6 @@ export default function VideoSection() {
)
})}
</h2>
<div className="mt-12 flex justify-center">
<div className="w-24 h-24 rounded-full border-2 border-white/30 flex items-center justify-center group cursor-pointer hover:bg-white transition-all duration-500">
<div className="w-0 h-0 border-t-[12px] border-t-transparent border-l-[20px] border-l-white border-b-[12px] border-b-transparent ml-2 group-hover:border-l-primary-dark transition-colors" />
</div>
</div>
</div>
</div>
</section>

View File

@@ -1,100 +0,0 @@
'use client';
import React from 'react';
export default function ProductsIllustration() {
return (
<div className="absolute inset-0 z-0 overflow-hidden pointer-events-none bg-primary">
<svg
viewBox="0 0 1000 500"
className="w-full h-full"
preserveAspectRatio="xMidYMid slice"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<defs>
<linearGradient id="scan-beam" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="#82ed20" stopOpacity="0" />
<stop offset="50%" stopColor="#82ed20" stopOpacity="0.5" />
<stop offset="100%" stopColor="#82ed20" stopOpacity="0" />
</linearGradient>
</defs>
{/* 3D Cable Wireframe Construction */}
<g transform="translate(100, 250) rotate(-10)">
{/* Inner Core Strands (Twisted) */}
{[...Array(5)].map((_, i) => (
<path
key={`strand-${i}`}
d={`M 0 ${i*10 - 20} Q 400 ${i*10 - 60} 800 ${i*10 - 20}`}
stroke="white"
strokeWidth="2"
strokeOpacity="0.8"
fill="none"
>
<animate attributeName="d"
values={`M 0 ${i*10 - 20} Q 400 ${i*10 - 60} 800 ${i*10 - 20};
M 0 ${i*10 - 20} Q 400 ${i*10 + 20} 800 ${i*10 - 20};
M 0 ${i*10 - 20} Q 400 ${i*10 - 60} 800 ${i*10 - 20}`}
dur="4s"
repeatCount="indefinite"
/>
</path>
))}
{/* Insulation Layers (Ellipses along the path) */}
{[...Array(8)].map((_, i) => (
<ellipse
key={`ring-${i}`}
cx={100 + i * 100}
cy="0"
rx="40"
ry="80"
stroke="white"
strokeWidth="1"
strokeOpacity="0.2"
fill="none"
/>
))}
{/* Outer Sheath (Top and Bottom Lines) */}
<path d="M 0 -80 L 800 -80" stroke="white" strokeWidth="1" strokeOpacity="0.3" strokeDasharray="10 5" />
<path d="M 0 80 L 800 80" stroke="white" strokeWidth="1" strokeOpacity="0.3" strokeDasharray="10 5" />
{/* Scanning Ring (Animated) */}
<g>
<ellipse cx="0" cy="0" rx="50" ry="90" stroke="#82ed20" strokeWidth="2" strokeOpacity="0.8" fill="none">
<animate attributeName="cx" from="0" to="800" dur="3s" repeatCount="indefinite" />
<animate attributeName="rx" values="50;45;50" dur="0.5s" repeatCount="indefinite" />
</ellipse>
{/* Scan Beam */}
<rect x="-50" y="-100" width="100" height="200" fill="url(#scan-beam)" opacity="0.3">
<animate attributeName="x" from="-50" to="750" dur="3s" repeatCount="indefinite" />
</rect>
</g>
</g>
{/* Floating Data/Tech Elements */}
<g transform="translate(0, 0)">
{[...Array(20)].map((_, i) => (
<rect
key={`bit-${i}`}
x={Math.random() * 1000}
y={Math.random() * 500}
width={Math.random() * 20 + 5}
height="2"
fill="white"
fillOpacity="0.3"
>
<animate attributeName="opacity" values="0;0.5;0" dur={`${Math.random() * 2 + 1}s`} repeatCount="indefinite" />
<animate attributeName="width" values="5;30;5" dur={`${Math.random() * 2 + 1}s`} repeatCount="indefinite" />
</rect>
))}
</g>
</svg>
<div className="absolute inset-0 bg-gradient-to-r from-primary/80 via-transparent to-primary/80" />
</div>
);
}

File diff suppressed because one or more lines are too long