feat: centralize home cms defaults
This commit is contained in:
217
src/spa/homeContent.ts
Normal file
217
src/spa/homeContent.ts
Normal file
@@ -0,0 +1,217 @@
|
||||
export const homeContent = {
|
||||
hero: {
|
||||
backgroundImageFilename: 'gala-saal-overview.jpg',
|
||||
imageAlt: 'Awards Gala',
|
||||
badge: 'Bewerbungsphase 2026 geschlossen',
|
||||
headingLine1: 'BAYERNS BESTE',
|
||||
headingAccent: 'MITTELSTÄNDLER.',
|
||||
description:
|
||||
'Der Bayerische Mittelstandspreis würdigt herausragende Leistungen – von Innovation über Nachhaltigkeit bis hin zur Exzellenz.',
|
||||
primaryCta: { label: 'Jetzt kostenlos bewerben', url: '/teilnahme' },
|
||||
secondaryCta: { label: 'Mitglied werden', url: '/mitglied-werden' },
|
||||
videoLabel: 'Film abspielen',
|
||||
partnersLabel: 'Unsere Partner',
|
||||
partners: [
|
||||
{ name: 'RSM Ebner Stolz' },
|
||||
{ name: 'WWK' },
|
||||
{ name: 'Deutsche Bank' },
|
||||
{ name: 'Bionorica' },
|
||||
{ name: 'Berchtesgadener Land' },
|
||||
{ name: 'Metzler' },
|
||||
{ name: 'vbw' },
|
||||
{ name: 'Wirtschaftsbeirat Bayern' },
|
||||
{ name: 'Radio Gong 96.3' },
|
||||
{ name: 'münchen.tv' },
|
||||
{ name: 'EWS' },
|
||||
],
|
||||
},
|
||||
quickCheck: {
|
||||
eyebrow: 'Schnell-Check',
|
||||
heading: 'SIND SIE\nBERECHTIGT?',
|
||||
imageFilename: 'buehne-gewinner.jpg',
|
||||
imageAlt: 'Preisverleihung Bühne',
|
||||
body:
|
||||
'Der Bayerische Mittelstandspreis richtet sich an inhabergeführte KMU im Freistaat. Fünf Kriterien entscheiden, erfüllen Sie alle fünf, steht Ihrer Bewerbung nichts im Weg.',
|
||||
criteria: [
|
||||
{ label: 'Standort Bayern', desc: 'Sitz oder Betriebsstätte im Freistaat' },
|
||||
{ label: '50–1.500 Mitarbeiter', desc: 'Klassischer Mittelstand' },
|
||||
{ label: 'Min. 3 Geschäftsjahre', desc: 'Markterfahrung und Stabilität' },
|
||||
{ label: 'Privatwirtschaft', desc: 'Kein staatlicher Träger' },
|
||||
{ label: 'Familien- bzw. eigentümergeführt', desc: 'Ihr Unternehmen ist inhabergeführt' },
|
||||
],
|
||||
note:
|
||||
'Auch ein Verbund bzw. eine Gemeinschaft von mittelständischen Unternehmen oder von mittelständischen Unternehmen und Organisationen/Institutionen mit Schwerpunkt in Bayern kann teilnehmen.',
|
||||
cta: { label: 'Ihr Weg zum Preis', url: '/teilnahme' },
|
||||
},
|
||||
intro: {
|
||||
eyebrow: 'Ein Gewinn für alle',
|
||||
heading: 'AUSZEICHNUNG\nFÜR DIE BESTEN.',
|
||||
imageFilename: 'preistraeger-jubel.jpg',
|
||||
imageAlt: 'BMP Auszeichnung',
|
||||
stats: [
|
||||
{ value: '20+', label: 'Jahre Exzellenz' },
|
||||
{ value: '0 €', label: 'Teilnahmegebühr' },
|
||||
{ value: '100%', label: 'Unabhängig' },
|
||||
],
|
||||
quote: '„Ein Unternehmen zu gründen erfordert nicht allein spezielle Fähigkeiten. Es erfordert Persönlichkeit!“',
|
||||
body:
|
||||
'Wir suchen Vorbilder, die sich trotz aller Risiken nicht scheuen, Visionen in Businesspläne und Ideen in Unternehmungen zu verwandeln, und das mit großem persönlichen Einsatz und Verantwortung für Ihre Mitarbeiter. Seit vielen Jahren würdigen wir herausragende unternehmerische Leistungen im Freistaat.',
|
||||
cta: { label: 'Mehr über den Preis', url: '/der-bmp' },
|
||||
},
|
||||
status: {
|
||||
activePhase: '0',
|
||||
noActionLabel: 'Kein Handlungsbedarf',
|
||||
successApplicationsLabel: 'Bewerbungen',
|
||||
successWinnersLabel: 'Preisträger',
|
||||
phases: [
|
||||
{
|
||||
num: '01',
|
||||
tag: 'JETZT OFFEN',
|
||||
pulse: true,
|
||||
phase: 'Bewerbungsphase 2026',
|
||||
headline: 'BEWERBEN SIE SICH JETZT.',
|
||||
body:
|
||||
'Die Bewerbungsphase 2026 ist eröffnet – es ist noch nicht zu spät. Reichen Sie Ihre Unterlagen bis zum 30. Juni kostenlos ein und zeigen Sie, was den bayerischen Mittelstand ausmacht.',
|
||||
cta: { label: 'Jetzt kostenlos bewerben', url: '/teilnahme' },
|
||||
accent: '#EFBF04',
|
||||
bg: '#020A1E',
|
||||
glow: 'rgba(239,191,4,0.14)',
|
||||
meta: 'Deadline: 30. Juni 2026',
|
||||
membershipCta: { label: 'Mitglied werden', url: '/mitglied-werden' },
|
||||
},
|
||||
{
|
||||
num: '02',
|
||||
tag: 'IN AUSWERTUNG',
|
||||
pulse: true,
|
||||
phase: 'Auswertungsphase 2026',
|
||||
headline: 'DIE JURY BEWERTET GERADE.',
|
||||
body:
|
||||
'Die Anmeldephase 2026 ist geschlossen. Unsere unabhängige Expertenjury aus Wissenschaft und Praxis sichtet und bewertet derzeit alle Einreichungen.',
|
||||
cta: null,
|
||||
accent: '#4A8FC9',
|
||||
bg: '#060D1C',
|
||||
glow: 'rgba(74,143,201,0.12)',
|
||||
meta: 'Ergebnis: August 2026',
|
||||
membershipCta: { label: 'Mitglied werden', url: '/mitglied-werden' },
|
||||
},
|
||||
{
|
||||
num: '03',
|
||||
tag: 'ABGESCHLOSSEN',
|
||||
pulse: false,
|
||||
phase: 'Preisverleihung · Oktober 2026',
|
||||
headline: 'DER BMP 2026 WAR EIN ERFOLG.',
|
||||
body:
|
||||
'Wir danken allen 247 Bewerberinnen und Bewerbern für Mut und Exzellenz. Drei außergewöhnliche Unternehmen wurden in München ausgezeichnet – ein unvergesslicher Abend.',
|
||||
cta: { label: 'Alle Preisträger ansehen', url: '/preistraeger' },
|
||||
accent: '#EFBF04',
|
||||
bg: '#06090F',
|
||||
glow: 'rgba(239,191,4,0.08)',
|
||||
meta: 'Gala · Oktober 2026 · München',
|
||||
successApplications: '247',
|
||||
successWinners: '3',
|
||||
},
|
||||
],
|
||||
},
|
||||
winners: {
|
||||
eyebrow: 'Success Stories',
|
||||
heading: 'DIE BESTEN UNTERNEHMEN IN BAYERN',
|
||||
cta: { label: 'Alle Preisträger', url: '/preistraeger' },
|
||||
fallbackImageFilename: 'gala-saal-overview.jpg',
|
||||
cardFallbackTitle: 'Preisträger',
|
||||
hoverLabel: 'Detail →',
|
||||
},
|
||||
testimonials: {
|
||||
eyebrow: 'Stimmen der Preisträger',
|
||||
heading: 'DAS SAGEN UNSERE\nPREISTRÄGER.',
|
||||
items: [
|
||||
{
|
||||
imageUrl: 'https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?auto=format&fit=crop&q=80&w=600',
|
||||
name: 'Dr. Maria Huber',
|
||||
role: 'Geschäftsführerin',
|
||||
company: 'TechVision GmbH',
|
||||
year: '2025',
|
||||
quote: 'Der BMP hat uns neue Türen geöffnet. Die Auszeichnung ist ein wichtiges Qualitätssiegel für unser gesamtes Team.',
|
||||
},
|
||||
{
|
||||
imageUrl: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?auto=format&fit=crop&q=80&w=600',
|
||||
name: 'Hannes Weber',
|
||||
role: 'Inhaber & CEO',
|
||||
company: 'Weber Präzision GmbH',
|
||||
year: '2023',
|
||||
quote: 'Der Gewinn war ein Moment des Stolzes für die gesamte Belegschaft. Die höchste Anerkennung für unsere tägliche Arbeit.',
|
||||
},
|
||||
{
|
||||
imageUrl: 'https://images.unsplash.com/photo-1580489944761-15a19d654956?auto=format&fit=crop&q=80&w=600',
|
||||
name: 'Lisa Berger',
|
||||
role: 'Gründerin & CEO',
|
||||
company: 'EcoTech Bavaria',
|
||||
year: '2024',
|
||||
quote: 'Das Netzwerk, das wir durch den BMP gewonnen haben, ist unbezahlbar. Wir fanden Partner, die unsere Werte teilen.',
|
||||
},
|
||||
{
|
||||
imageUrl: 'https://images.unsplash.com/photo-1560250097-0b93528c311a?auto=format&fit=crop&q=80&w=600',
|
||||
name: 'Dr. Michael Schuh',
|
||||
role: 'Vorstand',
|
||||
company: 'Bayerischer Maschinenbau',
|
||||
year: '2024',
|
||||
quote: 'Der Preis hat unsere Sichtbarkeit weit über die bayerischen Grenzen hinaus gestärkt. Ein echtes Premium-Siegel.',
|
||||
},
|
||||
{
|
||||
imageUrl: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?auto=format&fit=crop&q=80&w=600',
|
||||
name: 'Anna Kellner',
|
||||
role: 'Mitgründerin',
|
||||
company: 'AlpinTech Solutions',
|
||||
year: '2024',
|
||||
quote:
|
||||
'Der BMP hat unsere Employer Brand transformiert. Wir gewinnen heute die besten Talente, weil wir Preisträger sind.',
|
||||
},
|
||||
],
|
||||
},
|
||||
benefits: {
|
||||
eyebrow: 'Mehr als nur ein Preis',
|
||||
heading: 'WARUM SICH DIE\nTEILNAHME LOHNT.',
|
||||
imageFilename: 'networking-innenhof.jpg',
|
||||
imageAlt: 'BMP Gala Netzwerk',
|
||||
imageLabel: 'BMP Gala-Netzwerk',
|
||||
items: [
|
||||
{
|
||||
num: '01',
|
||||
title: 'Netzwerk',
|
||||
desc: 'Direkter Zugang zu Entscheidern aus Staatsregierung, Wirtschaft und Wissenschaft.',
|
||||
},
|
||||
{
|
||||
num: '02',
|
||||
title: 'Sichtbarkeit',
|
||||
desc: 'Breite mediale Begleitung durch TV-, Radio- und Print-Partner bayernweit.',
|
||||
},
|
||||
{
|
||||
num: '03',
|
||||
title: 'Bestätigung',
|
||||
desc: 'Ein unabhängiger Qualitätsnachweis – das stärkste Siegel für Ihren Marktauftritt.',
|
||||
},
|
||||
],
|
||||
},
|
||||
application: {
|
||||
eyebrow: 'Chance ergreifen',
|
||||
heading: 'SCHREIBEN\nAUCH SIE\nGESCHICHTE.',
|
||||
body: 'Werden Sie Teil der Wall of Fame des bayerischen Mittelstands – vollständig kostenfrei.',
|
||||
benefits: [
|
||||
{ num: '01', label: 'Kostenfrei', desc: 'Ohne Teilnahmegebühr' },
|
||||
{ num: '02', label: 'Jury', desc: 'Aus Wissenschaft und Praxis' },
|
||||
{ num: '03', label: 'Sichtbarkeit', desc: 'Medial bayernweit' },
|
||||
{ num: '04', label: 'Gala', desc: 'Verleihung München' },
|
||||
],
|
||||
awardImageFilename: 'preisuebergabe.jpg',
|
||||
awardImageAlt: 'Preisverleihung Bayerischer Mittelstandspreis',
|
||||
awardCaption: 'Preisverleihung 2025',
|
||||
formEyebrow: 'Direktbewerbung 2026',
|
||||
formTitle: 'Kostenlos bewerben',
|
||||
footnote: 'Kostenlos und unverbindlich –',
|
||||
footnoteStrong: 'keine Teilnahmegebühr',
|
||||
},
|
||||
videoModal: {
|
||||
title: 'Video-Player Platzhalter',
|
||||
description: 'Hier würde das Image-Video des BMP geladen werden.',
|
||||
closeLabel: 'Schließen',
|
||||
},
|
||||
}
|
||||
@@ -11,125 +11,63 @@ import { useIsMobile } from '@/spa/hooks/useIsMobile';
|
||||
import Image from '@/spa/components/ui/UnoptimizedImage'
|
||||
import { useCmsCollection, useCmsRoute } from '@/spa/cmsRoute'
|
||||
import { mediaAlt, mediaUrl } from '@/spa/cmsMediaField'
|
||||
|
||||
const PARTNERS = [
|
||||
{ id: 'rsm', label: <><span style={{fontWeight:700,fontSize:11,letterSpacing:2}}>RSM</span><br/><span style={{fontWeight:300,fontSize:8,letterSpacing:1,opacity:.7}}>Ebner Stolz</span></> },
|
||||
{ id: 'wwk', label: <span style={{fontWeight:800,fontSize: 15,letterSpacing:3}}>WWK</span> },
|
||||
{ id: 'db', label: <span style={{fontWeight:700,fontSize:10,letterSpacing:1.5}}>Deutsche Bank</span> },
|
||||
{ id: 'bio', label: <span style={{fontFamily:'Georgia,serif',fontSize: 14,letterSpacing:.5}}>Bionorica</span> },
|
||||
{ id: 'bcl', label: <span style={{fontWeight:700,fontSize:9,letterSpacing:1.5,lineHeight:1.3,textAlign:'center' as const,display:'block'}}>Berchtesgadener<br/>Land</span> },
|
||||
{ id: 'mtz', label: <span style={{fontFamily:'Georgia,serif',fontStyle:'italic',fontSize: 14}}>Metzler</span> },
|
||||
{ id: 'vbw', label: <span style={{fontWeight:800,fontSize: 14,letterSpacing:2}}>vbw</span> },
|
||||
{ id: 'wby', label: <span style={{fontWeight:700,fontSize:9,letterSpacing:1,lineHeight:1.3,textAlign:'center' as const,display:'block'}}>Wirtschafts-<br/>beirat Bayern</span> },
|
||||
{ id: 'rgong', label: <span style={{fontWeight:700,fontSize:9,letterSpacing:1}}>Radio Gong 96.3</span> },
|
||||
{ id: 'mtvr', label: <span style={{fontWeight:700,fontSize:10,letterSpacing:1.5}}>münchen.tv</span> },
|
||||
{ id: 'ews', label: <span style={{fontWeight:800,fontSize: 14,letterSpacing:2}}>EWS</span> },
|
||||
];
|
||||
import { homeContent } from '@/spa/homeContent'
|
||||
|
||||
const FF = '"IBM Plex Sans", sans-serif';
|
||||
|
||||
type CmsRecord = Record<string, unknown>;
|
||||
type HomeCms = Record<string, any>;
|
||||
type StatusPhase = HomeCms & {
|
||||
cta?: { label?: string; to?: string; url?: string } | null;
|
||||
membershipCta?: { label?: string; to?: string; url?: string } | null;
|
||||
};
|
||||
type WinnerCardData = CmsRecord & {
|
||||
id?: string | number;
|
||||
slug?: string;
|
||||
title?: string;
|
||||
name?: string;
|
||||
img?: string;
|
||||
image?: unknown;
|
||||
spaPath?: string;
|
||||
year?: string | number;
|
||||
awardType?: string;
|
||||
type?: string;
|
||||
category?: string;
|
||||
};
|
||||
|
||||
const fallbackText = (value: unknown, fallback: string) =>
|
||||
typeof value === 'string' && value.length > 0 ? value : fallback;
|
||||
|
||||
const fallbackArray = <T,>(value: unknown, fallback: T[]) =>
|
||||
const fallbackArray = <T,>(value: unknown, fallback: readonly T[]) =>
|
||||
Array.isArray(value) && value.length > 0 ? (value as T[]) : fallback;
|
||||
|
||||
function Lines({ text }: { text: string }) {
|
||||
return <>{text.split('\n').map((line, i) => <React.Fragment key={`${line}-${i}`}>{i > 0 && <br />}{line}</React.Fragment>)}</>;
|
||||
}
|
||||
|
||||
const DEFAULT_QUICK_CRITERIA = [
|
||||
{ label: 'Standort Bayern', desc: 'Sitz oder Betriebsstätte im Freistaat' },
|
||||
{ label: '50–1.500 Mitarbeiter', desc: 'Klassischer Mittelstand' },
|
||||
{ label: 'Min. 3 Geschäftsjahre', desc: 'Markterfahrung und Stabilität' },
|
||||
{ label: 'Privatwirtschaft', desc: 'Kein staatlicher Träger' },
|
||||
{ label: 'Familien- bzw. eigentümergeführt', desc: 'Ihr Unternehmen ist inhabergeführt' },
|
||||
];
|
||||
|
||||
const DEFAULT_INTRO_STATS = [['20+', 'Jahre Exzellenz'], ['0 €', 'Teilnahmegebühr'], ['100%', 'Unabhängig']];
|
||||
|
||||
const DEFAULT_BENEFITS = [
|
||||
{ num: '01', title: 'Netzwerk', desc: 'Direkter Zugang zu Entscheidern aus Staatsregierung, Wirtschaft und Wissenschaft.' },
|
||||
{ num: '02', title: 'Sichtbarkeit', desc: 'Breite mediale Begleitung durch TV-, Radio- und Print-Partner bayernweit.' },
|
||||
{ num: '03', title: 'Bestätigung', desc: 'Ein unabhängiger Qualitätsnachweis – das stärkste Siegel für Ihren Marktauftritt.' },
|
||||
];
|
||||
|
||||
const DEFAULT_APPLICATION_BENEFITS = [
|
||||
{ num: '01', label: 'Kostenfrei', desc: 'Ohne Teilnahmegebühr' },
|
||||
{ num: '02', label: 'Jury', desc: 'Aus Wissenschaft und Praxis' },
|
||||
{ num: '03', label: 'Sichtbarkeit', desc: 'Medial bayernweit' },
|
||||
{ num: '04', label: 'Gala', desc: 'Verleihung München' },
|
||||
];
|
||||
|
||||
// ─── Status Phase Slider ────────────────────────────────────────────────────
|
||||
/**
|
||||
* 🔧 DEPLOYMENT CONFIG
|
||||
* Setze ACTIVE_PHASE je nach aktuellem Stand des BMP-Zyklus:
|
||||
* 0 = Bewerbungsphase offen
|
||||
* 1 = Auswertungsphase (Jury bewertet)
|
||||
* 2 = Nach der Preisverleihung (Erfolg)
|
||||
*/
|
||||
const ACTIVE_PHASE: 0 | 1 | 2 = 0;
|
||||
|
||||
interface StatusPhase {
|
||||
num: string;
|
||||
tag: string;
|
||||
pulse: boolean;
|
||||
phase: string;
|
||||
headline: string;
|
||||
body: string;
|
||||
cta: { label: string; to: string } | null;
|
||||
accent: string;
|
||||
bg: string;
|
||||
glow: string;
|
||||
meta: string;
|
||||
function partnerLogos(partners: unknown) {
|
||||
return fallbackArray(partners, homeContent.hero.partners).map((partner) => {
|
||||
const item = partner as { id?: string; name?: string; label?: React.ReactNode };
|
||||
return item.label
|
||||
? { id: item.id || String(item.name || ''), label: item.label }
|
||||
: {
|
||||
id: item.id || String(item.name || ''),
|
||||
label: <span style={{ fontWeight: 700, fontSize: 10, letterSpacing: 1.5 }}>{item.name}</span>,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const STATUS_PHASES: StatusPhase[] = [
|
||||
{
|
||||
num: '01',
|
||||
tag: 'JETZT OFFEN',
|
||||
pulse: true,
|
||||
phase: 'Bewerbungsphase 2026',
|
||||
headline: 'BEWERBEN SIE SICH JETZT.',
|
||||
body: 'Die Bewerbungsphase 2026 ist eröffnet – es ist noch nicht zu spät. Reichen Sie Ihre Unterlagen bis zum 30. Juni kostenlos ein und zeigen Sie, was den bayerischen Mittelstand ausmacht.',
|
||||
cta: { label: 'Jetzt kostenlos bewerben', to: '/teilnahme' },
|
||||
accent: '#EFBF04',
|
||||
bg: '#020A1E',
|
||||
glow: 'rgba(239,191,4,0.14)',
|
||||
meta: 'Deadline: 30. Juni 2026',
|
||||
},
|
||||
{
|
||||
num: '02',
|
||||
tag: 'IN AUSWERTUNG',
|
||||
pulse: true,
|
||||
phase: 'Auswertungsphase 2026',
|
||||
headline: 'DIE JURY BEWERTET GERADE.',
|
||||
body: 'Die Anmeldephase 2026 ist geschlossen. Unsere unabhängige Expertenjury aus Wissenschaft und Praxis sichtet und bewertet derzeit alle Einreichungen.',
|
||||
cta: null,
|
||||
accent: '#4A8FC9',
|
||||
bg: '#060D1C',
|
||||
glow: 'rgba(74,143,201,0.12)',
|
||||
meta: 'Ergebnis: August 2026',
|
||||
},
|
||||
{
|
||||
num: '03',
|
||||
tag: 'ABGESCHLOSSEN',
|
||||
pulse: false,
|
||||
phase: 'Preisverleihung · Oktober 2026',
|
||||
headline: 'DER BMP 2026 WAR EIN ERFOLG.',
|
||||
body: 'Wir danken allen 247 Bewerberinnen und Bewerbern für Mut und Exzellenz. Drei außergewöhnliche Unternehmen wurden in München ausgezeichnet – ein unvergesslicher Abend.',
|
||||
cta: { label: 'Alle Preisträger ansehen', to: '/preistraeger' },
|
||||
accent: '#EFBF04',
|
||||
bg: '#06090F',
|
||||
glow: 'rgba(239,191,4,0.08)',
|
||||
meta: 'Gala · Oktober 2026 · München',
|
||||
},
|
||||
];
|
||||
|
||||
function HomeWinnerCard({ winner }: { winner: any }) {
|
||||
function HomeWinnerCard({
|
||||
winner,
|
||||
fallbackTitle,
|
||||
fallbackImage,
|
||||
hoverLabel,
|
||||
}: {
|
||||
winner: WinnerCardData;
|
||||
fallbackTitle: string;
|
||||
fallbackImage: string;
|
||||
hoverLabel: string;
|
||||
}) {
|
||||
const [hovered, setHovered] = useState(false);
|
||||
const isMobile = useIsMobile();
|
||||
const staticWinner = WINNERS.find(
|
||||
@@ -139,8 +77,8 @@ function HomeWinnerCard({ winner }: { winner: any }) {
|
||||
item.name === winner?.title ||
|
||||
item.name === winner?.name,
|
||||
);
|
||||
const title = fallbackText(winner?.title, fallbackText(winner?.name, staticWinner?.name || 'Preisträger'));
|
||||
const imageSrc = mediaUrl(winner?.image, winner?.img || staticWinner?.img || '/images/gala-saal-overview.jpg');
|
||||
const title = fallbackText(winner?.title, fallbackText(winner?.name, staticWinner?.name || fallbackTitle));
|
||||
const imageSrc = mediaUrl(winner?.image, winner?.img || staticWinner?.img || fallbackImage);
|
||||
const href = winner?.spaPath || (winner?.slug ? `/preistraeger/${winner.slug}` : staticWinner ? `/preistraeger/${staticWinner.slug}` : '/preistraeger');
|
||||
return (
|
||||
<Link
|
||||
@@ -161,7 +99,7 @@ function HomeWinnerCard({ winner }: { winner: any }) {
|
||||
<h3 style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 16, fontWeight: 700, color: '#fff', margin: '0 0 3px', lineHeight: 1.3 }}>{title}</h3>
|
||||
<p style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 14, color: 'rgba(255,255,255,0.75)', margin: 0 }}>{winner?.category || staticWinner?.category}</p>
|
||||
<div style={{ marginTop: 10, display: 'inline-block', background: '#EFBF04', color: '#101828', padding: '5px 14px', borderRadius: 999, fontSize: 10, fontFamily: '"IBM Plex Sans", sans-serif', fontWeight: 800, letterSpacing: '0.1em', textTransform: 'uppercase', opacity: hovered ? 1 : 0, transform: hovered ? 'translateY(0)' : 'translateY(6px)', transition: 'all 0.25s' }}>
|
||||
Detail →
|
||||
{hoverLabel}
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
@@ -182,22 +120,21 @@ const Home: React.FC = () => {
|
||||
const cmsPreistraeger = useCmsCollection('preistraeger');
|
||||
const selectedWinners = fallbackArray(winnersSection.featured, []);
|
||||
const selectedWinnerDocs = selectedWinners
|
||||
.map((selected: any) => {
|
||||
const selectedID = typeof selected === 'object' ? selected.id : selected
|
||||
const listDoc = cmsPreistraeger.find((doc: any) => String(doc.id) === String(selectedID))
|
||||
.map((selected) => {
|
||||
const selectedRecord = selected as { id?: string | number }
|
||||
const selectedID = typeof selected === 'object' && selected !== null ? selectedRecord.id : selected
|
||||
const listDoc = cmsPreistraeger.find((doc) => String((doc as { id?: string | number }).id) === String(selectedID))
|
||||
return listDoc || (typeof selected === 'object' ? selected : undefined)
|
||||
})
|
||||
.filter(Boolean)
|
||||
.filter(Boolean)
|
||||
const homeWinners = selectedWinnerDocs.length
|
||||
? selectedWinnerDocs
|
||||
: (cmsPreistraeger.length ? cmsPreistraeger : WINNERS).filter((w: any) => Number(w.year) === 2025).slice(0, 8);
|
||||
const quickCriteria = fallbackArray(quickCheck.criteria, DEFAULT_QUICK_CRITERIA);
|
||||
const introStats = fallbackArray(
|
||||
intro.stats,
|
||||
DEFAULT_INTRO_STATS.map(([value, label]) => ({ value, label })),
|
||||
);
|
||||
const benefitItems = fallbackArray(benefits.items, DEFAULT_BENEFITS);
|
||||
const applicationBenefits = fallbackArray(application.benefits, DEFAULT_APPLICATION_BENEFITS);
|
||||
: (cmsPreistraeger.length ? cmsPreistraeger : WINNERS).filter((w) => Number((w as { year?: string | number }).year) === 2025).slice(0, 8);
|
||||
const quickCriteria = fallbackArray(quickCheck.criteria, homeContent.quickCheck.criteria);
|
||||
const introStats = fallbackArray(intro.stats, homeContent.intro.stats);
|
||||
const benefitItems = fallbackArray(benefits.items, homeContent.benefits.items);
|
||||
const applicationBenefits = fallbackArray(application.benefits, homeContent.application.benefits);
|
||||
const winnerFallbackImage = mediaUrl(winnersSection.fallbackImage, `/images/${homeContent.winners.fallbackImageFilename}`);
|
||||
|
||||
return (
|
||||
<div className="animate-fade-in">
|
||||
@@ -205,8 +142,8 @@ const Home: React.FC = () => {
|
||||
<section className="relative flex items-center overflow-hidden" style={{ background: '#111D55', height: isMobile ? '88svh' : '100vh' }}>
|
||||
<div className="absolute inset-0 z-0">
|
||||
<Image unoptimized
|
||||
src={mediaUrl(hero.backgroundImage, '/images/gala-saal-overview.jpg')}
|
||||
alt={mediaAlt(hero.backgroundImage, fallbackText(hero.imageAlt, 'Awards Gala'))}
|
||||
src={mediaUrl(hero.backgroundImage, `/images/${homeContent.hero.backgroundImageFilename}`)}
|
||||
alt={mediaAlt(hero.backgroundImage, fallbackText(hero.imageAlt, homeContent.hero.imageAlt))}
|
||||
className="w-full h-full object-cover scale-105"
|
||||
style={{ objectPosition: 'center top' }}
|
||||
/>
|
||||
@@ -217,35 +154,35 @@ const Home: React.FC = () => {
|
||||
<div style={{ maxWidth: isMobile ? '100%' : '48rem' }}>
|
||||
<div className="inline-flex items-center gap-3 bg-accent/20 border border-accent/30 rounded-full px-4 py-1.5 mb-8 backdrop-blur-sm animate-fade-in" style={{ marginBottom: isMobile ? 20 : undefined }}>
|
||||
<span className="flex h-2 w-2 rounded-full bg-accent"></span>
|
||||
<span className="text-accent text-[10px] uppercase tracking-[0.2em] font-bold">{fallbackText(hero.badge, 'Bewerbungsphase 2026 geschlossen')}</span>
|
||||
<span className="text-accent text-[10px] uppercase tracking-[0.2em] font-bold">{fallbackText(hero.badge, homeContent.hero.badge)}</span>
|
||||
</div>
|
||||
|
||||
<h1 className="font-display font-bold text-white mb-6 leading-[0.9] tracking-tight" style={{ fontSize: isMobile ? 'clamp(1.8rem, 10vw, 3rem)' : 'clamp(3.5rem, 8vw, 6rem)' }}>
|
||||
{fallbackText(hero.headingLine1, 'BAYERNS BESTE')} <br />
|
||||
<span className="text-accent">{fallbackText(hero.headingAccent, 'MITTELSTÄNDLER.')}</span>
|
||||
{fallbackText(hero.headingLine1, homeContent.hero.headingLine1)} <br />
|
||||
<span className="text-accent">{fallbackText(hero.headingAccent, homeContent.hero.headingAccent)}</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-white/70 mb-12 font-light leading-relaxed" style={{ fontSize: isMobile ? '1.0625rem' : '1.375rem', maxWidth: isMobile ? '100%' : '36rem', marginBottom: isMobile ? 28 : undefined }}>
|
||||
{fallbackText(hero.description, 'Der Bayerische Mittelstandspreis würdigt herausragende Leistungen – von Innovation über Nachhaltigkeit bis hin zur Exzellenz.')}
|
||||
{fallbackText(hero.description, homeContent.hero.description)}
|
||||
</p>
|
||||
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
|
||||
<Link
|
||||
to={fallbackText(hero.primaryCta?.url, '/teilnahme')}
|
||||
to={fallbackText(hero.primaryCta?.url, homeContent.hero.primaryCta.url)}
|
||||
style={{ fontFamily:'"IBM Plex Sans", sans-serif', fontSize: 16, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.12em', color:'#101828', background:'#EFBF04', padding:'16px 36px', textDecoration:'none', display:'inline-flex', alignItems:'center', justifyContent: isMobile ? 'center' : 'flex-start', gap:10, transition:'background 0.15s, box-shadow 0.2s', width: isMobile ? '100%' : 'auto' }}
|
||||
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = '#FFD130'; (e.currentTarget as HTMLElement).style.boxShadow = '0 0 18px rgba(239,191,4,0.65), 0 0 40px rgba(239,191,4,0.3)'; }}
|
||||
onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = '#EFBF04'; (e.currentTarget as HTMLElement).style.boxShadow = 'none'; }}
|
||||
>
|
||||
{fallbackText(hero.primaryCta?.label, 'Jetzt kostenlos bewerben')} <ChevronRight size={16} />
|
||||
{fallbackText(hero.primaryCta?.label, homeContent.hero.primaryCta.label)} <ChevronRight size={16} />
|
||||
</Link>
|
||||
<div style={{ display: 'flex', flexDirection: isMobile ? 'column' : 'row', gap: 16, alignItems: isMobile ? 'stretch' : 'center' }}>
|
||||
<Link
|
||||
to={fallbackText(hero.secondaryCta?.url, '/mitglied-werden')}
|
||||
to={fallbackText(hero.secondaryCta?.url, homeContent.hero.secondaryCta.url)}
|
||||
style={{ fontFamily:'"IBM Plex Sans", sans-serif', fontSize: 16, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.12em', color:'rgba(255,255,255,0.85)', border:'1.5px solid rgba(255,255,255,0.35)', padding:'14px 32px', textDecoration:'none', display:'inline-flex', alignItems:'center', justifyContent: isMobile ? 'center' : 'flex-start', gap:10, transition:'border-color 0.15s, color 0.15s', background:'transparent', width: isMobile ? '100%' : 'auto' }}
|
||||
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.borderColor = '#EFBF04'; (e.currentTarget as HTMLElement).style.color = '#EFBF04'; }}
|
||||
onMouseLeave={e => { (e.currentTarget as HTMLElement).style.borderColor = 'rgba(255,255,255,0.35)'; (e.currentTarget as HTMLElement).style.color = 'rgba(255,255,255,0.85)'; }}
|
||||
>
|
||||
{fallbackText(hero.secondaryCta?.label, 'Mitglied werden')}
|
||||
{fallbackText(hero.secondaryCta?.label, homeContent.hero.secondaryCta.label)}
|
||||
</Link>
|
||||
<button
|
||||
onClick={() => setShowVideo(true)}
|
||||
@@ -255,7 +192,7 @@ const Home: React.FC = () => {
|
||||
<div className="w-12 h-12 rounded-full border border-white/30 flex items-center justify-center group-hover:border-accent group-hover:bg-accent/10 transition-all">
|
||||
<Play size={20} fill="currentColor" />
|
||||
</div>
|
||||
<span className="uppercase text-xs tracking-widest font-bold">{fallbackText(hero.videoLabel, 'Film abspielen')}</span>
|
||||
<span className="uppercase text-xs tracking-widest font-bold">{fallbackText(hero.videoLabel, homeContent.hero.videoLabel)}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -266,12 +203,12 @@ const Home: React.FC = () => {
|
||||
<div className="absolute bottom-0 left-0 w-full bg-white/5 backdrop-blur-xl border-t border-white/10 hidden lg:block">
|
||||
<div className="px-8 py-5 flex items-center justify-between opacity-60 hover:opacity-100 transition-opacity duration-500">
|
||||
{/* Left: label – stays put */}
|
||||
<span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 9, fontWeight: 700, letterSpacing: '0.3em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.5)', whiteSpace: 'nowrap', flexShrink: 0 }}>{fallbackText(hero.partnersLabel, 'Unsere Partner')}</span>
|
||||
<span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 9, fontWeight: 700, letterSpacing: '0.3em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.5)', whiteSpace: 'nowrap', flexShrink: 0 }}>{fallbackText(hero.partnersLabel, homeContent.hero.partnersLabel)}</span>
|
||||
{/* Right: ticker – fixed window, exactly 4 logos wide */}
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 16, flexShrink: 0 }}>
|
||||
<div style={{ width: 1, height: 20, background: 'rgba(255,255,255,0.2)' }} />
|
||||
<div style={{ width: 560, overflow: 'hidden', flexShrink: 0 }}>
|
||||
<PartnerTicker logos={fallbackArray(hero.partners, PARTNERS).map((partner: any) => partner.label ? partner : { id: partner.id || partner.name, label: <span style={{fontWeight:700,fontSize:10,letterSpacing:1.5}}>{partner.name}</span> })} />
|
||||
<PartnerTicker logos={partnerLogos(hero.partners)} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -287,15 +224,15 @@ const Home: React.FC = () => {
|
||||
{/* Eyebrow + heading – desktop only (on mobile these are overlaid on the image) */}
|
||||
{!isMobile && (
|
||||
<>
|
||||
<span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 10, color: '#4A8FC9', textTransform: 'uppercase', letterSpacing: '0.3em', fontWeight: 700, display: 'block', marginBottom: 16 }}>{fallbackText(quickCheck.eyebrow, 'Schnell-Check')}</span>
|
||||
<span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 10, color: '#4A8FC9', textTransform: 'uppercase', letterSpacing: '0.3em', fontWeight: 700, display: 'block', marginBottom: 16 }}>{fallbackText(quickCheck.eyebrow, homeContent.quickCheck.eyebrow)}</span>
|
||||
<h2 style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 'clamp(1.8rem, 2.8vw, 2.5rem)', fontWeight: 900, color: '#101828', textTransform: 'uppercase', letterSpacing: '-0.02em', lineHeight: 1.05, margin: '0 0 20px' }}>
|
||||
<Lines text={fallbackText(quickCheck.heading, 'SIND SIE\nBERECHTIGT?')} />
|
||||
<Lines text={fallbackText(quickCheck.heading, homeContent.quickCheck.heading)} />
|
||||
</h2>
|
||||
</>
|
||||
)}
|
||||
<div style={{ width: 40, height: 2, background: '#EFBF04', marginBottom: 28 }} />
|
||||
<p style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 17, color: 'rgba(16,24,40,0.6)', lineHeight: 1.7, marginBottom: 32 }}>
|
||||
{fallbackText(quickCheck.body, 'Der Bayerische Mittelstandspreis richtet sich an inhabergeführte KMU im Freistaat. Fünf Kriterien entscheiden, erfüllen Sie alle fünf, steht Ihrer Bewerbung nichts im Weg.')}
|
||||
{fallbackText(quickCheck.body, homeContent.quickCheck.body)}
|
||||
</p>
|
||||
{/* Criteria list */}
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 0, marginBottom: 36, borderTop: '1px solid #D0D5DD' }}>
|
||||
@@ -312,23 +249,23 @@ const Home: React.FC = () => {
|
||||
))}
|
||||
</div>
|
||||
<p style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 14, color: 'rgba(16,24,40,0.55)', lineHeight: 1.6, marginTop: 16, marginBottom: 28 }}>
|
||||
{fallbackText(quickCheck.note, 'Auch ein Verbund bzw. eine Gemeinschaft von mittelständischen Unternehmen oder von mittelständischen Unternehmen und Organisationen/Institutionen mit Schwerpunkt in Bayern kann teilnehmen.')}
|
||||
{fallbackText(quickCheck.note, homeContent.quickCheck.note)}
|
||||
</p>
|
||||
<Link
|
||||
to={fallbackText(quickCheck.cta?.url, '/teilnahme')}
|
||||
to={fallbackText(quickCheck.cta?.url, homeContent.quickCheck.cta.url)}
|
||||
style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 15, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.12em', color: '#101828', background: '#EFBF04', padding: '15px 32px', textDecoration: 'none', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8, alignSelf: isMobile ? 'stretch' : 'flex-start', transition: 'background 0.15s, box-shadow 0.2s' }}
|
||||
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = '#FFD130'; (e.currentTarget as HTMLElement).style.boxShadow = '0 0 18px rgba(239,191,4,0.65), 0 0 40px rgba(239,191,4,0.3)'; }}
|
||||
onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = '#EFBF04'; (e.currentTarget as HTMLElement).style.boxShadow = 'none'; }}
|
||||
>
|
||||
{fallbackText(quickCheck.cta?.label, 'Ihr Weg zum Preis')} <ChevronRight size={14} />
|
||||
{fallbackText(quickCheck.cta?.label, homeContent.quickCheck.cta.label)} <ChevronRight size={14} />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Right (desktop) / Top (mobile) – image; on mobile the heading is overlaid here */}
|
||||
<div style={{ position: 'relative', minHeight: isMobile ? 280 : 560, overflow: 'hidden', order: isMobile ? 1 : 0 }}>
|
||||
<Image unoptimized
|
||||
src={mediaUrl(quickCheck.image, '/images/buehne-gewinner.jpg')}
|
||||
alt={mediaAlt(quickCheck.image, fallbackText(quickCheck.imageAlt, 'Preisverleihung Bühne'))}
|
||||
src={mediaUrl(quickCheck.image, `/images/${homeContent.quickCheck.imageFilename}`)}
|
||||
alt={mediaAlt(quickCheck.image, fallbackText(quickCheck.imageAlt, homeContent.quickCheck.imageAlt))}
|
||||
style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: isMobile ? 'center right' : 'center center' }}
|
||||
/>
|
||||
{/* Overlay: mobile = navy shadow bottom-left (for the heading); desktop = leftward fade into text bg */}
|
||||
@@ -338,9 +275,9 @@ const Home: React.FC = () => {
|
||||
{/* Heading overlay – mobile only */}
|
||||
{isMobile && (
|
||||
<div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, padding: '0 24px 26px', zIndex: 2 }}>
|
||||
<span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 10, color: '#8FBEEC', textTransform: 'uppercase', letterSpacing: '0.3em', fontWeight: 700, display: 'block', marginBottom: 12 }}>{fallbackText(quickCheck.eyebrow, 'Schnell-Check')}</span>
|
||||
<span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 10, color: '#8FBEEC', textTransform: 'uppercase', letterSpacing: '0.3em', fontWeight: 700, display: 'block', marginBottom: 12 }}>{fallbackText(quickCheck.eyebrow, homeContent.quickCheck.eyebrow)}</span>
|
||||
<h2 style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 'clamp(1.9rem, 8vw, 2.5rem)', fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.02em', lineHeight: 1.05, margin: 0, textShadow: '0 2px 18px rgba(3,9,58,0.5)' }}>
|
||||
<Lines text={fallbackText(quickCheck.heading, 'SIND SIE\nBERECHTIGT?')} />
|
||||
<Lines text={fallbackText(quickCheck.heading, homeContent.quickCheck.heading)} />
|
||||
</h2>
|
||||
</div>
|
||||
)}
|
||||
@@ -357,8 +294,8 @@ const Home: React.FC = () => {
|
||||
{/* Left – full-bleed image with stats overlay (+ heading on mobile) */}
|
||||
<div style={{ position: 'relative', minHeight: isMobile ? 300 : 600, overflow: 'hidden' }}>
|
||||
<Image unoptimized
|
||||
src={mediaUrl(intro.image, '/images/preistraeger-jubel.jpg')}
|
||||
alt={mediaAlt(intro.image, fallbackText(intro.imageAlt, 'BMP Auszeichnung'))}
|
||||
src={mediaUrl(intro.image, `/images/${homeContent.intro.imageFilename}`)}
|
||||
alt={mediaAlt(intro.image, fallbackText(intro.imageAlt, homeContent.intro.imageAlt))}
|
||||
style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center top' }}
|
||||
/>
|
||||
{/* Dark overlay */}
|
||||
@@ -368,9 +305,9 @@ const Home: React.FC = () => {
|
||||
{/* Heading overlay – mobile only (bottom-left) */}
|
||||
{isMobile && (
|
||||
<div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, padding: '0 24px 26px', zIndex: 2 }}>
|
||||
<span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 10, color: '#8FBEEC', textTransform: 'uppercase', letterSpacing: '0.3em', fontWeight: 700, display: 'block', marginBottom: 12 }}>{fallbackText(intro.eyebrow, 'Ein Gewinn für alle')}</span>
|
||||
<span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 10, color: '#8FBEEC', textTransform: 'uppercase', letterSpacing: '0.3em', fontWeight: 700, display: 'block', marginBottom: 12 }}>{fallbackText(intro.eyebrow, homeContent.intro.eyebrow)}</span>
|
||||
<h2 style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 'clamp(1.9rem, 8vw, 2.5rem)', fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.02em', lineHeight: 1.05, margin: 0, textShadow: '0 2px 18px rgba(3,9,58,0.5)' }}>
|
||||
<Lines text={fallbackText(intro.heading, 'AUSZEICHNUNG\nFÜR DIE BESTEN.')} />
|
||||
<Lines text={fallbackText(intro.heading, homeContent.intro.heading)} />
|
||||
</h2>
|
||||
</div>
|
||||
)}
|
||||
@@ -391,9 +328,9 @@ const Home: React.FC = () => {
|
||||
<div style={{ background: '#fff', padding: isMobile ? '32px 24px 40px' : '80px 72px', display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
|
||||
{!isMobile && (
|
||||
<>
|
||||
<span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 10, color: '#4A8FC9', textTransform: 'uppercase', letterSpacing: '0.3em', fontWeight: 700, display: 'block', marginBottom: 16 }}>{fallbackText(intro.eyebrow, 'Ein Gewinn für alle')}</span>
|
||||
<span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 10, color: '#4A8FC9', textTransform: 'uppercase', letterSpacing: '0.3em', fontWeight: 700, display: 'block', marginBottom: 16 }}>{fallbackText(intro.eyebrow, homeContent.intro.eyebrow)}</span>
|
||||
<h2 style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 'clamp(2rem, 3.2vw, 2.8rem)', fontWeight: 900, color: '#101828', textTransform: 'uppercase', letterSpacing: '-0.02em', lineHeight: 1.05, margin: '0 0 20px' }}>
|
||||
<Lines text={fallbackText(intro.heading, 'AUSZEICHNUNG\nFÜR DIE BESTEN.')} />
|
||||
<Lines text={fallbackText(intro.heading, homeContent.intro.heading)} />
|
||||
</h2>
|
||||
</>
|
||||
)}
|
||||
@@ -410,18 +347,18 @@ const Home: React.FC = () => {
|
||||
)}
|
||||
<div style={{ width: 40, height: 2, background: '#EFBF04', marginBottom: 28, display: isMobile ? 'none' : 'block' }} />
|
||||
<blockquote style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 18, fontStyle: 'italic', color: '#101828', lineHeight: 1.7, borderLeft: '3px solid #EFBF04', paddingLeft: 20, margin: '0 0 24px' }}>
|
||||
{fallbackText(intro.quote, '„Ein Unternehmen zu gründen erfordert nicht allein spezielle Fähigkeiten. Es erfordert Persönlichkeit!“')}
|
||||
{fallbackText(intro.quote, homeContent.intro.quote)}
|
||||
</blockquote>
|
||||
<p style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 17, color: 'rgba(16,24,40,0.6)', lineHeight: 1.7, margin: '0 0 36px' }}>
|
||||
{fallbackText(intro.body, 'Wir suchen Vorbilder, die sich trotz aller Risiken nicht scheuen, Visionen in Businesspläne und Ideen in Unternehmungen zu verwandeln, und das mit großem persönlichen Einsatz und Verantwortung für Ihre Mitarbeiter. Seit vielen Jahren würdigen wir herausragende unternehmerische Leistungen im Freistaat.')}
|
||||
{fallbackText(intro.body, homeContent.intro.body)}
|
||||
</p>
|
||||
<Link
|
||||
to={fallbackText(intro.cta?.url, '/der-bmp')}
|
||||
to={fallbackText(intro.cta?.url, homeContent.intro.cta.url)}
|
||||
style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 15, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.1em', color: '#101828', background: '#EFBF04', padding: '14px 28px', textDecoration: 'none', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8, alignSelf: isMobile ? 'stretch' : 'flex-start', transition: 'background 0.15s, box-shadow 0.2s' }}
|
||||
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = '#FFD130'; (e.currentTarget as HTMLElement).style.boxShadow = '0 0 18px rgba(239,191,4,0.65), 0 0 40px rgba(239,191,4,0.3)'; }}
|
||||
onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = '#EFBF04'; (e.currentTarget as HTMLElement).style.boxShadow = 'none'; }}
|
||||
>
|
||||
{fallbackText(intro.cta?.label, 'Mehr über den Preis')} <ChevronRight size={14} />
|
||||
{fallbackText(intro.cta?.label, homeContent.intro.cta.label)} <ChevronRight size={14} />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
@@ -434,16 +371,16 @@ const Home: React.FC = () => {
|
||||
<section style={{ background: '#111D55' }}>
|
||||
<div style={{ padding: isMobile ? '48px 24px 32px' : '72px 80px 48px', display: 'flex', flexDirection: isMobile ? 'column' : 'row', alignItems: isMobile ? 'flex-start' : 'flex-end', justifyContent: 'space-between', gap: isMobile ? 16 : 0 }}>
|
||||
<div>
|
||||
<span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 10, fontWeight: 700, letterSpacing: '0.3em', textTransform: 'uppercase', color: '#EFBF04', display: 'block', marginBottom: 12 }}>{fallbackText(winnersSection.eyebrow, 'Success Stories')}</span>
|
||||
<span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 10, fontWeight: 700, letterSpacing: '0.3em', textTransform: 'uppercase', color: '#EFBF04', display: 'block', marginBottom: 12 }}>{fallbackText(winnersSection.eyebrow, homeContent.winners.eyebrow)}</span>
|
||||
<h2 style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 'clamp(2rem, 4vw, 3rem)', fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.02em', margin: 0, lineHeight: 1 }}>
|
||||
<Lines text={fallbackText(winnersSection.heading, 'DIE BESTEN UNTERNEHMEN IN BAYERN')} />
|
||||
<Lines text={fallbackText(winnersSection.heading, homeContent.winners.heading)} />
|
||||
</h2>
|
||||
</div>
|
||||
<Link
|
||||
to={fallbackText(winnersSection.cta?.url, '/preistraeger')}
|
||||
to={fallbackText(winnersSection.cta?.url, homeContent.winners.cta.url)}
|
||||
style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 15, fontWeight: 700, letterSpacing: '0.1em', textTransform: 'uppercase', color: '#EFBF04', textDecoration: 'none', display: 'flex', alignItems: 'center', gap: 6, paddingBottom: 4, borderBottom: '1px solid #EFBF04', whiteSpace: 'nowrap' }}
|
||||
>
|
||||
{fallbackText(winnersSection.cta?.label, 'Alle Preisträger')} <ChevronRight size={14} />
|
||||
{fallbackText(winnersSection.cta?.label, homeContent.winners.cta.label)} <ChevronRight size={14} />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -460,8 +397,14 @@ const Home: React.FC = () => {
|
||||
WebkitOverflowScrolling: 'touch',
|
||||
scrollbarWidth: 'none',
|
||||
}}>
|
||||
{homeWinners.map((w: any) => (
|
||||
<HomeWinnerCard key={w.id || w.slug} winner={w} />
|
||||
{homeWinners.map((w) => (
|
||||
<HomeWinnerCard
|
||||
key={(w as WinnerCardData).id || (w as WinnerCardData).slug}
|
||||
winner={w as WinnerCardData}
|
||||
fallbackTitle={fallbackText(winnersSection.cardFallbackTitle, homeContent.winners.cardFallbackTitle)}
|
||||
fallbackImage={winnerFallbackImage}
|
||||
hoverLabel={fallbackText(winnersSection.hoverLabel, homeContent.winners.hoverLabel)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
@@ -479,9 +422,9 @@ const Home: React.FC = () => {
|
||||
<div style={{ background: '#E4E2E3', padding: isMobile ? '32px 24px 44px' : '80px 72px', display: 'flex', flexDirection: 'column', justifyContent: 'center', order: isMobile ? 2 : 0 }}>
|
||||
{!isMobile && (
|
||||
<>
|
||||
<span style={{ fontFamily: FF, fontSize: 10, color: '#4A8FC9', textTransform: 'uppercase', letterSpacing: '0.3em', fontWeight: 700, display: 'block', marginBottom: 16 }}>{fallbackText(benefits.eyebrow, 'Mehr als nur ein Preis')}</span>
|
||||
<span style={{ fontFamily: FF, fontSize: 10, color: '#4A8FC9', textTransform: 'uppercase', letterSpacing: '0.3em', fontWeight: 700, display: 'block', marginBottom: 16 }}>{fallbackText(benefits.eyebrow, homeContent.benefits.eyebrow)}</span>
|
||||
<h2 style={{ fontFamily: FF, fontSize: 'clamp(2rem, 3vw, 2.6rem)', fontWeight: 900, color: '#101828', textTransform: 'uppercase', letterSpacing: '-0.02em', lineHeight: 1.05, margin: '0 0 48px' }}>
|
||||
<Lines text={fallbackText(benefits.heading, 'WARUM SICH DIE\nTEILNAHME LOHNT.')} />
|
||||
<Lines text={fallbackText(benefits.heading, homeContent.benefits.heading)} />
|
||||
</h2>
|
||||
</>
|
||||
)}
|
||||
@@ -508,8 +451,8 @@ const Home: React.FC = () => {
|
||||
{/* Right – full-bleed photo (+ heading on mobile) */}
|
||||
<div style={{ position: 'relative', overflow: 'hidden', minHeight: isMobile ? 280 : 'auto', order: isMobile ? 1 : 0 }}>
|
||||
<Image unoptimized
|
||||
src={mediaUrl(benefits.image, '/images/networking-innenhof.jpg')}
|
||||
alt={mediaAlt(benefits.image, fallbackText(benefits.imageAlt, 'BMP Gala Netzwerk'))}
|
||||
src={mediaUrl(benefits.image, `/images/${homeContent.benefits.imageFilename}`)}
|
||||
alt={mediaAlt(benefits.image, fallbackText(benefits.imageAlt, homeContent.benefits.imageAlt))}
|
||||
style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center center', display: 'block' }}
|
||||
/>
|
||||
<div style={{ position: 'absolute', inset: 0, background: isMobile
|
||||
@@ -518,16 +461,16 @@ const Home: React.FC = () => {
|
||||
{/* Heading overlay – mobile only (bottom-left) */}
|
||||
{isMobile && (
|
||||
<div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, padding: '0 24px 26px', zIndex: 2 }}>
|
||||
<span style={{ fontFamily: FF, fontSize: 10, color: '#8FBEEC', textTransform: 'uppercase', letterSpacing: '0.3em', fontWeight: 700, display: 'block', marginBottom: 12 }}>{fallbackText(benefits.eyebrow, 'Mehr als nur ein Preis')}</span>
|
||||
<span style={{ fontFamily: FF, fontSize: 10, color: '#8FBEEC', textTransform: 'uppercase', letterSpacing: '0.3em', fontWeight: 700, display: 'block', marginBottom: 12 }}>{fallbackText(benefits.eyebrow, homeContent.benefits.eyebrow)}</span>
|
||||
<h2 style={{ fontFamily: FF, fontSize: 'clamp(1.9rem, 8vw, 2.4rem)', fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.02em', lineHeight: 1.05, margin: 0, textShadow: '0 2px 18px rgba(3,9,58,0.5)' }}>
|
||||
<Lines text={fallbackText(benefits.heading, 'WARUM SICH DIE\nTEILNAHME LOHNT.')} />
|
||||
<Lines text={fallbackText(benefits.heading, homeContent.benefits.heading)} />
|
||||
</h2>
|
||||
</div>
|
||||
)}
|
||||
{/* Bottom-left label – desktop only */}
|
||||
{!isMobile && (
|
||||
<div style={{ position: 'absolute', bottom: 40, left: 40 }}>
|
||||
<div style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, letterSpacing: '0.2em', textTransform: 'uppercase', color: '#EFBF04', marginBottom: 6 }}>{fallbackText(benefits.imageLabel, 'BMP Gala-Netzwerk')}</div>
|
||||
<div style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, letterSpacing: '0.2em', textTransform: 'uppercase', color: '#EFBF04', marginBottom: 6 }}>{fallbackText(benefits.imageLabel, homeContent.benefits.imageLabel)}</div>
|
||||
<div style={{ width: 32, height: 2, background: '#EFBF04' }} />
|
||||
</div>
|
||||
)}
|
||||
@@ -544,13 +487,13 @@ const Home: React.FC = () => {
|
||||
|
||||
{/* Left – pitch copy */}
|
||||
<div style={{ padding: isMobile ? '32px 24px 24px' : '36px 36px 32px 52px', display: 'flex', flexDirection: 'column', justifyContent: 'center', overflow: 'hidden' }}>
|
||||
<span style={{ fontFamily: FF, fontSize: 10, color: '#EFBF04', textTransform: 'uppercase', letterSpacing: '0.36em', fontWeight: 700, display: 'block', marginBottom: 16, opacity: 0.8 }}>{fallbackText(application.eyebrow, 'Chance ergreifen')}</span>
|
||||
<span style={{ fontFamily: FF, fontSize: 10, color: '#EFBF04', textTransform: 'uppercase', letterSpacing: '0.36em', fontWeight: 700, display: 'block', marginBottom: 16, opacity: 0.8 }}>{fallbackText(application.eyebrow, homeContent.application.eyebrow)}</span>
|
||||
<h2 style={{ fontFamily: FF, fontSize: isMobile ? 'clamp(1.8rem, 8vw, 2.6rem)' : 'clamp(1.8rem, 2.8vw, 2.6rem)', fontWeight: 900, color: '#fff', textTransform: 'uppercase', letterSpacing: '-0.03em', lineHeight: 1.0, marginBottom: 16 }}>
|
||||
<Lines text={fallbackText(application.heading, 'SCHREIBEN\nAUCH SIE\nGESCHICHTE.')} />
|
||||
<Lines text={fallbackText(application.heading, homeContent.application.heading)} />
|
||||
</h2>
|
||||
<div style={{ width: 32, height: 2, background: '#EFBF04', marginBottom: 20 }} />
|
||||
<p style={{ fontFamily: FF, fontSize: 15, color: 'rgba(255,255,255,0.6)', lineHeight: 1.7, marginBottom: 32 }}>
|
||||
{fallbackText(application.body, 'Werden Sie Teil der Wall of Fame des bayerischen Mittelstands – vollständig kostenfrei.')}
|
||||
{fallbackText(application.body, homeContent.application.body)}
|
||||
</p>
|
||||
|
||||
{/* Benefit rows */}
|
||||
@@ -590,8 +533,8 @@ const Home: React.FC = () => {
|
||||
{!isMobile && (
|
||||
<div style={{ height: 220, position: 'relative', overflow: 'hidden', flexShrink: 0, zIndex: 1 }}>
|
||||
<Image unoptimized
|
||||
src={mediaUrl(application.awardImage, '/images/preisuebergabe.jpg')}
|
||||
alt={mediaAlt(application.awardImage, fallbackText(application.awardImageAlt, 'Preisverleihung Bayerischer Mittelstandspreis'))}
|
||||
src={mediaUrl(application.awardImage, `/images/${homeContent.application.awardImageFilename}`)}
|
||||
alt={mediaAlt(application.awardImage, fallbackText(application.awardImageAlt, homeContent.application.awardImageAlt))}
|
||||
style={{ width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center 25%', filter: 'sepia(0.18) brightness(0.92)' }}
|
||||
/>
|
||||
{/* Blend photo into gold panel */}
|
||||
@@ -599,15 +542,15 @@ const Home: React.FC = () => {
|
||||
<div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: 2, background: 'rgba(17,29,85,0.35)' }} />
|
||||
<div style={{ position: 'absolute', bottom: 14, left: 40, display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||
<div style={{ width: 5, height: 5, borderRadius: '50%', background: 'rgba(17,29,85,0.7)' }} />
|
||||
<span style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, color: 'rgba(17,29,85,0.75)', textTransform: 'uppercase', letterSpacing: '0.2em' }}>{fallbackText(application.awardCaption, 'Preisverleihung 2025')}</span>
|
||||
<span style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, color: 'rgba(17,29,85,0.75)', textTransform: 'uppercase', letterSpacing: '0.2em' }}>{fallbackText(application.awardCaption, homeContent.application.awardCaption)}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Form area */}
|
||||
<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 }}>{fallbackText(application.formEyebrow, '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 }}>{fallbackText(application.formTitle, 'Kostenlos bewerben')}</h3>
|
||||
<span style={{ fontFamily: FF, fontSize: 10, color: 'rgba(17,29,85,0.5)', textTransform: 'uppercase', letterSpacing: '0.32em', fontWeight: 700, display: 'block', marginBottom: 8 }}>{fallbackText(application.formEyebrow, homeContent.application.formEyebrow)}</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 }}>{fallbackText(application.formTitle, homeContent.application.formTitle)}</h3>
|
||||
<BewerbungsForm theme="gold" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -616,8 +559,8 @@ const Home: React.FC = () => {
|
||||
|
||||
{/* Footnote row */}
|
||||
<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: isMobile ? 6 : 10 }}>{fallbackText(application.footnote, 'Kostenlos und unverbindlich –')}</span>
|
||||
<span style={{ fontFamily: FF, fontSize: 15, fontWeight: 700, color: 'rgba(239,191,4,0.8)' }}>{fallbackText(application.footnoteStrong, 'keine Teilnahmegebühr')}</span>
|
||||
<span style={{ fontFamily: FF, fontSize: 15, color: 'rgba(255,255,255,0.45)', marginRight: isMobile ? 6 : 10 }}>{fallbackText(application.footnote, homeContent.application.footnote)}</span>
|
||||
<span style={{ fontFamily: FF, fontSize: 15, fontWeight: 700, color: 'rgba(239,191,4,0.8)' }}>{fallbackText(application.footnoteStrong, homeContent.application.footnoteStrong)}</span>
|
||||
</div>
|
||||
<div style={{ height: 2, background: 'linear-gradient(to right, #EFBF04, rgba(239,191,4,0.25), transparent)', flexShrink: 0 }} />
|
||||
</section>
|
||||
@@ -634,9 +577,9 @@ const Home: React.FC = () => {
|
||||
<div className="w-full max-w-6xl aspect-video bg-white/5 rounded-3xl overflow-hidden flex items-center justify-center relative">
|
||||
<div className="text-center">
|
||||
<Play size={80} className="text-accent mx-auto mb-6 opacity-40" />
|
||||
<p className="text-white/40 uppercase tracking-widest text-sm">{fallbackText(videoModal.title, 'Video-Player Platzhalter')}</p>
|
||||
<p className="text-white/60 mt-4 text-xs italic font-body">{fallbackText(videoModal.description, 'Hier würde das Image-Video des BMP geladen werden.')}</p>
|
||||
<Button onClick={() => setShowVideo(false)} className="mt-8" variant="outline">{fallbackText(videoModal.closeLabel, 'Schließen')}</Button>
|
||||
<p className="text-white/40 uppercase tracking-widest text-sm">{fallbackText(videoModal.title, homeContent.videoModal.title)}</p>
|
||||
<p className="text-white/60 mt-4 text-xs italic font-body">{fallbackText(videoModal.description, homeContent.videoModal.description)}</p>
|
||||
<Button onClick={() => setShowVideo(false)} className="mt-8" variant="outline">{fallbackText(videoModal.closeLabel, homeContent.videoModal.closeLabel)}</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -649,19 +592,24 @@ const Home: React.FC = () => {
|
||||
|
||||
function StatusSlider({ data }: { data?: HomeCms }) {
|
||||
const isMobile = useIsMobile();
|
||||
const phases = fallbackArray(data?.phases, STATUS_PHASES).map((phase: any, i) => {
|
||||
const fallbackPhase = STATUS_PHASES[i]
|
||||
const cta = phase?.cta?.label
|
||||
? { label: phase.cta.label, to: phase.cta.to || phase.cta.url || fallbackPhase?.cta?.to || '/' }
|
||||
: fallbackPhase?.cta
|
||||
const membershipCta = phase?.membershipCta?.label
|
||||
? { label: phase.membershipCta.label, to: phase.membershipCta.to || phase.membershipCta.url || '/mitglied-werden' }
|
||||
const phases = fallbackArray(data?.phases, homeContent.status.phases).map((phase, i) => {
|
||||
const phaseRecord = phase as StatusPhase
|
||||
const fallbackPhase = homeContent.status.phases[i]
|
||||
const fallbackCta = fallbackPhase?.cta
|
||||
? { label: fallbackPhase.cta.label, to: fallbackPhase.cta.url }
|
||||
: null
|
||||
const cta = phaseRecord?.cta?.label
|
||||
? { label: phaseRecord.cta.label, to: phaseRecord.cta.to || phaseRecord.cta.url || fallbackPhase?.cta?.url || '/' }
|
||||
: fallbackCta
|
||||
const membershipCta = phaseRecord?.membershipCta?.label
|
||||
? { label: phaseRecord.membershipCta.label, to: phaseRecord.membershipCta.to || phaseRecord.membershipCta.url || homeContent.hero.secondaryCta.url }
|
||||
: undefined
|
||||
|
||||
return { ...fallbackPhase, ...phase, cta, membershipCta }
|
||||
return { ...fallbackPhase, ...phaseRecord, cta, membershipCta }
|
||||
});
|
||||
const configuredActive = data?.activePhase !== undefined && data?.activePhase !== null ? Number(data.activePhase) : ACTIVE_PHASE;
|
||||
const active = Math.max(0, Math.min(phases.length - 1, Number.isFinite(configuredActive) ? configuredActive : ACTIVE_PHASE));
|
||||
const fallbackActivePhase = Number(homeContent.status.activePhase);
|
||||
const configuredActive = data?.activePhase !== undefined && data?.activePhase !== null ? Number(data.activePhase) : fallbackActivePhase;
|
||||
const active = Math.max(0, Math.min(phases.length - 1, Number.isFinite(configuredActive) ? configuredActive : fallbackActivePhase));
|
||||
const phase = phases[active];
|
||||
|
||||
return (
|
||||
@@ -673,14 +621,32 @@ function StatusSlider({ data }: { data?: HomeCms }) {
|
||||
minHeight: isMobile ? 360 : 'auto',
|
||||
}}
|
||||
>
|
||||
<StatusSlideCard phase={phase} isMobile={isMobile} noActionLabel={fallbackText(data?.noActionLabel, 'Kein Handlungsbedarf')} />
|
||||
<StatusSlideCard
|
||||
phase={phase}
|
||||
isMobile={isMobile}
|
||||
noActionLabel={fallbackText(data?.noActionLabel, homeContent.status.noActionLabel)}
|
||||
successApplicationsLabel={fallbackText(data?.successApplicationsLabel, homeContent.status.successApplicationsLabel)}
|
||||
successWinnersLabel={fallbackText(data?.successWinnersLabel, homeContent.status.successWinnersLabel)}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
// ─── StatusSlideCard ──────────────────────────────────────────────────────────
|
||||
|
||||
function StatusSlideCard({ phase, isMobile, noActionLabel }: { phase: StatusPhase & HomeCms; isMobile: boolean; noActionLabel: string }) {
|
||||
function StatusSlideCard({
|
||||
phase,
|
||||
isMobile,
|
||||
noActionLabel,
|
||||
successApplicationsLabel,
|
||||
successWinnersLabel,
|
||||
}: {
|
||||
phase: StatusPhase & HomeCms;
|
||||
isMobile: boolean;
|
||||
noActionLabel: string;
|
||||
successApplicationsLabel: string;
|
||||
successWinnersLabel: string;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@@ -755,11 +721,11 @@ function StatusSlideCard({ phase, isMobile, noActionLabel }: { phase: StatusPhas
|
||||
) : (
|
||||
/* Success stats */
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<div style={{ fontFamily: FF, fontSize: 68, fontWeight: 900, color: phase.accent, lineHeight: 1, opacity: 0.9 }}>{fallbackText(phase.successApplications, '247')}</div>
|
||||
<div style={{ fontFamily: FF, fontSize: 8, fontWeight: 700, letterSpacing: '0.35em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.50)', marginTop: 4, marginBottom: 20 }}>Bewerbungen</div>
|
||||
<div style={{ fontFamily: FF, fontSize: 68, fontWeight: 900, color: phase.accent, lineHeight: 1, opacity: 0.9 }}>{fallbackText(phase.successApplications, homeContent.status.phases[2]?.successApplications || '')}</div>
|
||||
<div style={{ fontFamily: FF, fontSize: 8, fontWeight: 700, letterSpacing: '0.35em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.50)', marginTop: 4, marginBottom: 20 }}>{successApplicationsLabel}</div>
|
||||
<div style={{ width: 1, height: 28, background: 'rgba(255,255,255,0.08)', margin: '0 auto 20px' }} />
|
||||
<div style={{ fontFamily: FF, fontSize: 44, fontWeight: 900, color: '#fff', lineHeight: 1 }}>{fallbackText(phase.successWinners, '3')}</div>
|
||||
<div style={{ fontFamily: FF, fontSize: 8, fontWeight: 700, letterSpacing: '0.35em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.50)', marginTop: 4 }}>Preisträger</div>
|
||||
<div style={{ fontFamily: FF, fontSize: 44, fontWeight: 900, color: '#fff', lineHeight: 1 }}>{fallbackText(phase.successWinners, homeContent.status.phases[2]?.successWinners || '')}</div>
|
||||
<div style={{ fontFamily: FF, fontSize: 8, fontWeight: 700, letterSpacing: '0.35em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.50)', marginTop: 4 }}>{successWinnersLabel}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -768,7 +734,7 @@ function StatusSlideCard({ phase, isMobile, noActionLabel }: { phase: StatusPhas
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<div style={{ width: 1, height: 20, background: 'rgba(255,255,255,0.08)', margin: '0 auto 20px' }} />
|
||||
<Link
|
||||
to={fallbackText(phase.membershipCta?.to || phase.membershipCta?.url, '/mitglied-werden')}
|
||||
to={fallbackText(phase.membershipCta?.to || phase.membershipCta?.url, homeContent.hero.secondaryCta.url)}
|
||||
onMouseDown={e => e.stopPropagation()}
|
||||
style={{
|
||||
fontFamily: FF,
|
||||
@@ -793,7 +759,7 @@ function StatusSlideCard({ phase, isMobile, noActionLabel }: { phase: StatusPhas
|
||||
(e.currentTarget as HTMLElement).style.borderColor = `${phase.accent}55`;
|
||||
}}
|
||||
>
|
||||
{fallbackText(phase.membershipCta?.label, 'Mitglied werden')} <ChevronRight size={13} />
|
||||
{fallbackText(phase.membershipCta?.label, homeContent.hero.secondaryCta.label)} <ChevronRight size={13} />
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user