feat: overhaul competence pages, unify brand colors, and polish site integrity
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 23s
Build & Deploy / 🧪 QA (push) Failing after 1m8s
Build & Deploy / 🏗️ Build (push) Has been skipped
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 1s

- Rewrote all 5 competence pages (Kabeltiefbau, Bohrtechnik, Glasfaser, Planung, Vermessung) with factual data from references
- Unified brand colors: replaced toxic neon green with brand-aligned teal (#10a379)
- Fixed ReferencesSlider injection in dynamic MDX pages
- Enhanced Footer with icon parity, improved branding placement, and unified hover effects
- Refined Header with 3D micro-animations and improved dropdown visibility
- Fixed localized tracking API (rewrites for /stats/api/send)
- Resolved ReferenceErrors in InteractiveGermanyMap and Header state management
- Cleaned reference titles and truncated metadata in lists
This commit is contained in:
2026-05-15 21:07:25 +02:00
parent 4dcd5f511a
commit 843d61cd5d
47 changed files with 1125 additions and 690 deletions

View File

@@ -20,6 +20,7 @@ interface HeaderProps {
export function Header({ navLinks }: HeaderProps) {
const [isScrolled, setIsScrolled] = React.useState(false);
const [forceSolid, setForceSolid] = React.useState(false);
const [headerVariant, setHeaderVariant] = React.useState<'capsule' | 'standard'>('capsule');
const pathname = usePathname() || '/';
// Scroll bound shine effect (continuous looping as user scrolls)
@@ -41,17 +42,18 @@ export function Header({ navLinks }: HeaderProps) {
window.addEventListener('scroll', handleScroll);
// Check for forced solid header (used by error pages, legal pages without hero, etc.)
const checkSolid = () => {
const checkHeaderState = () => {
setForceSolid(document.body.getAttribute('data-force-solid-header') === 'true');
setHeaderVariant((document.body.getAttribute('data-header-variant') as 'capsule' | 'standard') || 'capsule');
};
checkSolid();
checkHeaderState();
// Set up observer for client-side navigation changes
const observer = new MutationObserver(checkSolid);
observer.observe(document.body, { attributes: true, attributeFilter: ['data-force-solid-header'] });
const observer = new MutationObserver(checkHeaderState);
observer.observe(document.body, { attributes: true, attributeFilter: ['data-force-solid-header', 'data-header-variant'] });
// Re-check when pathname changes
checkSolid();
checkHeaderState();
return () => {
window.removeEventListener('scroll', handleScroll);
@@ -59,23 +61,26 @@ export function Header({ navLinks }: HeaderProps) {
};
}, [pathname]);
// Check for force solid initially
const isSolidMode = isScrolled || forceSolid;
const isSolidMode = isScrolled || forceSolid || headerVariant === 'standard';
const isStandard = headerVariant === 'standard';
return (
<>
<header
className={`fixed top-0 left-0 right-0 z-50 flex justify-center transition-all duration-700 ease-[cubic-bezier(0.16,1,0.3,1)] ${
isSolidMode ? 'pt-4 px-4' : 'pt-0 px-0'
isStandard
? 'bg-[#050B14]/95 backdrop-blur-xl border-b border-white/10'
: (isSolidMode ? 'pt-4 px-4' : 'pt-0 px-0')
}`}
>
<div
className={`relative w-full max-w-7xl mx-auto transition-all duration-700 ease-[cubic-bezier(0.16,1,0.3,1)] flex items-center justify-between ${
isSolidMode
? 'rounded-full bg-white/50 backdrop-blur-xl shadow-[0_8px_32px_rgba(0,0,0,0.08)] border border-white/40 py-2.5 px-6 md:px-8'
: 'rounded-none bg-transparent py-6 px-4 md:px-8 border border-transparent'
isStandard
? 'py-4 px-6 md:px-8'
: isSolidMode
? 'rounded-full bg-white/50 backdrop-blur-xl shadow-[0_8px_32px_rgba(0,0,0,0.08)] border border-white/40 py-2.5 px-6 md:px-8'
: 'rounded-none bg-transparent py-6 px-4 md:px-8 border border-transparent'
}`}
>
{/* Scroll bound shine effect */}
@@ -202,13 +207,17 @@ function NavItem({ link, currentLocale, pathname, isSolidMode }: { link: NavLink
<AnimatePresence>
{isHovered && link.children && (
<motion.div
initial={{ opacity: 0, y: 10, scale: 0.95 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
exit={{ opacity: 0, y: 10, scale: 0.95 }}
transition={{ duration: 0.2, ease: 'easeOut' }}
className="absolute top-full left-1/2 -translate-x-1/2 pt-4 w-56"
initial={{ opacity: 0, y: 10, scale: 0.95, rotateX: -10 }}
animate={{ opacity: 1, y: 0, scale: 1, rotateX: 0 }}
exit={{ opacity: 0, y: 10, scale: 0.95, rotateX: -10 }}
transition={{ duration: 0.3, ease: [0.16, 1, 0.3, 1] }}
style={{ perspective: 1000, transformOrigin: 'top center' }}
className="absolute top-full left-1/2 -translate-x-1/2 pt-6 w-64 z-50"
>
<div className={`p-2 rounded-3xl shadow-[0_20px_40px_-15px_rgba(0,0,0,0.1)] border ${isSolidMode ? 'bg-white/95 border-neutral-200/60' : 'bg-[#050B14]/90 border-white/10'} backdrop-blur-xl flex flex-col gap-1`}>
<div className={`p-2.5 rounded-3xl shadow-[0_30px_60px_-15px_rgba(0,0,0,0.3)] border ${isSolidMode ? 'bg-white/95 border-neutral-200/60' : 'bg-[#050B14]/95 border-white/[0.08] shadow-[0_0_40px_rgba(0,0,0,0.4)]'} backdrop-blur-2xl flex flex-col gap-1 relative overflow-hidden`}>
{/* Top glowing accent line */}
<div className="absolute top-0 left-0 w-full h-[2px] bg-gradient-to-r from-transparent via-primary to-transparent opacity-70" />
{link.children.map((child) => {
const childUrl = child.url.startsWith('/') && !child.url.match(/^\/(en|de)/)
? `/${currentLocale}${child.url}`
@@ -218,13 +227,21 @@ function NavItem({ link, currentLocale, pathname, isSolidMode }: { link: NavLink
<TransitionLink
key={child.url}
href={childUrl}
className={`block px-4 py-3 rounded-2xl text-sm font-medium transition-all ${
className={`group/dropitem relative block px-4 py-3.5 rounded-2xl text-sm font-medium transition-all duration-300 overflow-hidden ${
isSolidMode
? isChildActive ? 'bg-primary/10 text-primary' : 'text-neutral-600 hover:bg-neutral-100 hover:text-primary'
: isChildActive ? 'bg-white/10 text-white' : 'text-neutral-300 hover:bg-white/5 hover:text-white'
? isChildActive ? 'bg-primary/10 text-primary' : 'text-neutral-600 hover:text-primary hover:bg-neutral-50/80'
: isChildActive ? 'bg-white/10 text-white' : 'text-neutral-300 hover:text-white hover:bg-white/[0.06]'
}`}
>
{child.label}
<div className="relative z-10 flex items-center justify-between">
<span className="relative">
{child.label}
<span className={`absolute -bottom-0.5 left-0 w-0 h-0.5 rounded-full transition-all duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] group-hover/dropitem:w-full ${isSolidMode ? 'bg-primary/40' : 'bg-primary/60'} ${isChildActive ? 'opacity-0' : 'opacity-100'}`} />
</span>
<svg className={`w-4 h-4 transition-all duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] -translate-x-3 opacity-0 group-hover/dropitem:translate-x-0 group-hover/dropitem:opacity-100 ${isSolidMode ? 'text-primary' : 'text-white'}`} fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M9 5l7 7-7 7" />
</svg>
</div>
</TransitionLink>
);
})}