feat(marketing-website): add BreakPilot marketing website with CMP integration

Multi-page marketing website positioned as "Deterministic Regulatory Engineering Platform":
- 7 pages: Home, Plattform, CE-Prozess, Product Compliance, Architektur, Team, Preise
- Platform Bridge animation (adapted from pitch-deck USP slide)
- Cookie-Banner with consent-service integration (breakpilot-marketing site)
- DE/EN language toggle + Dark/Light theme
- Docker service on port 3014

[guardrail-change] PlatformBridgeSection.tsx added to loc-exceptions (816 LOC, SVG animation)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-10 22:41:00 +02:00
parent 937eca6b77
commit d13f4511cb
68 changed files with 11493 additions and 0 deletions
@@ -0,0 +1,65 @@
'use client'
import { Check } from 'lucide-react'
import { t } from '@/lib/content'
import { useApp } from '@/lib/context'
import SectionHeading from '@/components/ui/SectionHeading'
import FadeInView from '@/components/ui/FadeInView'
const riskColors = {
red: { bg: 'bg-red-500/10', border: 'border-red-500/20', text: 'text-red-400', bar: 'bg-red-500' },
amber: { bg: 'bg-amber-500/10', border: 'border-amber-500/20', text: 'text-amber-400', bar: 'bg-amber-500' },
blue: { bg: 'bg-blue-500/10', border: 'border-blue-500/20', text: 'text-blue-400', bar: 'bg-blue-500' },
green: { bg: 'bg-green-500/10', border: 'border-green-500/20', text: 'text-green-400', bar: 'bg-green-500' },
}
export default function AIGovernanceSection() {
const { lang } = useApp()
const i = t(lang)
return (
<section id="ai-governance" className="py-24 sm:py-32 section-alt">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionHeading
tag={i.aiGovernance.tag}
title={i.aiGovernance.title}
titleHighlight={i.aiGovernance.titleHighlight}
subtitle={i.aiGovernance.subtitle}
/>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
<FadeInView direction="left">
<div className="space-y-3">
{i.aiGovernance.riskLevels.map((level, idx) => {
const colors = riskColors[level.color]
return (
<div key={idx} className={`rounded-xl border ${colors.border} ${colors.bg} p-4 flex items-center gap-4`}>
<div className={`w-1 h-10 rounded-full ${colors.bar} shrink-0`} />
<div>
<h4 className={`text-sm font-bold ${colors.text}`}>{level.level}</h4>
<p className="text-xs text-white/40">{level.description}</p>
</div>
</div>
)
})}
</div>
</FadeInView>
<FadeInView direction="right">
<div className="rounded-2xl border border-white/[0.06] bg-white/[0.03] p-6 h-full">
<h3 className="text-lg font-bold mb-4">Deterministische AI-Act-Compliance</h3>
<ul className="space-y-3">
{i.aiGovernance.features.map((feature, idx) => (
<li key={idx} className="flex items-start gap-3 text-sm text-white/60">
<Check className="w-4 h-4 text-accent-signal mt-0.5 shrink-0" />
{feature}
</li>
))}
</ul>
</div>
</FadeInView>
</div>
</div>
</section>
)
}
@@ -0,0 +1,73 @@
'use client'
import { Layers, Server, Database } from 'lucide-react'
import { t } from '@/lib/content'
import { useApp } from '@/lib/context'
import SectionHeading from '@/components/ui/SectionHeading'
import FadeInView from '@/components/ui/FadeInView'
import TechBadge from '@/components/ui/TechBadge'
const layerIcons = [Layers, Server, Database]
const layerColors = ['border-accent-electric/30', 'border-accent-indigo/30', 'border-accent-purple/30']
const layerBg = ['bg-accent-electric/5', 'bg-accent-indigo/5', 'bg-accent-purple/5']
export default function ArchitectureSection() {
const { lang } = useApp()
const i = t(lang)
return (
<section id="architecture" className="py-24 sm:py-32 section-alt">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionHeading
tag={i.architecture.tag}
title={i.architecture.title}
titleHighlight={i.architecture.titleHighlight}
subtitle={i.architecture.subtitle}
/>
<div className="space-y-4 mb-12">
{i.architecture.layers.map((layer, idx) => {
const Icon = layerIcons[idx]
return (
<FadeInView key={idx} delay={idx * 0.15}>
<div className={`rounded-2xl border ${layerColors[idx]} ${layerBg[idx]} p-6`}>
<div className="flex flex-col md:flex-row md:items-center gap-4">
<div className="flex items-center gap-3 md:w-64 shrink-0">
<Icon className="w-5 h-5 text-white/60" />
<h3 className="font-bold text-sm">{layer.name}</h3>
</div>
<div className="flex-1 flex flex-wrap gap-2">
{layer.components.map((comp, ci) => (
<span
key={ci}
className="px-3 py-1.5 rounded-lg text-xs bg-white/[0.06] border border-white/[0.06] text-white/70"
>
{comp}
</span>
))}
</div>
<TechBadge className="shrink-0">{layer.tech}</TechBadge>
</div>
</div>
</FadeInView>
)
})}
</div>
<FadeInView delay={0.5}>
<div className="flex flex-wrap justify-center gap-3">
{i.architecture.badges.map((badge, idx) => (
<span
key={idx}
className="inline-flex items-center gap-2 px-4 py-2 rounded-full border border-white/[0.08] bg-white/[0.03] text-xs text-white/60 font-medium"
>
<span className="w-1.5 h-1.5 rounded-full bg-accent-signal" />
{badge}
</span>
))}
</div>
</FadeInView>
</div>
</section>
)
}
@@ -0,0 +1,171 @@
'use client'
import { motion } from 'framer-motion'
import { FileText, Cpu, Shield, Search, ClipboardCheck, Download } from 'lucide-react'
import { useApp } from '@/lib/context'
import FadeInView from '@/components/ui/FadeInView'
import TechBadge from '@/components/ui/TechBadge'
import { ANIMATION } from '@/lib/constants'
const stepIcons = [FileText, Cpu, Shield, Search, ClipboardCheck, Download]
const flow = {
de: {
steps: [
{
num: '01',
title: 'Grenzen & Verwendung',
description: 'Der Nutzer füllt 14 Textfelder aus — Maschinenbeschreibung, bestimmungsgemäße Verwendung, Energiequellen, Betriebsarten, Personengruppen.',
example: '"Kollaborativer 6-Achs-Roboter UR10e mit Kraft-/Momentsensorik, elektrischer Antrieb 48V DC, Ethernet/PROFINET..."',
tags: [],
},
{
num: '02',
title: 'Automatische Analyse',
description: '6 deterministische Schritte in Sekunden: Narrative Parser (200 Keywords) → Komponenten → Pattern Engine (1.058 Patterns) → Gefährdungen → Maßnahmen (225 Bibliothek) → Normen (751 A/B/C).',
example: 'Pattern HP059 "Kollisionsgefahr Cobot": RequiredTags [cobot, rotating_joint] — PATTERN FEUERT ✓',
tags: ['Deterministisch', 'Kein LLM', 'AND/NOT-Logik'],
},
{
num: '03',
title: 'Risikobewertung',
description: 'Im Hazard Log erscheinen alle Gefährdungen mit Erstbewertung (S/E/P), RPZ-Berechnung und automatischer SIL/PL-Ableitung nach ISO-Risikograph.',
example: 'Cobot-Ergebnis: 12 Gefährdungen, RPZ 4-48, SIL 0-2, PL a-d',
tags: ['ISO 12100', 'SIL/PL', 'RPZ'],
},
{
num: '04',
title: 'Regulatorische Hinweise',
description: 'On-Demand RAG-Suche in 36.708 Chunks: BAuA (TRBS/TRGS/ASR), OSHA Technical Manual, EU-Verordnungen. Keine ISO-Texte — nur gemeinfreie Quellen.',
example: 'Gefährdung "Kollision" → TRBS 2111 Kap. 4.3, OSHA 1910.212(a)(1)',
tags: ['RAG', 'BAuA', 'OSHA'],
},
{
num: '05',
title: 'Verifikation & Nachweise',
description: '25 Evidenztypen werden automatisch vorgeschlagen. Der Nutzer erstellt Verifikationspläne und ordnet Prüfberichte zu.',
example: 'E01 Hazard Analysis Report, E04 Electrical Safety Test, E14 Software Validation',
tags: ['25 Evidenztypen', 'Traceability'],
},
{
num: '06',
title: 'CE-Akte generieren',
description: 'Strukturiertes Dokument nach MVO 2023/1230 Anhang IV: Beschreibung, Risikobeurteilung, Normen, Maßnahmen, Nachweise, Konformitätserklärung. Export als PDF.',
example: 'Vollständige Technische Dokumentation per Klick',
tags: ['MVO 2023/1230', 'Anhang IV', 'PDF'],
},
],
},
en: {
steps: [
{
num: '01',
title: 'Limits & Intended Use',
description: 'The user fills in 14 text fields — machine description, intended use, energy sources, operating modes, user groups.',
example: '"Collaborative 6-axis robot UR10e with force/torque sensing, electric drive 48V DC, Ethernet/PROFINET..."',
tags: [],
},
{
num: '02',
title: 'Automatic Analysis',
description: '6 deterministic steps in seconds: Narrative Parser (200 keywords) → Components → Pattern Engine (1,058 patterns) → Hazards → Mitigations (225 library) → Norms (751 A/B/C).',
example: 'Pattern HP059 "Collision hazard cobot": RequiredTags [cobot, rotating_joint] — PATTERN FIRES ✓',
tags: ['Deterministic', 'No LLM', 'AND/NOT logic'],
},
{
num: '03',
title: 'Risk Assessment',
description: 'The Hazard Log shows all hazards with initial assessment (S/E/P), RPZ calculation and automatic SIL/PL derivation per ISO risk graph.',
example: 'Cobot result: 12 hazards, RPZ 4-48, SIL 0-2, PL a-d',
tags: ['ISO 12100', 'SIL/PL', 'RPZ'],
},
{
num: '04',
title: 'Regulatory Guidance',
description: 'On-demand RAG search across 36,708 chunks: BAuA (TRBS/TRGS/ASR), OSHA Technical Manual, EU regulations. No ISO texts — only public domain sources.',
example: 'Hazard "Collision" → TRBS 2111 Ch. 4.3, OSHA 1910.212(a)(1)',
tags: ['RAG', 'BAuA', 'OSHA'],
},
{
num: '05',
title: 'Verification & Evidence',
description: '25 evidence types are automatically suggested. Users create verification plans and assign test reports.',
example: 'E01 Hazard Analysis Report, E04 Electrical Safety Test, E14 Software Validation',
tags: ['25 evidence types', 'Traceability'],
},
{
num: '06',
title: 'Generate CE File',
description: 'Structured document per MR 2023/1230 Annex IV: Description, risk assessment, norms, mitigations, evidence, declaration of conformity. Export as PDF.',
example: 'Complete technical documentation with one click',
tags: ['MR 2023/1230', 'Annex IV', 'PDF'],
},
],
},
}
function StepContent({ step, Icon }: { step: typeof flow.de.steps[0]; Icon: typeof FileText }) {
return (
<div className="relative pl-16">
<div className="absolute left-0 w-12 h-12 rounded-xl bg-accent-electric/10 border border-accent-electric/20 flex items-center justify-center">
<Icon className="w-5 h-5 text-accent-electric" />
</div>
<div className="rounded-2xl border border-white/[0.06] bg-white/[0.03] p-6">
<div className="flex items-center gap-3 mb-3">
<span className="font-mono text-xs text-accent-electric/60">{step.num}</span>
<h3 className="text-lg font-bold">{step.title}</h3>
</div>
<p className="text-sm text-white/50 mb-3">{step.description}</p>
<div className="rounded-lg bg-enterprise-darker border border-white/[0.04] px-4 py-3 mb-3">
<p className="font-mono text-xs text-white/40">{step.example}</p>
</div>
{step.tags.length > 0 && (
<div className="flex flex-wrap gap-1.5">
{step.tags.map(tag => (
<TechBadge key={tag}>{tag}</TechBadge>
))}
</div>
)}
</div>
</div>
)
}
export default function CEFlowSection() {
const { lang } = useApp()
const { steps } = flow[lang]
return (
<section className="py-16 sm:py-24">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="relative">
{/* Vertical line */}
<div className="absolute left-6 top-0 bottom-0 w-px bg-white/[0.06]" />
<div className="space-y-8">
{steps.map((step, idx) => {
const Icon = stepIcons[idx]
if (idx < 2) {
return (
<motion.div
key={idx}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: ANIMATION.duration, delay: 0.3 + idx * 0.15, ease: ANIMATION.ease }}
>
<StepContent step={step} Icon={Icon} />
</motion.div>
)
}
return (
<FadeInView key={idx} delay={0}>
<StepContent step={step} Icon={Icon} />
</FadeInView>
)
})}
</div>
</div>
</div>
</section>
)
}
@@ -0,0 +1,84 @@
'use client'
import { Check, AlertTriangle, X } from 'lucide-react'
import { useApp } from '@/lib/context'
import FadeInView from '@/components/ui/FadeInView'
import SectionHeading from '@/components/ui/SectionHeading'
type ReqStatus = 'done' | 'partial' | 'missing'
const statusIcons = { done: Check, partial: AlertTriangle, missing: X }
const statusColors = { done: 'text-green-400 bg-green-500/10', partial: 'text-amber-400 bg-amber-500/10', missing: 'text-red-400 bg-red-500/10' }
const heading = {
de: {
tag: 'CRA COMPLIANCE',
title: 'Was muss ich tun um',
titleHighlight: 'CRA-konform zu werden?',
subtitle: 'Der Cyber Resilience Act (EU 2024/2847) gilt ab September 2027. BreakPilot zeigt den Status pro Anforderung.',
},
en: {
tag: 'CRA COMPLIANCE',
title: 'What do I need to do to become',
titleHighlight: 'CRA-compliant?',
subtitle: 'The Cyber Resilience Act (EU 2024/2847) applies from September 2027. BreakPilot shows the status per requirement.',
},
}
const requirements = {
de: [
{ req: 'Schwachstellenmanagement einrichten', detail: 'Prozess für Identifikation, Bewertung und Behebung von Schwachstellen', status: 'missing' as ReqStatus },
{ req: 'SBOM erstellen und pflegen', detail: 'Software Bill of Materials für jedes Produkt mit digitalen Elementen', status: 'partial' as ReqStatus },
{ req: 'Security-Updates ermöglichen (OTA/SOTA)', detail: 'Mechanismus für sichere Software-Updates über die gesamte Lebensdauer', status: 'missing' as ReqStatus },
{ req: 'Meldepflichten etablieren (24h/72h)', detail: 'Aktiv ausgenutzte Schwachstellen innerhalb 24h an ENISA melden', status: 'missing' as ReqStatus },
{ req: 'Koordinierte Offenlegung (PSIRT)', detail: 'Product Security Incident Response Team und Disclosure Policy', status: 'missing' as ReqStatus },
{ req: 'Technische Dokumentation aktualisieren', detail: 'Risikoanalyse, Design-Entscheidungen, Test-Ergebnisse dokumentieren', status: 'partial' as ReqStatus },
{ req: 'Secure by Design', detail: 'Standardmäßig sichere Konfiguration, minimale Angriffsfläche', status: 'done' as ReqStatus },
{ req: 'Keine bekannten Schwachstellen ausliefern', detail: 'Vor Inverkehrbringen alle bekannten CVEs beheben', status: 'partial' as ReqStatus },
],
en: [
{ req: 'Establish vulnerability management', detail: 'Process for identification, assessment and remediation of vulnerabilities', status: 'missing' as ReqStatus },
{ req: 'Create and maintain SBOM', detail: 'Software Bill of Materials for every product with digital elements', status: 'partial' as ReqStatus },
{ req: 'Enable security updates (OTA/SOTA)', detail: 'Mechanism for secure software updates throughout the product lifetime', status: 'missing' as ReqStatus },
{ req: 'Establish reporting obligations (24h/72h)', detail: 'Report actively exploited vulnerabilities to ENISA within 24h', status: 'missing' as ReqStatus },
{ req: 'Coordinated disclosure (PSIRT)', detail: 'Product Security Incident Response Team and disclosure policy', status: 'missing' as ReqStatus },
{ req: 'Update technical documentation', detail: 'Document risk analysis, design decisions, test results', status: 'partial' as ReqStatus },
{ req: 'Secure by Design', detail: 'Secure configuration by default, minimal attack surface', status: 'done' as ReqStatus },
{ req: 'Ship without known vulnerabilities', detail: 'Remediate all known CVEs before placing on market', status: 'partial' as ReqStatus },
],
}
export default function CRAFahrplanSection() {
const { lang } = useApp()
const h = heading[lang]
const reqs = requirements[lang]
return (
<section className="py-24 sm:py-32">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionHeading tag={h.tag} title={h.title} titleHighlight={h.titleHighlight} subtitle={h.subtitle} />
<div className="space-y-3">
{reqs.map((item, idx) => {
const Icon = statusIcons[item.status]
return (
<FadeInView key={idx} delay={idx * 0.05}>
<div className="rounded-xl border border-white/[0.06] bg-white/[0.03] p-4 flex items-start gap-4">
<div className={`w-8 h-8 rounded-lg ${statusColors[item.status]} flex items-center justify-center shrink-0 mt-0.5`}>
<Icon className="w-4 h-4" />
</div>
<div className="flex-1 min-w-0">
<h4 className="text-sm font-bold mb-0.5">{item.req}</h4>
<p className="text-xs text-white/40">{item.detail}</p>
</div>
<span className={`text-xs font-mono shrink-0 ${item.status === 'done' ? 'text-green-400' : item.status === 'partial' ? 'text-amber-400' : 'text-red-400'}`}>
{item.status === 'done' ? '✓' : item.status === 'partial' ? '◐' : '✗'}
</span>
</div>
</FadeInView>
)
})}
</div>
</div>
</section>
)
}
@@ -0,0 +1,72 @@
'use client'
import { Shield, GitBranch, Server, Scan, FileCheck, Layers } from 'lucide-react'
import { useApp } from '@/lib/context'
import SectionHeading from '@/components/ui/SectionHeading'
import GlassCard from '@/components/ui/GlassCard'
const icons = [Shield, GitBranch, Scan, Server, FileCheck, Layers]
const content = {
de: {
tag: '05 / DIFFERENZIERUNG',
title: 'Was BreakPilot',
titleHighlight: 'einzigartig macht.',
subtitle: 'Sechs Alleinstellungsmerkmale, die kein anderer Anbieter in einer Plattform vereint.',
items: [
{ title: 'Deterministisch, nicht generativ', description: 'Regelbasierte Analyse statt LLM-Interpretation. Jedes Ergebnis ist reproduzierbar und versioniert — unabhängig vom Modell.' },
{ title: 'Lückenloser Decision Trail', description: 'Von der Rechtsquelle über die Obligation zum Control bis zur Maßnahme. Jeder Schritt ist auditierbar und dokumentiert.' },
{ title: 'Code Security integriert', description: 'SAST, DAST, SBOM und Container Scanning als Teil der Compliance-Plattform — nicht als separates Tool.' },
{ title: 'Vollständig on-premise deploybar', description: 'Kein US-Cloud-Anbieter in der gesamten Architektur. Betrieb auf eigener Hardware oder in BSI-zertifizierten Rechenzentren.' },
{ title: 'Regulierungsübergreifend', description: 'DSGVO, NIS2, AI Act, Maschinenverordnung, TDDDG, DORA — eine Plattform statt sieben Einzellösungen.' },
{ title: '294.000+ atomare Controls', description: 'Abgeleitet aus 380+ Rechtsquellen. Nicht manuell kuratiert, sondern systematisch aus Originaltext extrahiert und verifiziert.' },
],
},
en: {
tag: '05 / DIFFERENTIATION',
title: 'What makes BreakPilot',
titleHighlight: 'unique.',
subtitle: 'Six unique selling points that no other provider combines in a single platform.',
items: [
{ title: 'Deterministic, not generative', description: 'Rule-based analysis instead of LLM interpretation. Every result is reproducible and versioned — independent of the model.' },
{ title: 'Seamless decision trail', description: 'From legal source through obligation to control to action. Every step is auditable and documented.' },
{ title: 'Code security integrated', description: 'SAST, DAST, SBOM and container scanning as part of the compliance platform — not as a separate tool.' },
{ title: 'Fully on-premise deployable', description: 'No US cloud provider in the entire architecture. Operation on own hardware or in BSI-certified data centers.' },
{ title: 'Cross-regulatory', description: 'GDPR, NIS2, AI Act, Machinery Regulation, TDDDG, DORA — one platform instead of seven individual solutions.' },
{ title: '294,000+ atomic controls', description: 'Derived from 380+ legal sources. Not manually curated, but systematically extracted and verified from original text.' },
],
},
}
export default function ComparisonSection() {
const { lang } = useApp()
const c = content[lang]
return (
<section id="comparison" className="py-24 sm:py-32">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionHeading
tag={c.tag}
title={c.title}
titleHighlight={c.titleHighlight}
subtitle={c.subtitle}
/>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{c.items.map((item, idx) => {
const Icon = icons[idx]
return (
<GlassCard key={idx} delay={idx * 0.08}>
<div className="w-10 h-10 rounded-xl bg-accent-electric/10 flex items-center justify-center mb-4">
<Icon className="w-5 h-5 text-accent-electric" />
</div>
<h3 className="text-sm font-bold mb-2">{item.title}</h3>
<p className="text-xs text-white/40 leading-relaxed">{item.description}</p>
</GlassCard>
)
})}
</div>
</div>
</section>
)
}
@@ -0,0 +1,62 @@
'use client'
import { X, Check } from 'lucide-react'
import { t } from '@/lib/content'
import { useApp } from '@/lib/context'
import SectionHeading from '@/components/ui/SectionHeading'
import FadeInView from '@/components/ui/FadeInView'
import StatusIndicator from '@/components/ui/StatusIndicator'
export default function ContinuousSection() {
const { lang } = useApp()
const i = t(lang)
return (
<section id="continuous" className="py-24 sm:py-32 section-alt">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionHeading
tag={i.continuous.tag}
title={i.continuous.title}
titleHighlight={i.continuous.titleHighlight}
subtitle={i.continuous.subtitle}
/>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<FadeInView direction="left">
<div className="rounded-2xl border border-red-500/15 bg-red-500/[0.03] p-6 h-full">
<div className="flex items-center gap-3 mb-6">
<StatusIndicator label="Offline" status="error" />
<h3 className="text-sm font-bold text-red-400">{i.continuous.comparison.annual.title}</h3>
</div>
<ul className="space-y-3">
{i.continuous.comparison.annual.points.map((point, idx) => (
<li key={idx} className="flex items-start gap-3 text-sm text-white/40">
<X className="w-4 h-4 text-red-400/50 mt-0.5 shrink-0" />
{point}
</li>
))}
</ul>
</div>
</FadeInView>
<FadeInView direction="right">
<div className="rounded-2xl border border-green-500/15 bg-green-500/[0.03] p-6 h-full">
<div className="flex items-center gap-3 mb-6">
<StatusIndicator label="Live" status="active" />
<h3 className="text-sm font-bold text-green-400">{i.continuous.comparison.continuous.title}</h3>
</div>
<ul className="space-y-3">
{i.continuous.comparison.continuous.points.map((point, idx) => (
<li key={idx} className="flex items-start gap-3 text-sm text-white/60">
<Check className="w-4 h-4 text-green-400 mt-0.5 shrink-0" />
{point}
</li>
))}
</ul>
</div>
</FadeInView>
</div>
</div>
</section>
)
}
@@ -0,0 +1,129 @@
'use client'
import { motion } from 'framer-motion'
import { X } from 'lucide-react'
import { useApp } from '@/lib/context'
const data = {
de: {
before: {
title: 'Ausgangslage',
items: [
'15 Jahre altes Embedded Board',
'Kein Secure Element / TPM',
'Kein Secure Boot, kein OTA',
'Hardcoded Credentials im Firmware',
'Alter TCP/IP Stack ohne Patches',
'Penetration-Test: 187 Findings',
'"Was davon ist wirklich kritisch?"',
],
},
after: {
title: 'BreakPilot Delta-Analyse',
items: [
{ text: '3 Findings blockieren CE/CRA → sofort handeln', type: 'critical' as const },
{ text: '12 Findings sind Software-only Fixes', type: 'fixable' as const },
{ text: '172 Findings sind kosmetisch oder low-risk', type: 'ok' as const },
{ text: 'Hardware-Redesign: wahrscheinlich NICHT nötig', type: 'ok' as const },
{ text: 'RED-Re-Zertifizierung: nur bei Funkmodul-Änderung', type: 'fixable' as const },
{ text: 'Geschätzter Aufwand: €15k statt €50k', type: 'ok' as const },
{ text: 'Jira-Tickets mit Fix-Vorschlägen erstellt', type: 'ok' as const },
],
},
},
en: {
before: {
title: 'Starting Point',
items: [
'15-year-old embedded board',
'No Secure Element / TPM',
'No Secure Boot, no OTA',
'Hardcoded credentials in firmware',
'Legacy TCP/IP stack without patches',
'Penetration test: 187 findings',
'"Which ones actually matter?"',
],
},
after: {
title: 'BreakPilot Delta Analysis',
items: [
{ text: '3 findings block CE/CRA → act immediately', type: 'critical' as const },
{ text: '12 findings are software-only fixes', type: 'fixable' as const },
{ text: '172 findings are cosmetic or low-risk', type: 'ok' as const },
{ text: 'Hardware redesign: probably NOT necessary', type: 'ok' as const },
{ text: 'RED re-certification: only if RF module changes', type: 'fixable' as const },
{ text: 'Estimated effort: €15k instead of €50k', type: 'ok' as const },
{ text: 'Jira tickets with fix suggestions created', type: 'ok' as const },
],
},
},
}
const typeColors = {
critical: 'text-red-400',
fixable: 'text-amber-400',
ok: 'text-green-400',
}
const typeIcons = {
critical: '●',
fixable: '◐',
ok: '●',
}
export default function DeltaImpactSection() {
const { lang } = useApp()
const d = data[lang]
return (
<section className="py-16 sm:py-24">
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 relative">
{/* Before */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, ease: [0.22, 1, 0.36, 1] }}
>
<div className="rounded-2xl border border-red-500/15 bg-red-500/[0.03] p-6 h-full">
<h3 className="text-sm font-bold text-red-400 mb-5 font-mono uppercase tracking-wider">
{d.before.title}
</h3>
<ul className="space-y-3">
{d.before.items.map((item, idx) => (
<li key={idx} className="flex items-start gap-3 text-sm text-white/40">
<X className="w-4 h-4 text-red-400/50 mt-0.5 shrink-0" />
{item}
</li>
))}
</ul>
</div>
</motion.div>
{/* After */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1] }}
>
<div className="rounded-2xl border border-green-500/15 bg-green-500/[0.03] p-6 h-full">
<h3 className="text-sm font-bold text-green-400 mb-5 font-mono uppercase tracking-wider">
{d.after.title}
</h3>
<ul className="space-y-3">
{d.after.items.map((item, idx) => (
<li key={idx} className="flex items-start gap-3 text-sm text-white/60">
<span className={`mt-0.5 shrink-0 text-xs ${typeColors[item.type]}`}>
{typeIcons[item.type]}
</span>
{item.text}
</li>
))}
</ul>
</div>
</motion.div>
</div>
</div>
</section>
)
}
@@ -0,0 +1,79 @@
'use client'
import { Shield, FileCheck, ClipboardCheck, Check, X } from 'lucide-react'
import { t } from '@/lib/content'
import { useApp } from '@/lib/context'
import SectionHeading from '@/components/ui/SectionHeading'
import GlassCard from '@/components/ui/GlassCard'
import FadeInView from '@/components/ui/FadeInView'
const iconMap: Record<string, typeof Shield> = {
Shield,
FileCheck,
ClipboardCheck,
}
export default function DeterministicSection() {
const { lang } = useApp()
const i = t(lang)
return (
<section id="deterministic" className="py-24 sm:py-32">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionHeading
tag={i.deterministic.tag}
title={i.deterministic.title}
titleHighlight={i.deterministic.titleHighlight}
subtitle={i.deterministic.subtitle}
/>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-16">
{i.deterministic.pillars.map((pillar, idx) => {
const Icon = iconMap[pillar.icon]
return (
<GlassCard key={idx} delay={idx * 0.1}>
<div className="w-12 h-12 rounded-xl bg-accent-indigo/10 flex items-center justify-center mb-4">
<Icon className="w-6 h-6 text-accent-indigo" />
</div>
<h3 className="text-lg font-bold mb-2">{pillar.title}</h3>
<p className="text-sm text-white/50">{pillar.description}</p>
</GlassCard>
)
})}
</div>
<FadeInView>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="rounded-2xl border border-red-500/20 bg-red-500/[0.04] p-6">
<h4 className="text-sm font-bold text-red-400 mb-4 font-mono uppercase tracking-wider">
{i.deterministic.comparison.llm.title}
</h4>
<ul className="space-y-3">
{i.deterministic.comparison.llm.items.map((item, idx) => (
<li key={idx} className="flex items-start gap-3 text-sm text-white/50">
<X className="w-4 h-4 text-red-400/60 mt-0.5 shrink-0" />
{item}
</li>
))}
</ul>
</div>
<div className="rounded-2xl border border-green-500/20 bg-green-500/[0.04] p-6">
<h4 className="text-sm font-bold text-green-400 mb-4 font-mono uppercase tracking-wider">
{i.deterministic.comparison.breakpilot.title}
</h4>
<ul className="space-y-3">
{i.deterministic.comparison.breakpilot.items.map((item, idx) => (
<li key={idx} className="flex items-start gap-3 text-sm text-white/70">
<Check className="w-4 h-4 text-green-400 mt-0.5 shrink-0" />
{item}
</li>
))}
</ul>
</div>
</div>
</FadeInView>
</div>
</section>
)
}
@@ -0,0 +1,91 @@
'use client'
import { motion } from 'framer-motion'
import { ArrowRight, ChevronDown } from 'lucide-react'
import { t } from '@/lib/content'
import { useApp } from '@/lib/context'
import GradientText from '@/components/ui/GradientText'
import CTAButton from '@/components/ui/CTAButton'
import StatusIndicator from '@/components/ui/StatusIndicator'
import { ANIMATION } from '@/lib/constants'
export default function HeroSection() {
const { lang } = useApp()
const i = t(lang)
return (
<section id="hero" className="relative min-h-screen flex items-center justify-center enterprise-grid overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-transparent to-enterprise-dark" />
<div className="relative z-10 max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, ease: ANIMATION.ease }}
>
<div className="inline-flex items-center gap-3 mb-8 px-4 py-2 rounded-full border border-white/[0.08] bg-white/[0.04]">
<StatusIndicator label={i.hero.status} />
</div>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.1, ease: ANIMATION.ease }}
className="mb-3"
>
<span className="mono-label tracking-widest">{i.hero.badge}</span>
</motion.div>
<motion.h1
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.2, ease: ANIMATION.ease }}
className="text-5xl sm:text-6xl lg:text-7xl font-bold mb-6 leading-tight text-shadow-glow"
>
{i.hero.title}
<br />
<GradientText>{i.hero.titleHighlight}</GradientText>
</motion.h1>
<motion.p
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.3, ease: ANIMATION.ease }}
className="text-lg sm:text-xl text-white/50 max-w-2xl mx-auto mb-10"
>
{i.hero.subtitle}
</motion.p>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.4, ease: ANIMATION.ease }}
className="flex flex-col sm:flex-row items-center justify-center gap-4"
>
<CTAButton href="/plattform">
{lang === 'de' ? 'Plattform entdecken' : 'Discover Platform'}
<ArrowRight className="w-4 h-4" />
</CTAButton>
<CTAButton variant="ghost" href="/preise">
{i.hero.cta}
</CTAButton>
</motion.div>
</div>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 1, delay: 1 }}
className="absolute bottom-8 left-1/2 -translate-x-1/2"
>
<motion.div
animate={{ y: [0, 8, 0] }}
transition={{ duration: 2, repeat: Infinity, ease: 'easeInOut' }}
>
<ChevronDown className="w-5 h-5 text-white/20" />
</motion.div>
</motion.div>
</section>
)
}
@@ -0,0 +1,82 @@
'use client'
import { t } from '@/lib/content'
import { useApp } from '@/lib/context'
import SectionHeading from '@/components/ui/SectionHeading'
import FadeInView from '@/components/ui/FadeInView'
const statusColors = {
success: 'text-green-400',
warning: 'text-amber-400',
neutral: 'text-accent-electric',
}
const statusDots = {
success: 'bg-green-400',
warning: 'bg-amber-400',
neutral: 'bg-accent-electric',
}
export default function ImpactSection() {
const { lang } = useApp()
const i = t(lang)
return (
<section id="impact" className="py-24 sm:py-32">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionHeading
tag={i.impact.tag}
title={i.impact.title}
titleHighlight={i.impact.titleHighlight}
subtitle={i.impact.subtitle}
/>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
<FadeInView direction="left">
<div className="rounded-2xl bg-enterprise-darker border border-white/[0.06] p-6 font-mono text-sm overflow-hidden">
<div className="flex items-center gap-2 mb-4 pb-3 border-b border-white/[0.06]">
<div className="w-3 h-3 rounded-full bg-red-500/60" />
<div className="w-3 h-3 rounded-full bg-amber-500/60" />
<div className="w-3 h-3 rounded-full bg-green-500/60" />
<span className="ml-2 text-xs text-white/30">regulatory-impact-analysis</span>
</div>
<div className="space-y-2">
{i.impact.terminalLines.map((line, idx) => (
<div
key={idx}
className={`
${line.type === 'input' ? 'text-white/70' : ''}
${line.type === 'output' ? 'text-white/40' : ''}
${line.type === 'signal' ? 'text-green-400' : ''}
`}
>
{line.text}
</div>
))}
</div>
</div>
</FadeInView>
<FadeInView direction="right">
<div className="grid grid-cols-2 gap-4 h-full">
{i.impact.outputs.map((output, idx) => (
<div
key={idx}
className="rounded-2xl bg-white/[0.04] border border-white/[0.06] p-5 flex flex-col justify-between"
>
<p className="text-xs text-white/40 mb-2">{output.label}</p>
<div className="flex items-center gap-2">
<span className={`w-2 h-2 rounded-full ${statusDots[output.status]}`} />
<span className={`text-2xl font-bold ${statusColors[output.status]}`}>
{output.value}
</span>
</div>
</div>
))}
</div>
</FadeInView>
</div>
</div>
</section>
)
}
@@ -0,0 +1,46 @@
'use client'
import { Check } from 'lucide-react'
import { t } from '@/lib/content'
import { useApp } from '@/lib/context'
import SectionHeading from '@/components/ui/SectionHeading'
import GlassCard from '@/components/ui/GlassCard'
const accentColors = ['border-t-accent-electric', 'border-t-accent-indigo', 'border-t-accent-purple']
export default function LegalSection() {
const { lang } = useApp()
const i = t(lang)
return (
<section id="legal" className="py-24 sm:py-32">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionHeading
tag={i.legal.tag}
title={i.legal.title}
titleHighlight={i.legal.titleHighlight}
subtitle={i.legal.subtitle}
/>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{i.legal.regulations.map((reg, idx) => (
<GlassCard key={idx} delay={idx * 0.1} className={`border-t-2 ${accentColors[idx]}`}>
<div className="mb-4">
<h3 className="text-2xl font-bold font-mono">{reg.name}</h3>
<p className="text-xs text-white/40 mt-1">{reg.fullName}</p>
</div>
<ul className="space-y-2">
{reg.features.map((feature, fi) => (
<li key={fi} className="flex items-start gap-2 text-sm text-white/50">
<Check className="w-3.5 h-3.5 text-accent-signal mt-0.5 shrink-0" />
{feature}
</li>
))}
</ul>
</GlassCard>
))}
</div>
</div>
</section>
)
}
@@ -0,0 +1,816 @@
'use client'
import { useState, useEffect, useRef, useMemo } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import GradientText from '@/components/ui/GradientText'
import FadeInView from '@/components/ui/FadeInView'
import { useApp } from '@/lib/context'
import { X } from 'lucide-react'
const MONO: React.CSSProperties = {
fontFamily: '"JetBrains Mono","SF Mono",ui-monospace,monospace',
fontVariantNumeric: 'tabular-nums',
}
const CSS_KF = `
@keyframes uspFlowR { 0%{stroke-dashoffset:0} 100%{stroke-dashoffset:-14px} }
@keyframes uspSpin { from{transform:rotate(0deg)} to{transform:rotate(360deg)} }
@keyframes uspPulse {
0%,100% { box-shadow: 0 0 38px rgba(167,139,250,.55), 0 0 80px rgba(167,139,250,.2), inset 0 3px 0 rgba(255,255,255,.35), inset 0 -6px 12px rgba(0,0,0,.35); }
50% { box-shadow: 0 0 58px rgba(167,139,250,.85), 0 0 110px rgba(167,139,250,.35), inset 0 3px 0 rgba(255,255,255,.4), inset 0 -6px 12px rgba(0,0,0,.35); }
}
@keyframes uspPulseLight {
0%,100% { box-shadow: 0 0 28px rgba(167,139,250,.4), 0 0 56px rgba(167,139,250,.15), inset 0 3px 0 rgba(255,255,255,.5), inset 0 -6px 12px rgba(0,0,0,.2); }
50% { box-shadow: 0 0 44px rgba(167,139,250,.65), 0 0 80px rgba(167,139,250,.25), inset 0 3px 0 rgba(255,255,255,.55), inset 0 -6px 12px rgba(0,0,0,.2); }
}
@keyframes uspHeading {
0%,100% { text-shadow: 0 0 22px rgba(167,139,250,.3); }
50% { text-shadow: 0 0 36px rgba(167,139,250,.55); }
}
`
// ── Light mode hook ───────────────────────────────────────────────────────────
function useIsLight() {
const [isLight, setIsLight] = useState(false)
useEffect(() => {
const check = () => setIsLight(document.documentElement.classList.contains('theme-light'))
check()
const obs = new MutationObserver(check)
obs.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] })
return () => obs.disconnect()
}, [])
return isLight
}
// ── Ticker ────────────────────────────────────────────────────────────────────
function useTicker(fn: () => void, min = 180, max = 420, skip = 0.1) {
const ref = useRef(fn)
ref.current = fn
useEffect(() => {
let t: ReturnType<typeof setTimeout>
const loop = () => {
if (Math.random() > skip) ref.current()
t = setTimeout(loop, min + Math.random() * (max - min))
}
loop()
return () => clearTimeout(t)
}, [min, max, skip])
}
function TickerShell({ tint, isLight, children }: { tint: string; isLight: boolean; children: React.ReactNode }) {
return (
<div style={{
...MONO, marginTop: 10, padding: '5px 9px',
background: isLight ? '#f1f5f9' : 'rgba(0,0,0,.38)',
border: `1px solid ${tint}55`,
borderRadius: 6, fontSize: 10.5,
color: isLight ? '#475569' : 'rgba(236,233,247,.88)',
display: 'flex', alignItems: 'center', gap: 7,
whiteSpace: 'nowrap', overflow: 'hidden', height: 22,
}}>{children}</div>
)
}
function TickTrace({ tint, isLight }: { tint: string; isLight: boolean }) {
const [n, setN] = useState(12748)
useTicker(() => setN(v => v + 1 + Math.floor(Math.random() * 3)), 250, 500)
return (
<TickerShell tint={tint} isLight={isLight}>
<span style={{ color: isLight ? '#16a34a' : '#4ade80' }}></span>
<span style={{ color: tint, opacity: .85 }}>trace</span>
<span style={{ color: isLight ? '#1a1a2e' : '#f5f3fc', fontWeight: 600 }}>{n.toLocaleString()}</span>
<span style={{ color: isLight ? '#94a3b8' : 'rgba(236,233,247,.45)' }}>evidence-chain</span>
</TickerShell>
)
}
function TickEngine({ tint, isLight }: { tint: string; isLight: boolean }) {
const [v, setV] = useState(428)
const [rate, setRate] = useState(99.4)
useTicker(() => {
setV(x => x + 1 + Math.floor(Math.random() * 4))
setRate(r => Math.max(97, Math.min(99.9, r + (Math.random() - 0.5) * 0.3)))
}, 220, 420)
return (
<TickerShell tint={tint} isLight={isLight}>
<span style={{ color: isLight ? '#16a34a' : '#4ade80' }}></span>
<span style={{ color: tint, opacity: .85 }}>validate</span>
<span style={{ color: isLight ? '#1a1a2e' : '#f5f3fc', fontWeight: 600 }}>{v.toLocaleString()}</span>
<span style={{ color: isLight ? '#16a34a' : '#4ade80' }}>{rate.toFixed(1)}%</span>
</TickerShell>
)
}
function TickOptimizer({ tint, isLight }: { tint: string; isLight: boolean }) {
const ops = ['ROI: 2.418 € / dev', 'gap → policy §4.2', 'dedup 128 tickets', 'sweet-spot: 22 KLOC', 'tradeoff: speed↔risk']
const [i, setI] = useState(0)
useTicker(() => setI(x => (x + 1) % ops.length), 900, 1600, 0.05)
return (
<TickerShell tint={tint} isLight={isLight}>
<span style={{ color: '#fbbf24' }}></span>
<span style={{ color: tint, opacity: .85 }}>optimize</span>
<span style={{ color: isLight ? '#1a1a2e' : '#f5f3fc', overflow: 'hidden', textOverflow: 'ellipsis', flex: 1 }}>{ops[i]}</span>
</TickerShell>
)
}
function TickStack({ tint, isLight }: { tint: string; isLight: boolean }) {
const regs = ['DSGVO', 'NIS-2', 'DORA', 'EU AI Act', 'ISO 27001', 'BSI C5']
const [i, setI] = useState(0)
const [c, setC] = useState(1208)
useTicker(() => { setI(x => (x + 1) % regs.length); setC(v => v + Math.floor(Math.random() * 3)) }, 800, 1400, 0.05)
return (
<TickerShell tint={tint} isLight={isLight}>
<span style={{ color: isLight ? '#16a34a' : '#4ade80' }}></span>
<span style={{ color: tint, opacity: .85 }}>check</span>
<span style={{ color: isLight ? '#1a1a2e' : '#f5f3fc', fontWeight: 600 }}>{regs[i]}</span>
<span style={{ color: isLight ? '#94a3b8' : 'rgba(236,233,247,.4)' }}>·</span>
<span style={{ color: isLight ? '#1a1a2e' : '#f5f3fc' }}>{c.toLocaleString()}</span>
</TickerShell>
)
}
// ── Data ──────────────────────────────────────────────────────────────────────
interface DetailItem {
tint: string
icon: string
kicker: string
title: string
body: string
bullets?: string[]
stat?: { k: string; v: string }
}
function getDetails(de: boolean): Record<string, DetailItem> {
return {
rfq: {
tint: '#a78bfa', icon: '⎈',
kicker: de ? 'Säule · Regulatory' : 'Pillar · Regulatory',
title: de ? 'DSGVO / NIS2 / AI Act' : 'GDPR / NIS2 / AI Act',
body: de
? '294.000+ atomare Controls aus 380+ Rechtsquellen. Jede Anforderung deterministisch abgeleitet und auf Artikel, Absatz und Erwägungsgrund rückführbar.'
: '294,000+ atomic controls from 380+ legal sources. Every requirement deterministically derived and traceable to article, paragraph and recital.',
bullets: de
? ['DSGVO, NIS2, AI Act, DORA, TDDDG in einer Plattform', 'Automatische Verarbeitungsverzeichnisse und DSFA', 'Meldepflichten und Fristen automatisch überwacht']
: ['GDPR, NIS2, AI Act, DORA, TDDDG in one platform', 'Automated records of processing and DPIA', 'Reporting obligations and deadlines automatically monitored'],
stat: { k: de ? 'atomare Controls' : 'atomic controls', v: '294.000+' },
},
process: {
tint: '#c084fc', icon: '⟲',
kicker: de ? 'Säule · Regulatory' : 'Pillar · Regulatory',
title: de ? 'CE & Maschinenverordnung' : 'CE & Machinery Regulation',
body: de
? 'Von der Maschinenbeschreibung zur CE-Akte. 1.058 Hazard Patterns, 225 Maßnahmen, 751 Normen — deterministisch zugeordnet, nicht generiert.'
: 'From machine description to CE file. 1,058 hazard patterns, 225 mitigations, 751 standards — deterministically mapped, not generated.',
bullets: de
? ['Risikobeurteilung nach EN ISO 12100 automatisiert', 'SIL/PL-Berechnung aus RPZ-Werten', 'CE-Akte nach MVO 2023/1230 Anhang IV per Klick']
: ['Risk assessment per EN ISO 12100 automated', 'SIL/PL calculation from RPZ values', 'CE file per MR 2023/1230 Annex IV with one click'],
stat: { k: de ? 'Hazard Patterns' : 'hazard patterns', v: '1.058' },
},
bidir: {
tint: '#fbbf24', icon: '⟨/⟩',
kicker: de ? 'Säule · Code Security' : 'Pillar · Code Security',
title: 'SAST / DAST / SBOM',
body: de
? 'Kontinuierliche Code-Analyse für Firmware, Embedded und Backend. Jedes Finding wird automatisch priorisiert: Blocker vs. Major vs. kosmetisch.'
: 'Continuous code analysis for firmware, embedded and backend. Every finding is automatically prioritized: blocker vs. major vs. cosmetic.',
bullets: de
? ['Statische + dynamische Analyse bei jedem Commit', 'SBOM-Generierung (CRA-Pflicht ab 2027)', 'Secret Detection für hardcoded Credentials']
: ['Static + dynamic analysis on every commit', 'SBOM generation (CRA mandatory from 2027)', 'Secret detection for hardcoded credentials'],
stat: { k: de ? 'Validierungen / Tag' : 'validations / day', v: '~2.400' },
},
cont: {
tint: '#f59e0b', icon: '◎',
kicker: de ? 'Säule · Code Security' : 'Pillar · Code Security',
title: de ? 'Continuous Pentesting' : 'Continuous Pentesting',
body: de
? 'Automatisierte Schwachstellensuche statt jährlicher Penetrationstests. Findings werden sofort als Jira-Tickets mit Fix-Vorschlägen erstellt.'
: 'Automated vulnerability scanning instead of annual penetration tests. Findings immediately become Jira tickets with fix suggestions.',
bullets: de
? ['€30.000+ Einsparung vs. externe Pentests', 'Automatische Entscheidung: Hardware-Redesign oder Software-Fix?', 'CVE → Ticket → Fix → Nachweis in einer Pipeline']
: ['€30,000+ savings vs. external pentests', 'Automatic decision: hardware redesign or software fix?', 'CVE → ticket → fix → evidence in one pipeline'],
stat: { k: de ? 'Ø Kosten-Einsparung' : 'avg cost savings', v: '€30k+ / year' },
},
trace: {
tint: '#a78bfa', icon: '⇄',
kicker: de ? 'Integration' : 'Integration',
title: de ? 'Jira / Linear Integration' : 'Jira / Linear Integration',
body: de
? 'Jedes Finding wird automatisch als Ticket im Issue-Tracker erstellt — mit Priorität, Kontext, Fix-Vorschlag und Verknüpfung zur Rechtsquelle.'
: 'Every finding is automatically created as a ticket in your issue tracker — with priority, context, fix suggestion and link to legal source.',
bullets: de
? ['Jira, Linear, GitLab Issues, GitHub Issues', 'Blocker / Major / Minor automatisch klassifiziert', 'Fix-Vorschläge direkt im Ticket']
: ['Jira, Linear, GitLab Issues, GitHub Issues', 'Blocker / Major / Minor automatically classified', 'Fix suggestions directly in the ticket'],
},
engine: {
tint: '#c084fc', icon: '◉',
kicker: de ? 'Integration' : 'Integration',
title: de ? 'End-to-End Traceability' : 'End-to-End Traceability',
body: de
? 'Lückenloser Decision Trail: Rechtsquelle → Obligation → Control → Maßnahme → Code-Änderung → Nachweis. Ein Klick von der Klausel bis zur Codezeile.'
: 'Seamless decision trail: Legal source → Obligation → Control → Action → Code change → Evidence. One click from clause to line of code.',
bullets: de
? ['Versionierte Evidence-Chain', 'Audit-Log pro Änderung signiert', 'Rechtsquelle bis Codezeile nachvollziehbar']
: ['Versioned evidence chain', 'Audit log signed per change', 'Legal source to code line traceable'],
},
opt: {
tint: '#fbbf24', icon: '✦',
kicker: de ? 'Integration' : 'Integration',
title: de ? 'Delta-Impact-Analyse' : 'Delta Impact Analysis',
body: de
? 'Neues Funkmodul eingebaut? BreakPilot zeigt sofort: neue Hazards, neue Normen, CRA-Relevanz, RED-Re-Zertifizierung nötig? Hardware-Redesign oder Software-Fix?'
: 'New wireless module installed? BreakPilot immediately shows: new hazards, new standards, CRA relevance, RED re-certification needed? Hardware redesign or software fix?',
bullets: de
? ['Änderungsfolgenanalyse in Echtzeit', 'Hardware vs. Software Entscheidungsunterstützung', 'Spart €50k+ an externer Beratung']
: ['Change impact analysis in real-time', 'Hardware vs. software decision support', 'Saves €50k+ in external consulting'],
},
stack: {
tint: '#f59e0b', icon: '◎',
kicker: de ? 'Integration' : 'Integration',
title: de ? 'Sovereign AI · On-Premise' : 'Sovereign AI · On-Premise',
body: de
? 'Kein US-Cloud-Anbieter. Self-hosted LLM auf Apple Silicon. BSI-konforme Infrastruktur. Ihre Daten verlassen nie Ihr Netzwerk.'
: 'No US cloud provider. Self-hosted LLM on Apple Silicon. BSI-compliant infrastructure. Your data never leaves your network.',
bullets: de
? ['Kein FISA 702, kein CLOUD Act', 'On-Premise Appliance ab €7.900', 'EU-souveräner Software-Stack']
: ['No FISA 702, no CLOUD Act', 'On-premise appliance from €7,900', 'EU-sovereign software stack'],
},
hub: {
tint: '#a78bfa', icon: '∞',
kicker: de ? 'Die Schleife' : 'The Loop',
title: de ? 'Compliance ↔ Code · Immer in Sync' : 'Compliance ↔ Code · Always in sync',
body: de
? 'Die Plattform ist eine einzige geschlossene Schleife. Jede Policy-Änderung fliesst in den Code; jede Code-Änderung fliesst in die Policy zurück.'
: 'The platform is a single closed loop. Every policy change ripples into code; every code change ripples back into policy. That\'s the USP in one diagram.',
bullets: de
? ['Single Source of Truth, zwei Oberflächen', 'Echtzeit-Sync, kein Batch-Abgleich', 'Auditoren, Entwickler und Sales fragen denselben Graphen ab']
: ['Single source of truth, two surfaces', 'Real-time sync, not batch reconciliation', 'Auditors, engineers and sales all query the same graph'],
},
}
}
// ── Pillar row ────────────────────────────────────────────────────────────────
function PillarRow({ side, title, body, tint, onClick, active, isLight }: {
side: 'left' | 'right'
title: string; body: string; tint: string
onClick: () => void; active: boolean; isLight: boolean
}) {
const [hover, setHover] = useState(false)
const lit = hover || active
const isLeft = side === 'left'
return (
<div
onClick={onClick}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
style={{
display: 'flex', alignItems: 'flex-start', gap: 12,
flexDirection: isLeft ? 'row-reverse' : 'row',
textAlign: isLeft ? 'right' : 'left',
padding: '10px 14px', borderRadius: 10, cursor: 'pointer',
transition: 'transform .25s, background .25s, box-shadow .25s',
background: lit
? `linear-gradient(${isLeft ? '270deg' : '90deg'}, ${tint}24 0%, ${tint}0a 70%, transparent 100%)`
: 'transparent',
boxShadow: lit
? `0 10px 30px ${tint}26, inset 0 0 0 1px ${tint}44`
: 'inset 0 0 0 1px transparent',
transform: lit ? (isLeft ? 'translateX(-3px)' : 'translateX(3px)') : 'translateX(0)',
}}
>
<div style={{
flex: '0 0 30px', width: 30, height: 30, borderRadius: 9,
background: lit ? `${tint}3a` : `${tint}22`,
border: `1px solid ${lit ? tint : tint + '66'}`,
display: 'flex', alignItems: 'center', justifyContent: 'center',
color: lit ? (isLight ? tint : '#fff') : tint, fontSize: 13, fontWeight: 700, marginTop: 2,
boxShadow: lit ? `0 0 14px ${tint}88, inset 0 1px 0 ${tint}80` : `inset 0 1px 0 ${tint}50`,
transition: 'all .25s',
}}></div>
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{
fontSize: 13, fontWeight: 700,
color: isLight ? '#1a1a2e' : '#f7f5fc',
letterSpacing: -0.15, marginBottom: 3,
display: 'flex', alignItems: 'center', gap: 6,
justifyContent: isLeft ? 'flex-end' : 'flex-start',
}}>
<span>{title}</span>
<span style={{
fontSize: 10, color: tint, opacity: lit ? 1 : 0,
transform: `translateX(${lit ? 0 : (isLeft ? 4 : -4)}px)`,
transition: 'all .25s',
}}>{isLeft ? '' : ''}</span>
</div>
<div style={{
fontSize: 11, lineHeight: 1.55,
color: isLight
? `rgba(71,85,105,${lit ? 1 : .78})`
: `rgba(236,233,247,${lit ? .82 : .62})`,
transition: 'color .25s',
}}>{body}</div>
</div>
</div>
)
}
// ── Column header ─────────────────────────────────────────────────────────────
function ColHeader({ side, label, color, icon, sub, isLight }: {
side: 'left' | 'right'; label: string; color: string; icon: string; sub: string; isLight: boolean
}) {
const isLeft = side === 'left'
return (
<div style={{
display: 'flex', alignItems: 'center', gap: 10,
flexDirection: isLeft ? 'row-reverse' : 'row',
paddingBottom: 10, borderBottom: `1px solid ${color}35`,
}}>
<div style={{
width: 34, height: 34, borderRadius: 9,
background: `linear-gradient(135deg, ${color}55, ${color}20)`,
border: `1px solid ${color}88`,
display: 'flex', alignItems: 'center', justifyContent: 'center',
color: isLight ? color : '#fff', fontSize: 15, fontWeight: 700,
boxShadow: `0 0 18px ${color}55, inset 0 1px 0 ${color}aa`,
}}>{icon}</div>
<div>
<div style={{ fontSize: 18, fontWeight: 700, color: isLight ? '#1a1a2e' : '#f7f5fc', letterSpacing: -0.3, lineHeight: 1 }}>{label}</div>
<div style={{ ...MONO, fontSize: 9.5, letterSpacing: 2, color, opacity: .75, marginTop: 3, textTransform: 'uppercase' as const }}>{sub}</div>
</div>
</div>
)
}
// ── Central hub ───────────────────────────────────────────────────────────────
function CentralHub({ caption, isLight }: { caption: string; isLight: boolean }) {
return (
<div style={{ position: 'relative', width: 260, height: 320, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<div style={{
position: 'relative', width: 120, height: 120, borderRadius: '50%',
background: 'radial-gradient(circle at 32% 28%, #f0e9ff 0%, #c4aaff 26%, #7b5cd6 58%, #2a1560 100%)',
border: '1.5px solid rgba(216,202,255,.7)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
boxShadow: isLight
? '0 0 30px rgba(167,139,250,.4), 0 0 60px rgba(167,139,250,.15), inset 0 3px 0 rgba(255,255,255,.5), inset 0 -8px 14px rgba(0,0,0,.2)'
: '0 0 50px rgba(167,139,250,.65), 0 0 100px rgba(167,139,250,.25), inset 0 3px 0 rgba(255,255,255,.35), inset 0 -8px 14px rgba(0,0,0,.35)',
animation: isLight ? 'uspPulseLight 2.6s ease-in-out infinite' : 'uspPulse 2.6s ease-in-out infinite',
zIndex: 3,
}}>
<div style={{ position: 'absolute', inset: -14, borderRadius: '50%', border: `1px dashed ${isLight ? 'rgba(167,139,250,.5)' : 'rgba(216,202,255,.42)'}`, animation: 'uspSpin 14s linear infinite' }} />
<div style={{ position: 'absolute', inset: -30, borderRadius: '50%', border: `1px dashed ${isLight ? 'rgba(167,139,250,.3)' : 'rgba(216,202,255,.2)'}`, animation: 'uspSpin 22s linear infinite reverse' }} />
<svg width="54" height="26" viewBox="0 0 54 26" fill="none" stroke="#fff" strokeWidth="2.8" strokeLinecap="round" strokeLinejoin="round"
style={{ filter: 'drop-shadow(0 1px 3px rgba(0,0,0,.5))' }}>
<path d="M 10 13 C 10 5, 22 5, 27 13 C 32 21, 44 21, 44 13 C 44 5, 32 5, 27 13 C 22 21, 10 21, 10 13 Z" />
</svg>
</div>
<div style={{
position: 'absolute', left: 0, right: 0, bottom: 24, textAlign: 'center',
...MONO, fontSize: 9.5, letterSpacing: 2.5,
color: isLight ? 'rgba(109,77,194,.75)' : 'rgba(216,202,255,.75)',
textTransform: 'uppercase' as const, fontWeight: 600,
}}>{caption}</div>
</div>
)
}
// ── Bridge SVG connectors ─────────────────────────────────────────────────────
function BridgeConnectors({ isLight }: { isLight: boolean }) {
const rfpY = 130
const sub2Y = 250
const hubCx = 500
const hubR = 72
return (
<svg viewBox="0 0 1000 400" preserveAspectRatio="none"
style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', pointerEvents: 'none', zIndex: 1 }}>
<defs>
<linearGradient id="uspFromL" x1="0" x2="1">
<stop offset="0" stopColor="#a78bfa" stopOpacity="0" />
<stop offset=".3" stopColor="#a78bfa" stopOpacity={isLight ? '.6' : '.85'} />
<stop offset="1" stopColor="#c084fc" stopOpacity={isLight ? '.2' : '.3'} />
</linearGradient>
<linearGradient id="uspToR" x1="0" x2="1">
<stop offset="0" stopColor="#c084fc" stopOpacity={isLight ? '.2' : '.3'} />
<stop offset=".7" stopColor="#fbbf24" stopOpacity={isLight ? '.6' : '.85'} />
<stop offset="1" stopColor="#fbbf24" stopOpacity="0" />
</linearGradient>
</defs>
<line x1="40" y1={rfpY} x2={hubCx - hubR} y2={rfpY}
stroke="url(#uspFromL)" strokeWidth="2" strokeDasharray="4 5"
style={{ animation: 'uspFlowR 1.6s linear infinite' }} />
<line x1={hubCx + hubR} y1={rfpY} x2="960" y2={rfpY}
stroke="url(#uspToR)" strokeWidth="2" strokeDasharray="4 5"
style={{ animation: 'uspFlowR 1.6s linear infinite' }} />
<line x1="40" y1={sub2Y} x2={hubCx - hubR} y2={sub2Y}
stroke="url(#uspFromL)" strokeWidth="2" strokeDasharray="4 5"
style={{ animation: 'uspFlowR 1.6s linear infinite' }} />
<line x1={hubCx + hubR} y1={sub2Y} x2="960" y2={sub2Y}
stroke="url(#uspToR)" strokeWidth="2" strokeDasharray="4 5"
style={{ animation: 'uspFlowR 1.6s linear infinite' }} />
{([rfpY, sub2Y] as number[]).map(y => (
<g key={y}>
<circle cx={hubCx - hubR} cy={y} r="4" fill={isLight ? '#eef2ff' : '#1a0f34'} stroke="#a78bfa" strokeWidth="1.2" />
<circle cx={hubCx - hubR} cy={y} r="1.5" fill="#a78bfa" />
<circle cx={hubCx + hubR} cy={y} r="4" fill={isLight ? '#eef2ff' : '#1a0f34'} stroke="#fbbf24" strokeWidth="1.2" />
<circle cx={hubCx + hubR} cy={y} r="1.5" fill="#fbbf24" />
</g>
))}
<circle r="3" fill="#c4aaff" style={{ filter: 'drop-shadow(0 0 6px #a78bfa)' }}>
<animate attributeName="cx" from="40" to="960" dur="3.5s" repeatCount="indefinite" />
<animate attributeName="cy" values={`${rfpY};${rfpY}`} dur="3.5s" repeatCount="indefinite" />
</circle>
<circle r="3" fill="#fde68a" style={{ filter: 'drop-shadow(0 0 6px #fbbf24)' }}>
<animate attributeName="cx" from="960" to="40" dur="3.5s" repeatCount="indefinite" />
<animate attributeName="cy" values={`${sub2Y};${sub2Y}`} dur="3.5s" repeatCount="indefinite" />
</circle>
</svg>
)
}
// ── Under-the-hood feature card ───────────────────────────────────────────────
function FeatureCard({ icon, title, body, tint, Ticker, onClick, active, isLight }: {
icon: string; title: string; body: string; tint: string
Ticker: React.ComponentType<{ tint: string; isLight: boolean }>
onClick: () => void; active: boolean; isLight: boolean
}) {
const [hover, setHover] = useState(false)
const lit = hover || active
return (
<div
onClick={onClick}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
style={{
position: 'relative', padding: '13px 15px',
background: isLight
? lit
? `linear-gradient(180deg, ${tint}18 0%, ${tint}08 55%, rgba(248,250,252,.95) 100%)`
: 'linear-gradient(180deg, #ffffff, #f8fafc)'
: `linear-gradient(180deg, ${tint}${lit ? '2a' : '1a'} 0%, ${tint}07 55%, rgba(14,8,28,.85) 100%)`,
border: `1px solid ${lit ? tint : isLight ? 'rgba(0,0,0,.1)' : tint + '4a'}`,
borderRadius: 12,
boxShadow: lit
? `0 18px 40px ${tint}33, 0 0 0 1px ${tint}66, inset 0 1px 0 ${tint}60`
: isLight
? '0 2px 8px rgba(0,0,0,.08), inset 0 1px 0 rgba(255,255,255,.8)'
: `0 10px 24px rgba(0,0,0,.4), inset 0 1px 0 ${tint}35`,
minWidth: 0, cursor: 'pointer',
transform: lit ? 'translateY(-3px)' : 'translateY(0)',
transition: 'transform .25s, box-shadow .25s, background .25s, border-color .25s',
}}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}>
<span style={{
width: 22, height: 22, borderRadius: 6,
background: lit ? `${tint}44` : `${tint}22`,
border: `1px solid ${lit ? tint : tint + '66'}`,
display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
color: lit ? (isLight ? tint : '#fff') : tint, fontSize: 12,
boxShadow: lit ? `0 0 12px ${tint}88` : 'none',
transition: 'all .25s',
}}>{icon}</span>
<span style={{ fontSize: 12.5, fontWeight: 700, color: isLight ? '#1a1a2e' : '#f7f5fc', letterSpacing: -0.15, flex: 1 }}>{title}</span>
<span style={{ fontSize: 10, color: tint, opacity: lit ? 1 : 0.5, transform: `translateX(${lit ? 0 : -3}px)`, transition: 'all .25s' }}></span>
</div>
<div style={{
fontSize: 11, lineHeight: 1.45,
color: isLight
? `rgba(71,85,105,${lit ? 1 : .78})`
: `rgba(236,233,247,${lit ? .82 : .65})`,
transition: 'color .25s',
}}>{body}</div>
<Ticker tint={tint} isLight={isLight} />
</div>
)
}
// ── Detail modal ──────────────────────────────────────────────────────────────
function DetailModal({ item, onClose, isLight }: { item: DetailItem | null; onClose: () => void; isLight: boolean }) {
useEffect(() => {
if (!item) return
const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose() }
window.addEventListener('keydown', onKey)
return () => window.removeEventListener('keydown', onKey)
}, [item, onClose])
return (
<AnimatePresence>
{item && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
onClick={onClose}
style={{
position: 'absolute', inset: 0, zIndex: 50,
background: isLight ? 'rgba(240,244,255,.72)' : 'rgba(5,2,16,.72)',
backdropFilter: 'blur(6px)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
}}
>
<motion.div
initial={{ opacity: 0, scale: 0.94 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.94 }}
transition={{ duration: 0.22 }}
onClick={e => e.stopPropagation()}
style={{
width: 560, maxWidth: '88%',
background: isLight
? `linear-gradient(180deg, ${item.tint}10 0%, rgba(255,255,255,.98) 50%, rgba(248,250,252,.99) 100%)`
: `linear-gradient(180deg, ${item.tint}18 0%, rgba(20,10,40,.96) 50%, rgba(14,8,28,.98) 100%)`,
border: `1px solid ${item.tint}${isLight ? '44' : '66'}`,
borderRadius: 16,
boxShadow: isLight
? `0 20px 60px rgba(0,0,0,.12), 0 0 40px ${item.tint}18, inset 0 1px 0 rgba(255,255,255,.9)`
: `0 30px 80px rgba(0,0,0,.6), 0 0 60px ${item.tint}33, inset 0 1px 0 ${item.tint}55`,
padding: '22px 26px',
color: isLight ? '#1a1a2e' : '#ece9f7',
}}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 14 }}>
<div style={{
width: 38, height: 38, borderRadius: 10,
background: `linear-gradient(135deg, ${item.tint}66, ${item.tint}22)`,
border: `1px solid ${item.tint}`,
display: 'flex', alignItems: 'center', justifyContent: 'center',
color: isLight ? item.tint : '#fff', fontSize: 16, fontWeight: 700,
boxShadow: `0 0 18px ${item.tint}66`,
}}>{item.icon}</div>
<div style={{ flex: 1 }}>
<div style={{ ...MONO, fontSize: 9.5, letterSpacing: 2.5, color: item.tint, textTransform: 'uppercase' as const, fontWeight: 600, marginBottom: 2 }}>
{item.kicker}
</div>
<div style={{ fontSize: 19, fontWeight: 700, color: isLight ? '#1a1a2e' : '#f7f5fc', letterSpacing: -0.3 }}>{item.title}</div>
</div>
<button onClick={onClose} style={{
background: 'transparent', border: `1px solid ${item.tint}55`,
borderRadius: 8, cursor: 'pointer', width: 30, height: 30,
display: 'flex', alignItems: 'center', justifyContent: 'center',
color: isLight ? '#64748b' : 'rgba(236,233,247,.6)',
}}>
<X style={{ width: 14, height: 14 }} />
</button>
</div>
<div style={{ fontSize: 13, lineHeight: 1.6, color: isLight ? '#475569' : 'rgba(236,233,247,.82)', marginBottom: 16 }}>
{item.body}
</div>
{item.bullets && (
<div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 14 }}>
{item.bullets.map((b, i) => (
<div key={i} style={{
display: 'flex', alignItems: 'flex-start', gap: 10,
padding: '8px 12px', borderRadius: 8,
background: isLight ? 'rgba(0,0,0,.04)' : 'rgba(0,0,0,.3)',
border: `1px solid ${item.tint}${isLight ? '22' : '33'}`,
}}>
<span style={{ color: item.tint, fontSize: 12, marginTop: 1 }}></span>
<span style={{ fontSize: 12, lineHeight: 1.5, color: isLight ? '#475569' : 'rgba(236,233,247,.78)' }}>{b}</span>
</div>
))}
</div>
)}
{item.stat && (
<div style={{
...MONO, padding: '10px 14px', borderRadius: 8,
background: isLight ? 'rgba(0,0,0,.04)' : 'rgba(0,0,0,.45)',
border: `1px solid ${item.tint}${isLight ? '33' : '55'}`,
fontSize: 12, color: isLight ? '#475569' : 'rgba(236,233,247,.9)',
display: 'flex', alignItems: 'center', gap: 10,
}}>
<span style={{ color: isLight ? '#16a34a' : '#4ade80' }}></span>
<span style={{ color: item.tint }}>{item.stat.k}</span>
<span style={{ color: isLight ? '#1a1a2e' : '#f5f3fc', fontWeight: 600 }}>{item.stat.v}</span>
</div>
)}
</motion.div>
</motion.div>
)}
</AnimatePresence>
)
}
// ── Star field ────────────────────────────────────────────────────────────────
function StarField({ isLight }: { isLight: boolean }) {
const stars = useMemo(() => {
let s = 41
const r = () => { s = (s * 9301 + 49297) % 233280; return s / 233280 }
return Array.from({ length: 90 }, () => ({ x: r() * 100, y: r() * 100, size: r() * 1.4 + 0.3, op: r() * 0.5 + 0.15 }))
}, [])
if (isLight) return null
return (
<div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
{stars.map((st, i) => (
<div key={i} style={{
position: 'absolute', left: `${st.x}%`, top: `${st.y}%`,
width: st.size, height: st.size, borderRadius: '50%',
background: '#fff', opacity: st.op,
boxShadow: `0 0 ${st.size * 3}px rgba(180,160,255,.7)`,
}} />
))}
</div>
)
}
// ── Main slide ────────────────────────────────────────────────────────────────
export default function PlatformBridgeSection() {
const { lang } = useApp()
const de = lang === 'de'
const isLight = useIsLight()
const details = getDetails(de)
const [detail, setDetail] = useState<DetailItem | null>(null)
const open = (k: string) => setDetail(details[k])
const close = () => setDetail(null)
return (
<div>
<style>{CSS_KF}</style>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, ease: [0.22, 1, 0.36, 1] }}
className="text-center mb-1"
>
<h2 className="text-5xl md:text-6xl font-bold mb-1">
<GradientText>{de ? 'Eine Plattform' : 'One Platform'}</GradientText>
</h2>
<p className="text-lg text-white/50 max-w-2xl mx-auto">
{de ? 'Regulatorik, Code Security und CE — verbunden, nicht isoliert' : 'Regulatory, code security and CE — connected, not isolated'}
</p>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.15, ease: [0.22, 1, 0.36, 1] }}
>
{/* ── MAIN CANVAS ───────────────────────────────────────────────── */}
<div style={{
position: 'relative', overflow: 'hidden', borderRadius: 16,
background: isLight
? 'linear-gradient(160deg, #f0f4ff 0%, #eff6ff 50%, #f5f0ff 100%)'
: 'radial-gradient(ellipse at 50% 30%, #1a0f34 0%, #0e0720 55%, #050210 100%)',
color: isLight ? '#1a1a2e' : '#ece9f7',
fontFamily: '"Inter", system-ui, sans-serif',
WebkitFontSmoothing: 'antialiased',
}}>
{/* Ambient glow — dark only, subtle */}
{!isLight && (
<div style={{
position: 'absolute', top: -80, left: '50%', transform: 'translateX(-50%)',
width: 600, height: 400, borderRadius: '50%',
background: 'radial-gradient(ellipse, rgba(167,139,250,.12), transparent 65%)',
filter: 'blur(50px)', pointerEvents: 'none',
}} />
)}
{/* Bridge */}
<div style={{ position: 'relative', margin: '16px 48px 0', height: 330 }}>
<BridgeConnectors isLight={isLight} />
<div style={{
position: 'relative', zIndex: 2,
display: 'grid', gridTemplateColumns: '1fr 260px 1fr', gap: 0,
alignItems: 'start', height: '100%',
}}>
{/* LEFT — Compliance */}
<div style={{ display: 'flex', flexDirection: 'column', paddingRight: 20 }}>
<div style={{ height: 40, marginBottom: 36 }}>
<ColHeader side="left" label={de ? 'Regulatorik' : 'Regulatory'} color="#a78bfa" icon="⎈" sub="dsgvo · nis2 · ce · cra" isLight={isLight} />
</div>
<div style={{ height: 110, display: 'flex', alignItems: 'center' }}>
<div style={{ width: '100%' }}>
<PillarRow side="left" tint="#a78bfa" isLight={isLight}
title={de ? 'DSGVO / NIS2 / AI Act' : 'GDPR / NIS2 / AI Act'}
body={de
? '294.000+ atomare Controls aus 380+ Rechtsquellen. Deterministische Ableitung, keine Halluzinationen.'
: '294,000+ atomic controls from 380+ legal sources. Deterministic derivation, no hallucinations.'}
onClick={() => open('rfq')}
active={detail?.title === details.rfq.title}
/>
</div>
</div>
<div style={{ height: 110, display: 'flex', alignItems: 'center' }}>
<div style={{ width: '100%' }}>
<PillarRow side="left" tint="#c084fc" isLight={isLight}
title={de ? 'CE & Maschinenverordnung' : 'CE & Machinery Regulation'}
body={de
? '1.058 Hazard Patterns, 225 Maßnahmen, 751 Normen. CE-Akte nach MVO 2023/1230 per Klick.'
: '1,058 hazard patterns, 225 mitigations, 751 standards. CE file per MR 2023/1230 with one click.'}
onClick={() => open('process')}
active={detail?.title === details.process.title}
/>
</div>
</div>
</div>
{/* CENTER hub */}
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
<div
onClick={() => open('hub')}
style={{ cursor: 'pointer', transition: 'transform .25s, filter .25s' }}
onMouseEnter={e => { (e.currentTarget as HTMLDivElement).style.transform = 'scale(1.05)'; (e.currentTarget as HTMLDivElement).style.filter = 'brightness(1.15)' }}
onMouseLeave={e => { (e.currentTarget as HTMLDivElement).style.transform = 'scale(1)'; (e.currentTarget as HTMLDivElement).style.filter = 'brightness(1)' }}
>
<CentralHub caption={de ? 'Immer in Sync' : 'Always in sync'} isLight={isLight} />
</div>
</div>
{/* RIGHT — Code */}
<div style={{ display: 'flex', flexDirection: 'column', paddingLeft: 20 }}>
<div style={{ height: 40, marginBottom: 36 }}>
<ColHeader side="right" label="Code Security" color="#fbbf24" icon="⟨/⟩" sub="sast · dast · sbom · pentest" isLight={isLight} />
</div>
<div style={{ height: 110, display: 'flex', alignItems: 'center' }}>
<div style={{ width: '100%' }}>
<PillarRow side="right" tint="#fbbf24" isLight={isLight}
title="SAST / DAST / SBOM"
body={de
? 'Kontinuierliche Code-Analyse für Firmware und Embedded. Jedes Finding automatisch priorisiert: Blocker vs. kosmetisch.'
: 'Continuous code analysis for firmware and embedded. Every finding automatically prioritized: blocker vs. cosmetic.'}
onClick={() => open('bidir')}
active={detail?.title === details.bidir.title}
/>
</div>
</div>
<div style={{ height: 110, display: 'flex', alignItems: 'center' }}>
<div style={{ width: '100%' }}>
<PillarRow side="right" tint="#f59e0b" isLight={isLight}
title={de ? 'Continuous Pentesting' : 'Continuous Pentesting'}
body={de
? 'Automatisierte Schwachstellensuche statt jährlicher Pentests. Findings werden sofort zu Jira-Tickets mit Fix-Vorschlägen.'
: 'Automated vulnerability scanning instead of annual pentests. Findings become Jira tickets with fix suggestions.'}
onClick={() => open('cont')}
active={detail?.title === details.cont.title}
/>
</div>
</div>
</div>
</div>
</div>
{/* Integrations */}
<div style={{ position: 'relative', zIndex: 2, padding: '0 48px 20px' }}>
<div style={{
...MONO, fontSize: 9.5, letterSpacing: 3.5,
color: isLight ? 'rgba(109,77,194,.7)' : 'rgba(167,139,250,.7)',
textTransform: 'uppercase', fontWeight: 600, textAlign: 'center', marginBottom: 12,
display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 14,
}}>
<span style={{ width: 80, height: 1, background: isLight ? 'linear-gradient(90deg, transparent, rgba(109,77,194,.4))' : 'linear-gradient(90deg, transparent, rgba(167,139,250,.5))' }} />
{de ? 'Integrationen & Infrastruktur' : 'Integrations & Infrastructure'}
<span style={{ width: 80, height: 1, background: isLight ? 'linear-gradient(270deg, transparent, rgba(109,77,194,.4))' : 'linear-gradient(270deg, transparent, rgba(167,139,250,.5))' }} />
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 10 }}>
{([
{ tint: '#a78bfa', icon: '⇄', key: 'trace',
title: de ? 'Jira / Linear' : 'Jira / Linear',
body: de ? 'Findings → Tickets mit Fix-Vorschlägen' : 'Findings → tickets with fix suggestions' },
{ tint: '#c084fc', icon: '◉', key: 'engine',
title: 'Traceability',
body: de ? 'Rechtsquelle → Code → Nachweis' : 'Legal source → code → evidence' },
{ tint: '#fbbf24', icon: '✦', key: 'opt',
title: de ? 'Delta-Impact' : 'Delta Impact',
body: de ? 'Änderungsfolgen sofort sehen' : 'See change impact instantly' },
{ tint: '#f59e0b', icon: '◎', key: 'stack',
title: 'Sovereign AI',
body: de ? 'On-Premise, kein US-Cloud' : 'On-premise, no US cloud' },
] as const).map((card) => (
<div
key={card.key}
onClick={() => open(card.key)}
style={{
padding: '12px 14px', borderRadius: 10, cursor: 'pointer',
background: isLight
? `linear-gradient(180deg, ${card.tint}10 0%, rgba(248,250,252,.95) 100%)`
: `linear-gradient(180deg, ${card.tint}18 0%, rgba(14,8,28,.85) 100%)`,
border: `1px solid ${isLight ? 'rgba(0,0,0,.08)' : card.tint + '3a'}`,
transition: 'transform .2s, box-shadow .2s',
}}
onMouseEnter={e => { (e.currentTarget as HTMLDivElement).style.transform = 'translateY(-2px)'; (e.currentTarget as HTMLDivElement).style.boxShadow = `0 8px 24px ${card.tint}33` }}
onMouseLeave={e => { (e.currentTarget as HTMLDivElement).style.transform = 'translateY(0)'; (e.currentTarget as HTMLDivElement).style.boxShadow = 'none' }}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 7, marginBottom: 4 }}>
<span style={{
width: 20, height: 20, borderRadius: 5,
background: `${card.tint}22`, border: `1px solid ${card.tint}66`,
display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
color: card.tint, fontSize: 11,
}}>{card.icon}</span>
<span style={{ fontSize: 12, fontWeight: 700, color: isLight ? '#1a1a2e' : '#f7f5fc' }}>{card.title}</span>
</div>
<div style={{ fontSize: 11, lineHeight: 1.4, color: isLight ? 'rgba(71,85,105,.8)' : 'rgba(236,233,247,.55)' }}>{card.body}</div>
</div>
))}
</div>
</div>
<DetailModal item={detail} onClose={close} isLight={isLight} />
</div>
</motion.div>
</div>
)
}
@@ -0,0 +1,104 @@
'use client'
import { Check, ArrowRight, Cpu } from 'lucide-react'
import { t } from '@/lib/content'
import { useApp } from '@/lib/context'
import SectionHeading from '@/components/ui/SectionHeading'
import GlassCard from '@/components/ui/GlassCard'
import CTAButton from '@/components/ui/CTAButton'
import FadeInView from '@/components/ui/FadeInView'
export default function PricingSection() {
const { lang } = useApp()
const i = t(lang)
return (
<section id="pricing" className="py-24 sm:py-32">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionHeading
tag={i.pricing.tag}
title={i.pricing.title}
titleHighlight={i.pricing.titleHighlight}
subtitle={i.pricing.subtitle}
/>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
{i.pricing.tiers.map((tier, idx) => (
<GlassCard
key={idx}
delay={idx * 0.1}
className={`relative ${tier.highlighted ? 'border-accent-electric/30 ring-1 ring-accent-electric/20' : ''}`}
>
{tier.highlighted && (
<div className="absolute -top-3 left-1/2 -translate-x-1/2">
<span className="px-3 py-1 rounded-full text-xs font-bold bg-accent-electric text-white">
{tier.badge}
</span>
</div>
)}
{!tier.highlighted && (
<span className="inline-block mono-label text-xs mb-2">{tier.badge}</span>
)}
<h3 className="text-xl font-bold mt-2 mb-1">{tier.name}</h3>
<div className="flex items-baseline gap-1 mb-3">
<span className="text-3xl font-bold">EUR {tier.price}</span>
<span className="text-white/40 text-sm">{tier.period}</span>
</div>
<p className="text-sm text-white/40 mb-6">{tier.description}</p>
<ul className="space-y-3 mb-8">
{tier.features.map((feature, fi) => (
<li key={fi} className="flex items-start gap-2 text-sm text-white/60">
<Check className="w-4 h-4 text-accent-signal mt-0.5 shrink-0" />
{feature}
</li>
))}
</ul>
<CTAButton
variant={tier.highlighted ? 'primary' : 'ghost'}
href="#"
className="w-full justify-center"
>
{i.pricing.cta}
<ArrowRight className="w-4 h-4" />
</CTAButton>
</GlassCard>
))}
</div>
<FadeInView>
<div className="rounded-2xl border border-white/[0.08] bg-white/[0.03] p-6 md:p-8">
<div className="flex flex-col md:flex-row items-start md:items-center gap-6">
<div className="w-14 h-14 rounded-2xl bg-accent-purple/10 flex items-center justify-center shrink-0">
<Cpu className="w-7 h-7 text-accent-purple" />
</div>
<div className="flex-1">
<div className="flex items-center gap-3 mb-1">
<h3 className="text-lg font-bold">{i.pricing.appliance.name}</h3>
<span className="mono-label text-xs px-2 py-0.5 rounded bg-white/[0.06]">
{i.pricing.appliance.badge}
</span>
</div>
<p className="text-sm text-white/40 mb-3">{i.pricing.appliance.description}</p>
<div className="flex flex-wrap gap-2">
{i.pricing.appliance.features.map((f, idx) => (
<span key={idx} className="inline-flex items-center gap-1.5 text-xs text-white/50 bg-white/[0.04] px-2.5 py-1 rounded-md">
<Check className="w-3 h-3 text-accent-signal" />
{f}
</span>
))}
</div>
</div>
<div className="text-right shrink-0">
<div className="text-2xl font-bold">EUR {i.pricing.appliance.priceRange}</div>
<div className="text-xs text-white/40">{i.pricing.appliance.priceLabel}</div>
</div>
</div>
</div>
</FadeInView>
</div>
</section>
)
}
@@ -0,0 +1,81 @@
'use client'
import { Mail, Table, UserSearch, Clock, AlertCircle, Euro, Timer, HelpCircle } from 'lucide-react'
import { useApp } from '@/lib/context'
import FadeInView from '@/components/ui/FadeInView'
import GradientText from '@/components/ui/GradientText'
const steps = {
de: [
{ icon: Mail, label: 'Alles per Email', detail: 'Anforderungen, Rückfragen, Freigaben — verstreut in 200 Threads' },
{ icon: Table, label: 'Alles per Excel', detail: 'Risikobeurteilungen, Maßnahmenlisten, Normverweise in 15 Dateien' },
{ icon: UserSearch, label: 'Hinterherlaufen', detail: '"Wer war nochmal zuständig für die EMV-Messung?"' },
{ icon: Clock, label: 'Wartezeiten & Urlaub', detail: 'CE-Review blockiert weil der Experte 3 Wochen weg ist' },
{ icon: AlertCircle, label: 'CE-Berater zu spät', detail: 'Maschine ist fertig, CE-Bewertung fängt erst jetzt an' },
{ icon: Euro, label: '€50.000+ pro Jahr', detail: 'Externe Audits, Penetrationstests, CE-Beratung, Normen kaufen' },
{ icon: Timer, label: 'Time-to-Market verzögert', detail: 'Wochen bis Monate für eine vollständige CE-Akte' },
{ icon: HelpCircle, label: 'Silo-Experten', detail: 'CRA, AI Act, MVO, NIS2 — jeder kennt nur sein Thema' },
],
en: [
{ icon: Mail, label: 'Everything by email', detail: 'Requirements, follow-ups, approvals — scattered across 200 threads' },
{ icon: Table, label: 'Everything in Excel', detail: 'Risk assessments, mitigation lists, norm references in 15 files' },
{ icon: UserSearch, label: 'Chasing people', detail: '"Who was responsible for the EMC measurement again?"' },
{ icon: Clock, label: 'Wait times & vacation', detail: 'CE review blocked because the expert is away for 3 weeks' },
{ icon: AlertCircle, label: 'CE consultants too late', detail: 'Machine is finished, CE assessment only starts now' },
{ icon: Euro, label: '€50,000+ per year', detail: 'External audits, penetration tests, CE consulting, buying norms' },
{ icon: Timer, label: 'Time-to-market delayed', detail: 'Weeks to months for a complete CE file' },
{ icon: HelpCircle, label: 'Silo experts', detail: 'CRA, AI Act, MVO, NIS2 — everyone only knows their topic' },
],
}
const heading = {
de: { tag: 'DAS PROBLEM', title: 'So läuft es', titleHighlight: 'heute.', bridge: 'BreakPilot baut die Brücke zwischen Code, Produkt und Regulation — in Echtzeit, ohne Excel, Email und ohne Hinterherlaufen.' },
en: { tag: 'THE PROBLEM', title: "How it works", titleHighlight: 'today.', bridge: 'BreakPilot bridges the gap between code, product and regulation — in real-time, without Excel, email or chasing people.' },
}
export default function ProblemFlowSection() {
const { lang } = useApp()
const h = heading[lang]
const items = steps[lang]
return (
<section className="py-24 sm:py-32 section-alt">
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
<FadeInView className="text-center mb-16">
<p className="mono-label mb-4">{h.tag}</p>
<h2 className="text-4xl md:text-5xl font-bold mb-6">
{h.title} <GradientText>{h.titleHighlight}</GradientText>
</h2>
</FadeInView>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-16">
{items.map((step, idx) => {
const Icon = step.icon
return (
<FadeInView key={idx} delay={idx * 0.06}>
<div className="rounded-xl border border-red-500/10 bg-red-500/[0.03] p-5 h-full">
<div className="flex items-center gap-3 mb-3">
<div className="w-8 h-8 rounded-lg bg-red-500/10 flex items-center justify-center">
<Icon className="w-4 h-4 text-red-400" />
</div>
<span className="font-mono text-xs text-red-400/60">{String(idx + 1).padStart(2, '0')}</span>
</div>
<h3 className="text-sm font-bold mb-1 text-red-300/80">{step.label}</h3>
<p className="text-xs text-white/30 leading-relaxed">{step.detail}</p>
</div>
</FadeInView>
)
})}
</div>
<FadeInView>
<div className="rounded-2xl border border-accent-electric/20 bg-accent-electric/[0.04] p-8 text-center">
<p className="text-lg text-white/70 max-w-3xl mx-auto font-medium leading-relaxed">
{h.bridge}
</p>
</div>
</FadeInView>
</div>
</section>
)
}
@@ -0,0 +1,57 @@
'use client'
import { TrendingUp, ShieldAlert, Euro } from 'lucide-react'
import { t } from '@/lib/content'
import { useApp } from '@/lib/context'
import SectionHeading from '@/components/ui/SectionHeading'
import GlassCard from '@/components/ui/GlassCard'
import AnimatedCounter from '@/components/ui/AnimatedCounter'
import FadeInView from '@/components/ui/FadeInView'
const icons = [TrendingUp, ShieldAlert, Euro]
export default function ProblemSection() {
const { lang } = useApp()
const i = t(lang)
return (
<section id="problem" className="py-24 sm:py-32 section-alt">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionHeading
tag={i.problem.tag}
title={i.problem.title}
titleHighlight={i.problem.titleHighlight}
subtitle={i.problem.subtitle}
/>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{i.problem.cards.map((card, idx) => {
const Icon = icons[idx]
return (
<GlassCard key={idx} delay={idx * 0.1}>
<div className="flex items-center gap-3 mb-4">
<div className="w-10 h-10 rounded-xl bg-accent-electric/10 flex items-center justify-center">
<Icon className="w-5 h-5 text-accent-electric" />
</div>
</div>
<div className="text-3xl font-bold mb-2">
<AnimatedCounter value={card.metric} />
</div>
<p className="text-sm font-medium text-white/80 mb-2">{card.label}</p>
<p className="text-sm text-white/40 mb-3">{card.description}</p>
<p className="mono-label text-xs">{card.source}</p>
</GlassCard>
)
})}
</div>
<FadeInView delay={0.4} className="mt-12 text-center">
<p className="text-white/40 text-sm max-w-2xl mx-auto border-t border-white/[0.06] pt-8">
Die Konsequenz: Unternehmen riskieren Bussgelder, Betriebsstillstand und Wettbewerbsnachteile
oder sie investieren in eine Plattform, die regulatorische Komplexitaet deterministisch beherrscht.
</p>
</FadeInView>
</div>
</section>
)
}
@@ -0,0 +1,42 @@
'use client'
import { AlertTriangle, ShieldCheck, RefreshCw, Cpu, FileText, Link } from 'lucide-react'
import { t } from '@/lib/content'
import { useApp } from '@/lib/context'
import SectionHeading from '@/components/ui/SectionHeading'
import GlassCard from '@/components/ui/GlassCard'
const iconMap: Record<string, typeof AlertTriangle> = { AlertTriangle, ShieldCheck, RefreshCw, Cpu, FileText, Link }
export default function SafetySection() {
const { lang } = useApp()
const i = t(lang)
return (
<section id="safety" className="py-24 sm:py-32 section-alt">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionHeading
tag={i.safety.tag}
title={i.safety.title}
titleHighlight={i.safety.titleHighlight}
subtitle={i.safety.subtitle}
/>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{i.safety.features.map((feature, idx) => {
const Icon = iconMap[feature.icon]
return (
<GlassCard key={idx} delay={idx * 0.08}>
<div className="w-10 h-10 rounded-xl bg-amber-500/10 flex items-center justify-center mb-4">
<Icon className="w-5 h-5 text-amber-400" />
</div>
<h3 className="text-sm font-bold mb-2">{feature.title}</h3>
<p className="text-xs text-white/40 leading-relaxed">{feature.description}</p>
</GlassCard>
)
})}
</div>
</div>
</section>
)
}
@@ -0,0 +1,64 @@
'use client'
import { ArrowRight } from 'lucide-react'
import { t } from '@/lib/content'
import { useApp } from '@/lib/context'
import SectionHeading from '@/components/ui/SectionHeading'
import GlassCard from '@/components/ui/GlassCard'
import FadeInView from '@/components/ui/FadeInView'
import TechBadge from '@/components/ui/TechBadge'
export default function SecuritySection() {
const { lang } = useApp()
const i = t(lang)
return (
<section id="security" className="py-24 sm:py-32">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionHeading
tag={i.security.tag}
title={i.security.title}
titleHighlight={i.security.titleHighlight}
subtitle={i.security.subtitle}
/>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
<FadeInView direction="left">
<div className="grid grid-cols-2 sm:grid-cols-3 gap-3">
{i.security.tools.map((tool, idx) => (
<GlassCard key={idx} delay={idx * 0.05} className="p-4">
<p className="font-mono text-sm font-bold text-accent-electric mb-1">{tool.name}</p>
<p className="text-xs text-white/40">{tool.description}</p>
</GlassCard>
))}
</div>
</FadeInView>
<FadeInView direction="right">
<div className="rounded-2xl border border-white/[0.06] bg-white/[0.03] p-6 h-full flex flex-col justify-center">
<h3 className="text-lg font-bold mb-2">{i.security.integration.title}</h3>
<p className="text-sm text-white/40 mb-6">{i.security.integration.description}</p>
<div className="flex flex-col gap-3">
<div className="flex items-center gap-3">
<span className="px-3 py-1.5 rounded-lg bg-red-500/10 border border-red-500/20 text-xs text-red-400 font-mono">
CVE-2024-XXXX
</span>
<ArrowRight className="w-4 h-4 text-white/20" />
<span className="px-3 py-1.5 rounded-lg bg-accent-electric/10 border border-accent-electric/20 text-xs text-accent-electric font-mono">
JIRA-SEC-142
</span>
</div>
<div className="flex flex-wrap gap-2 mt-3">
{i.security.integration.targets.map((target, idx) => (
<TechBadge key={idx}>{target}</TechBadge>
))}
</div>
</div>
</div>
</FadeInView>
</div>
</div>
</section>
)
}
@@ -0,0 +1,112 @@
'use client'
import { ArrowRight } from 'lucide-react'
import { useApp } from '@/lib/context'
import FadeInView from '@/components/ui/FadeInView'
import GlassCard from '@/components/ui/GlassCard'
import TechBadge from '@/components/ui/TechBadge'
import SectionHeading from '@/components/ui/SectionHeading'
const tools = [
{ name: 'SAST', de: 'Statische Code-Analyse für Firmware/Embedded', en: 'Static code analysis for firmware/embedded' },
{ name: 'DAST', de: 'Dynamische Sicherheitstests gegen laufende Systeme', en: 'Dynamic security testing against running systems' },
{ name: 'SBOM', de: 'Software Bill of Materials — CRA-Pflicht ab 2027', en: 'Software Bill of Materials — CRA mandatory from 2027' },
{ name: 'Pentesting', de: 'Automatisierte Schwachstellensuche', en: 'Automated vulnerability scanning' },
{ name: 'Secret Detection', de: 'Hardcoded Credentials im Code finden', en: 'Find hardcoded credentials in code' },
{ name: 'Dependency Audit', de: 'Bekannte CVEs in Abhängigkeiten', en: 'Known CVEs in dependencies' },
]
const heading = {
de: {
tag: 'SECURITY TOOLCHAIN',
title: 'Scan → Priorisierung →',
titleHighlight: 'Fix → Nachweis.',
subtitle: 'Jedes Finding wird automatisch priorisiert, als Jira-Ticket erstellt und mit Code-Fix-Vorschlag versehen.',
pipeline: ['Scan', 'Findings', 'Priorisierung', 'Jira-Ticket', 'Fix', 'Verifikation', 'Evidence'],
jiraTitle: 'Automatische Entscheidungsunterstützung',
jiraItems: [
'Blocker: Finding blockiert CE/CRA-Konformität',
'Major: Software-only Fix möglich',
'Minor: Kosmetisch, kein Compliance-Impact',
'Hardware vs. Software: Brauche ich ein Board-Redesign?',
'Code-Fix-Vorschlag direkt im Ticket',
],
},
en: {
tag: 'SECURITY TOOLCHAIN',
title: 'Scan → Prioritize →',
titleHighlight: 'Fix → Evidence.',
subtitle: 'Every finding is automatically prioritized, created as a Jira ticket and provided with a code fix suggestion.',
pipeline: ['Scan', 'Findings', 'Prioritization', 'Jira Ticket', 'Fix', 'Verification', 'Evidence'],
jiraTitle: 'Automatic decision support',
jiraItems: [
'Blocker: Finding blocks CE/CRA compliance',
'Major: Software-only fix possible',
'Minor: Cosmetic, no compliance impact',
'Hardware vs. Software: Do I need a board redesign?',
'Code fix suggestion directly in the ticket',
],
},
}
export default function SecurityToolchainSection() {
const { lang } = useApp()
const h = heading[lang]
return (
<section className="py-24 sm:py-32 section-alt">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionHeading tag={h.tag} title={h.title} titleHighlight={h.titleHighlight} subtitle={h.subtitle} />
{/* Pipeline visualization */}
<FadeInView className="mb-16">
<div className="flex flex-wrap items-center justify-center gap-2">
{h.pipeline.map((step, idx) => (
<div key={idx} className="flex items-center gap-2">
<span className="px-3 py-1.5 rounded-lg bg-accent-electric/10 border border-accent-electric/15 text-xs text-accent-electric font-mono">
{step}
</span>
{idx < h.pipeline.length - 1 && (
<ArrowRight className="w-3 h-3 text-white/20" />
)}
</div>
))}
</div>
</FadeInView>
{/* Tools grid + Jira integration */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
<FadeInView direction="left">
<div className="grid grid-cols-2 sm:grid-cols-3 gap-3">
{tools.map((tool, idx) => (
<GlassCard key={idx} delay={idx * 0.05} className="p-4">
<p className="font-mono text-sm font-bold text-accent-electric mb-1">{tool.name}</p>
<p className="text-xs text-white/40">{lang === 'de' ? tool.de : tool.en}</p>
</GlassCard>
))}
</div>
</FadeInView>
<FadeInView direction="right">
<div className="rounded-2xl border border-white/[0.06] bg-white/[0.03] p-6 h-full">
<h3 className="text-lg font-bold mb-4">{h.jiraTitle}</h3>
<ul className="space-y-3 mb-6">
{h.jiraItems.map((item, idx) => (
<li key={idx} className="flex items-start gap-3 text-sm text-white/50">
<span className={`mt-1 w-2 h-2 rounded-full shrink-0 ${idx === 0 ? 'bg-red-400' : idx === 1 ? 'bg-amber-400' : idx === 2 ? 'bg-green-400' : 'bg-accent-electric'}`} />
{item}
</li>
))}
</ul>
<div className="flex flex-wrap gap-2">
{['Jira', 'Linear', 'GitLab', 'GitHub'].map(t => (
<TechBadge key={t}>{t}</TechBadge>
))}
</div>
</div>
</FadeInView>
</div>
</div>
</section>
)
}
@@ -0,0 +1,66 @@
'use client'
import { Server, Shield, Globe } from 'lucide-react'
import { t } from '@/lib/content'
import { useApp } from '@/lib/context'
import SectionHeading from '@/components/ui/SectionHeading'
import GlassCard from '@/components/ui/GlassCard'
import FadeInView from '@/components/ui/FadeInView'
import TechBadge from '@/components/ui/TechBadge'
export default function SovereignSection() {
const { lang } = useApp()
const i = t(lang)
return (
<section id="sovereign" className="py-24 sm:py-32 section-alt">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionHeading
tag={i.sovereign.tag}
title={i.sovereign.title}
titleHighlight={i.sovereign.titleHighlight}
subtitle={i.sovereign.subtitle}
/>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
{i.sovereign.features.map((feature, idx) => {
const icons = [Server, Shield, Globe]
const Icon = icons[idx]
return (
<GlassCard key={idx} delay={idx * 0.1}>
<div className="w-10 h-10 rounded-xl bg-accent-purple/10 flex items-center justify-center mb-4">
<Icon className="w-5 h-5 text-accent-purple" />
</div>
<h3 className="text-sm font-bold mb-2">{feature.title}</h3>
<p className="text-xs text-white/40">{feature.description}</p>
</GlassCard>
)
})}
</div>
<FadeInView>
<div className="rounded-2xl border border-accent-purple/20 bg-accent-purple/[0.04] p-6 md:p-8">
<div className="flex flex-col md:flex-row items-start md:items-center gap-6">
<div className="flex-1">
<h3 className="text-lg font-bold mb-2">{i.sovereign.appliance.title}</h3>
<p className="text-sm text-white/40 mb-4">{i.sovereign.appliance.description}</p>
<div className="flex flex-wrap gap-2">
{i.sovereign.appliance.specs.map((spec, idx) => (
<TechBadge key={idx}>{spec}</TechBadge>
))}
</div>
</div>
<div className="w-32 h-32 rounded-2xl bg-white/[0.04] border border-white/[0.06] flex items-center justify-center shrink-0">
<div className="text-center">
<div className="w-16 h-3 bg-white/10 rounded-sm mx-auto mb-2" />
<div className="w-12 h-12 bg-white/[0.06] rounded-lg mx-auto border border-white/[0.08]" />
<div className="w-4 h-0.5 bg-white/10 rounded-full mx-auto mt-2" />
</div>
</div>
</div>
</div>
</FadeInView>
</div>
</section>
)
}
@@ -0,0 +1,48 @@
'use client'
import { Factory, Truck, Cpu, Zap } from 'lucide-react'
import { t } from '@/lib/content'
import { useApp } from '@/lib/context'
import SectionHeading from '@/components/ui/SectionHeading'
import GlassCard from '@/components/ui/GlassCard'
import TechBadge from '@/components/ui/TechBadge'
const iconMap: Record<string, typeof Factory> = { Factory, Truck, Cpu, Zap }
export default function TargetSection() {
const { lang } = useApp()
const i = t(lang)
return (
<section id="targets" className="py-24 sm:py-32">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionHeading
tag={i.targets.tag}
title={i.targets.title}
titleHighlight={i.targets.titleHighlight}
subtitle={i.targets.subtitle}
/>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
{i.targets.industries.map((industry, idx) => {
const Icon = iconMap[industry.icon]
return (
<GlassCard key={idx} delay={idx * 0.1}>
<div className="w-10 h-10 rounded-xl bg-accent-electric/10 flex items-center justify-center mb-4">
<Icon className="w-5 h-5 text-accent-electric" />
</div>
<h3 className="text-sm font-bold mb-3">{industry.name}</h3>
<div className="flex flex-wrap gap-1.5 mb-4">
{industry.regulations.map((reg, ri) => (
<TechBadge key={ri}>{reg}</TechBadge>
))}
</div>
<p className="text-xs text-accent-signal/80 font-mono">{industry.roi}</p>
</GlassCard>
)
})}
</div>
</div>
</section>
)
}
@@ -0,0 +1,191 @@
'use client'
import { motion } from 'framer-motion'
import { Linkedin, Github, ArrowUpRight } from 'lucide-react'
import { useApp } from '@/lib/context'
import SectionHeading from '@/components/ui/SectionHeading'
import FadeInView from '@/components/ui/FadeInView'
interface TeamMember {
name: string
roleDe: string
roleEn: string
bioDe: string
bioEn: string
equityPct: number
expertise: string[]
links: { type: 'linkedin' | 'github'; url: string }[]
initials: string
gradient: string
}
const team: TeamMember[] = [
{
name: 'Benjamin Bönisch',
roleDe: 'CEO & Co-Founder',
roleEn: 'CEO & Co-Founder',
bioDe: 'Ehemaliger Lehrer mit Leidenschaft für EdTech und Datenschutz. Hat BreakPilot als DSGVO-konforme Bildungsplattform gegründet und zum Self-Hosted Compliance-Anbieter weiterentwickelt.',
bioEn: 'Former teacher with a passion for EdTech and data privacy. Founded BreakPilot as a GDPR-compliant education platform and evolved it into a self-hosted compliance provider.',
equityPct: 50,
expertise: ['EdTech', 'DSGVO', 'Produktstrategie', 'Go-to-Market'],
links: [
{ type: 'linkedin', url: 'https://linkedin.com/in/benjamin-boenisch' },
],
initials: 'BB',
gradient: 'from-accent-electric to-accent-indigo',
},
{
name: 'Sharang Parnerkar',
roleDe: 'CTO & Co-Founder',
roleEn: 'CTO & Co-Founder',
bioDe: 'Full-Stack-Ingenieur mit Expertise in KI/ML, Apple Silicon Optimierung und verteilten Systemen. Verantwortlich für die technische Architektur der ComplAI-Plattform.',
bioEn: 'Full-stack engineer with expertise in AI/ML, Apple Silicon optimization, and distributed systems. Responsible for the technical architecture of the ComplAI platform.',
equityPct: 50,
expertise: ['AI/ML', 'Apple Silicon', 'Full-Stack', 'DevOps'],
links: [
{ type: 'github', url: 'https://github.com/sharangp' },
],
initials: 'SP',
gradient: 'from-accent-indigo to-accent-purple',
},
]
const headingContent = {
de: {
tag: 'TEAM',
title: 'Die Menschen hinter',
titleHighlight: 'BreakPilot.',
subtitle: 'Gründer mit Domain-Expertise in Compliance, KI und Produktentwicklung.',
equity: 'Equity',
cta: 'Offene Positionen ansehen',
hiring: 'Wir stellen ein',
hiringText: 'BreakPilot wächst. Wir suchen Ingenieure, die regulatorische Komplexität als technisches Problem lösen wollen.',
roles: ['Backend Engineer (Python/Go)', 'Regulatory Analyst', 'DevOps Engineer'],
},
en: {
tag: 'TEAM',
title: 'The people behind',
titleHighlight: 'BreakPilot.',
subtitle: 'Founders with domain expertise in compliance, AI and product development.',
equity: 'Equity',
cta: 'View open positions',
hiring: "We're hiring",
hiringText: 'BreakPilot is growing. We are looking for engineers who want to solve regulatory complexity as a technical problem.',
roles: ['Backend Engineer (Python/Go)', 'Regulatory Analyst', 'DevOps Engineer'],
},
}
const LinkIcons = { linkedin: Linkedin, github: Github }
export default function TeamSection() {
const { lang } = useApp()
const h = headingContent[lang]
return (
<section className="py-24 sm:py-32 pt-32">
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionHeading
tag={h.tag}
title={h.title}
titleHighlight={h.titleHighlight}
subtitle={h.subtitle}
/>
<div className="grid md:grid-cols-2 gap-6 mb-16">
{team.map((member, idx) => (
<motion.div
key={member.name}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ delay: idx * 0.15, duration: 0.5 }}
className="bg-white/[0.04] backdrop-blur-xl border border-white/[0.08] rounded-2xl p-6 flex flex-col hover:border-accent-electric/20 transition-colors"
>
{/* Header: avatar + name + role + equity */}
<div className="flex items-center gap-4 mb-5">
<div className={`w-16 h-16 rounded-2xl bg-gradient-to-br ${member.gradient} flex items-center justify-center shrink-0 shadow-lg shadow-accent-electric/20`}>
<span className="text-xl font-bold text-white">{member.initials}</span>
</div>
<div className="min-w-0 flex-1">
<div className="flex items-center gap-2 mb-0.5 flex-wrap">
<h3 className="text-xl font-bold text-white truncate">{member.name}</h3>
<div className="flex items-center gap-1.5">
{member.links.map((link) => {
const Icon = LinkIcons[link.type]
return (
<a
key={link.type}
href={link.url}
target="_blank"
rel="noopener noreferrer"
className="text-white/25 hover:text-accent-electric transition-colors"
>
<Icon className="w-4 h-4" />
</a>
)
})}
</div>
</div>
<p className="text-accent-electric text-sm font-medium">
{lang === 'de' ? member.roleDe : member.roleEn}
</p>
</div>
{/* Equity pill */}
<div className="text-right shrink-0">
<div className="text-[10px] uppercase tracking-wider text-white/30">{h.equity}</div>
<div className="text-base font-bold text-white tabular-nums">{member.equityPct}%</div>
</div>
</div>
{/* Bio */}
<p className="text-sm text-white/60 leading-relaxed mb-5 flex-1">
{lang === 'de' ? member.bioDe : member.bioEn}
</p>
{/* Expertise tags */}
<div className="flex flex-wrap gap-1.5 pt-4 border-t border-white/[0.06]">
{member.expertise.map((skill) => (
<span
key={skill}
className="text-xs px-2.5 py-1 rounded-full bg-accent-electric/10 text-accent-electric/80 border border-accent-electric/15"
>
{skill}
</span>
))}
</div>
</motion.div>
))}
</div>
{/* Hiring CTA */}
<FadeInView>
<div className="rounded-2xl border border-accent-electric/15 bg-accent-electric/[0.04] p-8 text-center">
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-accent-signal/10 border border-accent-signal/20 text-accent-signal text-xs font-medium mb-4">
<span className="w-1.5 h-1.5 rounded-full bg-accent-signal animate-pulse" />
{h.hiring}
</div>
<p className="text-sm text-white/50 max-w-lg mx-auto mb-6">
{h.hiringText}
</p>
<div className="flex flex-wrap justify-center gap-2 mb-6">
{h.roles.map((role) => (
<span key={role} className="px-3 py-1.5 rounded-lg bg-white/[0.06] border border-white/[0.06] text-xs text-white/60 font-mono">
{role}
</span>
))}
</div>
<a
href="mailto:jobs@breakpilot.ai"
className="inline-flex items-center gap-2 px-5 py-2.5 rounded-xl bg-accent-electric text-white text-sm font-medium hover:bg-blue-500 transition-colors glow-blue"
>
{h.cta}
<ArrowUpRight className="w-4 h-4" />
</a>
</div>
</FadeInView>
</div>
</section>
)
}
@@ -0,0 +1,71 @@
'use client'
import { Shield, FileCheck, ClipboardCheck } from 'lucide-react'
import { useApp } from '@/lib/context'
import FadeInView from '@/components/ui/FadeInView'
import AnimatedCounter from '@/components/ui/AnimatedCounter'
const pillars = {
de: [
{ icon: Shield, label: 'Deterministisch', detail: 'Regelbasiert, nicht generativ' },
{ icon: FileCheck, label: 'Nachvollziehbar', detail: 'Jedes Ergebnis mit Rechtsquelle' },
{ icon: ClipboardCheck, label: 'Auditierbar', detail: 'Vollständiger Decision Trail' },
],
en: [
{ icon: Shield, label: 'Deterministic', detail: 'Rule-based, not generative' },
{ icon: FileCheck, label: 'Traceable', detail: 'Every result with legal source' },
{ icon: ClipboardCheck, label: 'Auditable', detail: 'Complete decision trail' },
],
}
const stats = [
{ value: '294.000+', labelDe: 'atomare Controls', labelEn: 'atomic controls' },
{ value: '380+', labelDe: 'Rechtsquellen', labelEn: 'legal sources' },
{ value: '1.058', labelDe: 'Hazard Patterns', labelEn: 'hazard patterns' },
{ value: '751', labelDe: 'Normen', labelEn: 'standards' },
]
export default function TrustBar() {
const { lang } = useApp()
const items = pillars[lang]
return (
<section className="py-24 sm:py-32 section-alt">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
{/* Trust pillars */}
<FadeInView>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-16">
{items.map((pillar, idx) => {
const Icon = pillar.icon
return (
<div key={idx} className="flex items-center gap-4 p-4 rounded-xl border border-white/[0.06] bg-white/[0.03]">
<div className="w-10 h-10 rounded-xl bg-accent-indigo/10 flex items-center justify-center shrink-0">
<Icon className="w-5 h-5 text-accent-indigo" />
</div>
<div>
<h3 className="text-sm font-bold">{pillar.label}</h3>
<p className="text-xs text-white/40">{pillar.detail}</p>
</div>
</div>
)
})}
</div>
</FadeInView>
{/* Stats */}
<FadeInView delay={0.2}>
<div className="grid grid-cols-2 md:grid-cols-4 gap-6">
{stats.map((stat, idx) => (
<div key={idx} className="text-center">
<div className="text-3xl font-bold mb-1 gradient-text">
<AnimatedCounter value={stat.value} />
</div>
<p className="text-xs text-white/40">{lang === 'de' ? stat.labelDe : stat.labelEn}</p>
</div>
))}
</div>
</FadeInView>
</div>
</section>
)
}
@@ -0,0 +1,93 @@
'use client'
import Link from 'next/link'
import { ArrowRight, Scan, FileCheck, Users } from 'lucide-react'
import { useApp } from '@/lib/context'
import FadeInView from '@/components/ui/FadeInView'
import GlassCard from '@/components/ui/GlassCard'
const icons = [Scan, FileCheck, Users]
const gradients = ['from-red-500/10 to-amber-500/10', 'from-accent-electric/10 to-accent-indigo/10', 'from-accent-purple/10 to-accent-electric/10']
const cases = {
de: [
{
title: '187 Pentest-Findings — was davon ist wirklich kritisch?',
description: 'SAST/DAST + Pentesting liefern 187 Findings für ein Embedded Board. BreakPilot priorisiert automatisch: 3 blockieren CE/CRA, 12 sind Software-only Fixes, der Rest ist kosmetisch. Jira-Tickets mit Code-Fix-Vorschlägen werden automatisch erstellt.',
highlight: 'Hardware-Redesign für €50k? Wahrscheinlich nicht nötig.',
href: '/product-compliance',
cta: 'Product Compliance ansehen',
},
{
title: 'CE-Akte in Stunden statt Monaten',
description: 'Sondermaschinenbauer beschreibt einen Cobot in 14 Textfeldern. 1.058 Hazard Patterns feuern deterministisch. 12 Gefährdungen, 30 Maßnahmen, 45 Normen — automatisch zugeordnet, nicht generiert.',
highlight: 'CE-Akte nach MVO 2023/1230 Anhang IV per Klick.',
href: '/plattform',
cta: 'Plattform entdecken',
},
{
title: 'Der CE-Experte geht in Rente',
description: 'Ein Junior-Konstrukteur nutzt BreakPilot für seine erste Risikobeurteilung. Konsistente Erstbewertung mit Explainability. Der Senior reviewt nur noch, statt alles selbst zu machen.',
highlight: 'Expertenwissen operationalisiert, nicht in Köpfen eingesperrt.',
href: '/plattform',
cta: 'Plattform entdecken',
},
],
en: [
{
title: '187 pentest findings — which ones actually matter?',
description: 'SAST/DAST + pentesting deliver 187 findings for an embedded board. BreakPilot prioritizes automatically: 3 block CE/CRA, 12 are software-only fixes, the rest is cosmetic. Jira tickets with code fix suggestions are created automatically.',
highlight: 'Hardware redesign for €50k? Probably not necessary.',
href: '/product-compliance',
cta: 'View Product Compliance',
},
{
title: 'CE file in hours instead of months',
description: 'A special machine builder describes a cobot in 14 text fields. 1,058 hazard patterns fire deterministically. 12 hazards, 30 mitigations, 45 norms — automatically mapped, not generated.',
highlight: 'CE file per Machinery Regulation 2023/1230 Annex IV with one click.',
href: '/plattform',
cta: 'Discover Platform',
},
{
title: 'The CE expert is retiring',
description: 'A junior engineer uses BreakPilot for their first risk assessment. Consistent initial assessment with explainability. The senior only reviews instead of doing everything.',
highlight: 'Expert knowledge operationalized, not locked in heads.',
href: '/plattform',
cta: 'Discover Platform',
},
],
}
export default function UseCaseCards() {
const { lang } = useApp()
const items = cases[lang]
return (
<section className="py-24 sm:py-32">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
{items.map((item, idx) => {
const Icon = icons[idx]
return (
<GlassCard key={idx} delay={idx * 0.1} hover={false} className="flex flex-col">
<div className={`w-12 h-12 rounded-2xl bg-gradient-to-br ${gradients[idx]} flex items-center justify-center mb-5`}>
<Icon className="w-6 h-6 text-white/70" />
</div>
<h3 className="text-lg font-bold mb-3 leading-snug">{item.title}</h3>
<p className="text-sm text-white/40 mb-4 flex-1">{item.description}</p>
<p className="text-sm text-accent-electric font-medium mb-5">{item.highlight}</p>
<Link
href={item.href}
className="inline-flex items-center gap-2 text-sm text-white/50 hover:text-white transition-colors group"
>
{item.cta}
<ArrowRight className="w-4 h-4 group-hover:translate-x-1 transition-transform" />
</Link>
</GlassCard>
)
})}
</div>
</div>
</section>
)
}