Fix mobile/responsive view across all pages and components

Comprehensive mobile pass over every page, form, layout and shared
component: eliminate horizontal overflow, switch fixed-vh sections to
auto height, collapse multi-column grids to single column, scale down
display typography and padding, enforce 44px tap targets, and ensure
embedded gold forms render and scroll without clipping on small screens.
All changes gated behind isMobile; desktop layout unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Sebastian Pachon Araque
2026-05-31 13:27:05 +02:00
parent 0115ac069f
commit cecd9fc3b4
24 changed files with 282 additions and 146 deletions

View File

@@ -1,6 +1,7 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { ChevronRight } from 'lucide-react'; import { ChevronRight } from 'lucide-react';
import MunichSkylineBg from '@/components/ui/munich-skyline-bg'; import MunichSkylineBg from '@/components/ui/munich-skyline-bg';
import { useIsMobile } from '@/hooks/useIsMobile';
const FF = '"IBM Plex Sans", sans-serif'; const FF = '"IBM Plex Sans", sans-serif';
@@ -15,6 +16,7 @@ export const TESTIMONIALS = [
export default function TestimonialsSection() { export default function TestimonialsSection() {
const [active, setActive] = useState(0); const [active, setActive] = useState(0);
const t = TESTIMONIALS[active]; const t = TESTIMONIALS[active];
const isMobile = useIsMobile();
const prev = () => setActive(i => (i - 1 + TESTIMONIALS.length) % TESTIMONIALS.length); const prev = () => setActive(i => (i - 1 + TESTIMONIALS.length) % TESTIMONIALS.length);
const next = () => setActive(i => (i + 1) % TESTIMONIALS.length); const next = () => setActive(i => (i + 1) % TESTIMONIALS.length);
@@ -22,20 +24,20 @@ export default function TestimonialsSection() {
return ( return (
<section style={{ background: '#fff', overflow: 'hidden', position: 'relative', isolation: 'isolate' }}> <section style={{ background: '#fff', overflow: 'hidden', position: 'relative', isolation: 'isolate' }}>
<MunichSkylineBg /> <MunichSkylineBg />
<div style={{ display: 'grid', gridTemplateColumns: '42% 58%', height: 560, position: 'relative', zIndex: 1 }}> <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '42% 58%', height: isMobile ? 'auto' : 560, position: 'relative', zIndex: 1 }}>
{/* Left — portrait photo */} {/* Left — portrait photo */}
<div style={{ position: 'relative', overflow: 'hidden' }}> <div style={{ position: 'relative', overflow: 'hidden', height: isMobile ? 280 : 'auto' }}>
<img <img
key={t.img} key={t.img}
src={t.img} src={t.img}
alt={t.name} alt={t.name}
style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'top', display: 'block', transition: 'opacity 0.4s' }} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'top', display: 'block', transition: 'opacity 0.4s' }}
/> />
<div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(to right, transparent 60%, #fff 100%)' }} /> <div style={{ position: 'absolute', inset: 0, background: isMobile ? 'linear-gradient(to bottom, transparent 70%, #fff 100%)' : 'linear-gradient(to right, transparent 60%, #fff 100%)' }} />
</div> </div>
{/* Right — quote */} {/* Right — quote */}
<div style={{ padding: '80px 72px 80px 56px', display: 'flex', flexDirection: 'column', justifyContent: 'center' }}> <div style={{ padding: isMobile ? '40px 22px 56px' : '80px 72px 80px 56px', display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
<span style={{ fontFamily: FF, fontSize: 10, color: '#4A8FC9', textTransform: 'uppercase', letterSpacing: '0.3em', fontWeight: 700, display: 'block', marginBottom: 32 }}>Stimmen der Preisträger</span> <span style={{ fontFamily: FF, fontSize: 10, color: '#4A8FC9', textTransform: 'uppercase', letterSpacing: '0.3em', fontWeight: 700, display: 'block', marginBottom: 32 }}>Stimmen der Preisträger</span>
<p style={{ fontFamily: FF, fontSize: 'clamp(1.4rem, 2.2vw, 2rem)', fontWeight: 300, color: '#101828', lineHeight: 1.55, margin: '0 0 40px' }}> <p style={{ fontFamily: FF, fontSize: 'clamp(1.4rem, 2.2vw, 2rem)', fontWeight: 300, color: '#101828', lineHeight: 1.55, margin: '0 0 40px' }}>
@@ -50,13 +52,13 @@ export default function TestimonialsSection() {
</div> </div>
<div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 40 }}> <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 40 }}>
<button onClick={prev} style={{ width: 40, height: 40, border: '1.5px solid #D0D5DD', background: 'transparent', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', transition: 'all 0.15s' }} <button onClick={prev} style={{ width: isMobile ? 44 : 40, height: isMobile ? 44 : 40, border: '1.5px solid #D0D5DD', background: 'transparent', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', transition: 'all 0.15s' }}
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.borderColor = '#111D55'; (e.currentTarget as HTMLElement).style.background = '#111D55'; (e.currentTarget as HTMLElement).style.color = '#fff'; }} onMouseEnter={e => { (e.currentTarget as HTMLElement).style.borderColor = '#111D55'; (e.currentTarget as HTMLElement).style.background = '#111D55'; (e.currentTarget as HTMLElement).style.color = '#fff'; }}
onMouseLeave={e => { (e.currentTarget as HTMLElement).style.borderColor = '#D0D5DD'; (e.currentTarget as HTMLElement).style.background = 'transparent'; (e.currentTarget as HTMLElement).style.color = 'inherit'; }} onMouseLeave={e => { (e.currentTarget as HTMLElement).style.borderColor = '#D0D5DD'; (e.currentTarget as HTMLElement).style.background = 'transparent'; (e.currentTarget as HTMLElement).style.color = 'inherit'; }}
> >
<ChevronRight size={16} style={{ transform: 'rotate(180deg)' }} /> <ChevronRight size={16} style={{ transform: 'rotate(180deg)' }} />
</button> </button>
<button onClick={next} style={{ width: 40, height: 40, border: '1.5px solid #111D55', background: '#111D55', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', transition: 'all 0.15s', color: '#fff' }} <button onClick={next} style={{ width: isMobile ? 44 : 40, height: isMobile ? 44 : 40, border: '1.5px solid #111D55', background: '#111D55', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', transition: 'all 0.15s', color: '#fff' }}
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = '#EFBF04'; (e.currentTarget as HTMLElement).style.borderColor = '#EFBF04'; }} onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = '#EFBF04'; (e.currentTarget as HTMLElement).style.borderColor = '#EFBF04'; }}
onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = '#111D55'; (e.currentTarget as HTMLElement).style.borderColor = '#111D55'; }} onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = '#111D55'; (e.currentTarget as HTMLElement).style.borderColor = '#111D55'; }}
> >

View File

@@ -7,6 +7,7 @@ import {
ProcessCardBody, ProcessCardBody,
ProcessCardTitle, ProcessCardTitle,
} from '@/components/ui/process-timeline'; } from '@/components/ui/process-timeline';
import { useIsMobile } from '@/hooks/useIsMobile';
const FF = '"IBM Plex Sans", sans-serif'; const FF = '"IBM Plex Sans", sans-serif';
const FB = '"Inter", sans-serif'; const FB = '"Inter", sans-serif';
@@ -21,6 +22,61 @@ const STEPS = [
]; ];
export default function WegZurAuszeichnungSection() { export default function WegZurAuszeichnungSection() {
const isMobile = useIsMobile();
// ── MOBILE: stacked vertical list (no scroll-jack, no horizontal overflow) ──
if (isMobile) {
return (
<section id="schritte" style={{ background: NAVY, padding: '56px 22px' }}>
{/* Section header */}
<div style={{ marginBottom: 36 }}>
<span style={{ fontFamily: FF, fontSize: 10, color: '#4A8FC9', textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, display: 'block', marginBottom: 12 }}>Schritt für Schritt</span>
<h2 style={{ fontFamily: FF, fontSize: 'clamp(1.9rem, 8vw, 2.6rem)', fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.025em', lineHeight: 1.05, margin: '0 0 16px' }}>
IHR WEG ZUR<br />AUSZEICHNUNG.
</h2>
<p style={{ fontFamily: FB, fontSize: 15, color: 'rgba(255,255,255,0.65)', lineHeight: 1.7, margin: 0 }}>
Von der Einreichung bis zur Gala — vier klar definierte Schritte auf dem Weg zur höchsten Auszeichnung des bayerischen Mittelstands.
</p>
</div>
{/* Stacked step cards */}
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
{STEPS.map((item, index) => {
const Icon = item.Icon;
return (
<div key={item.step} style={{ border: '1px solid rgba(239,191,4,0.25)', background: '#111D55', padding: '24px 22px' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 20 }}>
<div style={{ width: 44, height: 44, border: '1px solid rgba(239,191,4,0.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<Icon size={18} style={{ color: GOLD }} strokeWidth={1.5} />
</div>
<div>
<div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 4 }}>
<span style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, color: GOLD, letterSpacing: '0.18em', textTransform: 'uppercase' }}>Schritt {item.step}</span>
<span style={{ width: 1, height: 11, background: 'rgba(255,255,255,0.2)' }} />
<span style={{ fontFamily: FF, fontSize: 10, color: 'rgba(255,255,255,0.62)', letterSpacing: '0.06em' }}>{item.date}</span>
</div>
<h3 style={{ fontFamily: FF, fontSize: '1.35rem', fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.02em', lineHeight: 1.1, margin: 0 }}>
{item.title}
</h3>
</div>
</div>
<p style={{ fontFamily: FB, fontSize: 15, color: 'rgba(255,255,255,0.68)', lineHeight: 1.7, margin: 0 }}>
{item.desc}
</p>
{/* Step progress indicator */}
<div style={{ display: 'flex', gap: 4, marginTop: 20 }}>
{[0, 1, 2, 3].map(i => (
<div key={i} style={{ height: 2, flex: i === index ? 2 : 1, background: i === index ? GOLD : 'rgba(255,255,255,0.1)' }} />
))}
</div>
</div>
);
})}
</div>
</section>
);
}
return ( return (
<ContainerScroll id="schritte" className="h-[380vh]" style={{ background: NAVY }}> <ContainerScroll id="schritte" className="h-[380vh]" style={{ background: NAVY }}>
<ContainerSticky className="top-0 h-screen flex flex-col"> <ContainerSticky className="top-0 h-screen flex flex-col">

View File

@@ -1,6 +1,7 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { AnimatePresence, motion } from 'framer-motion'; import { AnimatePresence, motion } from 'framer-motion';
import { ArrowRight, ArrowLeft, Check, Trophy, User, Send, Building2, AlertCircle } from 'lucide-react'; import { ArrowRight, ArrowLeft, Check, Trophy, User, Send, Building2, AlertCircle } from 'lucide-react';
import { useIsMobile } from '@/hooks/useIsMobile';
const FF = '"IBM Plex Sans", sans-serif'; const FF = '"IBM Plex Sans", sans-serif';
@@ -183,14 +184,15 @@ function Field({ label, error, children, optional, c }: {
function StyledInput({ c, ...props }: React.InputHTMLAttributes<HTMLInputElement> & { c: C }) { function StyledInput({ c, ...props }: React.InputHTMLAttributes<HTMLInputElement> & { c: C }) {
const [focused, setFocused] = useState(false); const [focused, setFocused] = useState(false);
const isMobile = useIsMobile();
return ( return (
<input <input
{...props} {...props}
onFocus={e => { setFocused(true); props.onFocus?.(e); }} onFocus={e => { setFocused(true); props.onFocus?.(e); }}
onBlur ={e => { setFocused(false); props.onBlur?.(e); }} onBlur ={e => { setFocused(false); props.onBlur?.(e); }}
style={{ style={{
width: '100%', height: 38, padding: '0 12px', width: '100%', height: isMobile ? 44 : 38, padding: isMobile ? '0 14px' : '0 12px',
fontFamily: FF, fontSize: 13, color: c.inputText, fontFamily: FF, fontSize: isMobile ? 16 : 13, color: c.inputText,
border: `1px solid ${focused ? c.borderActive : c.inputBorder}`, border: `1px solid ${focused ? c.borderActive : c.inputBorder}`,
background: focused ? c.inputBgFocus : c.inputBg, background: focused ? c.inputBgFocus : c.inputBg,
outline: 'none', boxSizing: 'border-box', outline: 'none', boxSizing: 'border-box',
@@ -221,16 +223,19 @@ function TypeCard({ selected, onClick, title, desc, c }: {
); );
} }
function OptionButton({ selected, onClick, label, c }: { function OptionButton({ selected, onClick, label, c, style }: {
selected: boolean; onClick: () => void; label: string; c: C; selected: boolean; onClick: () => void; label: string; c: C; style?: React.CSSProperties;
}) { }) {
const isMobile = useIsMobile();
return ( return (
<button type="button" onClick={onClick} style={{ <button type="button" onClick={onClick} style={{
padding: '8px 16px', fontFamily: FF, fontSize: 12, fontWeight: 600, cursor: 'pointer', padding: isMobile ? '12px 18px' : '8px 16px', minHeight: isMobile ? 44 : undefined,
fontFamily: FF, fontSize: isMobile ? 14 : 12, fontWeight: 600, cursor: 'pointer',
border: `1.5px solid ${selected ? c.optBorderSel : c.optBorder}`, border: `1.5px solid ${selected ? c.optBorderSel : c.optBorder}`,
background: selected ? c.optBgSel : c.optBg, background: selected ? c.optBgSel : c.optBg,
color: selected ? c.optTextSel : c.optText, color: selected ? c.optTextSel : c.optText,
transition: 'all 0.15s', transition: 'all 0.15s',
...style,
}}> }}>
{label} {label}
</button> </button>
@@ -240,10 +245,12 @@ function OptionButton({ selected, onClick, label, c }: {
function YesNo({ value, onChange, c }: { function YesNo({ value, onChange, c }: {
value: 'ja' | 'nein' | ''; onChange: (v: 'ja' | 'nein') => void; c: C; value: 'ja' | 'nein' | ''; onChange: (v: 'ja' | 'nein') => void; c: C;
}) { }) {
const isMobile = useIsMobile();
const flexStyle = isMobile ? { flex: 1 } : undefined;
return ( return (
<div style={{ display: 'flex', gap: 8 }}> <div style={{ display: 'flex', gap: 8 }}>
<OptionButton selected={value === 'ja'} onClick={() => onChange('ja')} label="Ja" c={c} /> <OptionButton selected={value === 'ja'} onClick={() => onChange('ja')} label="Ja" c={c} style={flexStyle} />
<OptionButton selected={value === 'nein'} onClick={() => onChange('nein')} label="Nein" c={c} /> <OptionButton selected={value === 'nein'} onClick={() => onChange('nein')} label="Nein" c={c} style={flexStyle} />
</div> </div>
); );
} }
@@ -256,6 +263,7 @@ function isEligible(data: FormData) {
export default function BewerbungsForm({ theme = 'dark' }: { theme?: 'dark' | 'gold' }) { export default function BewerbungsForm({ theme = 'dark' }: { theme?: 'dark' | 'gold' }) {
const c = theme === 'gold' ? GOLD : DARK; const c = theme === 'gold' ? GOLD : DARK;
const isMobile = useIsMobile();
const [step, setStep] = useState(0); const [step, setStep] = useState(0);
const [dir, setDir] = useState(1); const [dir, setDir] = useState(1);
@@ -362,7 +370,7 @@ export default function BewerbungsForm({ theme = 'dark' }: { theme?: 'dark' | 'g
</div> </div>
{/* Content */} {/* Content */}
<div style={{ padding: '20px 28px', flex: 1, minHeight: 0, overflowX: 'hidden', overflowY: 'auto' }}> <div style={{ padding: isMobile ? '18px 20px' : '20px 28px', flex: 1, minHeight: 0, overflowX: 'hidden', overflowY: 'auto' }}>
<AnimatePresence mode="wait" custom={dir}> <AnimatePresence mode="wait" custom={dir}>
<motion.div key={`${step}-${data.type}`} custom={dir} variants={variants} <motion.div key={`${step}-${data.type}`} custom={dir} variants={variants}
initial="enter" animate="center" exit="exit" initial="enter" animate="center" exit="exit"
@@ -373,7 +381,7 @@ export default function BewerbungsForm({ theme = 'dark' }: { theme?: 'dark' | 'g
<div> <div>
<p style={{ fontFamily: FF, fontSize: 10, color: c.accentLabel, textTransform: 'uppercase', letterSpacing: '0.25em', fontWeight: 700, marginBottom: 8 }}>Schritt 1</p> <p style={{ fontFamily: FF, fontSize: 10, color: c.accentLabel, textTransform: 'uppercase', letterSpacing: '0.25em', fontWeight: 700, marginBottom: 8 }}>Schritt 1</p>
<h3 style={{ fontFamily: FF, fontSize: 16, fontWeight: 900, color: c.heading, textTransform: 'uppercase', letterSpacing: '-0.01em', marginBottom: 14 }}>Art der Einreichung</h3> <h3 style={{ fontFamily: FF, fontSize: 16, fontWeight: 900, color: c.heading, textTransform: 'uppercase', letterSpacing: '-0.01em', marginBottom: 14 }}>Art der Einreichung</h3>
<div style={{ display: 'flex', gap: 8 }}> <div style={{ display: 'flex', flexDirection: isMobile ? 'column' : 'row', gap: 8 }}>
<TypeCard c={c} selected={data.type === 'selbst'} title="Eigenbewerbung" <TypeCard c={c} selected={data.type === 'selbst'} title="Eigenbewerbung"
desc="Ich bewerbe mein eigenes Unternehmen für den Bayerischen Mittelstandspreis." desc="Ich bewerbe mein eigenes Unternehmen für den Bayerischen Mittelstandspreis."
onClick={() => { set('type', 'selbst'); setDir(1); setStep(1); }} /> onClick={() => { set('type', 'selbst'); setDir(1); setStep(1); }} />
@@ -437,7 +445,7 @@ export default function BewerbungsForm({ theme = 'dark' }: { theme?: 'dark' | 'g
<p style={{ fontFamily: FF, fontSize: 10, color: c.accentLabel, textTransform: 'uppercase', letterSpacing: '0.25em', fontWeight: 700, marginBottom: 6 }}>Kontakt</p> <p style={{ fontFamily: FF, fontSize: 10, color: c.accentLabel, textTransform: 'uppercase', letterSpacing: '0.25em', fontWeight: 700, marginBottom: 6 }}>Kontakt</p>
<h3 style={{ fontFamily: FF, fontSize: 16, fontWeight: 900, color: c.heading, textTransform: 'uppercase', letterSpacing: '-0.01em' }}>Ihre Kontaktdaten</h3> <h3 style={{ fontFamily: FF, fontSize: 16, fontWeight: 900, color: c.heading, textTransform: 'uppercase', letterSpacing: '-0.01em' }}>Ihre Kontaktdaten</h3>
</div> </div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}> <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '1fr 1fr', gap: 14 }}>
<Field c={c} label="Firmenname" error={errors.firmenname}> <Field c={c} label="Firmenname" error={errors.firmenname}>
<StyledInput c={c} value={data.firmenname} onChange={e => set('firmenname', e.target.value)} placeholder="Muster GmbH" /> <StyledInput c={c} value={data.firmenname} onChange={e => set('firmenname', e.target.value)} placeholder="Muster GmbH" />
</Field> </Field>
@@ -474,7 +482,7 @@ export default function BewerbungsForm({ theme = 'dark' }: { theme?: 'dark' | 'g
].map(row => ( ].map(row => (
<div key={row.label} style={{ display: 'grid', gridTemplateColumns: '90px 1fr', gap: 12, padding: '10px 0', borderBottom: `1px solid ${c.border}`, alignItems: 'baseline' }}> <div key={row.label} style={{ display: 'grid', gridTemplateColumns: '90px 1fr', gap: 12, padding: '10px 0', borderBottom: `1px solid ${c.border}`, alignItems: 'baseline' }}>
<span style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, color: c.rowLabel, textTransform: 'uppercase', letterSpacing: '0.12em' }}>{row.label}</span> <span style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, color: c.rowLabel, textTransform: 'uppercase', letterSpacing: '0.12em' }}>{row.label}</span>
<span style={{ fontFamily: FF, fontSize: 13, color: c.rowValue }}>{row.value}</span> <span style={{ fontFamily: FF, fontSize: 13, color: c.rowValue, overflowWrap: 'anywhere' }}>{row.value}</span>
</div> </div>
))} ))}
</div> </div>
@@ -488,7 +496,7 @@ export default function BewerbungsForm({ theme = 'dark' }: { theme?: 'dark' | 'g
<p style={{ fontFamily: FF, fontSize: 10, color: c.accentLabel, textTransform: 'uppercase', letterSpacing: '0.25em', fontWeight: 700, marginBottom: 6 }}>Nominierung</p> <p style={{ fontFamily: FF, fontSize: 10, color: c.accentLabel, textTransform: 'uppercase', letterSpacing: '0.25em', fontWeight: 700, marginBottom: 6 }}>Nominierung</p>
<h3 style={{ fontFamily: FF, fontSize: 16, fontWeight: 900, color: c.heading, textTransform: 'uppercase', letterSpacing: '-0.01em' }}>Nominiertes Unternehmen</h3> <h3 style={{ fontFamily: FF, fontSize: 16, fontWeight: 900, color: c.heading, textTransform: 'uppercase', letterSpacing: '-0.01em' }}>Nominiertes Unternehmen</h3>
</div> </div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}> <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '1fr 1fr', gap: 14 }}>
<Field c={c} label="Firmenname" error={errors.nomFirma}> <Field c={c} label="Firmenname" error={errors.nomFirma}>
<StyledInput c={c} value={data.nomFirma} onChange={e => set('nomFirma', e.target.value)} placeholder="Muster GmbH" /> <StyledInput c={c} value={data.nomFirma} onChange={e => set('nomFirma', e.target.value)} placeholder="Muster GmbH" />
</Field> </Field>
@@ -509,7 +517,7 @@ export default function BewerbungsForm({ theme = 'dark' }: { theme?: 'dark' | 'g
<p style={{ fontFamily: FF, fontSize: 10, color: c.accentLabel, textTransform: 'uppercase', letterSpacing: '0.25em', fontWeight: 700, marginBottom: 6 }}>Nominierender</p> <p style={{ fontFamily: FF, fontSize: 10, color: c.accentLabel, textTransform: 'uppercase', letterSpacing: '0.25em', fontWeight: 700, marginBottom: 6 }}>Nominierender</p>
<h3 style={{ fontFamily: FF, fontSize: 16, fontWeight: 900, color: c.heading, textTransform: 'uppercase', letterSpacing: '-0.01em' }}>Ihre Angaben</h3> <h3 style={{ fontFamily: FF, fontSize: 16, fontWeight: 900, color: c.heading, textTransform: 'uppercase', letterSpacing: '-0.01em' }}>Ihre Angaben</h3>
</div> </div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}> <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '1fr 1fr', gap: 14 }}>
<Field c={c} label="Ihr Name" error={errors.nomName}> <Field c={c} label="Ihr Name" error={errors.nomName}>
<StyledInput c={c} value={data.nomName} onChange={e => set('nomName', e.target.value)} placeholder="Vor- und Nachname" /> <StyledInput c={c} value={data.nomName} onChange={e => set('nomName', e.target.value)} placeholder="Vor- und Nachname" />
</Field> </Field>
@@ -542,7 +550,7 @@ export default function BewerbungsForm({ theme = 'dark' }: { theme?: 'dark' | 'g
].map(row => ( ].map(row => (
<div key={row.label} style={{ display: 'grid', gridTemplateColumns: '100px 1fr', gap: 12, padding: '10px 0', borderBottom: `1px solid ${c.border}`, alignItems: 'baseline' }}> <div key={row.label} style={{ display: 'grid', gridTemplateColumns: '100px 1fr', gap: 12, padding: '10px 0', borderBottom: `1px solid ${c.border}`, alignItems: 'baseline' }}>
<span style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, color: c.rowLabel, textTransform: 'uppercase', letterSpacing: '0.12em' }}>{row.label}</span> <span style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, color: c.rowLabel, textTransform: 'uppercase', letterSpacing: '0.12em' }}>{row.label}</span>
<span style={{ fontFamily: FF, fontSize: 13, color: c.rowValue }}>{row.value}</span> <span style={{ fontFamily: FF, fontSize: 13, color: c.rowValue, overflowWrap: 'anywhere' }}>{row.value}</span>
</div> </div>
))} ))}
</div> </div>
@@ -555,12 +563,13 @@ export default function BewerbungsForm({ theme = 'dark' }: { theme?: 'dark' | 'g
{/* Navigation */} {/* Navigation */}
{step > 0 && ( {step > 0 && (
<div style={{ padding: '12px 28px', borderTop: `1px solid ${c.border}`, display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexShrink: 0 }}> <div style={{ padding: isMobile ? '12px 20px' : '12px 28px', borderTop: `1px solid ${c.border}`, display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexShrink: 0 }}>
<button type="button" onClick={prev} style={{ <button type="button" onClick={prev} style={{
fontFamily: FF, fontSize: 12, fontWeight: 700, textTransform: 'uppercase', fontFamily: FF, fontSize: 12, fontWeight: 700, textTransform: 'uppercase',
letterSpacing: '0.1em', color: c.backText, background: 'none', letterSpacing: '0.1em', color: c.backText, background: 'none',
border: 'none', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 5, border: 'none', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 5,
padding: 0, transition: 'color 0.15s', padding: isMobile ? '12px 4px' : 0, minHeight: isMobile ? 44 : undefined,
transition: 'color 0.15s',
}} }}
onMouseEnter={e => (e.currentTarget.style.color = c.backTextHover)} onMouseEnter={e => (e.currentTarget.style.color = c.backTextHover)}
onMouseLeave={e => (e.currentTarget.style.color = c.backText)} onMouseLeave={e => (e.currentTarget.style.color = c.backText)}
@@ -573,7 +582,7 @@ export default function BewerbungsForm({ theme = 'dark' }: { theme?: 'dark' | 'g
<button type="button" onClick={next} style={{ <button type="button" onClick={next} style={{
fontFamily: FF, fontSize: 12, fontWeight: 700, textTransform: 'uppercase', fontFamily: FF, fontSize: 12, fontWeight: 700, textTransform: 'uppercase',
letterSpacing: '0.1em', color: c.btnText, background: c.btnBg, letterSpacing: '0.1em', color: c.btnText, background: c.btnBg,
border: 'none', cursor: 'pointer', padding: '10px 22px', border: 'none', cursor: 'pointer', padding: isMobile ? '13px 24px' : '10px 22px',
display: 'flex', alignItems: 'center', gap: 6, transition: 'background 0.15s', display: 'flex', alignItems: 'center', gap: 6, transition: 'background 0.15s',
}} }}
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = c.btnBgHover; }} onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = c.btnBgHover; }}
@@ -585,7 +594,7 @@ export default function BewerbungsForm({ theme = 'dark' }: { theme?: 'dark' | 'g
<button type="button" onClick={submit} style={{ <button type="button" onClick={submit} style={{
fontFamily: FF, fontSize: 12, fontWeight: 700, textTransform: 'uppercase', fontFamily: FF, fontSize: 12, fontWeight: 700, textTransform: 'uppercase',
letterSpacing: '0.1em', color: c.btnText, background: c.btnBg, letterSpacing: '0.1em', color: c.btnText, background: c.btnBg,
border: 'none', cursor: 'pointer', padding: '10px 22px', border: 'none', cursor: 'pointer', padding: isMobile ? '13px 24px' : '10px 22px',
display: 'flex', alignItems: 'center', gap: 6, transition: 'background 0.15s', display: 'flex', alignItems: 'center', gap: 6, transition: 'background 0.15s',
}} }}
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = c.btnBgHover; }} onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = c.btnBgHover; }}

View File

@@ -115,14 +115,15 @@ const variants = {
function StyledInput({ c, ...props }: React.InputHTMLAttributes<HTMLInputElement> & { c: C }) { function StyledInput({ c, ...props }: React.InputHTMLAttributes<HTMLInputElement> & { c: C }) {
const [focused, setFocused] = useState(false); const [focused, setFocused] = useState(false);
const isMobile = useIsMobile();
return ( return (
<input <input
{...props} {...props}
onFocus={e => { setFocused(true); props.onFocus?.(e); }} onFocus={e => { setFocused(true); props.onFocus?.(e); }}
onBlur ={e => { setFocused(false); props.onBlur?.(e); }} onBlur ={e => { setFocused(false); props.onBlur?.(e); }}
style={{ style={{
width: '100%', height: 42, padding: '0 12px', width: '100%', height: isMobile ? 46 : 42, padding: '0 12px',
fontSize: 14, color: c.inputText, fontFamily: FF, fontSize: isMobile ? 16 : 14, color: c.inputText, fontFamily: FF,
border: `1.5px solid ${focused ? c.inputBorderFoc : c.inputBorder}`, border: `1.5px solid ${focused ? c.inputBorderFoc : c.inputBorder}`,
background: focused ? c.inputBgFocus : c.inputBg, background: focused ? c.inputBgFocus : c.inputBg,
outline: 'none', boxSizing: 'border-box', outline: 'none', boxSizing: 'border-box',
@@ -135,6 +136,7 @@ function StyledInput({ c, ...props }: React.InputHTMLAttributes<HTMLInputElement
function StyledTextarea({ c, ...props }: React.TextareaHTMLAttributes<HTMLTextAreaElement> & { c: C }) { function StyledTextarea({ c, ...props }: React.TextareaHTMLAttributes<HTMLTextAreaElement> & { c: C }) {
const [focused, setFocused] = useState(false); const [focused, setFocused] = useState(false);
const isMobile = useIsMobile();
return ( return (
<textarea <textarea
{...props} {...props}
@@ -142,7 +144,7 @@ function StyledTextarea({ c, ...props }: React.TextareaHTMLAttributes<HTMLTextAr
onBlur ={e => { setFocused(false); props.onBlur?.(e); }} onBlur ={e => { setFocused(false); props.onBlur?.(e); }}
style={{ style={{
width: '100%', padding: '10px 12px', width: '100%', padding: '10px 12px',
fontSize: 14, color: c.inputText, fontFamily: FF, fontSize: isMobile ? 16 : 14, color: c.inputText, fontFamily: FF,
border: `1.5px solid ${focused ? c.inputBorderFoc : c.inputBorder}`, border: `1.5px solid ${focused ? c.inputBorderFoc : c.inputBorder}`,
background: focused ? c.inputBgFocus : c.inputBg, background: focused ? c.inputBgFocus : c.inputBg,
outline: 'none', boxSizing: 'border-box', outline: 'none', boxSizing: 'border-box',
@@ -223,7 +225,7 @@ export default function KontaktForm({ theme = 'dark' }: { theme?: 'dark' | 'gold
<h3 style={{ fontSize: 20, fontWeight: 800, color: c.successHeading, marginBottom: 10, letterSpacing: '-0.02em', fontFamily: FF }}> <h3 style={{ fontSize: 20, fontWeight: 800, color: c.successHeading, marginBottom: 10, letterSpacing: '-0.02em', fontFamily: FF }}>
Nachricht gesendet Nachricht gesendet
</h3> </h3>
<p style={{ fontSize: 15, color: c.successBody, lineHeight: 1.7, maxWidth: 280, margin: '0 auto', fontFamily: FF }}> <p style={{ fontSize: 15, color: c.successBody, lineHeight: 1.7, maxWidth: 280, margin: '0 auto', fontFamily: FF, overflowWrap: 'anywhere' }}>
Danke, <strong style={{ color: c.successHeading }}>{data.name}</strong>. Wir melden uns zeitnah bei{' '} Danke, <strong style={{ color: c.successHeading }}>{data.name}</strong>. Wir melden uns zeitnah bei{' '}
<strong style={{ color: c.successIcon }}>{data.email}</strong>. <strong style={{ color: c.successIcon }}>{data.email}</strong>.
</p> </p>
@@ -313,7 +315,7 @@ export default function KontaktForm({ theme = 'dark' }: { theme?: 'dark' | 'gold
<button type="button" onClick={prev} style={{ <button type="button" onClick={prev} style={{
fontSize: 12, fontWeight: 600, color: c.backText, background: 'none', border: 'none', cursor: 'pointer', fontSize: 12, fontWeight: 600, color: c.backText, background: 'none', border: 'none', cursor: 'pointer',
display: 'flex', alignItems: 'center', justifyContent: isMobile ? 'center' : 'flex-start', gap: 5, display: 'flex', alignItems: 'center', justifyContent: isMobile ? 'center' : 'flex-start', gap: 5,
padding: isMobile ? '8px 0' : 0, fontFamily: FF, transition: 'color 0.15s', padding: isMobile ? '12px 0' : 0, minHeight: isMobile ? 44 : undefined, fontFamily: FF, transition: 'color 0.15s',
}} }}
onMouseEnter={e => (e.currentTarget.style.color = c.backTextHover)} onMouseEnter={e => (e.currentTarget.style.color = c.backTextHover)}
onMouseLeave={e => (e.currentTarget.style.color = c.backText)} onMouseLeave={e => (e.currentTarget.style.color = c.backText)}

View File

@@ -1,6 +1,7 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { AnimatePresence, motion } from 'framer-motion'; import { AnimatePresence, motion } from 'framer-motion';
import { ArrowRight, ArrowLeft, Check, Layers, Building2, Mail } from 'lucide-react'; import { ArrowRight, ArrowLeft, Check, Layers, Building2, Mail } from 'lucide-react';
import { useIsMobile } from '@/hooks/useIsMobile';
const FF = '"IBM Plex Sans", sans-serif'; const FF = '"IBM Plex Sans", sans-serif';
@@ -122,14 +123,15 @@ function Field({ c, label, error, children }: { c: C; label: string; error?: str
function StyledInput({ c, ...props }: React.InputHTMLAttributes<HTMLInputElement> & { c: C }) { function StyledInput({ c, ...props }: React.InputHTMLAttributes<HTMLInputElement> & { c: C }) {
const [focused, setFocused] = useState(false); const [focused, setFocused] = useState(false);
const isMobile = useIsMobile();
return ( return (
<input <input
{...props} {...props}
onFocus={e => { setFocused(true); props.onFocus?.(e); }} onFocus={e => { setFocused(true); props.onFocus?.(e); }}
onBlur ={e => { setFocused(false); props.onBlur?.(e); }} onBlur ={e => { setFocused(false); props.onBlur?.(e); }}
style={{ style={{
width: '100%', height: 44, padding: '0 14px', width: '100%', height: isMobile ? 46 : 44, padding: '0 14px',
fontFamily: FF, fontSize: 14, color: c.inputText, fontFamily: FF, fontSize: isMobile ? 16 : 14, color: c.inputText,
border: `1px solid ${focused ? c.inputBorderFoc : c.inputBorder}`, border: `1px solid ${focused ? c.inputBorderFoc : c.inputBorder}`,
background: focused ? c.inputBgFocus : c.inputBg, background: focused ? c.inputBgFocus : c.inputBg,
outline: 'none', boxSizing: 'border-box', outline: 'none', boxSizing: 'border-box',
@@ -165,6 +167,7 @@ function PaketCard({ c, pkg, selected, onClick }: { c: C; pkg: typeof PAKETE[0];
export default function SponsoringForm({ theme = 'dark' }: { theme?: 'dark' | 'gold' }) { export default function SponsoringForm({ theme = 'dark' }: { theme?: 'dark' | 'gold' }) {
const c = theme === 'gold' ? GOLD : DARK; const c = theme === 'gold' ? GOLD : DARK;
const isMobile = useIsMobile();
const [step, setStep] = useState(0); const [step, setStep] = useState(0);
const [dir, setDir] = useState(1); const [dir, setDir] = useState(1);
const [submitted, setSubmitted] = useState(false); const [submitted, setSubmitted] = useState(false);
@@ -301,7 +304,9 @@ export default function SponsoringForm({ theme = 'dark' }: { theme?: 'dark' | 'g
<button type="button" onClick={prev} style={{ <button type="button" onClick={prev} style={{
fontFamily: FF, fontSize: 12, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.1em', fontFamily: FF, fontSize: 12, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.1em',
color: c.backText, background: 'none', border: 'none', cursor: 'pointer', color: c.backText, background: 'none', border: 'none', cursor: 'pointer',
display: 'flex', alignItems: 'center', gap: 6, padding: 0, transition: 'color 0.15s', display: 'flex', alignItems: 'center', gap: 6,
padding: isMobile ? '12px 4px' : 0, minHeight: isMobile ? 44 : undefined,
transition: 'color 0.15s',
}} }}
onMouseEnter={e => (e.currentTarget.style.color = c.backTextHover)} onMouseEnter={e => (e.currentTarget.style.color = c.backTextHover)}
onMouseLeave={e => (e.currentTarget.style.color = c.backText)} onMouseLeave={e => (e.currentTarget.style.color = c.backText)}
@@ -314,7 +319,8 @@ export default function SponsoringForm({ theme = 'dark' }: { theme?: 'dark' | 'g
<button type="button" onClick={next} style={{ <button type="button" onClick={next} style={{
fontFamily: FF, fontSize: 12, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.1em', fontFamily: FF, fontSize: 12, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.1em',
color: c.btnText, background: c.btnBg, border: 'none', cursor: 'pointer', color: c.btnText, background: c.btnBg, border: 'none', cursor: 'pointer',
padding: '12px 24px', display: 'flex', alignItems: 'center', gap: 7, transition: 'background 0.15s', padding: isMobile ? '14px 24px' : '12px 24px', minHeight: isMobile ? 44 : undefined,
display: 'flex', alignItems: 'center', gap: 7, transition: 'background 0.15s',
}} }}
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = c.btnBgHover; }} onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = c.btnBgHover; }}
onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = c.btnBg; }} onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = c.btnBg; }}
@@ -325,7 +331,8 @@ export default function SponsoringForm({ theme = 'dark' }: { theme?: 'dark' | 'g
<button type="button" onClick={submit} style={{ <button type="button" onClick={submit} style={{
fontFamily: FF, fontSize: 12, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.1em', fontFamily: FF, fontSize: 12, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.1em',
color: c.btnText, background: c.btnBg, border: 'none', cursor: 'pointer', color: c.btnText, background: c.btnBg, border: 'none', cursor: 'pointer',
padding: '12px 24px', display: 'flex', alignItems: 'center', gap: 7, transition: 'background 0.15s', padding: isMobile ? '14px 24px' : '12px 24px', minHeight: isMobile ? 44 : undefined,
display: 'flex', alignItems: 'center', gap: 7, transition: 'background 0.15s',
}} }}
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = c.btnBgHover; }} onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = c.btnBgHover; }}
onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = c.btnBg; }} onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = c.btnBg; }}

View File

@@ -256,7 +256,7 @@ const Layout: React.FC<LayoutProps> = ({ children }) => {
<div style={{ display:'flex', alignItems:'center', justifyContent:'flex-end', padding:'0 12px', height:'100%' }}> <div style={{ display:'flex', alignItems:'center', justifyContent:'flex-end', padding:'0 12px', height:'100%' }}>
{/* Mobile CTA */} {/* Mobile CTA */}
<Link to="/teilnahme#bewerben" <Link to="/teilnahme#bewerben"
style={{ fontFamily:FF_DISPLAY, fontSize:9, fontWeight:700, textTransform:'uppercase', letterSpacing:'.1em', color:'#101828', background:GOLD, padding:'7px 12px', textDecoration:'none', marginRight:8, whiteSpace:'nowrap' }} style={{ display:'inline-flex', alignItems:'center', minHeight:36, fontFamily:FF_DISPLAY, fontSize:10, fontWeight:700, textTransform:'uppercase', letterSpacing:'.1em', color:'#101828', background:GOLD, padding:'0 14px', textDecoration:'none', marginRight:8, whiteSpace:'nowrap' }}
>BMP</Link> >BMP</Link>
{/* Mobile hamburger */} {/* Mobile hamburger */}
<button <button
@@ -551,10 +551,10 @@ const Layout: React.FC<LayoutProps> = ({ children }) => {
</div> </div>
{/* Mobile secondary links */} {/* Mobile secondary links */}
<div style={{ padding:'0 24px 24px', display:'flex', flexWrap:'wrap', gap:'10px 24px' }}> <div style={{ padding:'0 24px 24px', display:'flex', flexWrap:'wrap', gap:'4px 8px' }}>
{SECONDARY.map(item => ( {SECONDARY.map(item => (
<Link key={item.path} to={item.path} onClick={() => setMobileMenuOpen(false)} <Link key={item.path} to={item.path} onClick={() => setMobileMenuOpen(false)}
style={{ fontSize:12, color:MUTED, textDecoration:'none', fontFamily:FF_BODY }} style={{ display:'inline-flex', alignItems:'center', minHeight:44, padding:'0 8px', fontSize:13, color:MUTED, textDecoration:'none', fontFamily:FF_BODY }}
>{item.label}</Link> >{item.label}</Link>
))} ))}
</div> </div>

View File

@@ -1,4 +1,5 @@
import { useState, useRef, useEffect } from "react"; import { useState, useRef, useEffect } from "react";
import { useIsMobile } from "@/hooks/useIsMobile";
// ─── CONSTANTS ──────────────────────────────────────────────────────────────── // ─── CONSTANTS ────────────────────────────────────────────────────────────────
@@ -210,6 +211,7 @@ function Input({
maxLength?: number; maxLength?: number;
}) { }) {
const [focused, setFocused] = useState(false); const [focused, setFocused] = useState(false);
const isMobile = useIsMobile();
return ( return (
<input <input
type={type} type={type}
@@ -221,6 +223,8 @@ function Input({
onBlur={() => { setFocused(false); onBlur?.(); }} onBlur={() => { setFocused(false); onBlur?.(); }}
style={{ style={{
...fieldBase, ...fieldBase,
// ≥16px on mobile prevents iOS auto-zoom on focus
fontSize: isMobile ? 16 : fieldBase.fontSize,
borderColor: error ? GOLD : focused ? "rgba(239,191,4,0.6)" : "rgba(255,255,255,0.15)", borderColor: error ? GOLD : focused ? "rgba(239,191,4,0.6)" : "rgba(255,255,255,0.15)",
background: focused ? "rgba(255,255,255,0.1)" : "rgba(255,255,255,0.07)", background: focused ? "rgba(255,255,255,0.1)" : "rgba(255,255,255,0.07)",
}} }}
@@ -235,6 +239,7 @@ function Select({
options: { value: string; label: string }[]; placeholder?: string; error?: string; options: { value: string; label: string }[]; placeholder?: string; error?: string;
}) { }) {
const [focused, setFocused] = useState(false); const [focused, setFocused] = useState(false);
const isMobile = useIsMobile();
return ( return (
<select <select
value={value} value={value}
@@ -243,6 +248,8 @@ function Select({
onBlur={() => setFocused(false)} onBlur={() => setFocused(false)}
style={{ style={{
...fieldBase, ...fieldBase,
// ≥16px on mobile prevents iOS auto-zoom on focus
fontSize: isMobile ? 16 : fieldBase.fontSize,
cursor: "pointer", cursor: "pointer",
appearance: "none", appearance: "none",
borderColor: error ? GOLD : focused ? "rgba(239,191,4,0.6)" : "rgba(255,255,255,0.15)", borderColor: error ? GOLD : focused ? "rgba(239,191,4,0.6)" : "rgba(255,255,255,0.15)",
@@ -271,6 +278,7 @@ function Textarea({
maxLength?: number; error?: string; maxLength?: number; error?: string;
}) { }) {
const [focused, setFocused] = useState(false); const [focused, setFocused] = useState(false);
const isMobile = useIsMobile();
return ( return (
<div> <div>
<textarea <textarea
@@ -283,6 +291,8 @@ function Textarea({
rows={4} rows={4}
style={{ style={{
...fieldBase, ...fieldBase,
// ≥16px on mobile prevents iOS auto-zoom on focus
fontSize: isMobile ? 16 : fieldBase.fontSize,
resize: "vertical", resize: "vertical",
borderColor: error ? GOLD : focused ? "rgba(239,191,4,0.6)" : "rgba(255,255,255,0.15)", borderColor: error ? GOLD : focused ? "rgba(239,191,4,0.6)" : "rgba(255,255,255,0.15)",
background: focused ? "rgba(255,255,255,0.1)" : "rgba(255,255,255,0.07)", background: focused ? "rgba(255,255,255,0.1)" : "rgba(255,255,255,0.07)",
@@ -419,8 +429,9 @@ function ReviewRow({ label, value }: { label: string; value: string }) {
// ─── PROGRESS BAR ───────────────────────────────────────────────────────────── // ─── PROGRESS BAR ─────────────────────────────────────────────────────────────
function ProgressBar({ current, total }: { current: number; total: number }) { function ProgressBar({ current, total }: { current: number; total: number }) {
const isMobile = useIsMobile();
return ( return (
<div style={{ marginBottom: 36 }}> <div style={{ marginBottom: isMobile ? 24 : 36 }}>
{/* Step dots + connecting lines */} {/* Step dots + connecting lines */}
<div style={{ position: "relative", display: "flex", alignItems: "center", marginBottom: 12 }}> <div style={{ position: "relative", display: "flex", alignItems: "center", marginBottom: 12 }}>
{/* Background track */} {/* Background track */}
@@ -502,28 +513,43 @@ function ProgressBar({ current, total }: { current: number; total: number }) {
})} })}
</div> </div>
{/* Step labels */} {/* Step labels — full list on desktop; on mobile only the active label
<div style={{ display: "flex" }}> (the 5-up text row would overflow / wrap on narrow screens) */}
{STEPS.map((step) => { {isMobile ? (
const done = step.id < current; <div style={{
const active = step.id === current; textAlign: "center",
return ( fontSize: 11,
<div key={step.id} style={{ fontWeight: 700,
flex: 1, letterSpacing: "0.1em",
textAlign: step.id === 1 ? "left" : step.id === total ? "right" : "center", textTransform: "uppercase",
fontSize: 10, color: GOLD,
fontWeight: active ? 700 : 500, fontFamily: '"IBM Plex Sans", sans-serif',
letterSpacing: "0.08em", }}>
textTransform: "uppercase", {STEPS.find((s) => s.id === current)?.label} · {current}/{total}
color: active ? GOLD : done ? "rgba(239,191,4,0.5)" : "rgba(255,255,255,0.25)", </div>
fontFamily: '"IBM Plex Sans", sans-serif', ) : (
transition: "color 0.3s", <div style={{ display: "flex" }}>
}}> {STEPS.map((step) => {
{step.label} const done = step.id < current;
</div> const active = step.id === current;
); return (
})} <div key={step.id} style={{
</div> flex: 1,
textAlign: step.id === 1 ? "left" : step.id === total ? "right" : "center",
fontSize: 10,
fontWeight: active ? 700 : 500,
letterSpacing: "0.08em",
textTransform: "uppercase",
color: active ? GOLD : done ? "rgba(239,191,4,0.5)" : "rgba(255,255,255,0.25)",
fontFamily: '"IBM Plex Sans", sans-serif',
transition: "color 0.3s",
}}>
{step.label}
</div>
);
})}
</div>
)}
</div> </div>
); );
} }
@@ -587,6 +613,7 @@ function NavButtons({
}: { }: {
step: number; onBack: () => void; onNext: () => void; onSubmit: () => void; disabled?: boolean; step: number; onBack: () => void; onNext: () => void; onSubmit: () => void; disabled?: boolean;
}) { }) {
const isMobile = useIsMobile();
const isLast = step === 5; const isLast = step === 5;
return ( return (
<div style={{ <div style={{
@@ -602,7 +629,8 @@ function NavButtons({
onClick={onBack} onClick={onBack}
style={{ style={{
flex: "0 0 auto", flex: "0 0 auto",
padding: "12px 20px", padding: isMobile ? "12px 16px" : "12px 20px",
minHeight: 44,
background: "transparent", background: "transparent",
border: "1px solid rgba(255,255,255,0.2)", border: "1px solid rgba(255,255,255,0.2)",
borderRadius: 8, borderRadius: 8,
@@ -613,6 +641,7 @@ function NavButtons({
cursor: "pointer", cursor: "pointer",
letterSpacing: "0.05em", letterSpacing: "0.05em",
transition: "all 0.2s", transition: "all 0.2s",
whiteSpace: "nowrap",
}} }}
onMouseEnter={(e) => { onMouseEnter={(e) => {
(e.target as HTMLButtonElement).style.borderColor = "rgba(255,255,255,0.5)"; (e.target as HTMLButtonElement).style.borderColor = "rgba(255,255,255,0.5)";
@@ -633,17 +662,21 @@ function NavButtons({
style={{ style={{
flex: 1, flex: 1,
padding: "13px 20px", padding: "13px 20px",
minHeight: 44,
background: disabled ? "rgba(239,191,4,0.3)" : GOLD, background: disabled ? "rgba(239,191,4,0.3)" : GOLD,
border: "none", border: "none",
borderRadius: 8, borderRadius: 8,
color: disabled ? "rgba(17,29,85,0.5)" : NAVY, color: disabled ? "rgba(17,29,85,0.5)" : NAVY,
fontFamily: '"IBM Plex Sans", sans-serif', fontFamily: '"IBM Plex Sans", sans-serif',
fontSize: 13, // long final-step label needs a smaller size + wrapping on mobile
fontSize: isMobile && isLast ? 12 : 13,
fontWeight: 700, fontWeight: 700,
cursor: disabled ? "not-allowed" : "pointer", cursor: disabled ? "not-allowed" : "pointer",
letterSpacing: "0.1em", letterSpacing: isMobile && isLast ? "0.04em" : "0.1em",
textTransform: "uppercase", textTransform: "uppercase",
transition: "all 0.2s", transition: "all 0.2s",
lineHeight: 1.3,
overflowWrap: "anywhere",
}} }}
onMouseEnter={(e) => { onMouseEnter={(e) => {
if (!disabled) (e.target as HTMLButtonElement).style.background = "#f5ca1a"; if (!disabled) (e.target as HTMLButtonElement).style.background = "#f5ca1a";
@@ -663,6 +696,7 @@ function NavButtons({
function Step1({ data, onChange, errors }: { function Step1({ data, onChange, errors }: {
data: FormData; onChange: (k: keyof FormData, v: string | boolean) => void; errors: Errors; data: FormData; onChange: (k: keyof FormData, v: string | boolean) => void; errors: Errors;
}) { }) {
const isMobile = useIsMobile();
const rechtsformen = [ const rechtsformen = [
"GmbH","GmbH & Co. KG","AG","UG","KG","OHG","GbR", "GmbH","GmbH & Co. KG","AG","UG","KG","OHG","GbR",
"Einzelunternehmen","e.K.","Sonstige", "Einzelunternehmen","e.K.","Sonstige",
@@ -672,7 +706,7 @@ function Step1({ data, onChange, errors }: {
<> <>
<StepHeading step={1} title="Ihr Unternehmen" subtitle="Angaben zum antragstellenden Unternehmen" /> <StepHeading step={1} title="Ihr Unternehmen" subtitle="Angaben zum antragstellenden Unternehmen" />
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "0 16px" }}> <div style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr" : "1fr 1fr", gap: "0 16px" }}>
<div style={{ gridColumn: "1 / -1" }}> <div style={{ gridColumn: "1 / -1" }}>
<Field label="Firmenname" required error={errors.firmenname}> <Field label="Firmenname" required error={errors.firmenname}>
<Input value={data.firmenname} onChange={(v) => onChange("firmenname", v)} placeholder="Muster GmbH" error={errors.firmenname} /> <Input value={data.firmenname} onChange={(v) => onChange("firmenname", v)} placeholder="Muster GmbH" error={errors.firmenname} />
@@ -713,17 +747,18 @@ function Step1({ data, onChange, errors }: {
function Step2({ data, onChange, errors }: { function Step2({ data, onChange, errors }: {
data: FormData; onChange: (k: keyof FormData, v: string | boolean) => void; errors: Errors; data: FormData; onChange: (k: keyof FormData, v: string | boolean) => void; errors: Errors;
}) { }) {
const isMobile = useIsMobile();
return ( return (
<> <>
<StepHeading step={2} title="Kontaktperson" subtitle="Ansprechpartner für die Mitgliedschaft" /> <StepHeading step={2} title="Kontaktperson" subtitle="Ansprechpartner für die Mitgliedschaft" />
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "0 16px" }}> <div style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr" : "1fr 1fr", gap: "0 16px" }}>
<Field label="Anrede" required error={errors.anrede}> <Field label="Anrede" required error={errors.anrede}>
<Select value={data.anrede} onChange={(v) => onChange("anrede", v)} <Select value={data.anrede} onChange={(v) => onChange("anrede", v)}
options={[{value:"Herr",label:"Herr"},{value:"Frau",label:"Frau"},{value:"Divers",label:"Divers"}]} options={[{value:"Herr",label:"Herr"},{value:"Frau",label:"Frau"},{value:"Divers",label:"Divers"}]}
placeholder="Bitte wählen" error={errors.anrede} /> placeholder="Bitte wählen" error={errors.anrede} />
</Field> </Field>
<div /> {/* spacer */} {!isMobile && <div />} {/* spacer (desktop only) */}
<Field label="Vorname" required error={errors.vorname}> <Field label="Vorname" required error={errors.vorname}>
<Input value={data.vorname} onChange={(v) => onChange("vorname", v)} placeholder="Max" error={errors.vorname} /> <Input value={data.vorname} onChange={(v) => onChange("vorname", v)} placeholder="Max" error={errors.vorname} />
</Field> </Field>
@@ -755,6 +790,7 @@ function Step2({ data, onChange, errors }: {
function Step3({ data, onChange, errors }: { function Step3({ data, onChange, errors }: {
data: FormData; onChange: (k: keyof FormData, v: string | boolean) => void; errors: Errors; data: FormData; onChange: (k: keyof FormData, v: string | boolean) => void; errors: Errors;
}) { }) {
const isMobile = useIsMobile();
const beitrag = calcBeitrag(data.mitarbeiter); const beitrag = calcBeitrag(data.mitarbeiter);
return ( return (
<> <>
@@ -800,7 +836,7 @@ function Step3({ data, onChange, errors }: {
</div> </div>
)} )}
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "0 16px" }}> <div style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr" : "1fr 1fr", gap: "0 16px" }}>
<Field label="Gewünschtes Eintrittsdatum" required error={errors.eintrittsdatum}> <Field label="Gewünschtes Eintrittsdatum" required error={errors.eintrittsdatum}>
<Input value={data.eintrittsdatum} onChange={(v) => onChange("eintrittsdatum", v)} type="date" error={errors.eintrittsdatum} /> <Input value={data.eintrittsdatum} onChange={(v) => onChange("eintrittsdatum", v)} type="date" error={errors.eintrittsdatum} />
</Field> </Field>
@@ -826,6 +862,7 @@ function Step3({ data, onChange, errors }: {
function Step4({ data, onChange, errors }: { function Step4({ data, onChange, errors }: {
data: FormData; onChange: (k: keyof FormData, v: string | boolean) => void; errors: Errors; data: FormData; onChange: (k: keyof FormData, v: string | boolean) => void; errors: Errors;
}) { }) {
const isMobile = useIsMobile();
const ibanIsValid = validateIBAN(data.iban); const ibanIsValid = validateIBAN(data.iban);
return ( return (
@@ -849,7 +886,7 @@ function Step4({ data, onChange, errors }: {
Ich ermächtige den BMP e.V., Zahlungen von meinem Konto mittels Lastschrift einzuziehen. Zugleich weise ich mein Kreditinstitut an, die vom BMP e.V. auf mein Konto gezogenen Lastschriften einzulösen. Hinweis: Ich kann innerhalb von acht Wochen, beginnend mit dem Belastungsdatum, die Erstattung des belasteten Betrages verlangen. Es gelten dabei die mit meinem Kreditinstitut vereinbarten Bedingungen. Die Mandatsreferenz wird separat mitgeteilt. Gläubiger-Identifikationsnummer: DE98ZZZ09999999999. Ich ermächtige den BMP e.V., Zahlungen von meinem Konto mittels Lastschrift einzuziehen. Zugleich weise ich mein Kreditinstitut an, die vom BMP e.V. auf mein Konto gezogenen Lastschriften einzulösen. Hinweis: Ich kann innerhalb von acht Wochen, beginnend mit dem Belastungsdatum, die Erstattung des belasteten Betrages verlangen. Es gelten dabei die mit meinem Kreditinstitut vereinbarten Bedingungen. Die Mandatsreferenz wird separat mitgeteilt. Gläubiger-Identifikationsnummer: DE98ZZZ09999999999.
</div> </div>
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "0 16px" }}> <div style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr" : "1fr 1fr", gap: "0 16px" }}>
<div style={{ gridColumn: "1 / -1" }}> <div style={{ gridColumn: "1 / -1" }}>
<Field label="Kontoinhaber" required error={errors.kontoinhaber}> <Field label="Kontoinhaber" required error={errors.kontoinhaber}>
<Input value={data.kontoinhaber} onChange={(v) => onChange("kontoinhaber", v)} placeholder="Max Mustermann" error={errors.kontoinhaber} /> <Input value={data.kontoinhaber} onChange={(v) => onChange("kontoinhaber", v)} placeholder="Max Mustermann" error={errors.kontoinhaber} />
@@ -1084,6 +1121,7 @@ function SuccessScreen() {
// ─── MAIN COMPONENT ─────────────────────────────────────────────────────────── // ─── MAIN COMPONENT ───────────────────────────────────────────────────────────
function MembershipWizard() { function MembershipWizard() {
const isMobile = useIsMobile();
const [step, setStep] = useState(1); const [step, setStep] = useState(1);
const [submitted, setSubmitted] = useState(false); const [submitted, setSubmitted] = useState(false);
const [errors, setErrors] = useState<Errors>({}); const [errors, setErrors] = useState<Errors>({});
@@ -1162,7 +1200,7 @@ function MembershipWizard() {
backdropFilter: "blur(8px)", backdropFilter: "blur(8px)",
borderRadius: 16, borderRadius: 16,
border: "1px solid rgba(255,255,255,0.08)", border: "1px solid rgba(255,255,255,0.08)",
padding: "32px 28px", padding: isMobile ? "20px 16px" : "32px 28px",
color: WHITE, color: WHITE,
fontFamily: '"IBM Plex Sans", sans-serif', fontFamily: '"IBM Plex Sans", sans-serif',
boxShadow: "0 24px 64px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.06)", boxShadow: "0 24px 64px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.06)",
@@ -1191,7 +1229,7 @@ function MembershipWizard() {
<> <>
<ProgressBar current={step} total={STEPS.length} /> <ProgressBar current={step} total={STEPS.length} />
<div ref={contentRef} style={{ minHeight: 380 }}> <div ref={contentRef} style={{ minHeight: isMobile ? 300 : 380 }}>
{step === 1 && <Step1 data={data} onChange={onChange} errors={errors} />} {step === 1 && <Step1 data={data} onChange={onChange} errors={errors} />}
{step === 2 && <Step2 data={data} onChange={onChange} errors={errors} />} {step === 2 && <Step2 data={data} onChange={onChange} errors={errors} />}
{step === 3 && <Step3 data={data} onChange={onChange} errors={errors} />} {step === 3 && <Step3 data={data} onChange={onChange} errors={errors} />}

View File

@@ -24,10 +24,10 @@ const buttonVariants = cva(
"bg-accent text-accent-foreground shadow-xs hover:bg-accent/90", "bg-accent text-accent-foreground shadow-xs hover:bg-accent/90",
}, },
size: { size: {
default: "h-9 px-4 py-2 has-[>svg]:px-3", default: "h-9 px-4 py-2 has-[>svg]:px-3 max-md:min-h-11",
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5 max-md:min-h-11",
lg: "h-10 rounded-md px-6 has-[>svg]:px-4", lg: "h-10 rounded-md px-6 has-[>svg]:px-4 max-md:min-h-11",
icon: "size-9", icon: "size-9 max-md:min-h-11 max-md:min-w-11",
}, },
}, },
defaultVariants: { defaultVariants: {

View File

@@ -9,7 +9,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
<input <input
type={type} type={type}
className={cn( className={cn(
"flex h-11 w-full border border-stone-200 bg-white px-4 py-2 text-sm text-[#101828] placeholder:text-stone-400 focus:outline-none focus:ring-2 focus:ring-[#EFBF04] focus:border-transparent disabled:cursor-not-allowed disabled:opacity-50 transition-all", "flex h-11 w-full border border-stone-200 bg-white px-4 py-2 text-base md:text-sm text-[#101828] placeholder:text-stone-400 focus:outline-none focus:ring-2 focus:ring-[#EFBF04] focus:border-transparent disabled:cursor-not-allowed disabled:opacity-50 transition-all",
className className
)} )}
ref={ref} ref={ref}

View File

@@ -8,7 +8,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
return ( return (
<textarea <textarea
className={cn( className={cn(
"flex min-h-[100px] w-full border border-stone-200 bg-white px-4 py-3 text-sm text-[#101828] placeholder:text-stone-400 focus:outline-none focus:ring-2 focus:ring-[#EFBF04] focus:border-transparent disabled:cursor-not-allowed disabled:opacity-50 transition-all resize-none", "flex min-h-[100px] w-full border border-stone-200 bg-white px-4 py-3 text-base md:text-sm text-[#101828] placeholder:text-stone-400 focus:outline-none focus:ring-2 focus:ring-[#EFBF04] focus:border-transparent disabled:cursor-not-allowed disabled:opacity-50 transition-all resize-none",
className className
)} )}
ref={ref} ref={ref}

View File

@@ -115,11 +115,11 @@ const About: React.FC = () => {
</div> </div>
{/* Right — full-bleed image */} {/* Right — full-bleed image */}
<div style={{ position: 'relative', overflow: 'hidden' }}> <div style={{ position: 'relative', overflow: 'hidden', minHeight: isMobile ? 220 : undefined }}>
<img <img
src="/images/preistraeger-gruppe.jpg" src="/images/preistraeger-gruppe.jpg"
alt="BMP Gala Preisverleihung" alt="BMP Gala Preisverleihung"
style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center', display: 'block' }} style={{ position: isMobile ? 'relative' : 'absolute', inset: 0, width: '100%', height: isMobile ? 220 : '100%', objectFit: 'cover', objectPosition: 'center', display: 'block' }}
/> />
<div style={{ position: 'absolute', inset: 0, background: `linear-gradient(to right, ${CREAM} 0%, transparent 25%), linear-gradient(to top, rgba(3,9,58,0.75) 0%, transparent 60%)` }} /> <div style={{ position: 'absolute', inset: 0, background: `linear-gradient(to right, ${CREAM} 0%, transparent 25%), linear-gradient(to top, rgba(3,9,58,0.75) 0%, transparent 60%)` }} />
<div style={{ position: 'absolute', bottom: 36, left: 36 }}> <div style={{ position: 'absolute', bottom: 36, left: 36 }}>
@@ -423,6 +423,7 @@ function HighlightCard({ winner }: { winner: import('@/data/winners').Winner })
function GoalItem({ n, text, sub, last }: { n: string; text: string; sub?: string; last: boolean }) { function GoalItem({ n, text, sub, last }: { n: string; text: string; sub?: string; last: boolean }) {
const [hovered, setHovered] = useState(false); const [hovered, setHovered] = useState(false);
const isMobile = useIsMobile();
return ( return (
<div <div
style={{ display: 'grid', gridTemplateColumns: '36px 1fr', gap: '0 16px', padding: '16px 0', borderBottom: last ? 'none' : '1px solid rgba(255,255,255,0.07)', cursor: 'default', transition: 'background 0.15s', alignItems: 'center' }} style={{ display: 'grid', gridTemplateColumns: '36px 1fr', gap: '0 16px', padding: '16px 0', borderBottom: last ? 'none' : '1px solid rgba(255,255,255,0.07)', cursor: 'default', transition: 'background 0.15s', alignItems: 'center' }}
@@ -430,9 +431,9 @@ function GoalItem({ n, text, sub, last }: { n: string; text: string; sub?: strin
onMouseLeave={() => setHovered(false)} onMouseLeave={() => setHovered(false)}
> >
<span style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, color: hovered ? GOLD : 'rgba(239,191,4,0.45)', letterSpacing: '0.1em', transition: 'color 0.2s' }}>{n}</span> <span style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, color: hovered ? GOLD : 'rgba(239,191,4,0.45)', letterSpacing: '0.1em', transition: 'color 0.2s' }}>{n}</span>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 12 }}> <div style={{ display: 'flex', flexDirection: isMobile ? 'column' : 'row', justifyContent: 'space-between', alignItems: isMobile ? 'flex-start' : 'baseline', gap: isMobile ? 3 : 12 }}>
<span style={{ fontFamily: FF, fontSize: 15, fontWeight: 700, color: hovered ? '#fff' : 'rgba(255,255,255,0.75)', textTransform: 'uppercase', letterSpacing: '0.08em', transition: 'color 0.2s' }}>{text}</span> <span style={{ fontFamily: FF, fontSize: 15, fontWeight: 700, color: hovered ? '#fff' : 'rgba(255,255,255,0.75)', textTransform: 'uppercase', letterSpacing: '0.08em', transition: 'color 0.2s' }}>{text}</span>
{sub && <span style={{ fontFamily: FB, fontSize: 15, color: 'rgba(255,255,255,0.3)', flexShrink: 0 }}>{sub}</span>} {sub && <span style={{ fontFamily: FB, fontSize: 15, color: 'rgba(255,255,255,0.3)', flexShrink: isMobile ? 1 : 0 }}>{sub}</span>}
</div> </div>
</div> </div>
); );

View File

@@ -42,7 +42,7 @@ export default function BlogDetail() {
<div> <div>
{/* ── HERO ──────────────────────────────────────────────────────────── */} {/* ── HERO ──────────────────────────────────────────────────────────── */}
<section style={{ position: 'relative', height: '70vh', minHeight: 520, overflow: 'hidden', display: 'flex', alignItems: 'flex-end' }}> <section style={{ position: 'relative', height: isMobile ? 'auto' : '70vh', minHeight: 520, overflow: 'hidden', display: 'flex', alignItems: 'flex-end' }}>
<img <img
src={article.img} src={article.img}
alt={article.title} alt={article.title}

View File

@@ -113,7 +113,7 @@ const Contact: React.FC = () => {
{!isMobile && <div style={{ background: 'rgba(255,255,255,0.07)' }} />} {!isMobile && <div style={{ background: 'rgba(255,255,255,0.07)' }} />}
{/* Right — gold form panel */} {/* Right — gold form panel */}
<div style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden', minHeight: 0, position: 'relative', background: 'linear-gradient(160deg,#DDB84A 0%,#C9A227 52%,#A87800 100%)' }}> <div style={{ display: 'flex', flexDirection: 'column', overflow: isMobile ? 'visible' : 'hidden', height: isMobile ? 'auto' : undefined, 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"> <svg style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', pointerEvents: 'none', zIndex: 0 }} aria-hidden="true">
<defs> <defs>
<pattern id="kontaktCross" width="18" height="18" patternUnits="userSpaceOnUse"> <pattern id="kontaktCross" width="18" height="18" patternUnits="userSpaceOnUse">
@@ -139,7 +139,7 @@ const Contact: React.FC = () => {
</div> </div>
</div> </div>
)} )}
<div style={{ padding: isMobile ? '40px 24px' : '32px 48px 32px 40px', flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0, position: 'relative', zIndex: 1 }}> <div style={{ padding: isMobile ? '36px 20px' : '32px 48px 32px 40px', flex: isMobile ? 'none' : 1, display: 'flex', flexDirection: 'column', minHeight: isMobile ? 480 : 0, position: 'relative', zIndex: 1 }}>
<span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 10, color: 'rgba(17,29,85,0.5)', textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, display: 'block', marginBottom: 8 }}>Kontaktformular</span> <span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 10, color: 'rgba(17,29,85,0.5)', textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, display: 'block', marginBottom: 8 }}>Kontaktformular</span>
<h3 style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 'clamp(1.2rem, 1.8vw, 1.6rem)', fontWeight: 900, color: '#111D55', letterSpacing: '-0.025em', textTransform: 'uppercase', lineHeight: 1.1, marginBottom: 24 }}> <h3 style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 'clamp(1.2rem, 1.8vw, 1.6rem)', fontWeight: 900, color: '#111D55', letterSpacing: '-0.025em', textTransform: 'uppercase', lineHeight: 1.1, marginBottom: 24 }}>
Schreiben Sie uns Schreiben Sie uns

View File

@@ -221,6 +221,7 @@ const body: React.CSSProperties = {
color: 'rgba(58,58,58,0.82)', color: 'rgba(58,58,58,0.82)',
lineHeight: 1.85, lineHeight: 1.85,
margin: '0 0 16px', margin: '0 0 16px',
overflowWrap: 'anywhere',
}; };
function Section({ id, title, children }: { id: string; title: string; children: React.ReactNode }) { function Section({ id, title, children }: { id: string; title: string; children: React.ReactNode }) {
@@ -231,7 +232,7 @@ function Section({ id, title, children }: { id: string; title: string; children:
{title} {title}
</h2> </h2>
</div> </div>
<div style={{ background: '#fff', padding: '28px 32px', boxShadow: '0 1px 3px rgba(0,0,0,0.06)' }}> <div style={{ background: '#fff', padding: 'clamp(20px, 5vw, 28px) clamp(20px, 5vw, 32px)', boxShadow: '0 1px 3px rgba(0,0,0,0.06)' }}>
{children} {children}
</div> </div>
</div> </div>
@@ -251,16 +252,18 @@ function SubSection({ num, title, children }: { num: string; title: string; chil
} }
function AddressBlock({ children }: { children: React.ReactNode }) { function AddressBlock({ children }: { children: React.ReactNode }) {
const isMobile = useIsMobile();
return ( return (
<address style={{ fontFamily: '"Inter", sans-serif', fontSize: 14, color: 'rgba(58,58,58,0.75)', lineHeight: 1.9, fontStyle: 'normal', background: 'rgba(17,29,85,0.04)', padding: '16px 20px', borderLeft: '2px solid rgba(239,191,4,0.4)', marginBottom: 16 }}> <address style={{ fontFamily: '"Inter", sans-serif', fontSize: isMobile ? 15 : 14, color: 'rgba(58,58,58,0.75)', lineHeight: 1.9, fontStyle: 'normal', background: 'rgba(17,29,85,0.04)', padding: '16px 20px', borderLeft: '2px solid rgba(239,191,4,0.4)', marginBottom: 16, overflowWrap: 'anywhere' }}>
{children} {children}
</address> </address>
); );
} }
function Legal({ children }: { children: React.ReactNode }) { function Legal({ children }: { children: React.ReactNode }) {
const isMobile = useIsMobile();
return ( return (
<p style={{ fontFamily: '"Inter", sans-serif', fontSize: 14, color: NAVY, lineHeight: 1.75, background: 'rgba(17,29,85,0.04)', padding: '12px 16px', borderLeft: `3px solid ${NAVY}`, margin: '0 0 16px', fontWeight: 500 }}> <p style={{ fontFamily: '"Inter", sans-serif', fontSize: isMobile ? 15 : 14, color: NAVY, lineHeight: 1.75, background: 'rgba(17,29,85,0.04)', padding: '12px 16px', borderLeft: `3px solid ${NAVY}`, margin: '0 0 16px', fontWeight: 500, overflowWrap: 'anywhere' }}>
{children} {children}
</p> </p>
); );

View File

@@ -97,7 +97,7 @@ export default function EventDetail() {
<div style={{ paddingTop: 60, background: CREAM, minHeight: '100vh', fontFamily: '"Inter", sans-serif' }}> <div style={{ paddingTop: 60, background: CREAM, minHeight: '100vh', fontFamily: '"Inter", sans-serif' }}>
{/* ── Hero ─────────────────────────────────────────────────────────── */} {/* ── Hero ─────────────────────────────────────────────────────────── */}
<section style={{ position: 'relative', height: '65vh', minHeight: 480, overflow: 'hidden' }}> <section style={{ position: 'relative', height: isMobile ? 'auto' : '65vh', minHeight: isMobile ? 520 : 480, overflow: 'hidden' }}>
<img <img
src={event.img} src={event.img}
alt={event.title} alt={event.title}
@@ -116,7 +116,7 @@ export default function EventDetail() {
</div> </div>
{/* Hero content */} {/* Hero content */}
<div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, padding: isMobile ? '0 24px 48px' : '40px 80px', zIndex: 10, display: 'flex', flexDirection: isMobile ? 'column' : 'row', justifyContent: 'space-between', alignItems: isMobile ? 'flex-start' : 'flex-end', gap: isMobile ? 20 : 40 }}> <div style={{ position: isMobile ? 'relative' : 'absolute', bottom: 0, left: 0, right: 0, padding: isMobile ? '88px 24px 48px' : '40px 80px', zIndex: 10, display: 'flex', flexDirection: isMobile ? 'column' : 'row', justifyContent: isMobile ? 'flex-end' : 'space-between', alignItems: isMobile ? 'flex-start' : 'flex-end', gap: isMobile ? 20 : 40, minHeight: isMobile ? 520 : undefined, boxSizing: 'border-box' }}>
{/* Left */} {/* Left */}
<div style={{ flex: 1 }}> <div style={{ flex: 1 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 14, flexWrap: 'wrap' }}> <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 14, flexWrap: 'wrap' }}>
@@ -136,15 +136,15 @@ export default function EventDetail() {
</div> </div>
{/* Right — key facts */} {/* Right — key facts */}
<div style={{ display: 'flex', flexDirection: isMobile ? 'row' : 'column', flexWrap: isMobile ? 'wrap' : undefined, gap: 12, flexShrink: 0, background: 'rgba(3,9,58,0.55)', backdropFilter: 'blur(12px)', borderRadius: 16, padding: isMobile ? '16px 20px' : '24px 28px', border: '1px solid rgba(255,255,255,0.1)', width: isMobile ? '100%' : undefined }}> <div style={{ display: 'flex', flexDirection: 'column', gap: 12, flexShrink: 0, background: 'rgba(3,9,58,0.55)', backdropFilter: 'blur(12px)', borderRadius: 16, padding: isMobile ? '16px 20px' : '24px 28px', border: '1px solid rgba(255,255,255,0.1)', width: isMobile ? '100%' : undefined, boxSizing: 'border-box' }}>
{[ {[
{ icon: Calendar, label: event.date }, { icon: Calendar, label: event.date },
{ icon: Clock, label: event.time }, { icon: Clock, label: event.time },
{ icon: MapPin, label: `${event.venue}, ${event.location}` }, { icon: MapPin, label: `${event.venue}, ${event.location}` },
].map(({ icon: Icon, label }, i) => ( ].map(({ icon: Icon, label }, i) => (
<div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10, minWidth: isMobile ? 'auto' : undefined }}> <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10, minWidth: 0 }}>
<Icon size={15} color={GOLD} /> <Icon size={15} color={GOLD} style={{ flexShrink: 0 }} />
<span style={{ fontSize: 14, color: '#fff', fontWeight: 500 }}>{label}</span> <span style={{ fontSize: 14, color: '#fff', fontWeight: 500, overflowWrap: 'anywhere' }}>{label}</span>
</div> </div>
))} ))}
</div> </div>
@@ -180,7 +180,13 @@ export default function EventDetail() {
<div key={i} style={{ <div key={i} style={{
padding: '20px 24px', padding: '20px 24px',
background: i % 2 === 0 ? '#fff' : 'rgba(255,255,255,0.6)', background: i % 2 === 0 ? '#fff' : 'rgba(255,255,255,0.6)',
borderRadius: i === 0 ? '12px 0 0 0' : i === 1 ? '0 12px 0 0' : i === event.eckdaten.length - 2 ? '0 0 0 12px' : i === event.eckdaten.length - 1 ? '0 0 12px 0' : '0', borderRadius: isMobile
? (i === 0
? '12px 12px 0 0'
: i === event.eckdaten.length - 1
? '0 0 12px 12px'
: '0')
: (i === 0 ? '12px 0 0 0' : i === 1 ? '0 12px 0 0' : i === event.eckdaten.length - 2 ? '0 0 0 12px' : i === event.eckdaten.length - 1 ? '0 0 12px 0' : '0'),
border: '1px solid rgba(3,9,58,0.06)', border: '1px solid rgba(3,9,58,0.06)',
}}> }}>
<div style={{ fontSize: 10, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.12em', color: 'rgba(58,58,58,0.4)', marginBottom: 6 }}> <div style={{ fontSize: 10, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.12em', color: 'rgba(58,58,58,0.4)', marginBottom: 6 }}>
@@ -195,7 +201,7 @@ export default function EventDetail() {
</div> </div>
{/* CTA */} {/* CTA */}
<div style={{ marginTop: 40, display: 'flex', gap: 12 }}> <div style={{ marginTop: 40, display: 'flex', gap: 12, flexWrap: 'wrap' }}>
{event.status === 'anmeldung-offen' && ( {event.status === 'anmeldung-offen' && (
<Link to="/teilnahme" style={{ <Link to="/teilnahme" style={{
display: 'inline-flex', alignItems: 'center', gap: 8, display: 'inline-flex', alignItems: 'center', gap: 8,
@@ -258,7 +264,7 @@ export default function EventDetail() {
)} )}
{/* Timeline */} {/* Timeline */}
<div style={{ maxHeight: 560, overflowY: 'auto', paddingRight: 4 }}> <div style={{ maxHeight: isMobile ? 'none' : 560, overflowY: isMobile ? 'visible' : 'auto', paddingRight: 4 }}>
{event.updates.map((update, i) => ( {event.updates.map((update, i) => (
<UpdateCard key={update.id} update={update} index={i} /> <UpdateCard key={update.id} update={update} index={i} />
))} ))}

View File

@@ -193,8 +193,8 @@ export default function FormularUpload() {
<span style={{ fontFamily: FF, fontSize: 11, color: 'rgba(255,255,255,0.3)' }}>{formatBytes(f.size)}</span> <span style={{ fontFamily: FF, fontSize: 11, color: 'rgba(255,255,255,0.3)' }}>{formatBytes(f.size)}</span>
{f.status === 'uploading' && <div style={{ width: 14, height: 14, border: '2px solid rgba(255,255,255,0.2)', borderTopColor: GOLD, borderRadius: '50%', animation: 'spin 0.8s linear infinite' }} />} {f.status === 'uploading' && <div style={{ width: 14, height: 14, border: '2px solid rgba(255,255,255,0.2)', borderTopColor: GOLD, borderRadius: '50%', animation: 'spin 0.8s linear infinite' }} />}
{f.status !== 'uploading' && f.status !== 'done' && ( {f.status !== 'uploading' && f.status !== 'done' && (
<button onClick={() => remove(i)} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'rgba(255,255,255,0.3)', padding: 0, display: 'flex' }}> <button onClick={() => remove(i)} aria-label="Datei entfernen" style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'rgba(255,255,255,0.3)', padding: isMobile ? 12 : 0, margin: isMobile ? -12 : 0, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<X size={14} /> <X size={isMobile ? 18 : 14} />
</button> </button>
)} )}
</div> </div>

View File

@@ -398,7 +398,7 @@ const Home: React.FC = () => {
{/* Subtle radial glow behind left copy */} {/* Subtle radial glow behind left copy */}
<div style={{ position: 'absolute', left: -120, top: '50%', transform: 'translateY(-50%)', width: 600, height: 600, borderRadius: '50%', background: 'radial-gradient(circle, rgba(5,26,135,0.35) 0%, transparent 70%)', pointerEvents: 'none' }} /> <div style={{ position: 'absolute', left: -120, top: '50%', transform: 'translateY(-50%)', width: 600, height: 600, borderRadius: '50%', background: 'radial-gradient(circle, rgba(5,26,135,0.35) 0%, transparent 70%)', pointerEvents: 'none' }} />
<div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '4fr 1px 8fr', position: 'relative', flex: 1, minHeight: 0, overflow: 'hidden' }}> <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '4fr 1px 8fr', position: 'relative', flex: isMobile ? 'none' : 1, minHeight: 0, overflow: 'hidden' }}>
{/* Left — pitch copy */} {/* Left — pitch copy */}
<div style={{ padding: isMobile ? '32px 24px 24px' : '36px 36px 32px 52px', display: 'flex', flexDirection: 'column', justifyContent: 'center', overflow: 'hidden' }}> <div style={{ padding: isMobile ? '32px 24px 24px' : '36px 36px 32px 52px', display: 'flex', flexDirection: 'column', justifyContent: 'center', overflow: 'hidden' }}>
@@ -473,7 +473,7 @@ const Home: React.FC = () => {
)} )}
{/* Form area */} {/* Form area */}
<div style={{ padding: isMobile ? '32px 24px' : '24px 48px 32px 40px', flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0, position: 'relative', zIndex: 1 }}> <div style={{ padding: isMobile ? '32px 24px' : '24px 48px 32px 40px', flex: isMobile ? 'none' : 1, height: isMobile ? '82svh' : undefined, display: 'flex', flexDirection: 'column', minHeight: 0, position: 'relative', zIndex: 1 }}>
<span style={{ fontFamily: FF, fontSize: 10, color: 'rgba(17,29,85,0.5)', textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, display: 'block', marginBottom: 8 }}>Direktbewerbung 2026</span> <span style={{ fontFamily: FF, fontSize: 10, color: 'rgba(17,29,85,0.5)', textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, display: 'block', marginBottom: 8 }}>Direktbewerbung 2026</span>
<h3 style={{ fontFamily: FF, fontSize: 'clamp(1.2rem, 1.8vw, 1.6rem)', fontWeight: 900, color: '#111D55', textTransform: 'uppercase', letterSpacing: '-0.02em', lineHeight: 1.1, marginBottom: 24 }}>Kostenlos bewerben</h3> <h3 style={{ fontFamily: FF, fontSize: 'clamp(1.2rem, 1.8vw, 1.6rem)', fontWeight: 900, color: '#111D55', textTransform: 'uppercase', letterSpacing: '-0.02em', lineHeight: 1.1, marginBottom: 24 }}>Kostenlos bewerben</h3>
<BewerbungsForm theme="gold" /> <BewerbungsForm theme="gold" />
@@ -483,8 +483,8 @@ const Home: React.FC = () => {
</div> </div>
{/* Footnote row */} {/* Footnote row */}
<div style={{ position: 'relative', zIndex: 1, padding: '14px 56px 18px', display: 'flex', justifyContent: 'center', borderTop: '1px solid rgba(255,255,255,0.06)', flexShrink: 0 }}> <div style={{ position: 'relative', zIndex: 1, padding: isMobile ? '16px 24px 20px' : '14px 56px 18px', display: 'flex', flexWrap: 'wrap', justifyContent: 'center', textAlign: 'center', borderTop: '1px solid rgba(255,255,255,0.06)', flexShrink: 0 }}>
<span style={{ fontFamily: FF, fontSize: 15, color: 'rgba(255,255,255,0.45)', marginRight: 10 }}>Kostenlos und unverbindlich —</span> <span style={{ fontFamily: FF, fontSize: 15, color: 'rgba(255,255,255,0.45)', marginRight: isMobile ? 6 : 10 }}>Kostenlos und unverbindlich —</span>
<span style={{ fontFamily: FF, fontSize: 15, fontWeight: 700, color: 'rgba(239,191,4,0.8)' }}>keine Teilnahmegebühr</span> <span style={{ fontFamily: FF, fontSize: 15, fontWeight: 700, color: 'rgba(239,191,4,0.8)' }}>keine Teilnahmegebühr</span>
</div> </div>
<div style={{ height: 2, background: 'linear-gradient(to right, #EFBF04, rgba(239,191,4,0.25), transparent)', flexShrink: 0 }} /> <div style={{ height: 2, background: 'linear-gradient(to right, #EFBF04, rgba(239,191,4,0.25), transparent)', flexShrink: 0 }} />

View File

@@ -216,6 +216,7 @@ const body: React.CSSProperties = {
color: 'rgba(58,58,58,0.82)', color: 'rgba(58,58,58,0.82)',
lineHeight: 1.85, lineHeight: 1.85,
margin: '0 0 16px', margin: '0 0 16px',
overflowWrap: 'anywhere',
}; };
function Section({ id, title, children }: { id: string; title: string; children: React.ReactNode }) { function Section({ id, title, children }: { id: string; title: string; children: React.ReactNode }) {
@@ -226,7 +227,7 @@ function Section({ id, title, children }: { id: string; title: string; children:
{title} {title}
</h2> </h2>
</div> </div>
<div style={{ background: '#fff', padding: '28px 32px', boxShadow: '0 1px 3px rgba(0,0,0,0.06)' }}> <div style={{ background: '#fff', padding: 'clamp(20px, 5vw, 28px) clamp(20px, 5vw, 32px)', boxShadow: '0 1px 3px rgba(0,0,0,0.06)' }}>
{children} {children}
</div> </div>
</div> </div>
@@ -246,16 +247,18 @@ function SubSection({ num, title, children }: { num: string; title: string; chil
} }
function AddressBlock({ children }: { children: React.ReactNode }) { function AddressBlock({ children }: { children: React.ReactNode }) {
const isMobile = useIsMobile();
return ( return (
<address style={{ fontFamily: '"Inter", sans-serif', fontSize: 14, color: 'rgba(58,58,58,0.75)', lineHeight: 1.9, fontStyle: 'normal', background: 'rgba(17,29,85,0.04)', padding: '16px 20px', borderLeft: '2px solid rgba(239,191,4,0.4)', marginBottom: 16 }}> <address style={{ fontFamily: '"Inter", sans-serif', fontSize: isMobile ? 15 : 14, color: 'rgba(58,58,58,0.75)', lineHeight: 1.9, fontStyle: 'normal', background: 'rgba(17,29,85,0.04)', padding: '16px 20px', borderLeft: '2px solid rgba(239,191,4,0.4)', marginBottom: 16, overflowWrap: 'anywhere' }}>
{children} {children}
</address> </address>
); );
} }
function Legal({ children }: { children: React.ReactNode }) { function Legal({ children }: { children: React.ReactNode }) {
const isMobile = useIsMobile();
return ( return (
<p style={{ fontFamily: '"Inter", sans-serif', fontSize: 14, color: NAVY, lineHeight: 1.75, background: 'rgba(17,29,85,0.04)', padding: '12px 16px', borderLeft: `3px solid ${NAVY}`, margin: '0 0 16px', fontWeight: 500 }}> <p style={{ fontFamily: '"Inter", sans-serif', fontSize: isMobile ? 15 : 14, color: NAVY, lineHeight: 1.75, background: 'rgba(17,29,85,0.04)', padding: '12px 16px', borderLeft: `3px solid ${NAVY}`, margin: '0 0 16px', fontWeight: 500, overflowWrap: 'anywhere' }}>
{children} {children}
</p> </p>
); );

View File

@@ -240,20 +240,20 @@ function BeitragsrechnerSection({ isMobile }: { isMobile: boolean }) {
</button> </button>
{tableOpen && ( {tableOpen && (
<div style={{ background: '#fff', border: '1px solid rgba(16,24,40,0.12)', borderTop: 'none', borderRadius: '0 0 8px 8px', overflow: 'hidden' }}> <div style={{ background: '#fff', border: '1px solid rgba(16,24,40,0.12)', borderTop: 'none', borderRadius: '0 0 8px 8px', overflow: 'hidden' }}>
<table style={{ width: '100%', borderCollapse: 'collapse', fontFamily: FF }}> <table style={{ width: '100%', borderCollapse: 'collapse', fontFamily: FF, tableLayout: isMobile ? 'fixed' : 'auto' }}>
<thead> <thead>
<tr style={{ background: NAVY }}> <tr style={{ background: NAVY }}>
<th style={{ padding: '12px 18px', textAlign: 'left', fontSize: 10, fontWeight: 700, letterSpacing: '0.15em', textTransform: 'uppercase', color: GOLD }}>Mitarbeiter</th> <th style={{ padding: isMobile ? '10px 10px' : '12px 18px', textAlign: 'left', fontSize: 10, fontWeight: 700, letterSpacing: '0.15em', textTransform: 'uppercase', color: GOLD }}>Mitarbeiter</th>
<th style={{ padding: '12px 18px', textAlign: 'right', fontSize: 10, fontWeight: 700, letterSpacing: '0.15em', textTransform: 'uppercase', color: GOLD }}>Netto / Jahr</th> <th style={{ padding: isMobile ? '10px 10px' : '12px 18px', textAlign: 'right', fontSize: 10, fontWeight: 700, letterSpacing: '0.15em', textTransform: 'uppercase', color: GOLD }}>Netto / Jahr</th>
<th style={{ padding: '12px 18px', textAlign: 'right', fontSize: 10, fontWeight: 700, letterSpacing: '0.15em', textTransform: 'uppercase', color: GOLD }}>Brutto / Jahr</th> <th style={{ padding: isMobile ? '10px 10px' : '12px 18px', textAlign: 'right', fontSize: 10, fontWeight: 700, letterSpacing: '0.15em', textTransform: 'uppercase', color: GOLD }}>Brutto / Jahr</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{BEITRAGS_TIERS.map((t, i) => ( {BEITRAGS_TIERS.map((t, i) => (
<tr key={t.label} style={{ background: i % 2 === 0 ? 'rgba(239,191,4,0.04)' : '#fff', borderBottom: '1px solid rgba(16,24,40,0.06)' }}> <tr key={t.label} style={{ background: i % 2 === 0 ? 'rgba(239,191,4,0.04)' : '#fff', borderBottom: '1px solid rgba(16,24,40,0.06)' }}>
<td style={{ padding: '12px 18px', fontSize: 14, color: '#101828', fontWeight: selected === t.label ? 700 : 400 }}>{t.label}</td> <td style={{ padding: isMobile ? '10px 10px' : '12px 18px', fontSize: isMobile ? 13 : 14, color: '#101828', fontWeight: selected === t.label ? 700 : 400 }}>{t.label}</td>
<td style={{ padding: '12px 18px', fontSize: 14, textAlign: 'right', color: 'rgba(16,24,40,0.6)' }}>{formatEurLocal(t.annual)}</td> <td style={{ padding: isMobile ? '10px 10px' : '12px 18px', fontSize: isMobile ? 13 : 14, textAlign: 'right', color: 'rgba(16,24,40,0.6)' }}>{formatEurLocal(t.annual)}</td>
<td style={{ padding: '12px 18px', fontSize: 14, textAlign: 'right', fontWeight: 600, color: selected === t.label ? NAVY : '#101828' }}>{formatEurLocal(t.annual * (1 + BEITRAGS_VAT))}</td> <td style={{ padding: isMobile ? '10px 10px' : '12px 18px', fontSize: isMobile ? 13 : 14, textAlign: 'right', fontWeight: 600, color: selected === t.label ? NAVY : '#101828' }}>{formatEurLocal(t.annual * (1 + BEITRAGS_VAT))}</td>
</tr> </tr>
))} ))}
</tbody> </tbody>
@@ -745,7 +745,7 @@ const MitgliedWerden: React.FC = () => {
<h1 <h1
style={{ style={{
fontFamily: FF, fontFamily: FF,
fontSize: 'clamp(2.8rem, 6vw, 5rem)', fontSize: isMobile ? 'clamp(2rem, 9vw, 2.6rem)' : 'clamp(2.8rem, 6vw, 5rem)',
fontWeight: 900, fontWeight: 900,
color: '#fff', color: '#fff',
textTransform: 'uppercase', textTransform: 'uppercase',
@@ -1157,7 +1157,7 @@ const MitgliedWerden: React.FC = () => {
gridTemplateColumns: isMobile ? '1fr' : '4fr 1px 8fr', gridTemplateColumns: isMobile ? '1fr' : '4fr 1px 8fr',
flex: 1, flex: 1,
minHeight: 0, minHeight: 0,
overflow: 'hidden', overflow: isMobile ? 'visible' : 'hidden',
}} }}
> >
{/* Left — pitch */} {/* Left — pitch */}
@@ -1167,7 +1167,7 @@ const MitgliedWerden: React.FC = () => {
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
justifyContent: 'center', justifyContent: 'center',
overflow: 'hidden', overflow: isMobile ? 'visible' : 'hidden',
}} }}
> >
<span <span
@@ -1255,8 +1255,10 @@ const MitgliedWerden: React.FC = () => {
<div <div
style={{ style={{
display: 'flex', display: 'flex',
flexDirection: isMobile ? 'column' : 'row',
justifyContent: 'space-between', justifyContent: 'space-between',
alignItems: 'baseline', alignItems: isMobile ? 'flex-start' : 'baseline',
gap: isMobile ? 4 : 0,
}} }}
> >
<span <span
@@ -1274,7 +1276,7 @@ const MitgliedWerden: React.FC = () => {
<span <span
style={{ style={{
fontFamily: FB, fontFamily: FB,
fontSize: 17, fontSize: isMobile ? 15 : 17,
color: 'rgba(255,255,255,0.3)', color: 'rgba(255,255,255,0.3)',
}} }}
> >
@@ -1295,7 +1297,7 @@ const MitgliedWerden: React.FC = () => {
/> />
{/* Right — wizard */} {/* Right — wizard */}
<div style={{ display: 'flex', flexDirection: 'column', background: 'rgba(0,0,0,0.18)', overflowY: 'auto', minHeight: 0 }}> <div style={{ display: 'flex', flexDirection: 'column', background: 'rgba(0,0,0,0.18)', overflowY: isMobile ? 'visible' : 'auto', minHeight: 0 }}>
{!isMobile && ( {!isMobile && (
<div style={{ height: 180, position: 'relative', overflow: 'hidden', flexShrink: 0 }}> <div style={{ height: 180, position: 'relative', overflow: 'hidden', flexShrink: 0 }}>
<img src="/images/gewinner-gruppenfoto.jpg" alt="BMP Mitglieder" style={{ width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center 30%' }} /> <img src="/images/gewinner-gruppenfoto.jpg" alt="BMP Mitglieder" style={{ width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center 30%' }} />
@@ -1307,7 +1309,7 @@ const MitgliedWerden: React.FC = () => {
</div> </div>
</div> </div>
)} )}
<div style={{ padding: isMobile ? '24px' : '28px 40px 32px', flex: 1, overflowY: 'auto' }}> <div style={{ padding: isMobile ? '24px' : '28px 40px 32px', flex: 1, overflowY: isMobile ? 'visible' : 'auto' }}>
<MembershipWizard /> <MembershipWizard />
</div> </div>
</div> </div>

View File

@@ -33,9 +33,10 @@ interface PersonCardProps {
function PersonCard({ imgSrc, imgAlt, name, titleLine1, titleLine2, institution, borderRight }: PersonCardProps) { function PersonCard({ imgSrc, imgAlt, name, titleLine1, titleLine2, institution, borderRight }: PersonCardProps) {
const [hovered, setHovered] = useState(false); const [hovered, setHovered] = useState(false);
const isMobileCard = useIsMobile();
return ( return (
<div <div
style={{ borderRight: borderRight ? '1px solid rgba(255,255,255,0.08)' : 'none', display: 'flex', flexDirection: 'column' }} style={{ borderRight: borderRight && !isMobileCard ? '1px solid rgba(255,255,255,0.08)' : 'none', borderBottom: borderRight && isMobileCard ? '1px solid rgba(255,255,255,0.08)' : 'none', display: 'flex', flexDirection: 'column' }}
onMouseEnter={() => setHovered(true)} onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)} onMouseLeave={() => setHovered(false)}
> >
@@ -48,7 +49,7 @@ function PersonCard({ imgSrc, imgAlt, name, titleLine1, titleLine2, institution,
<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', 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 style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: 3, background: GOLD }} />
</div> </div>
<div style={{ padding: '36px 40px', background: NAVY, flex: 1 }}> <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: 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: `${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: 17, fontWeight: 400, color: 'rgba(255,255,255,0.5)', lineHeight: 1.6 }}>{titleLine2}</div>
@@ -69,11 +70,12 @@ interface JuryMember {
const JuryCard: React.FC<{ member: JuryMember; idx: number }> = ({ member, idx }) => { const JuryCard: React.FC<{ member: JuryMember; idx: number }> = ({ member, idx }) => {
const [hovered, setHovered] = useState(false); const [hovered, setHovered] = useState(false);
const isMobileCard = useIsMobile();
return ( return (
<div <div
onMouseEnter={() => setHovered(true)} onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)} onMouseLeave={() => setHovered(false)}
style={{ borderLeft: 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' }} style={{ borderLeft: !isMobileCard && idx > 0 ? '1px solid rgba(255,255,255,0.07)' : 'none', borderTop: 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' }}
> >
<div style={{ position: 'relative', overflow: 'hidden', aspectRatio: '3/4' }}> <div style={{ position: 'relative', overflow: 'hidden', aspectRatio: '3/4' }}>
<img src={member.img} alt={member.name} style={{ width: '100%', height: '100%', objectFit: 'cover', filter: hovered ? 'none' : 'grayscale(100%)', transition: 'filter 0.5s', display: 'block' }} /> <img src={member.img} alt={member.name} style={{ width: '100%', height: '100%', objectFit: 'cover', filter: hovered ? 'none' : 'grayscale(100%)', transition: 'filter 0.5s', display: 'block' }} />
@@ -105,16 +107,17 @@ interface Partner {
linkedin?: string; linkedin?: string;
} }
const PartnerCell: React.FC<{ partner: Partner; idx: number; onClick: () => void }> = ({ partner, idx, onClick }) => { const PartnerCell: React.FC<{ partner: Partner; idx: number; total: number; onClick: () => void }> = ({ partner, idx, total, onClick }) => {
const [hovered, setHovered] = useState(false); const [hovered, setHovered] = useState(false);
const isMobileCell = useIsMobile(); const isMobileCell = useIsMobile();
const borderLeft = isMobileCell ? (idx % 2 === 0 ? 'none' : '1px solid rgba(3,9,58,0.08)') : (idx % 4 === 0 ? 'none' : '1px solid rgba(3,9,58,0.08)'); const borderLeft = isMobileCell ? 'none' : (idx % 4 === 0 ? 'none' : '1px solid rgba(3,9,58,0.08)');
const showBottom = isMobileCell ? idx < total - 1 : idx < 8;
return ( return (
<div <div
onClick={onClick} onClick={onClick}
onMouseEnter={() => setHovered(true)} onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)} onMouseLeave={() => setHovered(false)}
style={{ padding: isMobileCell ? '24px 20px' : '36px 32px', borderLeft, borderBottom: (isMobileCell ? idx < 10 : idx < 8) ? '1px solid rgba(3,9,58,0.08)' : 'none', display: 'flex', flexDirection: 'column', gap: 16, cursor: 'pointer', background: hovered ? '#E8E5E4' : 'transparent', transition: 'background 0.15s' }} style={{ padding: isMobileCell ? '24px 20px' : '36px 32px', borderLeft, borderBottom: showBottom ? '1px solid rgba(3,9,58,0.08)' : 'none', display: 'flex', flexDirection: 'column', gap: 16, cursor: 'pointer', background: hovered ? '#E8E5E4' : 'transparent', transition: 'background 0.15s' }}
> >
<div style={{ height: 48, display: 'flex', alignItems: 'center' }}>{partner.logo}</div> <div style={{ height: 48, display: 'flex', alignItems: 'center' }}>{partner.logo}</div>
<div style={{ width: hovered ? 48 : 20, height: 1, background: GOLD, transition: 'width 0.3s ease' }} /> <div style={{ width: hovered ? 48 : 20, height: 1, background: GOLD, transition: 'width 0.3s ease' }} />
@@ -613,9 +616,9 @@ const Netzwerk: React.FC = () => {
Ein starkes Netzwerk für einen starken Mittelstand. Klicken für Details. Ein starkes Netzwerk für einen starken Mittelstand. Klicken für Details.
</p> </p>
</div> </div>
<div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr 1fr' : 'repeat(4, 1fr)' }}> <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : 'repeat(4, 1fr)' }}>
{partners.map((partner, idx) => ( {partners.map((partner, idx) => (
<PartnerCell key={partner.id} partner={partner} idx={idx} onClick={() => setSelectedPartner(partner)} /> <PartnerCell key={partner.id} partner={partner} idx={idx} total={partners.length} onClick={() => setSelectedPartner(partner)} />
))} ))}
</div> </div>
</section> </section>
@@ -627,9 +630,9 @@ const Netzwerk: React.FC = () => {
height: isMobile ? 'auto' : 'calc(100vh - 60px)', height: isMobile ? 'auto' : 'calc(100vh - 60px)',
display: 'flex', flexDirection: 'column', display: 'flex', flexDirection: 'column',
}}> }}>
<div style={{ flex: 1, position: 'relative', zIndex: 1, display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '4fr 1px 8fr', minHeight: 0, overflow: 'hidden' }}> <div style={{ flex: 1, position: 'relative', zIndex: 1, display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '4fr 1px 8fr', minHeight: 0, overflow: isMobile ? 'visible' : 'hidden' }}>
{/* Left — pitch */} {/* Left — pitch */}
<div style={{ padding: isMobile ? '32px 24px 24px' : '36px 36px 32px 52px', display: 'flex', flexDirection: 'column', justifyContent: 'center', overflow: 'hidden' }}> <div style={{ padding: isMobile ? '32px 24px 24px' : '36px 36px 32px 52px', display: 'flex', flexDirection: 'column', justifyContent: 'center', overflow: isMobile ? 'visible' : 'hidden' }}>
<span style={{ fontFamily: FF, fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, color: GOLD, display: 'block', marginBottom: 8 }}>Wachstum durch Partnerschaft</span> <span style={{ fontFamily: FF, fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, color: GOLD, display: 'block', marginBottom: 8 }}>Wachstum durch Partnerschaft</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' }}>WIR FREUEN UNS ÜBER NEUE SPONSOREN.</h2> <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' }}>WIR FREUEN UNS ÜBER NEUE SPONSOREN.</h2>
<div style={{ width: 36, height: 2, background: GOLD, margin: '0 0 14px', flexShrink: 0 }} /> <div style={{ width: 36, height: 2, background: GOLD, margin: '0 0 14px', flexShrink: 0 }} />
@@ -653,7 +656,7 @@ const Netzwerk: React.FC = () => {
{/* Center divider */} {/* Center divider */}
{!isMobile && <div style={{ background: 'rgba(255,255,255,0.07)' }} />} {!isMobile && <div style={{ background: 'rgba(255,255,255,0.07)' }} />}
{/* Right — gold form panel */} {/* Right — gold form panel */}
<div style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden', minHeight: 0, position: 'relative', background: 'linear-gradient(160deg,#DDB84A 0%,#C9A227 52%,#A87800 100%)' }}> <div style={{ display: 'flex', flexDirection: 'column', overflow: isMobile ? 'visible' : 'hidden', 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"> <svg style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', pointerEvents: 'none', zIndex: 0 }} aria-hidden="true">
<defs> <defs>
<pattern id="sponsoringCross" width="18" height="18" patternUnits="userSpaceOnUse"> <pattern id="sponsoringCross" width="18" height="18" patternUnits="userSpaceOnUse">
@@ -679,14 +682,14 @@ const Netzwerk: React.FC = () => {
</div> </div>
</div> </div>
)} )}
<div style={{ padding: isMobile ? '32px 24px' : '24px 48px 32px 40px', flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0, position: 'relative', zIndex: 1 }}> <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 }}>Sponsoring 2026</span> <span style={{ fontFamily: FF, fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, color: 'rgba(17,29,85,0.5)', display: 'block', marginBottom: 8 }}>Sponsoring 2026</span>
<SponsoringForm theme="gold" /> <SponsoringForm theme="gold" />
</div> </div>
</div> </div>
</div> </div>
{/* Footnote */} {/* Footnote */}
<div style={{ position: 'relative', zIndex: 1, padding: '14px 56px 18px', display: 'flex', justifyContent: 'center', borderTop: '1px solid rgba(255,255,255,0.06)', flexShrink: 0 }}> <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 }}>Oder:</span> <span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 15, color: 'rgba(255,255,255,0.45)', marginRight: 10 }}>Oder:</span>
<Link <Link
to="/mitglied-werden" to="/mitglied-werden"

View File

@@ -194,9 +194,9 @@ const Participation: React.FC = () => {
{/* ── FORM SECTION ─────────────────────────────────────────────────────── */} {/* ── FORM SECTION ─────────────────────────────────────────────────────── */}
<section style={{ background: NAVY, position: 'relative', overflow: 'hidden', height: isMobile ? 'auto' : 'calc(100vh - 60px)', display: 'flex', flexDirection: 'column' }} id="bewerben"> <section style={{ background: NAVY, position: 'relative', overflow: 'hidden', height: isMobile ? 'auto' : 'calc(100vh - 60px)', display: 'flex', flexDirection: 'column' }} id="bewerben">
<div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '4fr 1px 8fr', flex: 1, minHeight: 0, overflow: 'hidden' }}> <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '4fr 1px 8fr', flex: 1, minHeight: 0, overflow: isMobile ? 'visible' : 'hidden' }}>
{/* Left — copy */} {/* Left — copy */}
<div style={{ padding: isMobile ? '32px 24px 24px' : '36px 36px 32px 52px', display: 'flex', flexDirection: 'column', justifyContent: 'center', overflow: 'hidden' }}> <div style={{ padding: isMobile ? '32px 24px 24px' : '36px 36px 32px 52px', display: 'flex', flexDirection: 'column', justifyContent: 'center', overflow: isMobile ? 'visible' : 'hidden' }}>
<span style={{ fontFamily: FF, fontSize: 10, color: '#EFBF04', textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, display: 'block', marginBottom: 20 }}>Direktbewerbung</span> <span style={{ fontFamily: FF, fontSize: 10, color: '#EFBF04', textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, display: 'block', marginBottom: 20 }}>Direktbewerbung</span>
<h2 style={{ fontFamily: FF, fontSize: 'clamp(2rem, 3.2vw, 2.8rem)', fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.025em', lineHeight: 1.04, margin: '0 0 20px' }}> <h2 style={{ fontFamily: FF, fontSize: 'clamp(2rem, 3.2vw, 2.8rem)', fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.025em', lineHeight: 1.04, margin: '0 0 20px' }}>
BEWERBEN ODER<br />VORSCHLAGEN. BEWERBEN ODER<br />VORSCHLAGEN.
@@ -226,7 +226,7 @@ const Participation: React.FC = () => {
{!isMobile && <div style={{ background: 'rgba(255,255,255,0.07)' }} />} {!isMobile && <div style={{ background: 'rgba(255,255,255,0.07)' }} />}
{/* Right — gold form panel */} {/* Right — gold form panel */}
<div style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden', minHeight: 0, position: 'relative', background: 'linear-gradient(160deg,#DDB84A 0%,#C9A227 52%,#A87800 100%)' }}> <div style={{ display: 'flex', flexDirection: 'column', overflow: isMobile ? 'visible' : 'hidden', 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"> <svg style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', pointerEvents: 'none', zIndex: 0 }} aria-hidden="true">
<defs> <defs>
<pattern id="participationCross" width="18" height="18" patternUnits="userSpaceOnUse"> <pattern id="participationCross" width="18" height="18" patternUnits="userSpaceOnUse">
@@ -252,7 +252,7 @@ const Participation: React.FC = () => {
</div> </div>
</div> </div>
)} )}
<div style={{ padding: isMobile ? '32px 24px' : '24px 48px 32px 40px', flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0, position: 'relative', zIndex: 1 }}> <div style={{ padding: isMobile ? '28px 20px' : '24px 48px 32px 40px', flex: 1, display: 'flex', flexDirection: 'column', minHeight: isMobile ? 560 : 0, position: 'relative', zIndex: 1 }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16, marginBottom: 24 }}> <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16, marginBottom: 24 }}>
<span style={{ fontFamily: FF, fontSize: 10, color: 'rgba(17,29,85,0.5)', textTransform: 'uppercase', letterSpacing: '0.28em', fontWeight: 700 }}>Bewerbung 2026</span> <span style={{ fontFamily: FF, fontSize: 10, color: 'rgba(17,29,85,0.5)', textTransform: 'uppercase', letterSpacing: '0.28em', fontWeight: 700 }}>Bewerbung 2026</span>
<Link <Link
@@ -270,7 +270,7 @@ const Participation: React.FC = () => {
</div> </div>
</div> </div>
<div style={{ position: 'relative', zIndex: 1, padding: '14px 56px 18px', display: 'flex', justifyContent: 'center', borderTop: '1px solid rgba(255,255,255,0.06)', flexShrink: 0 }}> <div style={{ position: 'relative', zIndex: 1, padding: isMobile ? '16px 20px 20px' : '14px 56px 18px', display: 'flex', justifyContent: 'center', textAlign: 'center', borderTop: '1px solid rgba(255,255,255,0.06)', flexShrink: 0 }}>
<Link to="/formular-hochladen" style={{ fontFamily: FF, 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 }}> <Link to="/formular-hochladen" style={{ fontFamily: FF, 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 }}>
Formular hochladen → Formular hochladen →
</Link> </Link>
@@ -315,9 +315,10 @@ function QualRow({ item, Icon, last }: { item: { num: string; title: string; bod
function CriteriaCell({ crit, idx }: { crit: { percentage: string; title: string; desc: string }; idx: number }) { function CriteriaCell({ crit, idx }: { crit: { percentage: string; title: string; desc: string }; idx: number }) {
const [hovered, setHovered] = React.useState(false); const [hovered, setHovered] = React.useState(false);
const isMobileCell = useIsMobile();
return ( return (
<div <div
style={{ padding: '56px 40px', borderLeft: idx > 0 ? '1px solid rgba(255,255,255,0.07)' : 'none', display: 'flex', flexDirection: 'column', gap: 0, cursor: 'default', transition: 'background 0.2s', background: hovered ? 'rgba(255,255,255,0.03)' : 'transparent' }} style={{ padding: isMobileCell ? '32px 24px' : '56px 40px', borderLeft: !isMobileCell && idx > 0 ? '1px solid rgba(255,255,255,0.07)' : 'none', borderTop: isMobileCell && idx > 0 ? '1px solid rgba(255,255,255,0.07)' : 'none', display: 'flex', flexDirection: 'column', gap: 0, cursor: 'default', transition: 'background 0.2s', background: hovered ? 'rgba(255,255,255,0.03)' : 'transparent' }}
onMouseEnter={() => setHovered(true)} onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)} onMouseLeave={() => setHovered(false)}
> >

View File

@@ -55,14 +55,15 @@ export default function Preistraeger() {
</h1> </h1>
{/* Year Tabs */} {/* Year Tabs */}
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 0, marginBottom: 32, borderBottom: `2px solid ${BORDER}` }}> <div style={{ display: 'flex', flexWrap: isMobile ? 'nowrap' : 'wrap', gap: 0, marginBottom: 32, borderBottom: `2px solid ${BORDER}`, overflowX: isMobile ? 'auto' : 'visible', WebkitOverflowScrolling: 'touch', maxWidth: '100%' }}>
{YEARS.map(year => ( {YEARS.map(year => (
<button <button
key={year} key={year}
onClick={() => { setActiveYear(year); reset(); }} onClick={() => { setActiveYear(year); reset(); }}
style={{ style={{
fontFamily: FF, fontSize: 16, fontWeight: 700, fontFamily: FF, fontSize: 16, fontWeight: 700,
padding: '12px 32px', padding: isMobile ? '12px 20px' : '12px 32px',
flexShrink: 0,
background: 'none', border: 'none', cursor: 'pointer', background: 'none', border: 'none', cursor: 'pointer',
color: activeYear === year ? NAVY : GRAY, color: activeYear === year ? NAVY : GRAY,
borderBottom: activeYear === year ? `2px solid ${GOLD}` : '2px solid transparent', borderBottom: activeYear === year ? `2px solid ${GOLD}` : '2px solid transparent',
@@ -135,7 +136,7 @@ export default function Preistraeger() {
{/* Grid */} {/* Grid */}
{filtered.length === 0 ? ( {filtered.length === 0 ? (
<div style={{ padding: '80px', textAlign: 'center', color: GRAY, fontFamily: FF }}> <div style={{ padding: isMobile ? '56px 24px' : '80px', textAlign: 'center', color: GRAY, fontFamily: FF }}>
Keine Preisträger für diese Auswahl. Keine Preisträger für diese Auswahl.
</div> </div>
) : ( ) : (
@@ -162,7 +163,7 @@ export default function Preistraeger() {
> >
Jetzt kostenlos bewerben <ArrowRight size={14} /> Jetzt kostenlos bewerben <ArrowRight size={14} />
</Link> </Link>
<div style={{ marginTop: 20, display: 'flex', alignItems: 'center', gap: 8 }}> <div style={{ marginTop: 20, display: 'flex', alignItems: 'center', justifyContent: isMobile ? 'center' : undefined, flexWrap: isMobile ? 'wrap' : 'nowrap', gap: 8 }}>
<span style={{ width: 20, height: 1, background: 'rgba(239,191,4,0.3)', display: 'inline-block' }} /> <span style={{ width: 20, height: 1, background: 'rgba(239,191,4,0.3)', display: 'inline-block' }} />
<span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 11, color: 'rgba(16,24,40,0.4)' }}>Diese Arbeit unterstützen:</span> <span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 11, color: 'rgba(16,24,40,0.4)' }}>Diese Arbeit unterstützen:</span>
<Link <Link

View File

@@ -45,7 +45,7 @@ export default function PreistraegerDetail() {
{/* Header block */} {/* Header block */}
<div style={{ padding: isMobile ? '32px 24px 28px' : '48px 80px 40px', borderBottom: `1px solid ${BORDER}` }}> <div style={{ padding: isMobile ? '32px 24px 28px' : '48px 80px 40px', borderBottom: `1px solid ${BORDER}` }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 16 }}> <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 16, flexWrap: 'wrap' }}>
<span style={{ <span style={{
fontFamily: FF, fontSize: 11, fontWeight: 700, color: '#fff', fontFamily: FF, fontSize: 11, fontWeight: 700, color: '#fff',
background: NAVY, padding: '4px 14px', borderRadius: 999, background: NAVY, padding: '4px 14px', borderRadius: 999,
@@ -121,7 +121,7 @@ export default function PreistraegerDetail() {
].map(row => ( ].map(row => (
<div key={row.label} style={{ display: 'flex', flexDirection: 'column', gap: 2 }}> <div key={row.label} style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
<span style={{ fontFamily: FF, fontSize: 11, color: GRAY, textTransform: 'uppercase', letterSpacing: '0.08em' }}>{row.label}</span> <span style={{ fontFamily: FF, fontSize: 11, color: GRAY, textTransform: 'uppercase', letterSpacing: '0.08em' }}>{row.label}</span>
<span style={{ fontFamily: FF, fontSize: 17, fontWeight: 700, color: '#101828' }}>{row.value}</span> <span style={{ fontFamily: FF, fontSize: 17, fontWeight: 700, color: '#101828', overflowWrap: 'anywhere' }}>{row.value}</span>
</div> </div>
))} ))}
</div> </div>
@@ -138,7 +138,7 @@ export default function PreistraegerDetail() {
color: '#101828', border: `2px solid ${NAVY}`, color: '#101828', border: `2px solid ${NAVY}`,
padding: '12px 20px', textDecoration: 'none', padding: '12px 20px', textDecoration: 'none',
textTransform: 'uppercase', letterSpacing: '0.08em', textTransform: 'uppercase', letterSpacing: '0.08em',
transition: 'all 0.2s', borderRadius: 0, transition: 'all 0.2s', borderRadius: 0, overflowWrap: 'anywhere',
}} }}
onMouseEnter={e => { const el = e.currentTarget as HTMLElement; el.style.background = NAVY; el.style.color = '#fff'; }} onMouseEnter={e => { const el = e.currentTarget as HTMLElement; el.style.background = NAVY; el.style.color = '#fff'; }}
onMouseLeave={e => { const el = e.currentTarget as HTMLElement; el.style.background = 'transparent'; el.style.color = NAVY; }} onMouseLeave={e => { const el = e.currentTarget as HTMLElement; el.style.background = 'transparent'; el.style.color = NAVY; }}

View File

@@ -111,7 +111,7 @@ function NewsCard({ item, idx, isMobile }: { item: typeof news[0]; idx: number;
/> />
</div> </div>
{/* body */} {/* body */}
<div style={{ padding: '32px 36px 40px', display: 'flex', flexDirection: 'column', flex: 1 }}> <div style={{ padding: isMobile ? '24px 24px 32px' : '32px 36px 40px', display: 'flex', flexDirection: 'column', flex: 1 }}>
<span <span
style={{ style={{
fontFamily: FF, fontFamily: FF,
@@ -294,6 +294,7 @@ const Press: React.FC = () => {
letterSpacing: '-0.03em', letterSpacing: '-0.03em',
textTransform: 'uppercase', textTransform: 'uppercase',
margin: '0 0 24px', margin: '0 0 24px',
overflowWrap: 'anywhere',
}} }}
> >
EVENTS &amp;<br />BERICHTERSTATTUNG. EVENTS &amp;<br />BERICHTERSTATTUNG.
@@ -399,7 +400,7 @@ const Press: React.FC = () => {
<div style={{ padding: isMobile ? '24px 24px 32px' : '40px 56px 40px 48px', display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}> <div style={{ padding: isMobile ? '24px 24px 32px' : '40px 56px 40px 48px', display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
<div style={{ fontFamily: FF, fontSize: 9, color: '#4A8FC9', textTransform: 'uppercase' as const, letterSpacing: '0.22em', fontWeight: 700, marginBottom: 10 }}>{event.cat}</div> <div style={{ fontFamily: FF, fontSize: 9, color: '#4A8FC9', textTransform: 'uppercase' as const, letterSpacing: '0.22em', fontWeight: 700, marginBottom: 10 }}>{event.cat}</div>
<h3 style={{ fontFamily: FF, fontSize: 'clamp(1.3rem, 2vw, 1.7rem)', fontWeight: 900, color: '#101828', textTransform: 'uppercase' as const, letterSpacing: '-0.02em', margin: '0 0 14px' }}>{event.title}</h3> <h3 style={{ fontFamily: FF, fontSize: 'clamp(1.3rem, 2vw, 1.7rem)', fontWeight: 900, color: '#101828', textTransform: 'uppercase' as const, letterSpacing: '-0.02em', margin: '0 0 14px' }}>{event.title}</h3>
<div style={{ display: 'flex', gap: 28, alignItems: 'center', marginBottom: 16 }}> <div style={{ display: 'flex', gap: isMobile ? 16 : 28, alignItems: 'center', flexWrap: 'wrap', marginBottom: 16 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 6, fontFamily: FB, fontSize: 18, color: 'rgba(16,24,40,0.5)' }}> <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontFamily: FB, fontSize: 18, color: 'rgba(16,24,40,0.5)' }}>
<Calendar size={14} color={GOLD} />{event.date} <Calendar size={14} color={GOLD} />{event.date}
</div> </div>
@@ -623,6 +624,7 @@ const Press: React.FC = () => {
fontSize: 18, fontSize: 18,
color: 'rgba(16,24,40,0.55)', color: 'rgba(16,24,40,0.55)',
lineHeight: 1.8, lineHeight: 1.8,
overflowWrap: 'anywhere',
}} }}
> >
presse@bmp-bayern.de presse@bmp-bayern.de