import React, { useState, useEffect, useRef } from 'react'; import { Link, useLocation } from 'react-router-dom'; import { ArrowRight, Upload } from 'lucide-react'; import LoadingScreen from '@/components/ui/LoadingScreen'; import { useIsMobile } from '@/hooks/useIsMobile'; interface LayoutProps { children: React.ReactNode; } /* ── SVG icons ─────────────────────────────────────────── */ const IgIcon = () => ; const LiIcon = () => ; const FbIcon = () => ; const SOCIAL = [ { href:'https://instagram.com', Icon:IgIcon, label:'Instagram' }, { href:'https://linkedin.com', Icon:LiIcon, label:'LinkedIn' }, { href:'https://facebook.com', Icon:FbIcon, label:'Facebook' }, ]; /* ── Nav data ──────────────────────────────────────────── */ interface NavItem { key: string; label: string; path: string; subLabel?: string; sub?: { label: string; path: string }[]; } const NAV: NavItem[] = [ { key: 'preistraeger', label: 'Preisträger:innen', path: '/preistraeger', subLabel: 'PREISTRÄGER:INNEN', sub: [ { label: 'Alle Preisträger:innen', path: '/preistraeger' }, { label: 'Sieger & Aufsteiger 2025', path: '/preistraeger' }, ], }, { key: 'teilnahme', label: 'Ihr Weg zum Preis', path: '/teilnahme', subLabel: 'IHR WEG ZUM PREIS', sub: [ { label: 'Teilnahmevoraussetzungen', path: '/teilnahme#voraussetzungen' }, { label: 'Kriterien & Bewertung', path: '/teilnahme#kriterien' }, { label: 'Fristen & Termine', path: '/teilnahme#fristen' }, { label: 'Bewerbungsformular', path: '/teilnahme#bewerben' }, ], }, { key: 'bmp', label: 'Der BMP', path: '/der-bmp', subLabel: 'DER BMP', sub: [ { label: 'Was ist der Preis?', path: '/der-bmp#was-ist' }, { label: 'Geschichte & Werte', path: '/der-bmp#geschichte' }, { label: 'Vorteile der Auszeichnung', path: '/der-bmp#vorteile' }, ], }, { key: 'netzwerk', label: 'Netzwerk', path: '/netzwerk', subLabel: 'NETZWERK', sub: [ { label: 'Jury-Mitglieder', path: '/netzwerk#jury' }, { label: 'Partner & Sponsoren', path: '/netzwerk#partner' }, { label: 'Schirmherrschaft', path: '/netzwerk#schirmherrschaft' }, { label: 'Mitglied werden', path: '/mitglied-werden' }, ], }, { key: 'presse', label: 'Presse', path: '/presse', subLabel: 'PRESSE', sub: [ { label: 'Events & Gala', path: '/presse#events' }, { label: 'Downloads & Impressionen', path: '/presse#downloads' }, ], }, ]; const SECONDARY = [ { label:'Startseite', path:'/' }, { label:'Kontakt', path:'/kontakt' }, { label:'Impressum', path:'/impressum' }, { label:'Datenschutz', path:'/datenschutz' }, ]; /* ── Tokens ────────────────────────────────────────────── */ const NAVY = '#111D55'; const ANTHRA = '#1A2030'; // nav + footer shared bg const GOLD = '#EFBF04'; const MUTED = '#D0D5DD'; const SEP = 'rgba(239,191,4,0.2)'; const LINE = 'rgba(239,191,4,0.35)'; const FF_DISPLAY = '"IBM Plex Sans", sans-serif'; const FF_BODY = '"Inter", sans-serif'; /* ── SocialLink helper ─────────────────────────────────── */ const SocialLink: React.FC<{ href:string; Icon:()=>JSX.Element; label:string }> = ({ href, Icon, label }) => ( (e.currentTarget.style.color=GOLD)} onMouseLeave={e=>(e.currentTarget.style.color=MUTED)} > ); /* ── Component ──────────────────────────────────────────── */ const Layout: React.FC = ({ children }) => { const [open, setOpen] = useState(false); // desktop overlay const [activeKey, setActive] = useState(null); // desktop hover subnav const [mobileOpen, setMobileOpen] = useState(false); // mobile sidebar overlay const [expandKey, setExpand] = useState(null); // mobile accordion const [lang, setLang] = useState<'DE'|'EN'>('DE'); const [mounted, setMounted] = useState(false); const [showLoader, setShowLoader] = useState(() => { if (typeof window === 'undefined') return false; sessionStorage.removeItem('bmp-intro-seen'); return true; }); const [formVisible, setFormVisible] = useState(false); const location = useLocation(); const firstLinkRef = useRef(null); const isLegalPage = ['/impressum', '/datenschutz'].includes(location.pathname); const isMobile = useIsMobile(); // Close everything on route change useEffect(() => { setOpen(false); setMobileOpen(false); setExpand(null); if (location.hash) { setTimeout(() => { const el = document.querySelector(location.hash); if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' }); }, 120); } else { window.scrollTo(0, 0); } }, [location]); // Reset mobile accordion when its overlay closes useEffect(() => { if (!mobileOpen) setTimeout(() => setExpand(null), 220); }, [mobileOpen]); // Body scroll lock (either overlay) useEffect(() => { const anyOpen = open || mobileOpen; const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth; if (anyOpen) { document.body.style.overflow = 'hidden'; document.body.style.paddingRight = open ? `${scrollbarWidth}px` : ''; } else { document.body.style.overflow = ''; document.body.style.paddingRight = ''; setTimeout(() => setActive(null), 220); } return () => { document.body.style.overflow = ''; document.body.style.paddingRight = ''; }; }, [open, mobileOpen]); // Focus first desktop nav link on open useEffect(() => { if (open) setTimeout(() => firstLinkRef.current?.focus(), 300); }, [open]); // Escape closes either overlay useEffect(() => { const h = (e:KeyboardEvent) => { if (e.key === 'Escape') { if (open) setOpen(false); if (mobileOpen) setMobileOpen(false); } }; window.addEventListener('keydown', h); return () => window.removeEventListener('keydown', h); }, [open, mobileOpen]); useEffect(() => { const t = setTimeout(() => setMounted(true), 60); return () => clearTimeout(t); }, []); // Hide floating CTA when the form section (#bewerben) is in view – homepage only useEffect(() => { setFormVisible(false); if (location.pathname !== '/') return; const el = document.getElementById('bewerben'); if (!el) return; const obs = new IntersectionObserver( ([entry]) => setFormVisible(entry.isIntersecting), { threshold: 0.05 } ); obs.observe(el); return () => obs.disconnect(); }, [location.pathname]); return (
{showLoader && setShowLoader(false)} />} {/* ── GLOBAL BAYERN CSS ────────────────────────── */} {/* ═══════════════════════════════════════════════════════════ */} {/* ══ DESKTOP CHROME (≥768px) – original top bar + overlay ══ */} {/* ═══════════════════════════════════════════════════════════ */} {!isMobile && ( <> {/* ── TOP BAR ──────────────────────────────────── */}
{/* LEFT – logo */}
Der Bayerische Mittelstandspreis 2026
{/* CENTER – hamburger */}
{/* RIGHT – social + lang */}
{SOCIAL.map(s => )}
{(['DE','EN'] as const).map((l, i) => ( {i===1 && |} ))}
{/* ── DESKTOP OVERLAY ──────────────────────────── */}
{/* TOP – tagline + logo */}
Bayerischer Mittelstandspreis
EXZELLENZ HAT
EINEN NAMEN.
BMP Logo
{/* BOTTOM – 3 columns */}
{/* LEFT – main nav */}
    {NAV.map((item, idx) => (
  • setOpen(false)} onMouseEnter={() => setActive(item.key)} style={{ display:'flex', alignItems:'center', justifyContent:'space-between', padding:'14px 40px 14px 0', textDecoration:'none', color: activeKey===item.key ? GOLD : '#fff', fontSize:'clamp(15px,1.4vw,20px)', fontFamily:FF_DISPLAY, fontWeight:600, textTransform:'uppercase', letterSpacing:'.03em', transition:'color .15s, transform .15s, opacity .3s ease-out', transform: open ? `translateX(${activeKey===item.key ? 6 : 0}px)` : 'translateX(-16px)', opacity: open ? 1 : 0, transitionDelay: open ? `${.04 + idx*.06}s` : '0s', }} > {item.label}
  • ))}
{/* MIDDLE – subnav */}
{NAV.map(item => (
Überblick
{item.subLabel}
    {item.sub?.map(sub => (
  • setOpen(false)} style={{ display:'block', padding:'9px 0', textDecoration:'none', color:MUTED, fontSize: 16, fontFamily:FF_BODY, transition:'color .15s, padding-left .15s' }} onMouseEnter={e=>{ e.currentTarget.style.color='#fff'; e.currentTarget.style.paddingLeft='8px'; }} onMouseLeave={e=>{ e.currentTarget.style.color=MUTED; e.currentTarget.style.paddingLeft='0'; }} >{sub.label}
  • ))}
))}
{/* RIGHT – utilities */}
{(['DE','EN'] as const).map((l,i) => ( {i===1 && |} ))}
{SOCIAL.map(s => )}
{SECONDARY.map(item => ( setOpen(false)} style={{ fontSize: 16, color:MUTED, textDecoration:'none', fontFamily:FF_BODY, transition:'color .15s', width:'fit-content' }} onMouseEnter={e=>(e.currentTarget.style.color=GOLD)} onMouseLeave={e=>(e.currentTarget.style.color=MUTED)} >{item.label} ))}
setOpen(false)} style={{ display:'inline-block', background:'#EFBF04', color:'#101828', fontSize: 15, fontWeight:700, textTransform:'uppercase', letterSpacing:'.12em', padding:'11px 24px', textDecoration:'none', transition:'background .2s, box-shadow .2s', borderRadius:0, fontFamily:FF_DISPLAY }} onMouseEnter={e=>{ e.currentTarget.style.background='#FFD130'; e.currentTarget.style.boxShadow='0 0 18px rgba(239,191,4,0.65), 0 0 40px rgba(239,191,4,0.3)'; }} onMouseLeave={e=>{ e.currentTarget.style.background='#EFBF04'; e.currentTarget.style.boxShadow='none'; }} >Jetzt bewerben setOpen(false)} style={{ display:'inline-block', background:'transparent', color:MUTED, fontSize: 15, fontWeight:700, textTransform:'uppercase', letterSpacing:'.12em', padding:'10px 24px', textDecoration:'none', transition:'border-color .2s, color .2s', borderRadius:0, fontFamily:FF_DISPLAY, border:'1.5px solid rgba(239,191,4,0.35)' }} onMouseEnter={e=>{ e.currentTarget.style.borderColor='#EFBF04'; e.currentTarget.style.color='#EFBF04'; }} onMouseLeave={e=>{ e.currentTarget.style.borderColor='rgba(239,191,4,0.35)'; e.currentTarget.style.color=MUTED; }} >Mitglied werden
setOpen(false)} style={{ display:'flex', alignItems:'center', gap:10, background:'rgba(255,255,255,0.04)', color:'rgba(255,255,255,0.45)', fontSize:11, fontWeight:700, textTransform:'uppercase', letterSpacing:'.14em', padding:'10px 18px', textDecoration:'none', fontFamily:FF_DISPLAY, border:'1px dashed rgba(255,255,255,0.15)', transition:'color .2s, border-color .2s, background .2s', }} onMouseEnter={e=>{ e.currentTarget.style.color='#fff'; e.currentTarget.style.borderColor='rgba(255,255,255,0.4)'; e.currentTarget.style.background='rgba(255,255,255,0.07)'; }} onMouseLeave={e=>{ e.currentTarget.style.color='rgba(255,255,255,0.45)'; e.currentTarget.style.borderColor='rgba(255,255,255,0.15)'; e.currentTarget.style.background='rgba(255,255,255,0.04)'; }} > Formular hochladen
)} {/* ═══════════════════════════════════════════════════════════ */} {/* ══ MOBILE CHROME (<768px) – top bar + fullscreen overlay ══ */} {/* ═══════════════════════════════════════════════════════════ */} {isMobile && ( <> {/* ── TOP BAR ──────────────────────────────────── */}
{/* Logo */} Bayerischer Mittelstandspreis 2026 {/* Hamburger */}
{/* ── FULLSCREEN OVERLAY ───────────────────────── */}
{/* Brand watermark */}
Exzellenz
seit 2005
{/* Header row: logo + close */}
setMobileOpen(false)} style={{ display:'flex', alignItems:'center', textDecoration:'none' }}> BMP Logo
{/* Scrollable body */}
{/* Accordion nav */} {/* CTAs */}
setMobileOpen(false)} style={{ display:'flex', alignItems:'center', justifyContent:'center', minHeight:52, background:GOLD, color:'#101828', fontSize:14, fontWeight:700, textTransform:'uppercase', letterSpacing:'.12em', textDecoration:'none', fontFamily:FF_DISPLAY }} >Jetzt bewerben setMobileOpen(false)} style={{ display:'flex', alignItems:'center', justifyContent:'center', minHeight:50, background:'transparent', color:'#fff', fontSize:14, fontWeight:700, textTransform:'uppercase', letterSpacing:'.12em', textDecoration:'none', fontFamily:FF_DISPLAY, border:`1.5px solid ${LINE}` }} >Mitglied werden setMobileOpen(false)} style={{ display:'flex', alignItems:'center', justifyContent:'center', gap:8, minHeight:46, background:'none', color:'rgba(255,255,255,0.5)', fontSize:11, fontWeight:700, textTransform:'uppercase', letterSpacing:'.14em', textDecoration:'none', fontFamily:FF_DISPLAY, border:'1px dashed rgba(255,255,255,0.2)' }} > Formular hochladen
{/* Footer zone: lang + social + secondary */}
{/* Lang + social row */}
{(['DE','EN'] as const).map((l, i) => ( {i === 1 && |} ))}
{SOCIAL.map(s => )}
{/* Secondary links */}
{SECONDARY.map(item => ( setMobileOpen(false)} style={{ display:'inline-flex', alignItems:'center', minHeight:40, fontSize:13, color:'rgba(255,255,255,.5)', textDecoration:'none', fontFamily:FF_BODY }} >{item.label} ))}
)} {/* ── FLOATING CTA ─────────────────────────────── */} {location.pathname === '/' && !formVisible && !isMobile && ( { (e.currentTarget as HTMLElement).style.background = '#EFBF04'; (e.currentTarget as HTMLElement).style.color = '#101828'; }} onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = '#111D55'; (e.currentTarget as HTMLElement).style.color = '#fff'; }} > Jetzt bewerben )} {/* ── MAIN ─────────────────────────────────────── */}
{children}
{/* ── FOOTER ───────────────────────────────────── */}
); }; export default Layout;