feat: upgrade UI with premium industrial aesthetics, purely visual language switch, and resilient error pages

Former-commit-id: e4d801c24e64c41816f86de9767b47894abb6806
This commit is contained in:
2026-05-09 09:39:58 +02:00
parent 3590d47fdb
commit 2ce9ac11e7
15 changed files with 453 additions and 232 deletions

View File

@@ -18,115 +18,136 @@ export function Footer({ companyInfo }: FooterProps) {
const locale = useLocale();
return (
<footer className="bg-neutral-dark text-neutral-light py-16 relative overflow-hidden">
<div className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-white/10 to-transparent" />
<footer className="bg-[#050B14] text-neutral-light py-16 relative overflow-hidden border-t border-white/5">
{/* Subtle background tech grid */}
<div className="absolute inset-0 bg-[linear-gradient(to_right,#8080800a_1px,transparent_1px),linear-gradient(to_bottom,#8080800a_1px,transparent_1px)] bg-[size:32px_32px] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_100%)] pointer-events-none" />
<div className="container grid grid-cols-1 md:grid-cols-4 lg:grid-cols-12 gap-12 lg:gap-8 mb-12">
{/* Brand Column */}
<div className="col-span-1 md:col-span-2 lg:col-span-4 space-y-6">
<TransitionLink href={`/${locale}`} className="relative block h-14 w-48 mb-6 group">
<Image
src="/assets/logo-white.png"
alt="E-TIB Gruppe"
fill
className="object-contain object-left transition-transform duration-500 group-hover:scale-105"
/>
</TransitionLink>
<p className="text-white/60 text-base leading-relaxed max-w-sm">
{locale === 'de'
? 'Die Experten für Kabeltiefbau, Horizontalspülbohrungen und umfassende Infrastrukturprojekte. Qualität und Zuverlässigkeit aus Guben.'
: 'Experts in cable construction, horizontal directional drilling, and comprehensive infrastructure projects. Quality and reliability from Guben.'}
</p>
{/* Top glowing edge */}
<div className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-primary/40 to-transparent" />
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-1/3 h-[200px] bg-primary/20 blur-[100px] rounded-full pointer-events-none opacity-50" />
<div className="container relative z-10 grid grid-cols-1 md:grid-cols-4 lg:grid-cols-12 gap-6 lg:gap-8 mb-12">
{/* Brand Column Bento */}
<div className="col-span-1 md:col-span-4 lg:col-span-5 flex flex-col justify-between bg-white/[0.02] border border-white/5 rounded-3xl p-8 lg:p-10 backdrop-blur-md relative group overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-br from-white/[0.04] to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-700" />
<div className="space-y-6 relative z-10">
<TransitionLink href={`/${locale}`} className="relative block h-14 w-48 mb-6 group/logo">
<Image
src="/assets/logo-white.png"
alt="E-TIB Gruppe"
fill
className="object-contain object-left transition-transform duration-500 group-hover/logo:scale-105 origin-left"
/>
</TransitionLink>
<p className="text-white/60 text-base leading-relaxed max-w-sm">
{locale === 'de'
? 'Die Experten für Kabeltiefbau, Horizontalspülbohrungen und umfassende Infrastrukturprojekte. Qualität und Zuverlässigkeit aus Guben.'
: 'Experts in cable construction, horizontal directional drilling, and comprehensive infrastructure projects. Quality and reliability from Guben.'}
</p>
</div>
{companyInfo && (
<div className="text-white/70 text-sm space-y-3 mt-8 border-t border-white/10 pt-6 max-w-xs">
<p className="whitespace-pre-line font-medium">{companyInfo.address}</p>
<p>Email: <a href={`mailto:${companyInfo.contactEmail}`} className="hover:text-primary transition-colors">{companyInfo.contactEmail}</a></p>
<p>Tel: <a href={`tel:${companyInfo.contactPhone.replace(/\s+/g, '')}`} className="hover:text-primary transition-colors">{companyInfo.contactPhone}</a></p>
<div className="text-white/70 text-sm space-y-4 mt-12 relative z-10">
<div className="flex gap-4 p-4 rounded-2xl bg-white/[0.03] border border-white/[0.05] hover:bg-white/[0.05] transition-colors">
<div className="w-10 h-10 rounded-full bg-primary/20 flex items-center justify-center shrink-0">
<svg xmlns="http://www.w3.org/2000/svg" className="w-5 h-5 text-primary" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" /><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" /></svg>
</div>
<div>
<p className="text-xs text-white/40 uppercase tracking-wider mb-1 font-heading">{locale === 'de' ? 'Hauptsitz' : 'Headquarters'}</p>
<p className="whitespace-pre-line font-medium text-white/90">{companyInfo.address}</p>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<a href={`mailto:${companyInfo.contactEmail}`} className="flex flex-col gap-2 p-4 rounded-2xl bg-white/[0.03] border border-white/[0.05] hover:bg-white/[0.08] hover:border-primary/30 transition-all group/contact">
<p className="text-xs text-white/40 uppercase tracking-wider font-heading">E-Mail</p>
<p className="font-medium text-white/90 group-hover/contact:text-primary transition-colors truncate">{companyInfo.contactEmail}</p>
</a>
<a href={`tel:${companyInfo.contactPhone.replace(/\s+/g, '')}`} className="flex flex-col gap-2 p-4 rounded-2xl bg-white/[0.03] border border-white/[0.05] hover:bg-white/[0.08] hover:border-primary/30 transition-all group/contact">
<p className="text-xs text-white/40 uppercase tracking-wider font-heading">{locale === 'de' ? 'Telefon' : 'Phone'}</p>
<p className="font-medium text-white/90 group-hover/contact:text-primary transition-colors truncate">{companyInfo.contactPhone}</p>
</a>
</div>
</div>
)}
</div>
{/* Company Column */}
<div className="col-span-1 lg:col-span-3 lg:col-start-6">
<h4 className="font-heading font-bold uppercase tracking-widest text-xs mb-6 text-white/40">
{locale === 'de' ? 'Unternehmen' : 'Company'}
</h4>
<ul className="space-y-4">
<li>
<TransitionLink href={`/${locale}/kompetenzen`} className="text-white/70 hover:text-white hover:translate-x-1 inline-block transition-all">
{locale === 'de' ? 'Kompetenzen' : 'Competencies'}
</TransitionLink>
</li>
<li>
<TransitionLink href={`/${locale}/ueber-uns`} className="text-white/70 hover:text-white hover:translate-x-1 inline-block transition-all">
{locale === 'de' ? 'Über uns' : 'About us'}
</TransitionLink>
</li>
<li>
<TransitionLink href={`/${locale}/karriere`} className="text-white/70 hover:text-white hover:translate-x-1 inline-block transition-all">
{locale === 'de' ? 'Karriere' : 'Career'}
</TransitionLink>
</li>
<li>
<TransitionLink href={`/${locale}/messen`} className="text-white/70 hover:text-white hover:translate-x-1 inline-block transition-all">
{locale === 'de' ? 'Messen & Events' : 'Fairs & Events'}
</TransitionLink>
</li>
<li>
<TransitionLink href={`/${locale}/${locale === 'de' ? 'kontakt' : 'contact'}`} className="text-white/70 hover:text-white hover:translate-x-1 inline-block transition-all">
{locale === 'de' ? 'Kontakt' : 'Contact'}
</TransitionLink>
</li>
</ul>
</div>
{/* Navigation Bento Grid */}
<div className="col-span-1 md:col-span-4 lg:col-span-7 grid grid-cols-1 sm:grid-cols-2 gap-6 lg:gap-8">
{/* Company Column */}
<div className="bg-white/[0.02] border border-white/5 rounded-3xl p-8 lg:p-10 backdrop-blur-md relative group overflow-hidden flex flex-col">
<div className="absolute inset-0 bg-gradient-to-bl from-white/[0.04] to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-700 pointer-events-none" />
<h4 className="font-heading font-bold uppercase tracking-widest text-sm mb-8 text-white">
{locale === 'de' ? 'Unternehmen' : 'Company'}
<span className="block w-8 h-1 bg-primary mt-3 rounded-full" />
</h4>
<ul className="space-y-4 relative z-10 flex-grow">
{[
{ label: locale === 'de' ? 'Kompetenzen' : 'Competencies', href: `/${locale}/kompetenzen` },
{ label: locale === 'de' ? 'Über uns' : 'About us', href: `/${locale}/ueber-uns` },
{ label: locale === 'de' ? 'Karriere' : 'Career', href: `/${locale}/karriere` },
{ label: locale === 'de' ? 'Messen & Events' : 'Fairs & Events', href: `/${locale}/messen` },
{ label: locale === 'de' ? 'Kontakt' : 'Contact', href: `/${locale}/${locale === 'de' ? 'kontakt' : 'contact'}` },
].map((link) => (
<li key={link.href}>
<TransitionLink href={link.href} className="group/link flex items-center text-white/60 hover:text-white transition-colors py-1">
<span className="w-0 h-px bg-primary mr-0 group-hover/link:w-4 group-hover/link:mr-3 transition-all duration-300" />
<span className="font-medium">{link.label}</span>
</TransitionLink>
</li>
))}
</ul>
</div>
{/* Legal Column */}
<div className="bg-white/[0.02] border border-white/5 rounded-3xl p-8 lg:p-10 backdrop-blur-md relative group overflow-hidden flex flex-col">
<div className="absolute inset-0 bg-gradient-to-tr from-white/[0.04] to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-700 pointer-events-none" />
<h4 className="font-heading font-bold uppercase tracking-widest text-sm mb-8 text-white">
{locale === 'de' ? 'Rechtliches' : 'Legal'}
<span className="block w-8 h-1 bg-primary mt-3 rounded-full opacity-50" />
</h4>
<ul className="space-y-4 relative z-10 flex-grow">
{[
{ label: locale === 'de' ? 'Impressum' : 'Imprint', href: `/${locale}/impressum` },
{ label: locale === 'de' ? 'Datenschutz' : 'Privacy Policy', href: `/${locale}/datenschutz` },
{ label: locale === 'de' ? 'AGB' : 'Terms', href: `/${locale}/${locale === 'de' ? 'agb' : 'terms'}` },
].map((link) => (
<li key={link.href}>
<TransitionLink href={link.href} className="group/link flex items-center text-white/50 hover:text-white transition-colors py-1">
<span className="w-0 h-px bg-white/30 mr-0 group-hover/link:w-3 group-hover/link:mr-3 transition-all duration-300" />
<span className="font-medium">{link.label}</span>
</TransitionLink>
</li>
))}
</ul>
{/* Built Info inside Legal box for compact layout */}
<div className="mt-12 pt-6 border-t border-white/5 text-white/30 text-xs">
<a href="https://mintel.me" target="_blank" rel="noopener noreferrer" className="hover:text-white/60 transition-colors flex items-center gap-2">
<span>Designed & Engineered by Mintel</span>
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M7 17l9.2-9.2M17 17V7H7"/></svg>
</a>
</div>
</div>
{/* Legal Column */}
<div className="col-span-1 lg:col-span-3">
<h4 className="font-heading font-bold uppercase tracking-widest text-xs mb-6 text-white/40">
{locale === 'de' ? 'Rechtliches' : 'Legal'}
</h4>
<ul className="space-y-4">
<li>
<TransitionLink href={`/${locale}/impressum`} className="text-white/70 hover:text-white hover:translate-x-1 inline-block transition-all">
{locale === 'de' ? 'Impressum' : 'Imprint'}
</TransitionLink>
</li>
<li>
<TransitionLink href={`/${locale}/datenschutz`} className="text-white/70 hover:text-white hover:translate-x-1 inline-block transition-all">
{locale === 'de' ? 'Datenschutz' : 'Privacy Policy'}
</TransitionLink>
</li>
<li>
<TransitionLink href={`/${locale}/${locale === 'de' ? 'agb' : 'terms'}`} className="text-white/70 hover:text-white hover:translate-x-1 inline-block transition-all">
{locale === 'de' ? 'AGB' : 'Terms'}
</TransitionLink>
</li>
</ul>
</div>
</div>
<div className="container">
<div className="pt-8 border-t border-white/10 flex flex-col md:flex-row justify-between items-center gap-6 text-white/50 text-sm">
<p>&copy; {new Date().getFullYear()} E-TIB GmbH. {locale === 'de' ? 'Alle Rechte vorbehalten.' : 'All rights reserved.'}</p>
<div className="flex items-center gap-4">
<div className="container relative z-10">
<div className="flex flex-col md:flex-row justify-between items-center gap-6 py-6 px-8 rounded-2xl bg-white/[0.02] border border-white/5 backdrop-blur-md">
<p className="text-white/50 text-sm font-medium">&copy; {new Date().getFullYear()} E-TIB GmbH. {locale === 'de' ? 'Alle Rechte vorbehalten.' : 'All rights reserved.'}</p>
<div className="flex items-center gap-6">
<LanguageSwitcher isSolidMode={false} />
</div>
</div>
{/* Quality Badges */}
<div className="pt-8 mt-8 border-t border-white/5 flex flex-col md:flex-row justify-between items-center gap-6 text-white/30 text-xs">
<div>
<a href="https://mintel.me" target="_blank" rel="noopener noreferrer" className="hover:text-white/60 transition-colors">
Website developed by Mintel
</a>
</div>
<div className="flex flex-wrap justify-center gap-x-6 gap-y-3">
<div className="flex items-center gap-1.5"><ShieldCheck className="w-3.5 h-3.5" /><span>SSL Secured</span></div>
<div className="flex items-center gap-1.5"><Leaf className="w-3.5 h-3.5" /><span>Green Hosting</span></div>
<div className="flex items-center gap-1.5"><Lock className="w-3.5 h-3.5" /><span>DSGVO Compliant</span></div>
<div className="flex items-center gap-1.5"><Accessibility className="w-3.5 h-3.5" /><span>WCAG</span></div>
<div className="flex items-center gap-1.5"><Zap className="w-3.5 h-3.5" /><span>PageSpeed 90+</span></div>
</div>
<div className="mt-6 flex flex-wrap justify-center gap-x-8 gap-y-4 text-white/30 text-xs font-medium uppercase tracking-wider">
<div className="flex items-center gap-2"><ShieldCheck className="w-4 h-4 text-white/40" /><span>SSL Secured</span></div>
<div className="flex items-center gap-2"><Leaf className="w-4 h-4 text-primary/60" /><span>Green Hosting</span></div>
<div className="flex items-center gap-2"><Lock className="w-4 h-4 text-white/40" /><span>DSGVO Compliant</span></div>
<div className="flex items-center gap-2"><Zap className="w-4 h-4 text-white/40" /><span>High Performance</span></div>
</div>
</div>
</footer>

View File

@@ -26,27 +26,31 @@ export function LanguageSwitcher({ mobile = false, isSolidMode = false }: Langua
if (mobile) {
return (
<div className="flex flex-col gap-3">
{locales.map((loc) => (
<TransitionLink
key={loc.code}
href={getSwitchedUrl(loc.code)}
className={`group relative overflow-hidden flex items-center gap-3 px-5 py-3 rounded-xl text-lg font-semibold transition-all duration-300 ${
currentLocale === loc.code
? 'bg-primary/10 text-primary border border-primary/20'
: 'text-text-secondary hover:bg-neutral-50 border border-transparent'
}`}
>
<HoverShineOverlay shineColor="via-primary/5" />
<span className="relative z-10 text-2xl" aria-hidden="true">{loc.flag}</span>
<span className="relative z-10">{loc.fullLabel}</span>
{currentLocale === loc.code && (
<svg className="relative z-10 w-5 h-5 ml-auto text-primary" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
<polyline points="20 6 9 17 4 12" />
</svg>
)}
</TransitionLink>
))}
{locales.map((loc) => {
const currentLocObj = locales.find(l => l.code === currentLocale) || locales[0];
return (
<TransitionLink
key={loc.code}
href={getSwitchedUrl(loc.code)}
transitionMessage={currentLocale === loc.code ? undefined : `LANG_SWITCH:${currentLocObj.flag}:${loc.flag}`}
className={`group relative overflow-hidden flex items-center gap-3 px-5 py-3 rounded-xl text-lg font-semibold transition-all duration-300 ${
currentLocale === loc.code
? 'bg-primary/10 text-primary border border-primary/20'
: 'text-text-secondary hover:bg-neutral-50 border border-transparent'
}`}
>
<HoverShineOverlay shineColor="via-primary/5" />
<span className="relative z-10 text-2xl" aria-hidden="true">{loc.flag}</span>
<span className="relative z-10">{loc.fullLabel}</span>
{currentLocale === loc.code && (
<svg className="relative z-10 w-5 h-5 ml-auto text-primary" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
<polyline points="20 6 9 17 4 12" />
</svg>
)}
</TransitionLink>
);
})}
</div>
);
}
@@ -72,10 +76,13 @@ export function LanguageSwitcher({ mobile = false, isSolidMode = false }: Langua
: 'text-white/70 hover:text-white';
}
const currentLocObj = locales.find(l => l.code === currentLocale) || locales[0];
return (
<TransitionLink
key={loc.code}
href={getSwitchedUrl(loc.code)}
transitionMessage={isActive ? undefined : `LANG_SWITCH:${currentLocObj.flag}:${loc.flag}`}
className={`relative z-10 flex items-center gap-1.5 px-3 py-1.5 rounded-full text-xs font-bold uppercase tracking-wider transition-all duration-300 ${linkClass}`}
aria-label={`Switch to ${loc.fullLabel}`}
>