Files
bmp-website-2026/src/spa/pages/Netzwerk.tsx
2026-06-22 13:02:47 +02:00

799 lines
56 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useState, useEffect } from 'react';
import { Link } from '@/spa/router';
import { ChevronRight, X, ArrowRight, Globe, Linkedin, Building2, MapPin, ExternalLink } from 'lucide-react';
import SponsoringForm from '@/spa/components/forms/SponsoringForm';
import MunichSkylineBg from '@/spa/components/ui/munich-skyline-bg';
import { useIsMobile } from '@/spa/hooks/useIsMobile';
import { useCmsRoute } from '@/spa/cmsRoute';
import { mediaAlt, mediaUrl } from '@/spa/cmsMediaField';
import { netzwerkContent } from '@/spa/netzwerkContent';
import Image from '@/spa/components/ui/UnoptimizedImage'
const FF = '"IBM Plex Sans", sans-serif';
const FB = '"Inter", sans-serif';
const NAVY = '#111D55';
const GOLD = '#EFBF04';
const CREAM = '#E4E2E3';
const ROLE_COLOR: Record<string, string> = {
'Hauptsponsor': '#EFBF04',
'Sponsor': '#2563EB',
'Finanzpartner': '#16A34A',
'Partner': '#111D55',
'Medienpartner': '#DC2626',
};
type NetzwerkCms = Partial<typeof netzwerkContent> & {
hero?: Partial<typeof netzwerkContent.hero> & { image?: unknown }
sponsoring?: Partial<typeof netzwerkContent.sponsoring> & { image?: unknown }
}
type PatronPerson = (typeof netzwerkContent.patronage.people)[number]
type JuryMember = (typeof netzwerkContent.jury.members)[number]
type Partner = (typeof netzwerkContent.partners.items)[number] & { tier: 1 | 2 | 3; heroImg?: string; linkedin?: string; logoSubtext?: string }
type PartnerTier = (typeof netzwerkContent.partners.tiers)[number]
type ExpertiseRow = (typeof netzwerkContent.expertise.rows)[number]
type StatItem = (typeof netzwerkContent.juryIntro.stats)[number]
type BenefitItem = (typeof netzwerkContent.sponsoring.benefits)[number]
type PartnerModalCopy = typeof netzwerkContent.partners.modal
const fallbackText = (value: unknown, fallback: string) => typeof value === 'string' && value.length > 0 ? value : fallback;
const fallbackArray = <T,>(value: unknown, fallback: T[]) => Array.isArray(value) && value.length ? value as T[] : fallback;
function Lines({ text, highlight }: { text: string; highlight?: string }) {
return (
<>
{text.split('\n').map((line, i) => {
const highlighted = highlight && line.includes(highlight)
return (
<React.Fragment key={`${line}-${i}`}>
{i > 0 && <br />}
{highlighted ? (
<>
{line.replace(highlight, '')}<span style={{ color: GOLD }}>{highlight}</span>
</>
) : line}
</React.Fragment>
)
})}
</>
)
}
// ── PersonCard (Schirmherrschaft) ─────────────────────────────────────────────
interface PersonCardProps {
imgSrc: string;
imgAlt: string;
name: string;
titleLine1: string;
titleLine2: string;
institution: string;
borderRight?: boolean;
}
function PersonCard({ imgSrc, imgAlt, name, titleLine1, titleLine2, institution, borderRight }: PersonCardProps) {
const [hovered, setHovered] = useState(false);
const isMobileCard = useIsMobile();
return (
<div
style={{ borderRight: borderRight && !isMobileCard ? '1px solid rgba(255,255,255,0.08)' : 'none', display: 'flex', flexDirection: 'column', ...(isMobileCard ? { minWidth: '85vw', maxWidth: '85vw', flexShrink: 0, scrollSnapAlign: 'start', borderRadius: 16, overflow: 'hidden' } : {}) }}
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
>
<div style={{ position: 'relative', height: isMobileCard ? 250 : 320, overflow: 'hidden', width: '100%' }}>
<Image unoptimized
src={imgSrc}
alt={imgAlt}
style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block', filter: hovered ? 'grayscale(0%)' : 'grayscale(100%)', transition: 'filter 0.55s ease, transform 0.55s ease', transform: hovered ? 'scale(1.04)' : 'scale(1)' }}
/>
<div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(to top, rgba(3,9,58,0.8) 0%, transparent 60%)', pointerEvents: 'none' }} />
<div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: 3, background: GOLD }} />
</div>
<div style={{ padding: isMobileCard ? '28px 24px' : '36px 40px', background: NAVY, flex: 1 }}>
<div style={{ fontFamily: FF, fontSize: 20, fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.02em', lineHeight: 1.1, marginBottom: 10 }}>{name}</div>
<div style={{ fontFamily: FF, fontSize: 17, fontWeight: 400, color: `${GOLD}CC`, lineHeight: 1.6, marginBottom: 2 }}>{titleLine1}</div>
<div style={{ fontFamily: FF, fontSize: 17, fontWeight: 400, color: 'rgba(255,255,255,0.5)', lineHeight: 1.6 }}>{titleLine2}</div>
<div style={{ fontFamily: FF, fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.2em', color: 'rgba(255,255,255,0.3)', marginTop: 12 }}>{institution}</div>
</div>
</div>
);
}
// ── JuryCard ──────────────────────────────────────────────────────────────────
const JuryCard: React.FC<{ member: JuryMember; idx: number }> = ({ member, idx }) => {
const [hovered, setHovered] = useState(false);
const isMobileCard = useIsMobile();
return (
<div
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
style={{ borderLeft: !isMobileCard && idx > 0 ? '1px solid rgba(255,255,255,0.07)' : 'none', display: 'flex', flexDirection: 'column', cursor: 'default', background: hovered ? 'rgba(255,255,255,0.03)' : 'transparent', transition: 'background 0.2s', ...(isMobileCard ? { minWidth: '74vw', maxWidth: '74vw', flexShrink: 0, scrollSnapAlign: 'start', border: '1px solid rgba(255,255,255,0.08)', borderRadius: 16, overflow: 'hidden' } : {}) }}
>
<div style={{ position: 'relative', overflow: 'hidden', aspectRatio: '3/4' }}>
<Image unoptimized src={member.image} alt={member.name} style={{ width: '100%', height: '100%', objectFit: 'cover', filter: hovered ? 'none' : 'grayscale(100%)', transition: 'filter 0.5s', display: 'block' }} />
<div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: '40%', background: 'linear-gradient(to top, rgba(3,9,58,0.65), transparent)' }} />
</div>
<div style={{ padding: isMobileCard ? '28px 28px 32px' : '32px 32px 36px' }}>
<div style={{ fontFamily: FF, fontSize: 20, fontWeight: 700, color: '#fff', marginBottom: 5 }}>{member.name}</div>
<div style={{ fontFamily: FF, fontSize: 12, color: GOLD, textTransform: 'uppercase', letterSpacing: '0.16em', fontWeight: 700, marginBottom: 14 }}>{member.role}</div>
<div style={{ width: hovered ? '100%' : 24, height: 1, background: GOLD, opacity: 0.4, transition: 'width 0.4s ease', marginBottom: 14 }} />
<div style={{ fontFamily: FB, fontSize: 18, color: 'rgba(255,255,255,0.55)', lineHeight: 1.7 }}>{member.bio}</div>
</div>
</div>
);
};
// ── JuryChairCard (Vorsitz prominent) ───────────────────────────────────────
const JuryChairCard: React.FC<{ member: JuryMember; badge: string }> = ({ member, badge }) => {
const [hovered, setHovered] = useState(false);
const isMobileCard = useIsMobile();
return (
<div
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
style={{
display: 'grid',
gridTemplateColumns: isMobileCard ? '1fr' : '380px 1fr',
gap: 0,
background: 'rgba(255,255,255,0.03)',
border: `1px solid ${GOLD}40`,
borderRadius: 20,
overflow: 'hidden',
}}
>
<div style={{ position: 'relative', overflow: 'hidden', aspectRatio: isMobileCard ? '16/10' : '3/4', minHeight: isMobileCard ? 240 : 'auto' }}>
<Image unoptimized src={member.image} alt={member.name} style={{ width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center top', filter: hovered ? 'none' : 'grayscale(100%)', transition: 'filter 0.5s', display: 'block' }} />
<div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: '45%', background: 'linear-gradient(to top, rgba(3,9,58,0.7), transparent)' }} />
</div>
<div style={{ padding: isMobileCard ? '32px 28px 36px' : '56px 56px', display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
<span style={{ alignSelf: 'flex-start', fontFamily: FF, fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.18em', color: NAVY, background: GOLD, padding: '7px 16px', borderRadius: 999, marginBottom: 24 }}>
{badge}
</span>
<div style={{ fontFamily: FF, fontSize: isMobileCard ? 26 : 34, fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.02em', lineHeight: 1.05, marginBottom: 10 }}>{member.name}</div>
<div style={{ fontFamily: FF, fontSize: 13, color: GOLD, textTransform: 'uppercase', letterSpacing: '0.18em', fontWeight: 700, marginBottom: 24 }}>{member.role}</div>
<div style={{ width: 48, height: 2, background: GOLD, opacity: 0.5, marginBottom: 24 }} />
<div style={{ fontFamily: FB, fontSize: isMobileCard ? 18 : 21, color: 'rgba(255,255,255,0.6)', lineHeight: 1.7, maxWidth: 620 }}>{member.bio}</div>
</div>
</div>
);
};
// ── PartnerCell ───────────────────────────────────────────────────────────────
// ── SponsorCell (tiered) ──────────────────────────────────────────────────────
function PartnerLogo({ partner }: { partner: Partner }) {
const color = fallbackText(partner.logoColor, '#111D55');
const text = fallbackText(partner.logoText, partner.name);
const subtext = fallbackText(partner.logoSubtext, '');
if (partner.logoKind === 'badge') {
return <span style={{ background: color, color: '#fff', fontWeight: 900, fontSize: 14, padding: '4px 10px', lineHeight: 1.25, display: 'inline-block', textAlign: 'center' as const, fontFamily: FF }}>{text.split('\n').map((line, index) => <React.Fragment key={`${line}-${index}`}>{index > 0 && <br />}{line}</React.Fragment>)}</span>
}
if (partner.logoKind === 'monogram') {
return <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}><span style={{ width: 22, height: 22, background: '#3a3a3a', color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 900, fontSize: 11, fontFamily: FF }}>{subtext || text.slice(0, 2)}</span><span style={{ fontWeight: 700, fontSize: 15, color, fontFamily: FF }}>{text}</span></span>
}
if (partner.logoKind === 'dot') {
return <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}><span style={{ width: 20, height: 20, borderRadius: '50%', background: color, display: 'block' }} /><span style={{ fontWeight: 700, fontSize: 16, color, fontFamily: FF }}>{text}</span></span>
}
if (partner.logoKind === 'leaf') {
return <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}><svg width="20" height="20" viewBox="0 0 20 20"><circle cx="10" cy="10" r="9" fill={color} /><path d="M10 3 Q14 7 14 10 Q14 14 10 17 Q6 14 6 10 Q6 7 10 3Z" fill="white" opacity="0.8" /></svg><span style={{ fontWeight: 700, fontSize: 15, color, fontFamily: FB }}>{text}</span></span>
}
if (partner.logoKind === 'rsm') {
return <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}><span style={{ display: 'flex', gap: 2 }}><span style={{ width: 10, height: 10, background: '#6b7280', display: 'block' }} /><span style={{ width: 10, height: 10, background: '#22c55e', display: 'block' }} /><span style={{ width: 10, height: 10, background: '#3b82f6', display: 'block' }} /></span><span style={{ fontWeight: 900, fontSize: 15, letterSpacing: '-0.02em', color, fontFamily: FF }}>{text} {subtext && <span style={{ color: '#6b7280', fontWeight: 600 }}>{subtext}</span>}</span></span>
}
if (partner.logoKind === 'deutschebank') {
return <span style={{ display: 'flex', alignItems: 'center', gap: 8 }}><svg width="20" height="20" viewBox="0 0 20 20"><rect x="1" y="1" width="18" height="18" fill="none" stroke={color} strokeWidth="1.5" /><line x1="5" y1="15" x2="15" y2="5" stroke={color} strokeWidth="2" /></svg><span style={{ fontWeight: 600, fontSize: 15, color, fontFamily: FB }}>{text}</span></span>
}
return <span style={{ fontWeight: 900, fontSize: partner.logoKind === 'serif' ? 21 : 16, letterSpacing: partner.logoKind === 'serif' ? '0.12em' : '-0.01em', color, fontFamily: partner.logoKind === 'serif' ? 'Georgia, serif' : FF }}>{text}</span>
}
const SponsorCell: React.FC<{ partner: Partner; variant: 'lg' | 'md' | 'sm'; idx: number; cols: number; detailLabel: string; premiumLabel: string; onClick: () => void }> = ({ partner, variant, idx, cols, detailLabel, premiumLabel, onClick }) => {
const [hovered, setHovered] = useState(false);
const isMobileCell = useIsMobile();
const lg = variant === 'lg';
const sm = variant === 'sm';
const lastCol = (idx % cols) === cols - 1;
return (
<div
onClick={onClick}
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
style={{
padding: isMobileCell ? '24px 20px' : lg ? '40px 36px' : sm ? '28px 28px' : '32px 32px',
borderRight: !lastCol && !isMobileCell ? '1px solid rgba(3,9,58,0.08)' : 'none',
borderBottom: '1px solid rgba(3,9,58,0.08)',
display: 'flex', flexDirection: 'column', gap: 14,
cursor: 'pointer',
background: hovered ? '#E8E5E4' : 'transparent',
transition: 'background 0.15s',
position: 'relative',
}}
>
{lg && (
<span style={{ position: 'absolute', top: 18, right: 18, fontFamily: FF, fontSize: 9, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.18em', color: '#101828', background: GOLD, padding: '4px 10px', borderRadius: 100, zIndex: 1 }}>{premiumLabel}</span>
)}
<div style={{ height: lg ? 52 : 44, display: 'flex', alignItems: 'center' }}><PartnerLogo partner={partner} /></div>
<div style={{ width: hovered ? 48 : 20, height: 1, background: GOLD, transition: 'width 0.3s ease' }} />
<div style={{ fontFamily: FF, fontSize: lg ? 22 : 18, fontWeight: 700, color: '#101828', letterSpacing: '-0.01em', lineHeight: 1.15 }}>{partner.name}</div>
<div style={{ fontFamily: FF, fontSize: sm ? 10 : 11, color: GOLD, textTransform: 'uppercase', letterSpacing: '0.2em', fontWeight: 700 }}>{partner.role}</div>
{!sm && <div style={{ fontFamily: FB, fontSize: lg ? 17 : 16, color: 'rgba(16,24,40,0.45)', lineHeight: 1.6, flexGrow: 1 }}>{partner.desc}</div>}
<div style={{ fontFamily: FF, fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.12em', color: GOLD, fontWeight: 700, display: 'flex', alignItems: 'center', gap: 4 }}>
{detailLabel} <ArrowRight size={10} />
</div>
</div>
);
};
// ── PartnerModal ─────────────────────────────────────────────────────────────
function PartnerModal({ partner, copy, onClose }: { partner: Partner; copy: PartnerModalCopy; onClose: () => void }) {
const accentColor = ROLE_COLOR[partner.role] ?? GOLD;
useEffect(() => {
document.body.style.overflow = 'hidden';
return () => { document.body.style.overflow = ''; };
}, []);
return (
<div
onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}
style={{
position: 'fixed', inset: 0, zIndex: 500,
background: 'rgba(0,0,0,0.4)',
backdropFilter: 'blur(10px)',
WebkitBackdropFilter: 'blur(10px)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
padding: 24, overflowY: 'auto',
}}
>
<div
onClick={(e) => e.stopPropagation()}
style={{
background: '#fff', width: '100%', maxWidth: 720,
boxShadow: '0 32px 80px rgba(0,0,0,0.35)',
overflow: 'hidden', flexShrink: 0,
maxHeight: '92vh', overflowY: 'auto',
}}
>
{/* ── Hero ── */}
<div style={{ position: 'relative', height: 220, flexShrink: 0, overflow: 'hidden' }}>
{/* Background */}
{partner.heroImg
? <Image unoptimized src={partner.heroImg} alt="" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover' }} />
: <div style={{ position: 'absolute', inset: 0, background: `linear-gradient(135deg, ${accentColor}33 0%, ${NAVY} 70%)` }} />
}
{/* Gradient to white */}
<div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(to bottom, rgba(0,0,0,0.15) 0%, rgba(0,0,0,0) 35%, rgba(255,255,255,0.6) 75%, #fff 100%)' }} />
{/* Category badge top left */}
<div style={{ position: 'absolute', top: 20, left: 24 }}>
<span style={{
background: 'rgba(255,255,255,0.15)',
backdropFilter: 'blur(8px)', WebkitBackdropFilter: 'blur(8px)',
border: '1px solid rgba(255,255,255,0.25)',
color: '#fff', padding: '5px 13px',
fontFamily: FF, fontSize: 9, fontWeight: 700,
textTransform: 'uppercase', letterSpacing: '0.22em',
display: 'inline-block',
}}>
{partner.role}
</span>
</div>
{/* Social + Close top right */}
<div style={{ position: 'absolute', top: 16, right: 20, display: 'flex', gap: 8, alignItems: 'center' }}>
{partner.linkedin && (
<a href={partner.linkedin} target="_blank" rel="noopener noreferrer" style={{
width: 36, height: 36, borderRadius: '50%',
background: 'rgba(255,255,255,0.92)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
color: NAVY, textDecoration: 'none',
boxShadow: '0 2px 8px rgba(0,0,0,0.18)',
}}>
<Linkedin size={14} />
</a>
)}
{partner.website && (
<a href={`https://${partner.website}`} target="_blank" rel="noopener noreferrer" style={{
width: 36, height: 36, borderRadius: '50%',
background: 'rgba(255,255,255,0.92)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
color: NAVY, textDecoration: 'none',
boxShadow: '0 2px 8px rgba(0,0,0,0.18)',
}}>
<Globe size={14} />
</a>
)}
<button onClick={onClose} style={{
width: 36, height: 36, borderRadius: '50%',
background: 'rgba(255,255,255,0.92)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
border: 'none', cursor: 'pointer',
boxShadow: '0 2px 8px rgba(0,0,0,0.18)', color: NAVY,
}}>
<X size={15} />
</button>
</div>
{/* Logo box bottom left (overflows hero) */}
<div style={{
position: 'absolute', bottom: -28, left: 28,
width: 80, height: 80, background: '#fff',
borderRadius: 12, boxShadow: '0 4px 24px rgba(0,0,0,0.14)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
padding: 10, zIndex: 2,
}}>
<PartnerLogo partner={partner} />
</div>
</div>
{/* ── Content ── */}
<div style={{ padding: '52px 32px 32px' }}>
<h2 style={{
fontFamily: FF, fontSize: 'clamp(1.5rem, 3vw, 2rem)',
fontWeight: 900, color: '#101828',
letterSpacing: '-0.025em', lineHeight: 1.05,
margin: '0 0 10px',
}}>
{partner.name}
</h2>
<p style={{ fontFamily: FB, fontSize: 18, color: 'rgba(16,24,40,0.5)', lineHeight: 1.65, margin: '0 0 24px' }}>
{partner.desc}
</p>
{/* 3 info cards */}
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 10, marginBottom: 28 }}>
{[
{ Icon: Building2, label: fallbackText(copy.industryLabel, netzwerkContent.partners.modal.industryLabel), value: partner.industry },
{ Icon: MapPin, label: fallbackText(copy.locationLabel, netzwerkContent.partners.modal.locationLabel), value: partner.location },
{ Icon: Globe, label: fallbackText(copy.webLabel, netzwerkContent.partners.modal.webLabel), value: partner.website },
].map(({ Icon, label, value }) => (
<div key={label} style={{ background: 'hsl(220,40%,97%)', padding: '14px 16px', borderRadius: 8 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 6 }}>
<Icon size={11} color="rgba(16,24,40,0.35)" />
<span style={{ fontFamily: FF, fontSize: 9, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.14em', color: 'rgba(16,24,40,0.35)' }}>{label}</span>
</div>
<div style={{ fontFamily: FB, fontSize: 17, fontWeight: 600, color: '#101828', lineHeight: 1.4, wordBreak: 'break-word' }}>{value}</div>
</div>
))}
</div>
{/* Separator */}
<div style={{ height: 1, background: 'rgba(16,24,40,0.08)', marginBottom: 28 }} />
{/* Über section */}
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 14 }}>
<div style={{ width: 4, height: 20, background: accentColor, borderRadius: 2, flexShrink: 0 }} />
<span style={{ fontFamily: FF, fontSize: 17, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.12em', color: '#101828' }}>
{fallbackText(copy.aboutLabel, netzwerkContent.partners.modal.aboutLabel)}
</span>
</div>
<p style={{ fontFamily: FB, fontSize: 19, color: 'rgba(16,24,40,0.6)', lineHeight: 1.82, marginBottom: 36 }}>
{partner.fullDesc}
</p>
{/* CTAs */}
<div style={{ display: 'flex', gap: 12, flexWrap: 'wrap' }}>
{partner.website && (
<a
href={`https://${partner.website}`}
target="_blank" rel="noopener noreferrer"
style={{
padding: '13px 28px', background: GOLD, color: '#101828',
fontFamily: FF, fontSize: 11, fontWeight: 700,
textTransform: 'uppercase', letterSpacing: '0.1em',
textDecoration: 'none',
display: 'inline-flex', alignItems: 'center', gap: 8,
transition: 'background 0.15s, box-shadow 0.2s',
}}
onMouseEnter={e => { const el = e.currentTarget as HTMLElement; el.style.background = '#FFD130'; el.style.boxShadow = '0 0 18px rgba(239,191,4,0.65), 0 0 40px rgba(239,191,4,0.3)'; }}
onMouseLeave={e => { const el = e.currentTarget as HTMLElement; el.style.background = GOLD; el.style.boxShadow = 'none'; }}
>
{fallbackText(copy.websiteLabel, netzwerkContent.partners.modal.websiteLabel)} <ExternalLink size={12} />
</a>
)}
<button
onClick={onClose}
style={{
padding: '13px 28px', background: 'transparent',
color: 'rgba(16,24,40,0.45)', border: '1px solid rgba(16,24,40,0.12)',
fontFamily: FF, fontSize: 11, fontWeight: 700,
textTransform: 'uppercase', letterSpacing: '0.1em',
cursor: 'pointer', transition: 'all 0.15s',
}}
onMouseEnter={e => { const el = e.currentTarget as HTMLElement; el.style.background = NAVY; el.style.color = '#fff'; el.style.borderColor = NAVY; }}
onMouseLeave={e => { const el = e.currentTarget as HTMLElement; el.style.background = 'transparent'; el.style.color = 'rgba(16,24,40,0.45)'; el.style.borderColor = 'rgba(16,24,40,0.12)'; }}
>
{fallbackText(copy.closeLabel, netzwerkContent.partners.modal.closeLabel)}
</button>
</div>
</div>
{/* ── Footer strip ── */}
<div style={{
background: 'hsl(220,20%,96%)', padding: '14px 32px',
display: 'flex', justifyContent: 'space-between', alignItems: 'center',
borderTop: '1px solid rgba(16,24,40,0.06)',
}}>
<span style={{ fontFamily: FF, fontSize: 9, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.12em', color: 'rgba(16,24,40,0.3)' }}>
{fallbackText(copy.footerTitle, netzwerkContent.partners.modal.footerTitle)}
</span>
<span style={{ fontFamily: FF, fontSize: 9, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.12em', color: accentColor }}>
{fallbackText(copy.footerRolePrefix, netzwerkContent.partners.modal.footerRolePrefix)} {partner.role}
</span>
</div>
</div>
</div>
);
}
// ── Netzwerk ──────────────────────────────────────────────────────────────────
const Netzwerk: React.FC = () => {
const isMobile = useIsMobile();
const [selectedPartner, setSelectedPartner] = useState<Partner | null>(null);
const cms = (useCmsRoute()?.doc?.netzwerk || {}) as NetzwerkCms;
const hero = { ...netzwerkContent.hero, ...(cms.hero || {}) };
const patronage = { ...netzwerkContent.patronage, ...(cms.patronage || {}) };
const juryIntro = { ...netzwerkContent.juryIntro, ...(cms.juryIntro || {}) };
const jury = { ...netzwerkContent.jury, ...(cms.jury || {}) };
const expertise = { ...netzwerkContent.expertise, ...(cms.expertise || {}) };
const partnerSection = { ...netzwerkContent.partners, ...(cms.partners || {}) };
const partnerModal = { ...netzwerkContent.partners.modal, ...((cms.partners as typeof netzwerkContent.partners | undefined)?.modal || {}) };
const sponsoring = { ...netzwerkContent.sponsoring, ...(cms.sponsoring || {}) };
const patronPeople = fallbackArray<PatronPerson>(patronage.people, netzwerkContent.patronage.people);
const juryMembers = fallbackArray<JuryMember>(jury.members, netzwerkContent.jury.members);
const expertiseRows = fallbackArray<ExpertiseRow>(expertise.rows, netzwerkContent.expertise.rows);
const partners = fallbackArray<Partner>(partnerSection.items, netzwerkContent.partners.items as Partner[]);
const partnerTiers = fallbackArray<PartnerTier>(partnerSection.tiers, netzwerkContent.partners.tiers);
const mobileStats = fallbackArray<StatItem>(juryIntro.stats, netzwerkContent.juryIntro.stats);
const desktopStats = fallbackArray<StatItem>(juryIntro.desktopStats, netzwerkContent.juryIntro.desktopStats);
const sponsorBenefits = fallbackArray<BenefitItem>(sponsoring.benefits, netzwerkContent.sponsoring.benefits);
return (
<div className="animate-fade-in">
{/* ── 1. HERO ──────────────────────────────────────────────────────────── */}
<section style={{ position: 'relative', minHeight: '72vh', display: 'flex', alignItems: 'flex-end', overflow: 'hidden', background: '#060C14' }}>
<Image unoptimized src={mediaUrl(hero.image, `/images/${netzwerkContent.hero.imageFilename}`)} alt={mediaAlt(hero.image, fallbackText(hero.imageAlt, netzwerkContent.hero.imageAlt))} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center 30%' }} />
<div style={{ position: 'absolute', inset: 0, background: isMobile ? 'linear-gradient(to top, rgba(2,9,48,0.95) 0%, rgba(2,9,48,0.72) 38%, rgba(2,9,48,0.22) 72%, transparent 100%)' : 'linear-gradient(to right, #020930 0%, rgba(2,9,48,0.90) 38%, rgba(2,9,48,0.18) 65%, transparent 100%)' }} />
<div style={{ position: 'absolute', top: 0, left: 80, width: 2, height: '100%', background: `linear-gradient(to bottom, transparent, ${GOLD}, transparent)`, opacity: 0.4 }} />
<div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: 2, background: 'linear-gradient(to right, #EFBF04, rgba(239,191,4,0.3), transparent)', zIndex: 2 }} />
<div style={{ position: 'relative', zIndex: 1, padding: isMobile ? '0 24px 48px' : '0 80px 88px', maxWidth: 860 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 28 }}>
<div style={{ width: 40, height: 2, background: GOLD }} />
<span style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, letterSpacing: '0.3em', textTransform: 'uppercase', color: GOLD }}>{fallbackText(hero.eyebrow, netzwerkContent.hero.eyebrow)}</span>
</div>
<h1 style={{ fontFamily: FF, fontSize: isMobile ? 'clamp(1.6rem, 6vw, 5rem)' : 'clamp(2.8rem, 6vw, 5rem)', fontWeight: 900, color: '#fff', lineHeight: 0.95, letterSpacing: '-0.03em', textTransform: 'uppercase', margin: '0 0 28px' }}>
<Lines text={fallbackText(hero.heading, netzwerkContent.hero.heading)} highlight={fallbackText(hero.highlight, netzwerkContent.hero.highlight)} />
</h1>
<p style={{ fontFamily: FB, fontSize: 18, color: 'rgba(255,255,255,0.65)', lineHeight: 1.7, maxWidth: 560, margin: 0, fontWeight: 300 }}>
{fallbackText(hero.description, netzwerkContent.hero.description)}
</p>
</div>
</section>
{/* ── 2. SCHIRMHERRSCHAFT ──────────────────────────────────────────────── */}
<section id="schirmherrschaft" style={{ background: NAVY }}>
<div style={{ padding: isMobile ? '48px 24px 32px' : '80px 80px 56px' }}>
<span style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, letterSpacing: '0.3em', textTransform: 'uppercase', color: GOLD, display: 'block', marginBottom: 16 }}>{fallbackText(patronage.eyebrow, netzwerkContent.patronage.eyebrow)}</span>
<h2 style={{ fontFamily: FF, fontSize: 'clamp(2rem, 4vw, 3rem)', fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.02em', lineHeight: 1, margin: '0 0 20px' }}>{fallbackText(patronage.heading, netzwerkContent.patronage.heading)}</h2>
<div style={{ width: 40, height: 2, background: GOLD, marginBottom: 14 }} />
<p style={{ fontFamily: FF, fontSize: 18, color: 'rgba(255,255,255,0.5)', margin: 0 }}>{fallbackText(patronage.description, netzwerkContent.patronage.description)}</p>
</div>
<div style={{ display: isMobile ? 'flex' : 'grid', gridTemplateColumns: isMobile ? undefined : '1fr 1fr', overflowX: isMobile ? 'auto' : undefined, scrollSnapType: isMobile ? 'x mandatory' : undefined, gap: isMobile ? 14 : 0, padding: isMobile ? '0 24px 28px' : 0, WebkitOverflowScrolling: 'touch', scrollbarWidth: 'none' }}>
{patronPeople.map((person, index) => (
<PersonCard
key={`${person.name}-${index}`}
imgSrc={fallbackText(person.image, netzwerkContent.patronage.people[index]?.image || '')}
imgAlt={fallbackText(person.imageAlt, person.name)}
name={fallbackText(person.name, netzwerkContent.patronage.people[index]?.name || '')}
titleLine1={fallbackText(person.titleLine1, netzwerkContent.patronage.people[index]?.titleLine1 || '')}
titleLine2={fallbackText(person.titleLine2, netzwerkContent.patronage.people[index]?.titleLine2 || '')}
institution={fallbackText(person.institution, netzwerkContent.patronage.people[index]?.institution || '')}
borderRight={index === 0}
/>
))}
</div>
{/* Grußwort Ilse Aigner */}
<div style={{ background: 'rgba(255,255,255,0.03)', borderTop: '1px solid rgba(255,255,255,0.07)' }}>
<div style={{ padding: isMobile ? '32px 24px' : '64px 80px', display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '40% 60%', gap: isMobile ? '24px 0' : '0 64px', alignItems: 'flex-start' }}>
<div>
<span style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, letterSpacing: '0.3em', textTransform: 'uppercase', color: GOLD, display: 'block', marginBottom: 8 }}>{fallbackText(patronage.greetingEyebrow, netzwerkContent.patronage.greetingEyebrow)}</span>
<div style={{ fontFamily: FF, fontSize: 11, fontWeight: 400, textTransform: 'uppercase', letterSpacing: '0.08em', color: 'rgba(255,255,255,0.3)', marginBottom: 16 }}>{fallbackText(patronage.greetingRole, netzwerkContent.patronage.greetingRole)}</div>
<div style={{ fontFamily: FF, fontSize: 18, fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.02em', lineHeight: 1.15, marginBottom: 10 }}>{fallbackText(patronage.greetingName, netzwerkContent.patronage.greetingName)}</div>
<div style={{ fontFamily: FF, fontSize: 18, color: 'rgba(255,255,255,0.5)', lineHeight: 1.6, marginBottom: 4 }}>{fallbackText(patronage.greetingTitleLine1, netzwerkContent.patronage.greetingTitleLine1)}</div>
<div style={{ fontFamily: FF, fontSize: 17, color: 'rgba(255,255,255,0.4)', lineHeight: 1.6 }}>{fallbackText(patronage.greetingTitleLine2, netzwerkContent.patronage.greetingTitleLine2)}</div>
</div>
<div>
<blockquote style={{ fontFamily: FF, fontSize: 18, fontStyle: 'italic', color: 'rgba(255,255,255,0.8)', lineHeight: 1.75, margin: 0, paddingLeft: 24, borderLeft: `3px solid ${GOLD}` }}>
{fallbackText(patronage.greetingQuote, netzwerkContent.patronage.greetingQuote)}
</blockquote>
<div style={{ fontFamily: FF, fontSize: 11, color: 'rgba(255,255,255,0.35)', marginTop: 20, paddingLeft: 24 }}>
{fallbackText(patronage.greetingAttribution, netzwerkContent.patronage.greetingAttribution)}
</div>
</div>
</div>
</div>
<div style={{ height: 2, background: `linear-gradient(to right, ${GOLD}, rgba(239,191,4,0.2), transparent)` }} />
</section>
{/* ── 3. JURY-INTRO (editorial 2-col split) ────────────────────────────── */}
<section style={{ display: isMobile ? 'block' : 'grid', gridTemplateColumns: isMobile ? undefined : '40% 60%', minHeight: isMobile ? 'auto' : 400, position: 'relative', overflow: 'hidden', isolation: 'isolate', background: isMobile ? NAVY : undefined }}>
{!isMobile && <MunichSkylineBg />}
{isMobile && <MunichSkylineBg inset opacity={0.07} />}
{isMobile ? (
/* Mobile: one cohesive navy module copy + compact stat strip */
<div style={{ padding: '48px 24px', position: 'relative', zIndex: 1 }}>
<span style={{ fontFamily: FF, fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, color: GOLD, display: 'block', marginBottom: 18 }}>{fallbackText(juryIntro.eyebrow, netzwerkContent.juryIntro.eyebrow)}</span>
<h2 style={{ fontFamily: FF, fontSize: 'clamp(1.7rem, 8vw, 2.2rem)', fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.02em', lineHeight: 1.08, margin: '0 0 22px' }}>
<Lines text={fallbackText(juryIntro.heading, netzwerkContent.juryIntro.heading)} />
</h2>
<div style={{ width: 40, height: 2, background: GOLD, marginBottom: 22 }} />
<p style={{ fontFamily: FB, fontSize: 16, color: 'rgba(255,255,255,0.55)', lineHeight: 1.75, margin: 0 }}>
{fallbackText(juryIntro.description, netzwerkContent.juryIntro.description)}
</p>
{/* Stat strip */}
<div style={{ display: 'flex', marginTop: 32, paddingTop: 26, borderTop: '1px solid rgba(255,255,255,0.14)' }}>
{mobileStats.map((s, i) => (
<div key={i} style={{ flex: 1, minWidth: 0, paddingLeft: i > 0 ? 14 : 0, borderLeft: i > 0 ? '1px solid rgba(255,255,255,0.14)' : 'none' }}>
<div style={{ fontFamily: FF, fontSize: 'clamp(2.2rem, 9vw, 3rem)', fontWeight: 900, color: GOLD, letterSpacing: '-0.03em', lineHeight: 1 }}>{fallbackText(s.value, netzwerkContent.juryIntro.stats[i]?.value || '')}</div>
<div style={{ fontFamily: FF, fontSize: 9, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.12em', color: 'rgba(255,255,255,0.5)', marginTop: 8, lineHeight: 1.3 }}>{fallbackText(s.label, netzwerkContent.juryIntro.stats[i]?.label || '')}</div>
</div>
))}
</div>
</div>
) : (
<>
{/* Left Cream, stats */}
<div style={{ background: CREAM, padding: '72px 64px', display: 'flex', flexDirection: 'column', justifyContent: 'center', position: 'relative', zIndex: 1 }}>
<div>
<div style={{ fontFamily: FF, fontSize: 'clamp(5rem, 8.5vw, 7.5rem)', fontWeight: 900, color: '#101828', letterSpacing: '-0.04em', lineHeight: 1 }}>{fallbackText(desktopStats[0]?.value, netzwerkContent.juryIntro.desktopStats[0].value)}</div>
<div style={{ fontFamily: FF, fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.15em', color: 'rgba(16,24,40,0.4)', marginTop: 4 }}>{fallbackText(desktopStats[0]?.label, netzwerkContent.juryIntro.desktopStats[0].label)}</div>
</div>
<div style={{ width: '100%', height: 1, background: 'rgba(3,9,58,0.1)', margin: '32px 0' }} />
<div>
<div style={{ fontFamily: FF, fontSize: 'clamp(2.4rem, 4vw, 3.4rem)', fontWeight: 900, color: '#101828', letterSpacing: '-0.03em', lineHeight: 1 }}>{fallbackText(desktopStats[1]?.value, netzwerkContent.juryIntro.desktopStats[1].value)}</div>
<div style={{ fontFamily: FF, fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.15em', color: 'rgba(16,24,40,0.4)', marginTop: 8 }}>{fallbackText(desktopStats[1]?.label, netzwerkContent.juryIntro.desktopStats[1].label)}</div>
</div>
<div style={{ width: '100%', height: 1, background: 'rgba(3,9,58,0.1)', margin: '32px 0' }} />
<div>
<div style={{ fontFamily: FF, fontSize: 'clamp(5rem, 8.5vw, 7.5rem)', fontWeight: 900, color: '#101828', letterSpacing: '-0.04em', lineHeight: 1 }}>{fallbackText(desktopStats[2]?.value, netzwerkContent.juryIntro.desktopStats[2].value)}</div>
<div style={{ fontFamily: FF, fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.15em', color: 'rgba(16,24,40,0.4)', marginTop: 4 }}>{fallbackText(desktopStats[2]?.label, netzwerkContent.juryIntro.desktopStats[2].label)}</div>
</div>
</div>
{/* Right Navy, editorial copy */}
<div style={{ background: NAVY, padding: '72px 64px', display: 'flex', flexDirection: 'column', justifyContent: 'center', position: 'relative', zIndex: 1 }}>
<span style={{ fontFamily: FF, fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, color: GOLD, marginBottom: 20 }}>{fallbackText(juryIntro.eyebrow, netzwerkContent.juryIntro.eyebrow)}</span>
<h2 style={{ fontFamily: FF, fontSize: 'clamp(1.6rem, 2.5vw, 2.2rem)', fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.02em', lineHeight: 1.08, margin: '0 0 24px' }}>
<Lines text={fallbackText(juryIntro.heading, netzwerkContent.juryIntro.heading)} />
</h2>
<div style={{ width: 40, height: 2, background: GOLD }} />
<p style={{ marginTop: 24, fontFamily: FB, fontSize: 19, color: 'rgba(255,255,255,0.45)', lineHeight: 1.85 }}>
{fallbackText(juryIntro.description, netzwerkContent.juryIntro.description)}
</p>
</div>
</>
)}
</section>
{/* ── 4. JURY-MITGLIEDER ───────────────────────────────────────────────── */}
<section id="jury" style={{ background: NAVY, overflow: 'hidden', position: 'relative' }}>
<div style={{ padding: isMobile ? '48px 24px 32px' : '80px 80px 56px', display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '1fr 1fr', gap: isMobile ? 16 : 48, alignItems: 'flex-end', borderBottom: '1px solid rgba(255,255,255,0.07)' }}>
<div>
<span style={{ fontFamily: FF, fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, color: GOLD, display: 'block', marginBottom: 16 }}>{fallbackText(jury.eyebrow, netzwerkContent.jury.eyebrow)}</span>
<h2 style={{ fontFamily: FF, fontSize: 'clamp(2rem, 3.5vw, 3rem)', fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.025em', lineHeight: 0.95, margin: 0 }}><Lines text={fallbackText(jury.heading, netzwerkContent.jury.heading)} /></h2>
</div>
<p style={{ fontFamily: FB, fontSize: 19, color: 'rgba(255,255,255,0.4)', lineHeight: 1.8, margin: 0 }}>
{fallbackText(jury.description, netzwerkContent.jury.description)}
</p>
</div>
{/* ── Prominenter Vorsitz-Bereich ─────────────────────────────────── */}
{/* TODO: echten Jury-Vorsitzenden bestätigen (Name & Foto sind Platzhalter) */}
<div style={{ padding: isMobile ? '28px 24px 8px' : '64px 80px 16px' }}>
<JuryChairCard member={juryMembers[0]} badge={fallbackText(jury.chairBadge, netzwerkContent.jury.chairBadge)} />
</div>
{/* ── Übrige Jury-Mitglieder ──────────────────────────────────────── */}
<div style={{ display: isMobile ? 'flex' : 'grid', gridTemplateColumns: isMobile ? undefined : 'repeat(3, 1fr)', overflowX: isMobile ? 'auto' : undefined, scrollSnapType: isMobile ? 'x mandatory' : undefined, gap: isMobile ? 14 : 0, padding: isMobile ? '24px 24px 12px' : '0', WebkitOverflowScrolling: 'touch', scrollbarWidth: 'none', borderTop: isMobile ? 'none' : '1px solid rgba(255,255,255,0.07)' }}>
{juryMembers.slice(1).map((member, idx) => (
<JuryCard key={idx} member={member} idx={idx} />
))}
</div>
{/* ── Hinweis: Doppelrolle Jury / Partner (#179) ──────────────────── */}
<div style={{ padding: isMobile ? '4px 24px 36px' : '8px 80px 56px' }}>
<p style={{ fontFamily: FB, fontSize: isMobile ? 13 : 14, color: 'rgba(255,255,255,0.35)', lineHeight: 1.6, margin: 0, maxWidth: 720 }}>
{fallbackText(jury.note, netzwerkContent.jury.note)}
</p>
</div>
</section>
{/* ── 5. HINTERGRUND & EXPERTISE ───────────────────────────────────────── */}
<section style={{ background: '#101828', overflow: 'hidden', display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '55% 45%', borderTop: '1px solid rgba(255,255,255,0.07)' }}>
<div style={{ padding: isMobile ? '48px 24px' : 80, display: 'flex', flexDirection: 'column', justifyContent: 'center', background: '#101828' }}>
<span style={{ fontFamily: FF, fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, color: GOLD, display: 'block', marginBottom: 16 }}>{fallbackText(expertise.eyebrow, netzwerkContent.expertise.eyebrow)}</span>
<h2 style={{ fontFamily: FF, fontSize: 'clamp(1.8rem, 3vw, 2.6rem)', fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.025em', lineHeight: 1.0, margin: '0 0 24px' }}><Lines text={fallbackText(expertise.heading, netzwerkContent.expertise.heading)} /></h2>
<div style={{ width: 40, height: 2, background: GOLD, marginBottom: 40 }} />
<div>
{expertiseRows.map((row) => (
<div key={row.num} style={{ display: 'grid', gridTemplateColumns: '40px 1fr', gap: '0 20px', padding: '20px 0', borderBottom: '1px solid rgba(255,255,255,0.06)', alignItems: 'center' }}>
<div style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, color: 'rgba(239,191,4,0.5)' }}>{row.num}</div>
<div>
<div style={{ fontFamily: FF, fontSize: 16, fontWeight: 700, color: '#fff', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 3 }}>{row.label}</div>
<div style={{ fontFamily: FB, fontSize: 18, color: 'rgba(255,255,255,0.4)', lineHeight: 1.6 }}>{row.body}</div>
</div>
</div>
))}
</div>
</div>
<div style={{ padding: isMobile ? '48px 24px' : '80px 64px', display: 'flex', flexDirection: 'column', justifyContent: 'center', borderLeft: isMobile ? 'none' : '1px solid rgba(255,255,255,0.07)', borderTop: isMobile ? '1px solid rgba(255,255,255,0.07)' : 'none', overflow: 'hidden', background: '#101828' }}>
<span style={{ fontFamily: 'Georgia, serif', fontSize: 'clamp(60px, 8vw, 120px)', color: 'rgba(239,191,4,0.1)', lineHeight: 0.8, display: 'block', marginBottom: -20 }}>&ldquo;</span>
<p style={{ fontFamily: FF, fontSize: 'clamp(1.1rem, 1.8vw, 1.4rem)', fontWeight: 300, color: 'rgba(255,255,255,0.75)', lineHeight: 1.65, margin: '0 0 40px' }}>
{fallbackText(expertise.quote, netzwerkContent.expertise.quote)}
</p>
<div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
<div style={{ width: 40, height: 2, background: GOLD, flexShrink: 0 }} />
<span style={{ fontFamily: FF, fontSize: 17, color: 'rgba(255,255,255,0.4)' }}>{fallbackText(expertise.quoteAttribution, netzwerkContent.expertise.quoteAttribution)}</span>
</div>
</div>
</section>
{/* ── 6. PARTNER & SPONSOREN ───────────────────────────────────────────── */}
<section id="partner" style={{ background: CREAM, overflow: 'hidden', position: 'relative', isolation: 'isolate' }}>
<MunichSkylineBg />
<div style={{ padding: isMobile ? '48px 24px 32px' : '80px 80px 56px', display: 'flex', flexDirection: isMobile ? 'column' : 'row', gap: isMobile ? 12 : 0, justifyContent: 'space-between', alignItems: isMobile ? 'flex-start' : 'flex-end', borderBottom: '1px solid rgba(3,9,58,0.1)' }}>
<div>
<span style={{ fontFamily: FF, fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, color: '#4A8FC9', display: 'block', marginBottom: 16 }}>{fallbackText(partnerSection.eyebrow, netzwerkContent.partners.eyebrow)}</span>
<h2 style={{ fontFamily: FF, fontWeight: 900, color: '#101828', textTransform: 'uppercase', letterSpacing: '-0.025em', fontSize: 'clamp(2rem, 3.5vw, 3rem)', lineHeight: 0.95, margin: 0 }}><Lines text={fallbackText(partnerSection.heading, netzwerkContent.partners.heading)} /></h2>
</div>
<p style={{ fontFamily: FB, fontSize: 18, color: 'rgba(16,24,40,0.4)', maxWidth: isMobile ? '100%' : 220, textAlign: isMobile ? 'left' : 'right', lineHeight: 1.6, margin: 0 }}>
{fallbackText(partnerSection.description, netzwerkContent.partners.description)}
</p>
</div>
{/* Tiered grid continuous, ranks marked by label bars */}
<div style={{ position: 'relative', zIndex: 1 }}>
{partnerTiers.map(t => {
const tier = Number(t.tier) as 1 | 2 | 3;
const variant = tier === 1 ? 'lg' as const : tier === 2 ? 'md' as const : 'sm' as const;
const cols = isMobile ? (tier === 1 ? 1 : 2) : (tier === 3 ? 4 : 2);
const items = partners.filter(p => p.tier === tier);
return (
<div key={t.tier} style={{ display: 'grid', gridTemplateColumns: `repeat(${cols}, 1fr)` }}>
{items.map((p, i) => (
<SponsorCell key={p.id} partner={p} variant={variant} idx={i} cols={cols} detailLabel={fallbackText(partnerSection.detailLabel, netzwerkContent.partners.detailLabel)} premiumLabel={fallbackText(partnerSection.premiumLabel, netzwerkContent.partners.premiumLabel)} onClick={() => setSelectedPartner(p)} />
))}
</div>
);
})}
</div>
</section>
{/* ── 7. SPONSORING-FORM ───────────────────────────────────────────────── */}
<section id="sponsoring" style={{
background: NAVY, overflow: 'hidden', position: 'relative',
minHeight: isMobile ? 'auto' : 'calc(100vh - 60px)',
display: 'flex', flexDirection: 'column',
}}>
<div style={{ flex: 1, position: 'relative', zIndex: 1, display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '4fr 1px 8fr', minHeight: 0, overflow: isMobile ? 'visible' : 'visible' }}>
{/* Left pitch */}
<div style={{ padding: isMobile ? '32px 24px 24px' : '36px 36px 32px 52px', display: 'flex', flexDirection: 'column', justifyContent: 'center', overflow: 'visible' }}>
<span style={{ fontFamily: FF, fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, color: GOLD, display: 'block', marginBottom: 8 }}>{fallbackText(sponsoring.eyebrow, netzwerkContent.sponsoring.eyebrow)}</span>
<h2 style={{ fontFamily: FF, fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.025em', fontSize: 'clamp(1.6rem, 2.4vw, 2.4rem)', lineHeight: 1.0, margin: '0 0 12px' }}><Lines text={fallbackText(sponsoring.heading, netzwerkContent.sponsoring.heading)} /></h2>
<div style={{ width: 36, height: 2, background: GOLD, margin: '0 0 14px', flexShrink: 0 }} />
<p style={{ fontFamily: FB, fontSize: 'clamp(15px, 1.2vw, 17px)', color: 'rgba(255,255,255,0.75)', lineHeight: 1.65, marginBottom: 16 }}>
{fallbackText(sponsoring.description, netzwerkContent.sponsoring.description)}
</p>
{sponsorBenefits.map((item) => (
<div key={item.num} style={{ display: 'grid', gridTemplateColumns: '32px 1fr', gap: '0 12px', padding: '10px 0', borderBottom: '1px solid rgba(255,255,255,0.06)', alignItems: 'center' }}>
<span style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, color: 'rgba(239,191,4,0.5)' }}>{item.num}</span>
<div>
<div style={{ fontFamily: FF, fontSize: 'clamp(14px, 1.05vw, 16px)', fontWeight: 700, color: '#fff', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 2 }}>{item.label}</div>
<div style={{ fontFamily: FB, fontSize: 'clamp(13px, 1vw, 15px)', color: 'rgba(255,255,255,0.65)', lineHeight: 1.4 }}>{item.sub}</div>
</div>
</div>
))}
</div>
{/* Center divider */}
{!isMobile && <div style={{ background: 'rgba(255,255,255,0.07)' }} />}
{/* Right gold form panel */}
<div style={{ display: 'flex', flexDirection: 'column', overflow: 'visible', minHeight: 0, position: 'relative', background: 'linear-gradient(160deg,#DDB84A 0%,#C9A227 52%,#A87800 100%)' }}>
<svg style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', pointerEvents: 'none', zIndex: 0 }} aria-hidden="true">
<defs>
<pattern id="sponsoringCross" width="18" height="18" patternUnits="userSpaceOnUse">
<path d="M0,0 L18,18 M18,0 L0,18" stroke="rgba(17,29,85,0.055)" strokeWidth="0.65" />
</pattern>
<pattern id="sponsoringDiamond" width="36" height="36" patternUnits="userSpaceOnUse">
<polygon points="18,2 34,18 18,34 2,18" fill="none" stroke="rgba(17,29,85,0.045)" strokeWidth="0.6" />
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#sponsoringCross)" />
<rect width="100%" height="100%" fill="url(#sponsoringDiamond)" />
</svg>
<div style={{ position: 'absolute', inset: 0, background: 'radial-gradient(ellipse at center, transparent 55%, rgba(100,70,0,0.25) 100%)', pointerEvents: 'none', zIndex: 0 }} />
{!isMobile && (
<div style={{ height: 220, position: 'relative', overflow: 'hidden', flexShrink: 0, zIndex: 1 }}>
<Image unoptimized src={mediaUrl(sponsoring.image, `/images/${netzwerkContent.sponsoring.imageFilename}`)} alt={mediaAlt(sponsoring.image, fallbackText(sponsoring.imageAlt, netzwerkContent.sponsoring.imageAlt))} style={{ width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center 40%', filter: 'sepia(0.18) brightness(0.92)' }} />
<div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(to bottom, rgba(168,120,0,0.1) 0%, rgba(168,120,0,0.25) 50%, rgba(168,120,0,0.92) 88%, #A87800 100%)' }} />
<div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: 2, background: 'rgba(17,29,85,0.35)' }} />
<div style={{ position: 'absolute', bottom: 14, left: 40, display: 'flex', alignItems: 'center', gap: 8 }}>
<div style={{ width: 5, height: 5, borderRadius: '50%', background: 'rgba(17,29,85,0.7)' }} />
<span style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, color: 'rgba(17,29,85,0.75)', textTransform: 'uppercase', letterSpacing: '0.2em' }}>{fallbackText(sponsoring.imageLabel, netzwerkContent.sponsoring.imageLabel)}</span>
</div>
</div>
)}
<div style={{ padding: isMobile ? '28px 20px' : '24px 48px 32px 40px', flex: 1, display: 'flex', flexDirection: 'column', minHeight: isMobile ? 560 : 0, position: 'relative', zIndex: 1 }}>
<span style={{ fontFamily: FF, fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, color: 'rgba(17,29,85,0.5)', display: 'block', marginBottom: 8 }}>{fallbackText(sponsoring.formEyebrow, netzwerkContent.sponsoring.formEyebrow)}</span>
<SponsoringForm theme="gold" content={cms.sponsoringForm} />
</div>
</div>
</div>
{/* Footnote */}
<div style={{ position: 'relative', zIndex: 1, padding: isMobile ? '16px 20px 20px' : '14px 56px 18px', display: 'flex', flexWrap: 'wrap', justifyContent: 'center', alignItems: 'center', borderTop: '1px solid rgba(255,255,255,0.06)', flexShrink: 0 }}>
<span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 15, color: 'rgba(255,255,255,0.45)', marginRight: 10 }}>{fallbackText(sponsoring.footnotePrefix, netzwerkContent.sponsoring.footnotePrefix)}</span>
<Link
to={fallbackText(sponsoring.footnoteUrl, netzwerkContent.sponsoring.footnoteUrl)}
style={{
fontFamily: '"IBM Plex Sans", sans-serif',
fontSize: 15,
fontWeight: 700,
letterSpacing: '0.12em',
textTransform: 'uppercase',
color: 'rgba(239,191,4,0.7)',
textDecoration: 'none',
display: 'inline-flex',
alignItems: 'center',
gap: 6,
borderBottom: '1px solid rgba(239,191,4,0.3)',
paddingBottom: 1,
transition: 'color 0.15s, borderColor 0.15s',
}}
onMouseEnter={e => {
(e.currentTarget as HTMLElement).style.color = '#EFBF04';
(e.currentTarget as HTMLElement).style.borderBottomColor = '#EFBF04';
}}
onMouseLeave={e => {
(e.currentTarget as HTMLElement).style.color = 'rgba(239,191,4,0.7)';
(e.currentTarget as HTMLElement).style.borderBottomColor = 'rgba(239,191,4,0.3)';
}}
>
{fallbackText(sponsoring.footnoteLabel, netzwerkContent.sponsoring.footnoteLabel)} <ChevronRight size={11} />
</Link>
</div>
<div style={{ position: 'relative', zIndex: 1, height: 2, background: `linear-gradient(to right, ${GOLD}, rgba(239,191,4,0.3), transparent)`, flexShrink: 0 }} />
</section>
{/* ── 8. PARTNER MODAL ─────────────────────────────────────────────────── */}
{selectedPartner && (
<PartnerModal partner={selectedPartner} copy={partnerModal} onClose={() => setSelectedPartner(null)} />
)}
</div>
);
};
export default Netzwerk;