diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx index 2ec8c29..7fc6fa9 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx @@ -1,478 +1,468 @@ -import { PrintPage, SectionTitle, PrintTable, COLORS } from './PrintLayout' -import { Language, FMResult } from '@/lib/types' +import { Language } from '@/lib/types' +import { Page, COLORS, Callout, DataTable, ThreeCol, Bullets } from './PrintLayout' +import { ArchitectureDiagram, PipelineFlow } from './PrintDiagrams' interface SlideBase { lang: Language; pageNum: number; totalPages: number; versionName: string } -const STRATEGY_PHASES_DE = [ - { title: 'Phase 1: Foundation', period: 'Aug 2026 – Jun 2027', team: '5 MA', arr: '75–150k EUR', items: ['Security Engineer + CE-Risikoingenieur als erste Hires', '5 Pilotkunden im Maschinenbau', 'Gründer verkaufen selbst', 'Product-Market Fit beweisen'] }, - { title: 'Phase 2: Traction', period: 'Jul 2027 – Jun 2028', team: '10 MA', arr: '0,5–1,2M EUR', items: ['Channel Manager für Bechtle/CANCOM', 'DevSecOps + KI-Ingenieur', 'Lösungsberater für Partner-Demos', 'Wiederholbarer Vertriebsprozess'] }, - { title: 'Phase 3: Scale', period: 'Jul 2028 – Jun 2029', team: '17→25 MA', arr: '2–4M EUR', items: ['Erster Direktvertrieb neben Channel', 'Compliance-Jurist für Glaubwürdigkeit', 'Security-Analyst / Pentester', 'VP Sales übernimmt vom CEO'] }, - { title: 'Phase 4: Leadership', period: 'Jul 2029 – Dez 2030', team: '25→35 MA', arr: '4–10M EUR', items: ['EU-Expansion (AT, CH, Benelux)', 'Enterprise-Vertrieb', 'Developer Relations (Snyk-Modell)', 'Break-Even oder Series A'] }, -] -const STRATEGY_PHASES_EN = [ - { title: 'Phase 1: Foundation', period: 'Aug 2026 – Jun 2027', team: '5 emp.', arr: '75–150k EUR', items: ['Security Engineer + CE Risk Engineer as first hires', '5 pilot customers in manufacturing', 'Founders sell themselves', 'Prove product-market fit'] }, - { title: 'Phase 2: Traction', period: 'Jul 2027 – Jun 2028', team: '10 emp.', arr: '0.5–1.2M EUR', items: ['Channel Manager for Bechtle/CANCOM', 'DevSecOps + AI engineer', 'Solutions engineer for partner demos', 'Repeatable sales process'] }, - { title: 'Phase 3: Scale', period: 'Jul 2028 – Jun 2029', team: '17→25 emp.', arr: '2–4M EUR', items: ['First direct sales alongside channel', 'Compliance lawyer for credibility', 'Security analyst / pentester', 'VP Sales takes over from CEO'] }, - { title: 'Phase 4: Leadership', period: 'Jul 2029 – Dez 2030', team: '25→35 emp.', arr: '4–10M EUR', items: ['EU expansion (AT, CH, Benelux)', 'Enterprise sales', 'Developer Relations (Snyk model)', 'Break-even or Series A'] }, -] +/* The Anhang divider lives in PrintNewSlides.tsx so this file stays under + * the 500-LOC cap. */ + +/* ===== STRATEGY / GO-TO-MARKET ===== */ export function PrintStrategyPage({ lang, pageNum, totalPages, versionName }: SlideBase) { const de = lang === 'de' - const phases = de ? STRATEGY_PHASES_DE : STRATEGY_PHASES_EN + const phases = [ + { + n: '01', t: de ? 'Pilot, Jul/Aug 2026' : 'Pilot, Jul/Aug 2026', + subtitle: de ? 'Validierung im DACH-Maschinenbau' : 'DACH manufacturing validation', + items: de ? [ + 'GmbH-Gründung Breakpilot COMPLAI', + 'Direktvertrieb an Maschinenbauer 10–250 MA', + 'White-Glove-Onboarding: persönlich, hands-on', + '2 Referenzkunden aus Region Konstanz/Bodensee', + 'Case Studies, Testimonials, Referenz-Calls', + 'Ziel: 2 zahlende Kunden, ARR €30–50k', + ] : [ + 'GmbH incorporation Breakpilot COMPLAI', + 'Direct sales to manufacturers 10–250 emp.', + 'White-glove onboarding: personal, hands-on', + '2 reference customers from Konstanz/Bodensee region', + 'Case studies, testimonials, reference calls', + 'Goal: 2 paying customers, ARR €30–50k', + ], + kpi: de ? '2 Kunden · ARR €40k' : '2 customers · ARR €40k', + tone: COLORS.indigo600, + }, + { + n: '02', t: de ? 'Skalierung, 2027' : 'Scale, 2027', + subtitle: de ? 'Channel-Partnerschaften, IHK, Messen' : 'Channel partnerships, IHK, fairs', + items: de ? [ + 'Channel-Partnerschaften mit IT-Systemhäusern (5–10)', + 'IHK-Kooperationen Bodensee, Stuttgart, München', + 'VDMA-Kooperation, Hannover Messe, IT-SA', + 'Content-Marketing: Compliance-Webinare 2× / Monat', + 'Inbound-Funnel + SEO für AI-Act / NIS2 / CRA', + 'Headcount: 5–7 (Eng + 2 Sales + 1 CSM)', + 'Ziel: 50–80 Kunden, ARR €1,2–2M', + ] : [ + 'Channel partnerships with IT integrators (5–10)', + 'IHK partnerships Bodensee, Stuttgart, Munich', + 'VDMA cooperation, Hannover Messe, IT-SA', + 'Content marketing: compliance webinars 2× / month', + 'Inbound funnel + SEO for AI Act / NIS2 / CRA', + 'Headcount: 5–7 (eng + 2 sales + 1 CSM)', + 'Goal: 50–80 customers, ARR €1.2–2M', + ], + kpi: de ? '50–80 Kunden · ARR €1,5M' : '50–80 customers · ARR €1.5M', + tone: COLORS.indigo600, + }, + { + n: '03', t: de ? 'Expansion, 2028 +' : 'Expansion, 2028 +', + subtitle: de ? 'EU-Skalierung & Enterprise' : 'EU scale & enterprise', + items: de ? [ + 'Enterprise-Kunden (50–500 MA): dedicated AE-Team', + 'EU-Expansion: AT (DACH-nativ), CH, Benelux', + 'Distributor-Partnerschaften für Frankreich, Italien', + 'Branchenausweitung: Automotive, Pharma, Energie', + 'Series A vorbereiten (€8–12M, Q2 2029)', + 'Break-Even Q3 / 2029', + 'Ziel: 200+ Kunden, ARR €8–12M', + ] : [ + 'Enterprise customers (50–500 emp.): dedicated AE team', + 'EU expansion: AT (DACH-native), CH, Benelux', + 'Distributor partnerships for France, Italy', + 'Industry expansion: Automotive, Pharma, Energy', + 'Prepare Series A (€8–12M, Q2 2029)', + 'Break-even Q3 / 2029', + 'Goal: 200+ customers, ARR €8–12M', + ], + kpi: de ? '200+ Kunden · Break-Even' : '200+ customers · break-even', + tone: COLORS.emerald600, + }, + ] + return ( - - - {de ? 'Anhang · Strategie' : 'Appendix · Strategy'} - -
- {[ - { c: '#ef4444', t: de ? 'Code Security' : 'Code Security', s: 'Snyk, Checkmarx, Veracode', q: de ? '„47 Schwachstellen gefunden. CRA-konform? Nicht unser Problem."' : '"Found 47 vulnerabilities. CRA compliant? Not our problem."' }, - { c: COLORS.indigo, t: 'BreakPilot COMPLAI', s: de ? 'Verbindet beides' : 'Combines both', q: de ? '„Code gescannt, SBOM generiert, CRA gemappt, TOM aktualisiert, CE-Ordner fertig."' : '"Code scanned, SBOM generated, CRA mapped, TOM updated, CE folder ready."' }, - { c: '#06b6d4', t: de ? 'Compliance' : 'Compliance', s: 'DataGuard, Vanta, Drata', q: de ? '„Dokumentation fertig. Code sicher? Brauchen Sie ein anderes Tool."' : '"Documentation done. Code secure? You need a different tool."' }, - ].map(b => ( -
-

{b.t}

-

{b.s}

-

{b.q}

-
- ))} -
-

{de ? 'Firmenaufbau in 4 Phasen' : 'Company Building in 4 Phases'}

-
- {phases.map(p => ( -
-

{p.title}

-

{p.period}

-
- {p.team}{p.arr} + + + { + // Split "2 Kunden · ARR €40k" into pieces for a richer outcome block + const kpiParts = p.kpi.split(' · ') + return ( +
+ {p.n} +
{p.t}
+
{p.subtitle}
+
+
-
    - {p.items.map(i =>
  • {i}
  • )} -
-
- ))} -
-
-
-

CANCOM Cloud Marketplace

-

{de ? 'TecDAX · ~5.800 MA · 120+ SaaS-Produkte' : 'TecDAX · ~5,800 emp. · 120+ SaaS products'}

-

{de ? 'Formales ISV-Partnerprogramm, Marketplace-Listing in 3-6 Monaten, hunderte CANCOM-Vertriebsmitarbeiter co-sellen.' : 'Formal ISV partner program, marketplace listing in 3-6 months, hundreds of CANCOM reps co-sell.'}

-
-
-

Bechtle Systemhäuser

-

{de ? '15.000 MA · 85+ Standorte · 6,3 Mrd. EUR · 70.000 Kunden' : '15,000 emp. · 85+ locations · EUR 6.3B · 70,000 customers'}

-

{de ? 'Regionaler Einstieg mit lokalem Systemhaus, Champion evangelisiert intern, nationale Listung nach Pilot-Erfolg (12-18 Monate).' : 'Regional entry with local system house, champion evangelizes internally, national listing after pilot success (12-18 months).'}

-
-
-

- {de ? '* CANCOM und Bechtle sind geplante Distributionspartner. Eine Kontaktaufnahme ist noch nicht erfolgt.' : '* CANCOM and Bechtle are planned distribution partners. No contact has been made yet.'} -

- - ) -} - -export function PrintFinanzplanPage({ fmResults, lang, pageNum, totalPages, versionName }: SlideBase & { fmResults: FMResult[] }) { - const de = lang === 'de' - const byYear = new Map() - for (const r of fmResults) { - if (!byYear.has(r.year)) byYear.set(r.year, []) - byYear.get(r.year)!.push(r) - } - const years = Array.from(byYear.entries()).sort(([a], [b]) => a - b).map(([year, rows]) => { - const last = rows[rows.length - 1] - const revenue = rows.reduce((s, r) => s + r.revenue_eur, 0) - return { - year, - revenue, - customers: last?.total_customers ?? 0, - employees: last?.employees_count ?? 0, - arr: last?.arr_eur ?? 0, - mrr: last?.mrr_eur ?? 0, - } - }) - const fmt = (n: number) => { - const abs = Math.abs(n) - if (abs >= 1_000_000) return `${(n / 1_000_000).toLocaleString('de-DE', { maximumFractionDigits: 1 })}M` - if (abs >= 1_000) return `${(n / 1_000).toLocaleString('de-DE', { maximumFractionDigits: 0 })}k` - return n.toLocaleString('de-DE') - } - const maxRev = Math.max(1, ...years.map(y => y.revenue)) - return ( - - - {de ? 'Anhang · Finanzplan' : 'Appendix · Financial Plan'} - - {years.length === 0 ? ( -
-

- {de - ? 'Detaillierter Finanzplan (Umsatz, GuV, Liquidität, Personal, Kunden, Investitionen) ist im Investorenportal und im L-Bank Excel-Template verfügbar. Diese PDF-Version zeigt nur die annualisierten Kennzahlen aus dem Finanzmodell.' - : 'Detailed financial plan (revenue, P&L, liquidity, personnel, customers, capex) is available in the investor portal and L-Bank Excel template. This PDF version shows only annualized KPIs from the financial model.'} -

-
- ) : ( - <> -
- [ - {y.year}, - `${fmt(y.revenue)} EUR`, - `${fmt(y.arr)} EUR`, - `${fmt(y.mrr)} EUR`, - y.customers.toString(), - y.employees.toString(), - ])} - colWidths={['10%', '20%', '20%', '20%', '15%', '15%']} - /> -
-
-

{de ? 'Umsatzwachstum' : 'Revenue growth'}

- {years.map(y => ( -
- {y.year} -
-
-
- {fmt(y.revenue)} EUR + {/* Bottom outcome block fills remaining vertical space and reads as a KPI tile */} +
+
{de ? 'Outcome' : 'Outcome'}
+
1 ? '1fr 1fr' : '1fr', gap: '3mm' }}> + {kpiParts.map((part, j) => ( +
{part}
+ ))}
- ))} +
- - )} -

- {de ? '* Planzahlen aus dem internen Finanzmodell. SKR04-Kontenrahmen, monatliche Granularität. Detail-Tabs (GuV, Liquidität, Personalkosten, Kundenakquise) im Investor-Portal.' : '* Projections from internal financial model. SKR04 chart of accounts, monthly granularity. Detail tabs (P&L, liquidity, payroll, customer acquisition) in the investor portal.'} -

- + ) + })} /> + +
+ + {de + ? 'Maschinenbauer kaufen über Vertrauen + Referenzen. Phase 1: Beziehungen aufbauen. Phase 2: Multiplikatoren nutzen (Systemhäuser, IHK, VDMA). Phase 3: Inbound + Enterprise-Konten.' + : 'Manufacturers buy via trust + references. Phase 1: build relationships. Phase 2: leverage multipliers (system houses, IHK, VDMA). Phase 3: inbound + enterprise accounts.'} + +
+ ) } -const REG_DATA = { - de: [ - { name: 'DSGVO', full: 'EU 2016/679', deadline: 'Seit Mai 2018', fines: 'Bis 20 Mio. EUR / 4% Umsatz', reqs: ['VVT (Art. 30)', 'DSFA (Art. 35)', 'TOMs', 'Betroffenenrechte', 'AV-Verträge', 'DSB ab 20 MA', '72h-Meldepflicht'], help: ['Auto-VVT aus Unternehmensdaten', 'KI-gestützte DSFA', 'TOM-Generator', 'Self-Service Betroffenenportal', 'Audit-Trail'] }, - { name: 'AI Act', full: 'EU 2024/1689', deadline: 'Aug 2025 / 2026 / 2027', fines: 'Bis 35 Mio. EUR / 7% Umsatz', reqs: ['Risikoklassifizierung (Art. 6)', 'Konformitätsbewertung Hochrisiko (Art. 43)', 'Tech. Doku (Art. 11-13)', 'Menschliche Aufsicht (Art. 14)', 'EU-Datenbank-Registrierung (Art. 49)', 'GPAI-Pflichten (Art. 51-56)', 'FRIA (Art. 27)'], help: ['Auto-Risikoklassifizierung', 'Konformitäts-Checklisten', 'Template-basierte Doku', 'Audit-Vorbereitung', 'Monitoring Rechtsänderungen'] }, - { name: 'CRA', full: 'EU 2024/2847', deadline: 'Sep 2026 / Dez 2027', fines: 'Bis 15 Mio. EUR / 2,5% Umsatz', reqs: ['Security by Design', 'Schwachstellen-Mgmt über Lebenszyklus', 'SBOM für jedes Produkt', 'Kostenlose Security-Updates', '24h-Meldepflicht', 'Drittstellen-Bewertung kritisch', 'CE-Kennzeichnung Cyber'], help: ['Auto-SBOM aus Code-Repos', 'Kontinuierliches Vuln-Scanning (Trivy, Grype)', 'Security-Fixes via Cloud-LLM', 'CRA-Doku + Audit-Trail', 'Risikoanalysen Firmware'] }, - { name: 'NIS2', full: 'EU 2022/2555', deadline: 'NIS2UmsuCG 2025/26', fines: 'Bis 10 Mio. EUR / 2% Umsatz', reqs: ['Risikomgmt-Maßnahmen (Art. 21)', '24h Frühwarnung, 72h Bericht (Art. 23)', 'Business Continuity', 'Supply-Chain-Security', 'Geschäftsleiterhaftung', 'BSI-Registrierung', 'Regelmäßige Audits'], help: ['Policy-Generator nach BSI-Grundschutz', 'Incident-Response-Pläne', 'Supply-Chain-Risikoanalyse', 'Audit-Doku', 'NIS2-Readiness-Assessment'] }, - ], - en: [ - { name: 'GDPR', full: 'EU 2016/679', deadline: 'Since May 2018', fines: 'Up to EUR 20M / 4% revenue', reqs: ['RoPA (Art. 30)', 'DPIA (Art. 35)', 'TOMs', 'Data subject rights', 'DPAs', 'DPO from 20 emp.', '72h breach notification'], help: ['Auto-RoPA from company data', 'AI-powered DPIA', 'TOM generator', 'Self-service data subject portal', 'Audit trail'] }, - { name: 'AI Act', full: 'EU 2024/1689', deadline: 'Aug 2025 / 2026 / 2027', fines: 'Up to EUR 35M / 7% revenue', reqs: ['Risk classification (Art. 6)', 'Conformity assessment high-risk (Art. 43)', 'Technical doc (Art. 11-13)', 'Human oversight (Art. 14)', 'EU database registration (Art. 49)', 'GPAI obligations (Art. 51-56)', 'FRIA (Art. 27)'], help: ['Auto risk classification', 'Conformity checklists', 'Template-based docs', 'Audit prep', 'Regulatory change monitoring'] }, - { name: 'CRA', full: 'EU 2024/2847', deadline: 'Sep 2026 / Dec 2027', fines: 'Up to EUR 15M / 2.5% revenue', reqs: ['Security by design', 'Vuln mgmt across lifecycle', 'SBOM per product', 'Free security updates', '24h reporting', 'Third-party assessment critical', 'CE marking cyber'], help: ['Auto SBOM from code repos', 'Continuous vuln scanning (Trivy, Grype)', 'Security fixes via cloud LLM', 'CRA docs + audit trail', 'Firmware risk assessments'] }, - { name: 'NIS2', full: 'EU 2022/2555', deadline: 'NIS2 Act 2025/26', fines: 'Up to EUR 10M / 2% revenue', reqs: ['Risk mgmt measures (Art. 21)', '24h early warning, 72h report (Art. 23)', 'Business continuity', 'Supply chain security', 'Management liability', 'BSI registration', 'Regular audits'], help: ['Policy generator BSI standards', 'Incident response plans', 'Supply chain risk analysis', 'Audit docs', 'NIS2 readiness assessment'] }, - ], -} +/* ===== ANNEX REGULATORY ===== */ + +const PILLARS_DE = [ + { t: 'DSGVO + AI Act', d: 'Datenschutz + KI-Regulierung greifen ineinander. Hochrisiko-KI-Systeme (Art. 6 AI Act) benötigen DSFA + Konformitätsbewertung. BreakPilot generiert beide automatisch.', laws: ['VO 2016/679 (DSGVO)', 'VO 2024/1689 (AI Act)', '§§ 9, 27 BDSG'] }, + { t: 'NIS2 + Cyber Resilience Act', d: 'NIS2 schreibt Sicherheitsmaßnahmen für ~30k DE-Unternehmen vor. CRA addressiert Produkte mit digitalen Elementen. Beide brauchen kontinuierliches Vulnerability-Management.', laws: ['RL 2022/2555 (NIS2)', 'VO 2024/2847 (CRA)', '§§ 28 ff. BSIG'] }, + { t: 'Maschinen-VO + ProdSG', d: 'Neue EU-Maschinenverordnung (ab 2027 verpflichtend) fordert Software-Risikobeurteilung schon auf Code-Ebene. Klassische CE-Verfahren reichen nicht mehr.', laws: ['VO 2023/1230 (MaschVO)', 'ProdSG 2021', 'EN ISO 12100'] }, + { t: 'DORA + Branchenrecht', d: 'Finanzsektor: DORA. Gesundheit: MDR/IVDR. Öffentlicher Sektor: OZG. KRITIS: BSI-KritisV. BreakPilot deckt 380+ Regularien, branchenagnostisch.', laws: ['VO 2022/2554 (DORA)', 'VO 2017/745 (MDR)', 'BSI-KritisV'] }, +] +const PILLARS_EN = [ + { t: 'GDPR + AI Act', d: 'Data protection + AI regulation interlock. High-risk AI systems (AI Act Art. 6) require DPIA + conformity assessment. BreakPilot generates both automatically.', laws: ['Reg. 2016/679 (GDPR)', 'Reg. 2024/1689 (AI Act)', 'BDSG §§ 9, 27'] }, + { t: 'NIS2 + Cyber Resilience Act', d: 'NIS2 mandates security measures for ~30k DE companies. CRA addresses products with digital elements. Both require continuous vulnerability management.', laws: ['Dir. 2022/2555 (NIS2)', 'Reg. 2024/2847 (CRA)', 'BSIG §§ 28 ff.'] }, + { t: 'Machinery Reg. + ProdSG', d: 'New EU Machinery Regulation (mandatory from 2027) requires software risk assessment at code level. Traditional CE procedures are no longer sufficient.', laws: ['Reg. 2023/1230 (Mach. Reg.)', 'ProdSG 2021', 'EN ISO 12100'] }, + { t: 'DORA + Industry Law', d: 'Finance: DORA. Health: MDR/IVDR. Public sector: OZG. KRITIS: BSI-KritisV. BreakPilot covers 380+ regulations, industry-agnostic.', laws: ['Reg. 2022/2554 (DORA)', 'Reg. 2017/745 (MDR)', 'BSI-KritisV'] }, +] export function PrintRegulatoryPage({ lang, pageNum, totalPages, versionName }: SlideBase) { const de = lang === 'de' - const regs = de ? REG_DATA.de : REG_DATA.en + const pillars = de ? PILLARS_DE : PILLARS_EN return ( - - - {de ? 'Anhang · Regulatorische Details' : 'Appendix · Regulatory Details'} - -
- {regs.map(r => ( -
-
-

{r.name}

-

{r.full}

+ + +
+ {pillars.map((p, i) => ( +
+
+ {de ? `Säule ${String(i + 1).padStart(2, '0')}` : `Pillar ${String(i + 1).padStart(2, '0')}`} + {de ? '4-6 Regelwerke' : '4-6 regulations'}
-
- 📅 {r.deadline}⚠ {r.fines} -
-
-
-

{de ? 'Anforderungen' : 'Requirements'}

-
    - {r.reqs.slice(0, 5).map(x =>
  • {x}
  • )} -
-
-
-

{de ? 'Wie wir helfen' : 'How we help'}

-
    - {r.help.slice(0, 5).map(x =>
  • {x}
  • )} -
-
+
{p.t}
+
{p.d}
+
+ {p.laws.join(' · ')}
))}
- + +
+ + {de + ? 'DSGVO: bis zu 4% Jahresumsatz · AI Act: bis zu 7% bei verbotener KI · NIS2: bis zu 2% · CRA: bis zu 2% · MDR/IVDR: produktspezifisch, Rückruf möglich. Kontinuierliche Compliance senkt das Risiko gegen Null.' + : 'GDPR: up to 4% annual revenue · AI Act: up to 7% for prohibited AI · NIS2: up to 2% · CRA: up to 2% · MDR/IVDR: product-specific, recall possible. Continuous compliance reduces risk to near zero.'} + +
+ ) } -const ARCH_NODES_DE = [ - { id: 'certifai', title: 'CERTifAI', sub: 'GenAI Mandantenportal', tech: 'Rust · Dioxus · MongoDB · Keycloak · SearXNG · LangGraph', services: ['LiteLLM Dashboard', 'LibreChat + SSO', 'LangGraph Agents', 'MCP Hub'] }, - { id: 'complai', title: 'COMPLAI', sub: 'Compliance & Audit', tech: 'Next.js 15 · FastAPI · Go/Gin · PostgreSQL · Qdrant', services: ['DSGVO / AI Act / NIS2 (70k+ Controls)', 'RAG Pipeline (75+ Quellen)', 'Control Pipeline (LLM)', 'MCP Client'] }, - { id: 'scanner', title: 'Compliance Scanner', sub: 'Code-Sicherheit', tech: 'Rust · Axum · MongoDB · Semgrep · Gitleaks · Syft', services: ['SAST / SBOM / CVE Pipeline', 'KI-Triage (LLM-Filter)', 'KI-Pentest (autonom)', 'MCP Server'] }, - { id: 'litellm', title: 'LiteLLM Proxy', sub: 'KI-Gateway & Guardrails', tech: 'OpenAI-API · Bearer Auth · Rate Limiting · PII-Filter', services: ['Token-Budget pro Mandant', 'PII Guardrails', 'SearXNG Web-Suche (anonym)', 'Namespace-Isolierung', 'Failover-Routing'] }, - { id: 'llm', title: 'LLM Inferenz', sub: 'Lokale Sprachmodelle', tech: 'Qwen3-32B · Qwen3-Coder-30B · DeepSeek-R1-8B · Ollama', services: ['Vollständig lokal', 'Air-Gap-fähig', 'GPU-optimiert'] }, - { id: 'embeddings', title: 'Embeddings', sub: 'Semantische Suche', tech: 'bge-m3 · Qdrant · Sentence-Transformers', services: ['RAG (75+ Quellen)', 'Multi-linguale Embeddings', '100% lokal'] }, - { id: 'tools', title: 'KI-Tools', sub: 'Web-Suche & MCP', tech: 'SearXNG · MCP Protocol · Semgrep API · Gitleaks API', services: ['Anonymisierte EU-Websuche', 'MCP Tools (Audit/Code)', 'Kein US-Anbieter'] }, -] -const ARCH_NODES_EN = [ - { id: 'certifai', title: 'CERTifAI', sub: 'GenAI Tenant Portal', tech: 'Rust · Dioxus · MongoDB · Keycloak · SearXNG · LangGraph', services: ['LiteLLM Dashboard', 'LibreChat + SSO', 'LangGraph Agents', 'MCP Hub'] }, - { id: 'complai', title: 'COMPLAI', sub: 'Compliance & Audit', tech: 'Next.js 15 · FastAPI · Go/Gin · PostgreSQL · Qdrant', services: ['GDPR / AI Act / NIS2 (70k+ controls)', 'RAG Pipeline (75+ sources)', 'Control Pipeline (LLM)', 'MCP Client'] }, - { id: 'scanner', title: 'Compliance Scanner', sub: 'Code Security', tech: 'Rust · Axum · MongoDB · Semgrep · Gitleaks · Syft', services: ['SAST / SBOM / CVE pipeline', 'AI triage (LLM filter)', 'AI pentest (autonomous)', 'MCP Server'] }, - { id: 'litellm', title: 'LiteLLM Proxy', sub: 'AI Gateway & Guardrails', tech: 'OpenAI API · Bearer Auth · Rate Limiting · PII filter', services: ['Token budget per tenant', 'PII guardrails', 'SearXNG web search (anon)', 'Namespace isolation', 'Failover routing'] }, - { id: 'llm', title: 'LLM Inference', sub: 'Local Language Models', tech: 'Qwen3-32B · Qwen3-Coder-30B · DeepSeek-R1-8B · Ollama', services: ['Fully local', 'Air-gap capable', 'GPU optimized'] }, - { id: 'embeddings', title: 'Embeddings', sub: 'Semantic Search', tech: 'bge-m3 · Qdrant · Sentence-Transformers', services: ['RAG (75+ sources)', 'Multi-lingual embeddings', '100% local'] }, - { id: 'tools', title: 'AI Tools', sub: 'Web Search & MCP', tech: 'SearXNG · MCP Protocol · Semgrep API · Gitleaks API', services: ['Anonymized EU web search', 'MCP tools (audit/code)', 'No US providers'] }, -] +/* ===== ANNEX ARCHITECTURE ===== */ export function PrintArchitecturePage({ lang, pageNum, totalPages, versionName }: SlideBase) { const de = lang === 'de' - const nodes = de ? ARCH_NODES_DE : ARCH_NODES_EN return ( - - - {de ? 'Anhang · Systemarchitektur' : 'Appendix · System Architecture'} - -
- {nodes.map(n => ( -
-
-

{n.title}

-

{n.sub}

-
-

{n.tech}

-
    - {n.services.map(s =>
  • {s}
  • )} -
-
- ))} -
-
+ + + ) } +/* ===== ANNEX ENGINEERING ===== */ + export function PrintEngineeringPage({ lang, pageNum, totalPages, versionName }: SlideBase) { const de = lang === 'de' - const stats = [ - { v: '500K+', l: de ? 'Zeilen Code' : 'Lines of code', s: 'Go · Python · TypeScript' }, - { v: '385', l: de ? 'Dokumente im RAG' : 'Docs in RAG', s: 'EU · DACH · Frameworks · Urteile' }, - { v: '25K+', l: de ? 'Compliance Controls' : 'Compliance Controls', s: '6 Pipeline-Versionen' }, - ] - const langs = [ - { lang: 'TypeScript / TSX', pct: 49, loc: '235K', color: '#3b82f6' }, - { lang: 'Python', pct: 28, loc: '133K', color: '#eab308' }, - { lang: 'Go', pct: 23, loc: '113K', color: '#06b6d4' }, - ] - const devops = [ - { l: 'Gitea + Actions', d: de ? 'Self-hosted Git + CI/CD · Lint → Tests → Image-Build' : 'Self-hosted Git + CI/CD · Lint → Tests → Image build' }, - { l: 'orca', d: de ? 'Single-Binary Orchestrator (Rust) · Webhook-Deploy · Auto-TLS' : 'Single-binary orchestrator (Rust) · Webhook deploys · Auto-TLS' }, - { l: 'Private Registry', d: 'registry.meghsakha.com · Signed images · Per-commit tags' }, - { l: 'DevSecOps', d: 'Semgrep · Trivy · Gitleaks · CycloneDX SBOM' }, - { l: 'Infisical', d: de ? 'Secrets Mgmt · Rotation · RBAC · End-to-End-verschlüsselt' : 'Secrets mgmt · Rotation · RBAC · End-to-end encrypted' }, - { l: de ? 'EU-Cloud Infrastruktur' : 'EU Cloud Infrastructure', d: 'Hetzner · SysEleven (BSI) · PostgreSQL · Qdrant' }, - ] return ( - - - {de ? 'Anhang · Engineering Deep Dive' : 'Appendix · Engineering Deep Dive'} - -
- {stats.map(s => ( -
-

{s.v}

-

{s.l}

-

{s.s}

+ + +
+ {[ + { n: '500K+', l: 'Lines of Code' }, + { n: '45', l: de ? 'Container' : 'Containers' }, + { n: '4', l: de ? 'Sprachen' : 'Languages' }, + { n: '100%', l: 'Self-Hosted' }, + ].map((k, i) => ( +
+
{k.n}
+
{k.l}
))}
-
+ +
-

{de ? 'Sprachen-Mix' : 'Language Mix'}

-
- {langs.map(l =>
)} -
- {langs.map(l => ( -
- - - {l.lang} - - {l.loc}{l.pct}% -
- ))} +
{de ? 'Tech-Stack pro Schicht' : 'Tech stack per layer'}
+
+
-

{de ? 'DevOps & Toolchain' : 'DevOps & Toolchain'}

-
- {devops.map(t => ( -
-

{t.l}

-

{t.d}

-
- ))} +
{de ? 'Engineering-Prinzipien' : 'Engineering principles'}
+ + +
+ + {de + ? 'Seit Jan 2026: 500.000+ LoC in 4 Monaten. Mit Series-A-Funding: 2× Senior Engineers, Velocity verdoppelt sich. Architektur skaliert auf 10+ Engineers ohne Refactor.' + : 'Since Jan 2026: 500,000+ LoC in 4 months. With Series A funding: 2× senior engineers, velocity doubles. Architecture scales to 10+ engineers without refactor.'} +
-

- {de ? '100% EU-Cloud · Hetzner + SysEleven (BSI) · Keine US-Anbieter · Volle Datenkontrolle' : '100% EU Cloud · Hetzner + SysEleven (BSI) · No US providers · Full data control'} -

- + ) } -const PIPELINE_STEPS = { - de: [ - { t: '1. Dokument-Ingestion', d: '380+ Rechtsquellen (EU/DACH). Strukturelles Chunking an Artikel-Grenzen. Lizenz-Klassifikation. Geschützte Quellen werden reformuliert.' }, - { t: '2. Control-Extraktion', d: 'LLM extrahiert Pflichten aus jedem Textabschnitt. 6 Pipeline-Versionen. ~97k Pflichten identifiziert. Atomic Control Composition.' }, - { t: '3. Deduplizierung', d: '97k Controls → 70k+ nach Dedup. Embedding-basierte Similarity. Cross-Regulation-Harmonisierung. Master Controls als Single Source of Truth.' }, - { t: '4. Hybrid Search & Beratung', d: 'Vektor + Keyword über alle Quellen gleichzeitig. Cross-Encoder Re-Ranking. Antworten mit Quellen-Attribution (Artikel + Absatz).' }, - ], - en: [ - { t: '1. Document Ingestion', d: '380+ legal sources (EU/DACH). Structural chunking at article boundaries. License classification. Protected standards are reformulated.' }, - { t: '2. Control Extraction', d: 'LLM extracts obligations from each section. 6 pipeline versions. ~97k duties identified. Atomic control composition.' }, - { t: '3. Deduplication', d: '97k controls → 70k+ after dedup. Embedding-based similarity. Cross-regulation harmonization. Master controls as single source of truth.' }, - { t: '4. Hybrid Search & Advisory', d: 'Vector + keyword across all sources simultaneously. Cross-encoder re-ranking. Answers with source attribution (article + paragraph).' }, - ], -} +/* ===== ANNEX AI PIPELINE ===== */ export function PrintAIPipelinePage({ lang, pageNum, totalPages, versionName }: SlideBase) { const de = lang === 'de' - const stats = [ - { v: '380+', l: de ? 'Rechtsquellen' : 'Legal sources' }, - { v: '70k+', l: de ? 'Unique Controls' : 'Unique controls' }, - { v: '97k+', l: de ? 'Extrahierte Pflichten' : 'Extracted obligations' }, - { v: '6', l: de ? 'Pipeline-Versionen' : 'Pipeline versions' }, - ] - const agents = de - ? ['UCCA: Policy Engine (45 Regeln) + Eskalation E0–E3', 'Pflichten-Engine: Multi-Regulation (NIS2, DSGVO, AI Act, CRA, ...)', 'Compliance-Berater: Legal RAG + LLM Chatbot, 75+ Quellen', 'Dokument-Generator: AGB, DSE, AVV, DSFA, FRIA, BV …', 'DSFA-Agent: Art. 35 DSGVO, 16 Bundesländer-Leitlinien', 'Control-Pipeline: Auto-Extraktion aus neuen Rechtsquellen'] - : ['UCCA: Policy engine (45 rules) + escalation E0–E3', 'Obligations Engine: Multi-regulation (NIS2, GDPR, AI Act, CRA, ...)', 'Compliance Advisor: Legal RAG + LLM chatbot, 75+ sources', 'Document Generator: T&C, Privacy, DPA, DPIA, FRIA, Works Agreement …', 'DPIA Agent: Art. 35 GDPR, 16 federal state guidelines', 'Control Pipeline: Auto-extraction from new legal sources'] - const steps = de ? PIPELINE_STEPS.de : PIPELINE_STEPS.en return ( - - - {de ? 'Anhang · KI-Pipeline Deep Dive' : 'Appendix · AI Pipeline Deep Dive'} - -
- {stats.map(s => ( -
-

{s.v}

-

{s.l}

+ + +
+ {/* Pipeline flow */} +
+
{de ? 'Pipeline-Fluss' : 'Pipeline flow'}
+ 99% precision' }, + ]} + /> +
+ + {/* Agent system */} +
+
+
{de ? 'Multi-Agent-System (LangGraph)' : 'Multi-Agent System (LangGraph)'}
+
- ))} -
-
-
-

{de ? 'RAG-Pipeline (4 Stufen)' : 'RAG Pipeline (4 stages)'}

- {steps.map(s => ( -
-

{s.t}

-

{s.d}

+ +
+
{de ? 'Qualitäts-Kennzahlen' : 'Quality metrics'}
+
+ {[ + { l: de ? 'Precision (Controls)' : 'Precision (controls)', v: '>99%' }, + { l: 'Recall (RAG)', v: '~94%' }, + { l: de ? 'Audit-Sampling Rate' : 'Audit sampling rate', v: '5%' }, + { l: de ? 'False-Positive Rate' : 'False positive rate', v: '<2%' }, + { l: de ? 'Mean Latency (RAG)' : 'Mean latency (RAG)', v: '~180ms' }, + { l: de ? 'Throughput Control-Pipeline' : 'Throughput control pipeline', v: '~1.2k/min' }, + ].map((s, i) => ( +
+ {s.l} + {s.v} +
+ ))}
- ))} -
-
-

{de ? 'Compliance-Engines' : 'Compliance Engines'}

-
    - {agents.map(a => ( -
  • - - {a} -
  • - ))} -
-

- {de ? 'Wahrheit = Regeln + Evidenz · LLM = Übersetzer. Qdrant · BGE-M3 · MinIO. 100% EU-Cloud.' : 'Truth = Rules + Evidence · LLM = Translator. Qdrant · BGE-M3 · MinIO. 100% EU Cloud.'} -

+
- + ) } -const RISKS_DE = [ - { t: 'KI-Commoditisierung', sev: 'Hoch', sevColor: '#dc2626', timeline: '3-5 J.', d: 'LLMs senken Eintrittsbarrieren — Control-Generierung, DSFA-Erstellung, Policy-Templates werden Commodity.', m: 'Wir konkurrieren auf Layer 2-6: Integration, Auditierbarkeit, Workflows, EU-Hosting. KI ist Multiplikator, nicht Produkt.' }, - { t: 'US-Plattform-Expansion', sev: 'Mittel', sevColor: '#d97706', timeline: '2-4 J.', d: 'Microsoft Purview, Vanta oder Drata expandieren mit lokalisiertem EU-Angebot.', m: 'Struktureller Vorteil: 100% EU-Infrastruktur, kein US-SaaS, Betriebsrat-Fähigkeit. CLOUD Act ist Ausschlusskriterium.' }, - { t: 'Team-Risiko / Key-Person', sev: 'Mittel', sevColor: '#d97706', timeline: 'Jahr 1-2', d: 'Abhängigkeit von zwei Gründern in der Frühphase. Wissensverlust bei Ausfall.', m: 'Doku aller Prozesse in MkDocs. KI-Codebasis mit Tests. ESOP-Pool ab Hire 1. Frühe Einstellung Rechtsanwalt/DS.' }, - { t: 'Langsame Kundenakquise', sev: 'Mittel', sevColor: '#d97706', timeline: 'Jahr 1-3', d: 'B2B-Verkaufszyklen 3-9 Monate. Compliance-Budgets jährlich geplant.', m: 'Beratungsumsätze 5-30k/Mon überbrücken Anlauf. Channel (Bechtle/CANCOM) skaliert schneller. Land-and-Expand.' }, - { t: 'Regulatorische Änderungen', sev: 'Niedrig', sevColor: '#16a34a', timeline: 'Laufend', d: 'Neue EU-Gesetze erfordern Anpassung der Plattform.', m: 'Jede Änderung vergrößert unseren Markt. RAG-Pipeline indexiert neue Regularien in Tagen. 380+ schon im System.' }, - { t: 'Liquiditätsrisiko', sev: 'Niedrig', sevColor: '#16a34a', timeline: 'Jahr 1-2', d: 'Mit 200k Wandeldarlehen ist die Runway begrenzt. Ende 2027 nahe Null.', m: 'Organisches Wachstum durch Beratung. Break-Even 2029. Pre-Seed BW (L-Bank) verdoppelt Finanzierung auf 400k.' }, -] -const RISKS_EN = [ - { t: 'AI Commoditization', sev: 'High', sevColor: '#dc2626', timeline: '3-5 yrs', d: 'LLMs lower entry barriers — control generation, DPIA creation, policy templates become commodity.', m: 'We compete on Layers 2-6: integration, auditability, workflows, EU hosting. AI is multiplier, not product.' }, - { t: 'US Platform Expansion', sev: 'Medium', sevColor: '#d97706', timeline: '2-4 yrs', d: 'Microsoft Purview, Vanta or Drata expand with localized EU offering.', m: 'Structural advantage: 100% EU infra, no US SaaS, works council compliance. CLOUD Act is a deal-breaker.' }, - { t: 'Team Risk / Key Person', sev: 'Medium', sevColor: '#d97706', timeline: 'Year 1-2', d: 'Dependency on two founders. Knowledge loss in case of absence.', m: 'All processes documented in MkDocs. AI-assisted codebase with tests. ESOP pool from hire 1. Early lawyer hire.' }, - { t: 'Slow Customer Acquisition', sev: 'Medium', sevColor: '#d97706', timeline: 'Year 1-3', d: 'B2B sales cycles 3-9 months. Compliance budgets planned annually.', m: 'Consulting revenue 5-30k/month bridges ramp. Channel (Bechtle/CANCOM) scales faster. Land-and-expand.' }, - { t: 'Regulatory Changes', sev: 'Low', sevColor: '#16a34a', timeline: 'Ongoing', d: 'New EU laws require platform adaptation.', m: 'Every change enlarges our market. RAG pipeline indexes new regulations in days. 380+ already in system.' }, - { t: 'Liquidity Risk', sev: 'Low', sevColor: '#16a34a', timeline: 'Year 1-2', d: 'With 200k convertible loan, runway is limited. Near zero by end of 2027.', m: 'Organic growth via consulting. Break-even 2029. Pre-Seed BW (L-Bank) doubles funding to 400k.' }, -] +/* ===== RISKS ===== */ export function PrintRisksPage({ lang, pageNum, totalPages, versionName }: SlideBase) { const de = lang === 'de' - const risks = de ? RISKS_DE : RISKS_EN + const rows = de ? [ + ['Markt', 'Adoption langsamer als geplant', 'Mittel', 'Mittel', 'White-Glove-Onboarding, Channel über IHK/VDMA, Free-Tier für KMU <10 MA'], + ['Markt', 'Vanta/Drata gehen EU-First', 'Niedrig', 'Hoch', 'BreakPilot-Vorsprung 18 Monate, Code-Security ist Moat, EU-Marken-DPMA + EUIPO gesichert'], + ['Technologie', 'LLM-Anbieter (Qwen, DeepSeek) ändern Lizenz', 'Niedrig', 'Mittel', 'Multi-LLM-Strategie via LiteLLM, Offline-Modelle, eigene Embeddings'], + ['Technologie', 'False-Positive in Code-Scans', 'Hoch', 'Niedrig', 'AI-Triage senkt False-Positives auf <2%, manueller Review-Loop, kontinuierliches Training'], + ['Regulatorik', 'AI Act zwingt zu Konformitätsbewertung', 'Hoch', 'Mittel', 'Eigene Konformitätsbewertung im 2. Half 2026, sind selbst Hochrisiko-KI'], + ['Regulatorik', 'Schrems III ändert EU-Datenfluss', 'Mittel', 'Niedrig', '100% EU-Hosting bereits umgesetzt, kein Datentransfer in USA'], + ['Team', 'CTO-Abgang', 'Niedrig', 'Sehr hoch', 'CTO ist Gründer mit 37,3% Equity + Vesting, 4-Jahres-Bindung, Code-Doku exzellent'], + ['Team', 'Senior-Engineers nicht skalierbar', 'Mittel', 'Mittel', 'Remote-First, Region Konstanz/Bodensee, Anthropic-/Google-Netzwerk des CTO'], + ['Finanzen', 'Funding-Verzögerung', 'Mittel', 'Mittel', 'Gründerzuschuss aktiv, INVEST-Zuschuss vorbereitet, Wandeldarlehen-Bridge möglich'], + ['Operativ', 'Compliance-Verstoß im eigenen Betrieb', 'Niedrig', 'Hoch', 'BreakPilot ist eigener Kunde, audit-ready by design, DSB extern bestellt'], + ] : [ + ['Market', 'Adoption slower than planned', 'Medium', 'Medium', 'White-glove onboarding, channel via IHK/VDMA, free tier for SMEs <10 emp.'], + ['Market', 'Vanta/Drata go EU-first', 'Low', 'High', 'BreakPilot lead 18 months, code security is moat, EU trademark DPMA + EUIPO secured'], + ['Technology', 'LLM providers (Qwen, DeepSeek) change license', 'Low', 'Medium', 'Multi-LLM strategy via LiteLLM, offline models, own embeddings'], + ['Technology', 'False positives in code scans', 'High', 'Low', 'AI triage lowers false positives to <2%, manual review loop, continuous training'], + ['Regulatory', 'AI Act mandates conformity assessment', 'High', 'Medium', 'Own conformity assessment in 2nd half 2026, we are high-risk AI ourselves'], + ['Regulatory', 'Schrems III changes EU data flow', 'Medium', 'Low', '100% EU hosting already in place, no data transfer to USA'], + ['Team', 'CTO departure', 'Low', 'Very high', 'CTO is founder with 37.3% equity + vesting, 4-year tie-in, code documentation excellent'], + ['Team', 'Senior engineers not scalable', 'Medium', 'Medium', "Remote-first, Konstanz/Bodensee region, CTO's Anthropic/Google network"], + ['Finance', 'Funding delay', 'Medium', 'Medium', 'Founder grant active, INVEST grant prepared, convertible loan bridge possible'], + ['Operations', 'Compliance violation in own operations', 'Low', 'High', 'BreakPilot is its own customer, audit-ready by design, external DPO appointed'], + ] + return ( - - - {de ? 'Risiken & Mitigation' : 'Risks & Mitigation'} - - [ - {r.t}, - {r.sev}, - r.timeline, - r.d, - {r.m}, - ])} - colWidths={['17%', '8%', '10%', '32%', '33%']} + + + -
-

+ +

+ {de - ? '„Wir konkurrieren nicht mit KI. Wir konkurrieren mit Teams, die KI besser einsetzen als wir. Deshalb bauen wir nicht das beste LLM, sondern die vertrauenswürdigste Compliance-Infrastruktur."' - : '"We don\'t compete with AI. We compete with teams that use AI better than we do. That is why we don\'t build the best LLM but the most trustworthy compliance infrastructure."'} -

+ ? 'BreakPilot scannt seinen eigenen Code. Wir generieren unsere eigene VVT, eigene DSFA, eigene TOMs. Wir sind audit-ready bevor wir den ersten Kunden onboarden, und das ist die beste Mitigation für alle Compliance-bezogenen Risiken.' + : 'BreakPilot scans its own code. We generate our own RoPA, own DPIA, own TOMs. We are audit-ready before onboarding our first customer, and that is the best mitigation for all compliance-related risks.'} +
- + ) } -const GLOSSARY = { - de: [ - { cat: 'Code Security & DevSecOps', color: '#ef4444', terms: [['SAST', 'Static Application Security Testing — Quellcode-Analyse'], ['DAST', 'Dynamic Application Security Testing — Laufzeit-Tests'], ['SBOM', 'Software Bill of Materials — Komponenten-Liste'], ['SCA', 'Software Composition Analysis'], ['DevSecOps', 'Sicherheit integriert in Entwicklung'], ['CI/CD', 'Automatisierte Build/Deploy-Pipeline']] }, - { cat: 'Compliance & Datenschutz', color: COLORS.indigo, terms: [['DSGVO', 'EU-Datenschutzverordnung seit Mai 2018'], ['VVT', 'Verzeichnis von Verarbeitungstätigkeiten'], ['TOMs', 'Technisch-Organisatorische Maßnahmen'], ['DSFA', 'Datenschutz-Folgenabschätzung'], ['DSR', 'Betroffenenrechte (Auskunft, Löschung)'], ['DSB', 'Datenschutzbeauftragter'], ['ISMS', 'Information Security Management System']] }, - { cat: 'EU-Regulierungen', color: '#06b6d4', terms: [['AI Act', 'KI-Verordnung EU 2024/1689 — Risikoklassen'], ['CRA', 'Cyber Resilience Act — SBOM-Pflicht'], ['NIS2', 'EU-Cybersicherheits-Richtlinie'], ['MVO', 'Maschinenverordnung 2023/1230'], ['Cloud Act', 'US-Gesetz für extraterritorialen Datenzugriff'], ['FISA 702', 'US-Überwachungsgesetz'], ['BDSG', 'Bundesdatenschutzgesetz'], ['TISAX', 'Automotive Security Standard'], ['BSI', 'Bundesamt für Sicherheit in der IT']] }, - { cat: 'Kennzahlen', color: '#10b981', terms: [['ARR', 'Annual Recurring Revenue'], ['MRR', 'Monthly Recurring Revenue'], ['CAC', 'Customer Acquisition Cost'], ['LTV', 'Lifetime Value'], ['ARPU', 'Avg. Revenue Per User'], ['SaaS', 'Software as a Service'], ['ESOP', 'Employee Stock Option Plan'], ['ROI', 'Return on Investment']] }, - { cat: 'Technologie', color: '#f59e0b', terms: [['RAG', 'Retrieval Augmented Generation'], ['LLM', 'Large Language Model'], ['UCCA', 'Use-Case Compliance Assessment'], ['FRIA', 'Fundamental Rights Impact Assessment'], ['SDK', 'Software Development Kit'], ['OWASP', 'Open Web Application Security Project'], ['NIST', 'US-Standardisierungsbehörde'], ['ENISA', 'EU-Agentur für Cybersicherheit'], ['CE', 'EU-Konformitätskennzeichnung'], ['RFQ', 'Request for Quotation']] }, - ], - en: [ - { cat: 'Code Security & DevSecOps', color: '#ef4444', terms: [['SAST', 'Static Application Security Testing — source code'], ['DAST', 'Dynamic Application Security Testing — runtime'], ['SBOM', 'Software Bill of Materials — component list'], ['SCA', 'Software Composition Analysis'], ['DevSecOps', 'Security integrated into development'], ['CI/CD', 'Automated build/deploy pipeline']] }, - { cat: 'Compliance & Data Protection', color: COLORS.indigo, terms: [['GDPR', 'EU data protection regulation since May 2018'], ['RoPA', 'Record of Processing Activities'], ['TOMs', 'Technical & Organizational Measures'], ['DPIA', 'Data Protection Impact Assessment'], ['DSR', 'Data subject rights (access, erasure)'], ['DPO', 'Data Protection Officer'], ['ISMS', 'Information Security Management System']] }, - { cat: 'EU Regulations', color: '#06b6d4', terms: [['AI Act', 'AI Regulation EU 2024/1689 — risk classes'], ['CRA', 'Cyber Resilience Act — SBOM mandatory'], ['NIS2', 'EU cybersecurity directive'], ['MVO', 'Machinery Regulation 2023/1230'], ['Cloud Act', 'US law for extraterritorial data access'], ['FISA 702', 'US surveillance law'], ['BDSG', 'German Federal Data Protection Act'], ['TISAX', 'Automotive security standard'], ['BSI', 'German Federal Office for IT Security']] }, - { cat: 'Business Metrics', color: '#10b981', terms: [['ARR', 'Annual Recurring Revenue'], ['MRR', 'Monthly Recurring Revenue'], ['CAC', 'Customer Acquisition Cost'], ['LTV', 'Lifetime Value'], ['ARPU', 'Avg. Revenue Per User'], ['SaaS', 'Software as a Service'], ['ESOP', 'Employee Stock Option Plan'], ['ROI', 'Return on Investment']] }, - { cat: 'Technology', color: '#f59e0b', terms: [['RAG', 'Retrieval Augmented Generation'], ['LLM', 'Large Language Model'], ['UCCA', 'Use-Case Compliance Assessment'], ['FRIA', 'Fundamental Rights Impact Assessment'], ['SDK', 'Software Development Kit'], ['OWASP', 'Open Web Application Security Project'], ['NIST', 'US standards body'], ['ENISA', 'EU Agency for Cybersecurity'], ['CE', 'EU conformity marking'], ['RFQ', 'Request for Quotation']] }, - ], -} +/* ===== GLOSSARY ===== */ + +const GLOSSARY: [string, string][] = [ + ['AI Act', 'EU-Verordnung 2024/1689. Klassifiziert KI-Systeme in 4 Risikoklassen. Hochrisiko-KI benötigt DSFA + Konformitätsbewertung.'], + ['Audit-Trail', 'Lückenlose Nachverfolgung jeder Compliance-relevanten Änderung, wer, was, wann, warum. Auditor-tauglich.'], + ['BSI-C5', 'Cloud Computing Compliance Criteria Catalogue des BSI. Standard für Cloud-Sicherheit in DE.'], + ['BSI-KritisV', 'KRITIS-Verordnung. Definiert kritische Infrastrukturen, die NIS2-Maßnahmen umsetzen müssen.'], + ['CE-Kennzeichnung', 'Conformité Européenne. Pflicht für Produkte im EU-Binnenmarkt. Software-Anteil wird seit MaschVO 2023 bewertet.'], + ['CRA', 'Cyber Resilience Act (VO 2024/2847). Verbindlich ab Dez 2027 für Produkte mit digitalen Elementen.'], + ['DAST', 'Dynamic Application Security Testing. Prüft laufende Apps gegen Angriffe.'], + ['DORA', 'Digital Operational Resilience Act (VO 2022/2554). Für Finanzsektor seit Jan 2025.'], + ['DSFA', 'Datenschutz-Folgenabschätzung (Art. 35 DSGVO). Pflicht bei hohem Risiko für Betroffene.'], + ['DSR', 'Data Subject Request. Betroffenenrechte (Auskunft, Berichtigung, Löschung, Portabilität).'], + ['EUIPO', 'European Union Intellectual Property Office. EU-weite Markenanmeldung.'], + ['FISA 702', 'US-Gesetz zur Überwachung ausländischer Daten, gilt extraterritorial für US-Unternehmen.'], + ['INVEST-Zuschuss', 'BMWi-Förderung: 20% des Investments rückzahlungsfrei (bis €100k pro Investor / Jahr).'], + ['LiteLLM', 'Open-Source-Proxy für OpenAI-kompatible APIs. Failover, Rate-Limiting, PII-Filter.'], + ['Lines of Code (LoC)', 'Quelltextzeilen ohne Leerzeilen + Kommentare. Indikator für Engineering-Volumen.'], + ['MaschVO', 'EU-Maschinenverordnung 2023/1230. Verbindlich ab Jan 2027.'], + ['MCP', 'Model Context Protocol. Anthropic-Standard für Tool-Integration in LLMs.'], + ['MDR', 'Medical Device Regulation (VO 2017/745). Für Medizinprodukte inkl. Software.'], + ['NIS2', 'Network and Information Security Directive 2 (RL 2022/2555). Verbindlich seit Okt 2024 für ~30k DE-Unternehmen.'], + ['OPA', 'Open Policy Agent. Policy-as-Code für Autorisierung und Compliance-Regeln.'], + ['RAG', 'Retrieval-Augmented Generation. LLM mit Zugriff auf externe Wissensbasis.'], + ['RFQ', 'Request for Quotation. Anfrage zur Angebotsabgabe.'], + ['SAST', 'Static Application Security Testing. Code-Analyse ohne Ausführung.'], + ['SBOM', 'Software Bill of Materials. Inventar aller Komponenten + Lizenzen. CRA-Pflicht ab 2027.'], + ['Schrems II', 'EuGH-Urteil C-311/18 (2020). Erklärte EU-US Privacy Shield für ungültig.'], + ['Self-Hosted', 'Software, die der Kunde auf eigener Infrastruktur betreibt, kein externer SaaS.'], + ['TISAX', 'Trusted Information Security Assessment Exchange. Automotive-Sicherheitsstandard.'], + ['TOM', 'Technische und organisatorische Maßnahmen (Art. 32 DSGVO).'], + ['VVT', 'Verzeichnis von Verarbeitungstätigkeiten (Art. 30 DSGVO). Pflicht ab 250 Mitarbeitern.'], + ['Wandeldarlehen', 'Convertible Loan. Hybrid-Instrument zwischen Kredit und Equity. SAFE-ähnlich.'], +] export function PrintGlossaryPage({ lang, pageNum, totalPages, versionName }: SlideBase) { const de = lang === 'de' - const cats = de ? GLOSSARY.de : GLOSSARY.en + const half = Math.ceil(GLOSSARY.length / 2) + const left = GLOSSARY.slice(0, half) + const right = GLOSSARY.slice(half) + return ( - - - {de ? 'Anhang · Glossar & Abkürzungen' : 'Appendix · Glossary & Abbreviations'} - -
- {cats.map(c => ( -
-

{c.cat}

- - - {c.terms.map(([abbr, desc]) => ( - - - - - ))} - -
{abbr}{desc}
+ + +
+ {[left, right].map((col, ci) => ( +
+ {col.map((g, i) => ( +
+
{g[0]}
+
{g[1]}
+
+ ))}
))}
- +
) } diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintCharts.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintCharts.tsx new file mode 100644 index 0000000..0bd18bf --- /dev/null +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintCharts.tsx @@ -0,0 +1,267 @@ +import React from 'react' +import { COLORS } from './PrintLayout' + +/* ====================================================================== */ +/* CHARTS */ +/* ====================================================================== */ + +interface BarSeries { + label: string + value: number + /** Optional secondary label rendered above the bar value (e.g. "Mio."). */ + unit?: string + tone?: 'default' | 'positive' | 'negative' | 'accent' +} + +export function BarChart({ + data, height = 36, maxOverride, formatValue, title, yAxisHint, +}: { + data: BarSeries[] + height?: number // mm + maxOverride?: number + formatValue?: (n: number) => string + title?: string + yAxisHint?: string +}) { + const max = maxOverride ?? Math.max(...data.map(d => d.value), 1) + const fmt = formatValue ?? ((n: number) => n.toLocaleString('de-DE')) + const ticks = [0, 0.25, 0.5, 0.75, 1].map(t => Math.round(max * t)) + + return ( +
+ {(title || yAxisHint) && ( +
+ {title &&
{title}
} + {yAxisHint &&
{yAxisHint}
} +
+ )} +
+ {/* Y-axis ticks */} +
+ {ticks.slice().reverse().map((t, i) => ( +
{fmt(t)}
+ ))} +
+ {/* Bars + grid */} +
+ {/* Grid lines */} + {ticks.slice(1).map((_, i) => ( +
+ ))} + {/* Bars */} +
+ {data.map((d, i) => { + const h = (d.value / max) * 100 + const color = d.tone === 'positive' ? COLORS.emerald600 + : d.tone === 'negative' ? COLORS.red600 + : d.tone === 'accent' ? COLORS.amber600 + : COLORS.indigo600 + return ( +
+
{fmt(d.value)}
+
+
+ ) + })} +
+
+
+ {/* X-axis labels */} +
+ {data.map((d, i) => ( +
{d.label}
+ ))} +
+
+ ) +} + +interface LinePoint { label: string; value: number } + +export function LineChart({ + data, height = 36, formatValue, color = COLORS.indigo600, title, fill = true, +}: { + data: LinePoint[] + height?: number + formatValue?: (n: number) => string + color?: string + title?: string + fill?: boolean +}) { + if (data.length < 2) return null + const max = Math.max(...data.map(d => d.value), 1) + const fmt = formatValue ?? ((n: number) => n.toLocaleString('de-DE')) + const w = 100 + const points = data.map((d, i) => ({ + x: (i / (data.length - 1)) * w, + y: 100 - (d.value / max) * 100, + v: d.value, + label: d.label, + })) + const pathD = points.map((p, i) => (i === 0 ? `M${p.x},${p.y}` : `L${p.x},${p.y}`)).join(' ') + const areaD = `${pathD} L100,100 L0,100 Z` + + return ( +
+ {title &&
{title}
} +
+ + {/* Grid */} + {[0.25, 0.5, 0.75].map(t => ( + + ))} + {fill && } + + {points.map((p, i) => ( + + ))} + + {/* Value labels above each point */} +
+ {points.map((p, i) => ( +
{fmt(p.v)}
+ ))} +
+
+ {/* X labels */} +
+ {points.map((p, i) => ( +
{p.label}
+ ))} +
+
+ ) +} + +/** Horizontal stacked-bar comparison (e.g. "you pay" vs "you save") */ +export function ComparisonBars({ + rows, formatValue, +}: { + rows: { label: string; bars: { tone: 'positive' | 'negative' | 'accent' | 'default'; value: number; cap?: string }[] }[] + formatValue?: (n: number) => string +}) { + const max = Math.max(...rows.flatMap(r => r.bars.map(b => b.value)), 1) + const fmt = formatValue ?? ((n: number) => n.toLocaleString('de-DE')) + return ( +
+ {rows.map((row, i) => ( +
+
{row.label}
+
+ {row.bars.map((b, j) => { + const w = (b.value / max) * 100 + const color = b.tone === 'positive' ? COLORS.emerald600 + : b.tone === 'negative' ? COLORS.red600 + : b.tone === 'accent' ? COLORS.amber600 + : COLORS.indigo600 + return ( +
+
+
+ {b.cap &&
{b.cap}
} +
+
{fmt(b.value)}
+
+ ) + })} +
+
+ ))} +
+ ) +} + +/** Donut chart for percentages (use-of-funds, equity, etc.) */ +export function DonutChart({ + segments, size = 32, thickness = 6, +}: { + segments: { label: string; pct: number; color: string }[] + size?: number // mm + thickness?: number // mm +}) { + const R = 50 + const r = R - (thickness / size) * 50 + let acc = 0 + const arcs = segments.map(s => { + const start = acc / 100 * Math.PI * 2 - Math.PI / 2 + acc += s.pct + const end = acc / 100 * Math.PI * 2 - Math.PI / 2 + const x1 = 50 + R * Math.cos(start), y1 = 50 + R * Math.sin(start) + const x2 = 50 + R * Math.cos(end), y2 = 50 + R * Math.sin(end) + const x3 = 50 + r * Math.cos(end), y3 = 50 + r * Math.sin(end) + const x4 = 50 + r * Math.cos(start), y4 = 50 + r * Math.sin(start) + const large = s.pct > 50 ? 1 : 0 + const d = `M${x1},${y1} A${R},${R} 0 ${large} 1 ${x2},${y2} L${x3},${y3} A${r},${r} 0 ${large} 0 ${x4},${y4} Z` + return { d, color: s.color, pct: s.pct, label: s.label } + }) + return ( + + {arcs.map((a, i) => ( + + ))} + + ) +} + +/** Progress meter (0-100%) — horizontal */ +export function ProgressBar({ pct, color = COLORS.indigo600, label, value }: { pct: number; color?: string; label?: string; value?: string }) { + return ( +
+ {(label || value) && ( +
+ {label && {label}} + {value && {value}} +
+ )} +
+
+
+
+ ) +} + +/** Nested market-size visual (TAM/SAM/SOM) */ +export function MarketFunnel({ + tam, sam, som, fmt, +}: { + tam: { value: number; label: string; growth?: number; note?: string } + sam: { value: number; label: string; growth?: number; note?: string } + som: { value: number; label: string; growth?: number; note?: string } + fmt: (v: number) => string +}) { + const samPct = sam.value / tam.value + const somPct = som.value / tam.value + return ( +
+ {/* TAM outer */} +
+
+ TAM · {tam.label} + {tam.growth != null && +{tam.growth}% p.a.} +
+
{fmt(tam.value)}
+ {tam.note &&
{tam.note}
} + + {/* SAM inner */} +
+
+ SAM · {sam.label} + {sam.growth != null && +{sam.growth}% p.a. · {Math.round(samPct * 100)}% TAM} +
+
{fmt(sam.value)}
+ {sam.note &&
{sam.note}
} + + {/* SOM inner-inner */} +
+
+ SOM · {som.label} + {som.growth != null && +{som.growth}% p.a. · {(somPct * 100).toFixed(1)}% TAM} +
+
{fmt(som.value)}
+ {som.note &&
{som.note}
} +
+
+
+
+ ) +} diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintCompetitionSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintCompetitionSlides.tsx new file mode 100644 index 0000000..b153ead --- /dev/null +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintCompetitionSlides.tsx @@ -0,0 +1,190 @@ +import { Language } from '@/lib/types' +import { Page, MatrixGlyph, COLORS, Callout, Glyph } from './PrintLayout' +import { + EXTENDED_COMPETITORS, + ALL_FEATURES, + APPSEC_COMPETITORS, + APPSEC_FEATURES, + GROUP_LABELS, + DACH_NOTE, +} from '@/components/slides/CompetitionSlide.data' + +interface SlideBase { lang: Language; pageNum: number; totalPages: number; versionName: string } + +/* ===== COMPETITION, PAGE 1: Compliance space ===== */ + +export function PrintCompetitionPage1({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + // group features by category + const grouped = ALL_FEATURES.reduce>((acc, f) => { + const g = f.group || 'other' + if (!acc[g]) acc[g] = [] + acc[g].push(f) + return acc + }, {}) + const groupOrder = ['code-security', 'ai-data', 'frameworks', 'documentation', 'operations', 'platform', 'industry'] + + const competitorCols = ['vanta', 'drata', 'sprinto', 'proliance', 'dataguard', 'heydata'] as const + type CC = typeof competitorCols[number] + const competitorLabels: Record = { + vanta: 'V', drata: 'D', sprinto: 'S', proliance: 'P', dataguard: 'DG', heydata: 'H', + } + + return ( + + + {/* Competitor profile table */} + + + + {[de ? 'Wettbewerber' : 'Competitor', 'HQ', de ? 'Gegr.' : 'Founded', 'MA', 'ARR', de ? 'Kunden' : 'Customers', de ? 'Funding' : 'Funding', 'AI', 'Pricing'].map((h, i) => ( + + ))} + + + + {EXTENDED_COMPETITORS.map((c, i) => ( + + + + + + + + + + + + ))} + +
= 2 ? 'right' : 'left', borderBottom: `1px solid ${COLORS.slate300}`, WebkitPrintColorAdjust: 'exact', printColorAdjust: 'exact' }}>{h}
{c.flag} {c.name}{c.hqCountry}{c.founded}{c.employees.toLocaleString('de-DE')}{c.revenue}{c.customers.toLocaleString('de-DE')}{c.fundingTotal} + + {c.pricing}
+ + {/* Feature matrix */} +
+ + + + + + {competitorCols.map(k => ( + + ))} + + + + + {groupOrder.flatMap(g => { + const groupLabel = GROUP_LABELS[g] + const features = grouped[g] || [] + if (!features.length) return [] + return [ + + + , + ...features.map((f, i) => ( + + + + {competitorCols.map(k => ( + + ))} + + + )), + ] + })} + +
{de ? 'Feature (45)' : 'Feature (45)'}BP{competitorLabels[k]}USP
+ {de ? groupLabel.de : groupLabel.en} +
{de ? f.de : f.en}{f.isUSP ? '★' : ''}
+
+ + {/* Legend */} +
+ {de ? 'voll' : 'full'} + {de ? 'teilw.' : 'partial'} + {de ? 'fehlt' : 'missing'} + {de ? 'BreakPilot-USP' : 'BreakPilot USP'} + + V=Vanta · D=Drata · S=Sprinto · P=Proliance · DG=DataGuard · H=heyData +
+
+ ) +} + +/* ===== COMPETITION, PAGE 2: AppSec space ===== */ + +export function PrintCompetitionPage2({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + + return ( + + + {/* Competitor profile table */} + + + + {[de ? 'Anbieter' : 'Vendor', 'HQ', de ? 'Gegr.' : 'Founded', 'MA', 'ARR', de ? 'Kunden' : 'Customers', de ? 'Pricing' : 'Pricing', de ? 'Fokus' : 'Focus'].map((h, i) => ( + + ))} + + + + {APPSEC_COMPETITORS.map((c, i) => ( + + + + + + + + + + + ))} + +
= 2 && i <= 6 ? 'right' : 'left', borderBottom: `1px solid ${COLORS.slate300}`, WebkitPrintColorAdjust: 'exact', printColorAdjust: 'exact' }}>{h}
{c.flag} {c.name}{c.hq}{c.founded}{c.employees.toLocaleString('de-DE')}{c.revenue}{c.customers}{c.pricing}{de ? c.focus.de : c.focus.en}
+ + {/* Feature matrix */} +
+ + + + + + {['Snyk', 'Veracode', 'Checkmarx', 'Sonar', 'Semgrep', 'Pentera', 'Invicti', 'Intruder'].map(name => ( + + ))} + + + + {APPSEC_FEATURES.map((f, i) => ( + + + + + + + + + + + + + ))} + +
FeatureBP{name}
{de ? f.de : f.en}
+
+ +
+ + {de + ? 'AppSec-Tools liefern Findings. BreakPilot liefert Findings + Auto-Fix-Vorschläge + Compliance-Dokumentation + Audit-Trail, alles auf einer EU-souveränen Plattform. Snyk + Vanta zusammen kosten 4-6× mehr und bleiben US-gehostet.' + : 'AppSec tools deliver findings. BreakPilot delivers findings + auto-fix proposals + compliance documentation + audit trail, all on one EU-sovereign platform. Snyk + Vanta together cost 4-6× more and remain US-hosted.'} + +
+
+ ) +} diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintCoreSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintCoreSlides.tsx deleted file mode 100644 index 08e4c3e..0000000 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintCoreSlides.tsx +++ /dev/null @@ -1,301 +0,0 @@ -import { PrintPage, SectionTitle, PrintTable, Badge, COLORS } from './PrintLayout' -import { Language, PitchCompany, PitchFunding, PitchProduct, PitchMarket, PitchTeamMember, PitchMilestone } from '@/lib/types' - -const DE_PROBLEM_CARDS = [ - { title: 'KI-Dilemma', stat: 'Abgehängt', desc: 'Produzierende Unternehmen brauchen KI, um wettbewerbsfähig zu bleiben. Aber US-KI an den eigenen Quellcode und die Konstruktionsdaten zu lassen, kommt für die meisten nicht in Frage. Wer auf US-KI verzichtet, verliert den Anschluss. Wer sie nutzt, riskiert seine Datensouveränität und verstößt gegen europäisches Recht.' }, - { title: 'Patriot Act + FISA 702', stat: 'Kein Schutz', desc: 'Selbst wer EU-Server bei AWS, Google oder Microsoft bucht, ist nicht geschützt. US-Gesetze wie FISA 702 und der Cloud Act gelten extraterritorial — US-Behörden können auf Daten zugreifen, egal wo der Server steht. Das Schrems-II-Urteil des EuGH hat das bestätigt.' }, - { title: 'Regulierungs-Tsunami', stat: 'Nicht tragbar', desc: 'Seit 2024 greifen AI Act, NIS2 und Cyber Resilience Act — zusätzlich zu DSGVO, Data Act, Maschinenverordnung und Lieferkettengesetz. Europäische Unternehmen tragen Compliance-Kosten, die US- und Asien-Konkurrenten nicht haben. KMU können das nicht mehr allein stemmen.' }, -] -const EN_PROBLEM_CARDS = [ - { title: 'AI Dilemma', stat: 'Left Behind', desc: 'Manufacturing companies need AI to stay competitive. But letting US AI access their source code and engineering data is out of the question for most. Those avoiding US AI fall behind. Those using it risk their data sovereignty and may violate European law.' }, - { title: 'Patriot Act + FISA 702', stat: 'No Protection', desc: 'Even booking EU servers at AWS, Google or Microsoft offers no protection. US laws like FISA 702 and the Cloud Act apply extraterritorially — US authorities can access data regardless of server location. The Schrems II ruling by the CJEU confirmed this.' }, - { title: 'Regulation Tsunami', stat: 'Unsustainable', desc: 'Since 2024, the AI Act, NIS2 and Cyber Resilience Act apply — on top of GDPR, Data Act, Machinery Regulation and Supply Chain Act. European companies bear compliance costs that US and Asian competitors do not face. SMEs can no longer handle this alone.' }, -] - -const DE_PILLARS = [ - { title: 'Kontinuierliche Code-Security', desc: 'SAST, DAST, SBOM und Pentesting bei jeder Code-Änderung — nicht einmal im Jahr. Findings direkt als Tickets im Issue-Tracker deiner Wahl, mit Implementierungsvorschlägen. 15.000+ EUR pro Jahr und Anwendung an Pentest-Kosten gespart. Kein manueller Aufwand, keine vergessenen Schwachstellen.' }, - { title: 'Compliance auf Autopilot', desc: 'VVT, TOMs, DSFA, Löschfristen, CE-Risikobeurteilung automatisch generiert. Nach dem Audit: Haupt- und Nebenabweichungen End-to-End — Rollen zuweisen, Stichtage, Tickets, Nachweise einfordern, Eskalation an GF. Kein Excel, kein Hinterherlaufen, kein Stressaudit.' }, - { title: 'Deutsche Cloud, volle Integration', desc: 'BSI-zertifizierte Cloud in Deutschland. Live-Support über Jitsi (Video) und Matrix (Chat). Keine US-SaaS im Source Code — DSGVO-konform by design. Optional: Mac Mini/Studio für maximale Privacy bei Kleinstunternehmen. Nahtlose Integration in bestehende Workflows.' }, -] -const EN_PILLARS = [ - { title: 'Continuous Code Security', desc: 'SAST, DAST, SBOM and pentesting on every code change — not once a year. Findings as tickets in the issue tracker of your choice, with implementation suggestions. EUR 15,000+ per year per application in pentest costs saved. No manual effort, no forgotten vulnerabilities.' }, - { title: 'Compliance on Autopilot', desc: 'RoPA, TOMs, DPIA, retention policies, CE risk assessment generated automatically. Post-audit: major and minor deviations end-to-end — role assignment, deadlines, tickets, evidence collection, escalation to management. No Excel, no chasing, no stress audits.' }, - { title: 'German Cloud, Full Integration', desc: 'BSI-certified cloud in Germany. Live support via Jitsi (video) and Matrix (chat). No US SaaS in source code — GDPR compliant by design. Optional: Mac Mini/Studio for maximum privacy for micro businesses. Seamless integration into existing workflows.' }, -] - -function fmtEur(n: number) { return n.toLocaleString('de-DE', { maximumFractionDigits: 0 }) + ' EUR' } - -interface SlideBase { lang: Language; pageNum: number; totalPages: number; versionName: string } - -export function PrintCoverPage({ company, funding, versionName, lang }: { company: PitchCompany; funding: PitchFunding; lang: Language; versionName: string }) { - const de = lang === 'de' - const instrument = funding?.instrument || 'Pre-Seed' - return ( -
-
-
- BreakPilot - - {de ? 'Compliance & Code-Security' : 'Compliance & Code Security'} - -
- -
-

- {instrument} · {versionName} -

-

- {company?.name || 'BreakPilot'} -

-

- {de ? (company?.tagline_de || 'Kontinuierliche Compliance für europäische Unternehmen.') : (company?.tagline_en || 'Continuous compliance for European companies.')} -

-
- {([ - [de ? 'Gegründet' : 'Founded', company?.founding_date ? new Date(company.founding_date).getFullYear().toString() : 'Aug 2026'], - [de ? 'Standort' : 'HQ', company?.hq_city || 'Bodman-Ludwigshafen'], - [de ? 'Instrument' : 'Instrument', instrument], - [de ? 'Runde' : 'Round', funding?.round_name || 'Pre-Seed'], - ] as [string, string][]).map(([label, val]) => ( -
-

{label}

-

{val}

-
- ))} -
-
- -
- - {de ? 'Vertraulich — Nur für Investoren' : 'Confidential — For Investor Use Only'} - -
-
-
- ) -} - -export function PrintProblemPage({ lang, pageNum, totalPages, versionName }: SlideBase) { - const de = lang === 'de' - const cards = de ? DE_PROBLEM_CARDS : EN_PROBLEM_CARDS - return ( - - - {de ? 'Das Problem' : 'The Problem'} - -
- {cards.map((c) => ( -
-
- {c.stat} - {c.title} -
-

{c.desc}

-
- ))} -
-
-

- {de ? '„Produzierende Unternehmen brauchen eine KI-Lösung, die in Europa läuft, ihren Code schützt und Compliance automatisiert — ohne ihre Daten an US-Konzerne zu geben."' : '"Manufacturing companies need an AI solution that runs in Europe, protects their code and automates compliance — without giving their data to US corporations."'} -

-
-
- ) -} - -export function PrintSolutionPage({ lang, pageNum, totalPages, versionName }: SlideBase) { - const de = lang === 'de' - const pillars = de ? DE_PILLARS : EN_PILLARS - const icons = ['⬡', '◎', '▦'] - return ( - - - {de ? 'Die Lösung' : 'The Solution'} - -
- {pillars.map((p, i) => ( -
-
- {icons[i]} -
-

{p.title}

-

{p.desc}

-
- ))} -
-
- {(de - ? ['BSI-Cloud DE', 'DSGVO-konform', 'Kein US-SaaS', 'Kontinuierlich, nicht einmal/Jahr'] - : ['BSI Cloud DE', 'GDPR Compliant', 'No US SaaS', 'Continuous, not once/year'] - ).map(tag => {tag})} -
-
- ) -} - -export function PrintProductPage({ products, lang, pageNum, totalPages, versionName }: SlideBase & { products: PitchProduct[] }) { - const de = lang === 'de' - const headers = [de ? 'Produkt' : 'Product', de ? 'Preis/Monat' : 'Price/Month', 'Hardware', de ? 'Key Features' : 'Key Features'] - const rows = products.map(p => [ - {p.name}{p.is_popular ? ★ Beliebt : null}, - fmtEur(p.monthly_price_eur), - p.hardware || '—', - (de ? p.features_de : p.features_en)?.slice(0, 3).join(', ') || '—', - ]) - return ( - - - {de ? 'Produkte & Pricing' : 'Products & Pricing'} - -
- -
-

- {de - ? '💡 Kunden zahlen ~50.000 EUR/Jahr und sparen >50.000 EUR (Pentests + CE-Beurteilungen + Auditmanager). ROI ab Tag 1.' - : '💡 Customers pay ~EUR 50,000/year and save >EUR 50,000 (pentests + CE assessments + audit managers). ROI from day 1.'} -

-
-
-
- ) -} - -export function PrintMarketPage({ market, lang, pageNum, totalPages, versionName }: SlideBase & { market: PitchMarket[] }) { - const de = lang === 'de' - const headers = [de ? 'Segment' : 'Segment', de ? 'Marktbeschreibung' : 'Description', de ? 'Volumen' : 'Volume', de ? 'Wachstum p.a.' : 'Growth p.a.', de ? 'Quelle' : 'Source'] - const rows = market.map(m => [ - {m.market_segment.toUpperCase()}, - m.label, - fmtEur(m.value_eur), - `${m.growth_rate_pct}%`, - m.source, - ]) - return ( - - - {de ? 'Marktchance' : 'Market Opportunity'} - -
- -
- {market.map(m => ( -
-

{m.market_segment}

-

{fmtEur(m.value_eur)}

-

{m.growth_rate_pct}% p.a.

-
- ))} -
-
-
- ) -} - -export function PrintTeamPage({ team, lang, pageNum, totalPages, versionName }: SlideBase & { team: PitchTeamMember[] }) { - const de = lang === 'de' - return ( - - - {de ? 'Das Team' : 'The Team'} - -
- {team.slice(0, 4).map(m => ( -
-
-
-

{m.name}

-

{de ? m.role_de : m.role_en}

-
- {m.equity_pct > 0 && {m.equity_pct}%} -
-

- {de ? m.bio_de : m.bio_en} -

- {m.expertise?.length > 0 && ( -
- {m.expertise.slice(0, 5).map(e => {e})} -
- )} -
- ))} -
-
- ) -} - -export function PrintMilestonesPage({ milestones, lang, pageNum, totalPages, versionName }: SlideBase & { milestones: PitchMilestone[] }) { - const de = lang === 'de' - const ordered = [...milestones].sort((a, b) => { - const order = { completed: 0, in_progress: 1, planned: 2 } - return (order[a.status] - order[b.status]) || new Date(a.milestone_date).getTime() - new Date(b.milestone_date).getTime() - }).slice(0, 10) - const statusColor = (s: string) => ({ completed: '#16a34a', in_progress: '#d97706', planned: '#94a3b8' }[s] || '#94a3b8') - const statusLabel = (s: string) => de - ? ({ completed: 'Abgeschlossen', in_progress: 'In Arbeit', planned: 'Geplant' }[s] || s) - : ({ completed: 'Completed', in_progress: 'In Progress', planned: 'Planned' }[s] || s) - const fmtDate = (d: string) => new Date(d).toLocaleDateString(de ? 'de-DE' : 'en-GB', { month: 'short', year: 'numeric' }) - const rows = ordered.map(m => [ - fmtDate(m.milestone_date), - {de ? m.title_de : m.title_en}, - m.category, - {statusLabel(m.status)}, - ]) - return ( - - - {de ? 'Meilensteine' : 'Milestones'} - -
- -
-
- ) -} - -export function PrintTheAskPage({ funding, lang, pageNum, totalPages, versionName }: SlideBase & { funding: PitchFunding }) { - const de = lang === 'de' - const amount = Number(funding?.amount_eur) || 0 - const isWD = (funding?.instrument || '').toLowerCase() === 'wandeldarlehen' - const targetDate = funding?.target_date ? (() => { const d = new Date(funding.target_date); return `Q${Math.ceil((d.getMonth()+1)/3)} ${d.getFullYear()}` })() : 'TBD' - const uof = funding?.use_of_funds || [] - const amountLabel = amount >= 1_000_000 ? `${(amount / 1_000_000).toFixed(1)} Mio. EUR` : amount >= 1_000 ? `${Math.round(amount / 1_000)}k EUR` : `${amount} EUR` - return ( - - The Ask -
-
-

{amountLabel}

-
- {([ - [de ? 'Instrument' : 'Instrument', isWD ? 'Wandeldarlehen' : 'Equity'], - [de ? 'Runde' : 'Round', funding?.round_name || 'Pre-Seed'], - [de ? 'Zieldatum' : 'Target', targetDate], - ] as [string, string][]).map(([k, v]) => ( -
- {k} - {v} -
- ))} -
-
-
-

- {de ? 'Mittelverwendung' : 'Use of Funds'} -

- {uof.map(u => ( -
-
- {de ? u.label_de : u.label_en} - {u.percentage}% -
-
-
-
-
- ))} -
-
- - ) -} diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx index 4e92351..85a299d 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx @@ -3,23 +3,35 @@ import { useEffect } from 'react' import { Language, PitchData, FMResult, FMAssumption } from '@/lib/types' import { - PrintCoverPage, PrintProblemPage, PrintSolutionPage, PrintProductPage, - PrintMarketPage, PrintTeamPage, PrintMilestonesPage, PrintTheAskPage, -} from './PrintCoreSlides' + PrintCoverPage, PrintExecSummaryPage1, PrintExecSummaryPage2, + PrintProblemPage, PrintSolutionPage, +} from './PrintIntroSlides' import { - PrintFinancialsPage, PrintAssumptionsPage, PrintCapTablePage, - PrintDisclaimerPage, aggregateAnnualRows, -} from './PrintFinancialSlides' + PrintUSPPage1, PrintUSPPage2, PrintRegulatoryLandscapePage, + PrintProductPage, PrintHowItWorksPage, PrintBusinessModelPage, +} from './PrintProductSlides' import { - PrintExecutiveSummaryPage, PrintUSPPage, PrintRegulatoryLandscapePage, - PrintHowItWorksPage, PrintBusinessModelPage, PrintCompetitionPage, - PrintCustomerSavingsPage, -} from './PrintExtraSlides' + PrintMarketPage, PrintMilestonesPage, PrintTeamPage, + PrintTheAskPage, PrintCustomerSavingsPage, +} from './PrintMarketSlides' import { - PrintStrategyPage, PrintFinanzplanPage, PrintRegulatoryPage, - PrintArchitecturePage, PrintEngineeringPage, PrintAIPipelinePage, - PrintRisksPage, PrintGlossaryPage, + PrintCompetitionPage1, PrintCompetitionPage2, +} from './PrintCompetitionSlides' +import { + PrintStrategyPage, PrintRegulatoryPage, PrintArchitecturePage, + PrintEngineeringPage, PrintAIPipelinePage, PrintRisksPage, PrintGlossaryPage, } from './PrintAnnexSlides' +import { + PrintTLDRPage, PrintDifferentiatorsPage, PrintKPIHeroPage, + PrintTechStackPage, PrintAnnexDividerPage, +} from './PrintNewSlides' +import { + PrintFinanzplanPage1, PrintFinanzplanPage2, PrintAssumptionsPage, + PrintFinancialsPage, PrintCapTablePage, PrintDisclaimerPage, + aggregateAnnualRows, +} from './PrintFinancialSlides' + +export { aggregateAnnualRows } interface PrintDeckProps { pitchData: PitchData @@ -31,46 +43,55 @@ interface PrintDeckProps { } export default function PrintDeck({ pitchData, versionName, fmResults, fmAssumptions, financial, lang }: PrintDeckProps) { - const isWandeldarlehen = (pitchData.funding?.instrument || '').toLowerCase() === 'wandeldarlehen' + const isWandeldarlehen = (pitchData.funding?.instrument || '').toLowerCase().includes('wandeldarlehen') || + (pitchData.funding?.instrument || '').toLowerCase().includes('convertible') const hasCapTable = financial && !isWandeldarlehen const annualRows = aggregateAnnualRows(fmResults) - const hasFinancials = financial && annualRows.length > 0 - // Standard = 25 slides. Financial adds: detailed financials page + (optional) cap-table. - const totalPages = 25 + (hasFinancials ? 1 : 0) + (hasCapTable ? 1 : 0) + const hasFinancialData = annualRows.length > 0 const de = lang === 'de' + // Base standard PDF: 35 physical pages. + // 2 (exec) + 1 (TL;DR) + 1 (cover) + 1 (problem) + 1 (solution) + 2 (usp) + + // 1 (differentiators) + 1 (regL) + 1 (product) + 1 (how) + 1 (market) + 1 (bm) + + // 1 (milestones) + 2 (competition) + 1 (team) + 1 (ask) + 1 (savings) + + // 1 (anhang-divider) + 1 (strategy) + 1 (kpis) + 2 (finanzplan) + 1 (p&l detail) + + // 1 (assumptions) + 1 (regulatory) + 1 (architecture) + 1 (engineering) + + // 1 (tech-stack) + 1 (aipipeline) + 1 (risks) + 1 (glossary) + 1 (disclaimer) = 35 + // P&L detail is now in standard PDF (was financial-only); cap-table stays + // financial-only (and is suppressed for Wandeldarlehen). + const BASE_PAGES = 35 + const totalPages = BASE_PAGES + (hasCapTable ? 1 : 0) + void hasFinancialData + useEffect(() => { const t = setTimeout(() => window.print(), 900) return () => clearTimeout(t) }, []) let n = 0 - function p() { - n += 1 - return { lang, pageNum: n, totalPages, versionName } - } + const p = () => ({ lang, pageNum: ++n, totalPages, versionName }) return ( <> - {/* Toolbar — screen only */} + {/* Toolbar, screen only */}
- BreakPilot - {versionName} - - {financial ? (de ? 'PDF + Finanzen' : 'PDF + Financial') : 'Standard PDF'} + BreakPilot + {versionName} + + {financial ? (de ? 'PDF + Finanzen' : 'PDF + Financial') : (de ? 'Standard PDF' : 'Standard PDF')} - {totalPages} {de ? 'Seiten' : 'pages'} + {totalPages} {de ? 'Seiten' : 'pages'}
-
-
- {/* Slide order mirrors lib/slide-order.ts, minus intro-presenter, ai-qa, annex-sdk-demo. */} +
+ {/* PITCH (slides 01–17) */} - {/* 1. executive-summary */} - - {/* 2. cover (page 2 — uses its own layout; assign sequential number) */} + {/* 01–02 executive-summary (2 pages) */} + + + + {/* 03 TL;DR — 30 Sekunden */} + + + {/* 04 cover */} {(() => { n += 1; return })()} - {/* 3. problem */} + + {/* 05 problem */} - {/* 4. solution */} + + {/* 06 solution */} - {/* 5. usp */} - - {/* 6. regulatory-landscape */} + + {/* 07–08 usp (2 pages) */} + + + + {/* 09 differentiators */} + + + {/* 10 regulatory-landscape */} - {/* 7. product */} + + {/* 11 product / modular-toolkit */} - {/* 8. how-it-works */} + + {/* 12 how-it-works */} - {/* 9. market */} + + {/* 13 market */} - {/* 10. business-model */} + + {/* 14 business-model / pricing */} - {/* 11. traction (uses milestones table) */} + + {/* 15 traction (milestones) */} - {/* 12. competition */} - - {/* 13. team */} + + {/* 16–17 competition (2 pages) */} + + + + {/* 18 team */} - {/* 14. the-ask */} + + {/* 19 the-ask */} - {/* 15. customer-savings */} + + {/* 20 customer-savings */} - {/* 16. annex-strategy */} + + {/* 21 ANHANG divider — chapter break before the appendix */} + + + {/* APPENDIX (slides 22–35) */} + + {/* 22 annex-strategy */} - {/* 17. annex-finanzplan */} - - {/* Financial-only: detailed P&L table */} - {hasFinancials && } - {/* 18. annex-assumptions */} + + {/* 23 KPIs — 2026 → 2030 trajectory */} + + + {/* 24–25 annex-finanzplan (2 pages) */} + + + + {/* 26 P&L detail (was financial-only; now standard) */} + + + {/* 27 annex-assumptions */} - {/* 19. annex-regulatory */} + + {/* 28 annex-regulatory */} - {/* 20. annex-architecture */} + + {/* 29 annex-architecture */} - {/* 21. annex-engineering */} + + {/* 30 annex-engineering */} - {/* 22. annex-aipipeline */} + + {/* 31 tech-stack */} + + + {/* 32 annex-aipipeline */} - {/* 23. risks */} + + {/* 33 risks */} - {/* 24. annex-glossary */} + + {/* 34 annex-glossary */} - {/* Financial-only: cap table */} + + {/* Financial-only: cap-table (suppressed for Wandeldarlehen) */} {hasCapTable && } - {/* 25. legal-disclaimer */} + + {/* 35 legal-disclaimer */}
diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintDiagrams.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintDiagrams.tsx new file mode 100644 index 0000000..c27628b --- /dev/null +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintDiagrams.tsx @@ -0,0 +1,298 @@ +import React from 'react' +import { COLORS } from './PrintLayout' + +/* ====================================================================== */ +/* DIAGRAMS */ +/* ====================================================================== */ + +/** A single "node" in a flow / architecture diagram. */ +export function FlowNode({ + title, subtitle, items, accent = COLORS.indigo600, icon, kicker, footer, +}: { + title: string + subtitle?: string + items?: string[] + accent?: string + icon?: React.ReactNode + kicker?: string + footer?: string +}) { + return ( +
+ {kicker && ( +
{kicker}
+ )} +
+ {icon &&
{icon}
} +
+
{title}
+ {subtitle &&
{subtitle}
} +
+
+ {items && items.length > 0 && ( +
+ {items.map((it, i) => ( +
0 ? `1px solid ${COLORS.slate100}` : 'none', + lineHeight: 1.35, + }}>{it}
+ ))} +
+ )} + {footer && ( +
{footer}
+ )} +
+ ) +} + +/** Vertical down arrow (between rows of a flow diagram). */ +export function VArrow({ color = COLORS.slate400, label }: { color?: string; label?: string }) { + return ( +
+ + + + + {label &&
{label}
} +
+ ) +} + +/** Horizontal right arrow (between steps of a horizontal flow). */ +export function HArrow({ color = COLORS.slate400, label }: { color?: string; label?: string }) { + return ( +
+ + + + + {label &&
{label}
} +
+ ) +} + +/** Horizontal step strip with built-in arrows between items. */ +export function StepStrip({ + steps, accent = COLORS.indigo600, +}: { + steps: { n: string; t: string; d: string }[] + accent?: string +}) { + return ( +
+ {steps.map((s, i) => ( + +
+
+ {s.n} +
+
+
{s.t}
+
{s.d}
+
+ {i < steps.length - 1 && ( +
+ + + + +
+ )} + + ))} +
+ ) +} + +/** 3-tier architecture diagram (product → proxy → inference) */ +export function ArchitectureDiagram({ + product, proxy, inference, lang, +}: { + product: { kicker: string; title: string; subtitle: string; tech: string; services: string[] }[] + proxy: { title: string; subtitle: string; features: string[] } + inference: { title: string; subtitle: string; tech: string; desc: string }[] + lang: 'de' | 'en' +}) { + const de = lang === 'de' + const MONO = "'JetBrains Mono', ui-monospace, monospace" + + /** Layer pill: "01 · APPLICATION LAYER" + sub-label */ + const LayerChip = ({ n, label, sub, tint }: { n: string; label: string; sub: string; tint: string }) => ( +
+ {n} · {label} + {sub} +
+ ) + + /** + * ServiceNode — flat, no own border. Used INSIDE a tinted layer card so the + * whole layer reads as one panel rather than nested boxes (which is what + * was causing the architecture diagram to overflow). + */ + const ServiceNode = ({ kicker, title, subtitle, items, footer, accent }: { kicker?: string; title: string; subtitle?: string; items: string[]; footer?: string; accent: string }) => ( +
+ {kicker &&
{kicker}
} +
{title}
+ {subtitle &&
{subtitle}
} +
+ {items.slice(0, 4).map((it, i) => ( +
0 ? `1px solid ${COLORS.slate100}` : 'none' }}>· {it}
+ ))} +
+ {footer &&
{footer}
} +
+ ) + + const productLayerBg = `linear-gradient(135deg, ${COLORS.violet50} 0%, #ffffff 60%, ${COLORS.violet50} 100%)` + const proxyLayerBg = `linear-gradient(135deg, ${COLORS.amber50} 0%, #fffaf0 60%, ${COLORS.amber50} 100%)` + + return ( +
+ {/* APPLICATION (PRODUCT) LAYER */} +
+ +
+ {product.map((p, i) => ( + + ))} +
+
+ + {/* compact connector strip */} +
+ {[0, 1, 2].map(i => ( +
+ + + + +
+ ))} +
+ + {/* GATEWAY LAYER — compact: title row + features in 1 row */} +
+ +
+ {proxy.title} + {proxy.subtitle} +
+
+ {proxy.features.map((f, i) => ( +
{f}
+ ))} +
+
+ + {/* compact connector strip */} +
+ {[0, 1, 2].map(i => ( +
+ + + + +
+ ))} +
+ + {/* INFRASTRUCTURE (INFERENCE) LAYER */} +
+ +
+ {inference.map((p, i) => ( + + ))} +
+
+
+ ) +} + +/** Connected loop diagram for the USP "Compliance ↔ Code always in sync" closing card */ +export function LoopDiagram({ lang }: { lang: 'de' | 'en' }) { + const de = lang === 'de' + return ( + + + + + + + {/* Compliance box */} + + Compliance + {de ? 'Policies · Audits · VVT' : 'Policies · Audits · RoPA'} + + {/* Code box */} + + Code + {de ? 'Repos · CI/CD · Findings' : 'Repos · CI/CD · Findings'} + + {/* Top arrow: compliance → code */} + + {de ? 'Policies → Code (Real-time)' : 'Policies → Code (Real-time)'} + + {/* Bottom arrow: code → compliance */} + + {de ? 'Code-Δ → Evidence (Auto)' : 'Code-Δ → Evidence (Auto)'} + + ) +} + +/** 4-stage horizontal pipeline (e.g. RAG pipeline ingestion → ... → QA) */ +export function PipelineFlow({ + stages, accent = COLORS.indigo600, +}: { + stages: { n: string; t: string; d: string; kpi?: string }[] + accent?: string +}) { + return ( +
+ {stages.map((s, i) => ( + +
+
+
+ {s.n} + {s.kpi && {s.kpi}} +
+
{s.t}
+
{s.d}
+
+
+ {i < stages.length - 1 && ( +
+ + + + +
+ )} +
+ ))} +
+ ) +} diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintExtraSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintExtraSlides.tsx deleted file mode 100644 index af5a1ab..0000000 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintExtraSlides.tsx +++ /dev/null @@ -1,480 +0,0 @@ -import { PrintPage, SectionTitle, PrintTable, Badge, COLORS } from './PrintLayout' -import { Language, PitchMarket, PitchFunding } from '@/lib/types' - -interface SlideBase { lang: Language; pageNum: number; totalPages: number; versionName: string } - -function fmtEur(n: number) { - const abs = Math.abs(n) - if (abs >= 1_000_000_000) return `${(n / 1_000_000_000).toLocaleString('de-DE', { maximumFractionDigits: 1 })}B EUR` - if (abs >= 1_000_000) return `${(n / 1_000_000).toLocaleString('de-DE', { maximumFractionDigits: 1 })}M EUR` - if (abs >= 1_000) return `${(n / 1_000).toLocaleString('de-DE', { maximumFractionDigits: 0 })}k EUR` - return `${n.toLocaleString('de-DE')} EUR` -} - -export function PrintExecutiveSummaryPage({ market, funding, lang, pageNum, totalPages, versionName }: SlideBase & { market: PitchMarket[]; funding: PitchFunding }) { - const de = lang === 'de' - const tam = market.find(m => m.market_segment === 'TAM') - const sam = market.find(m => m.market_segment === 'SAM') - const som = market.find(m => m.market_segment === 'SOM') - const moat = [ - { k: 'Traceability', v: de ? 'Gesetz → Control → Code' : 'Law → Control → Code' }, - { k: 'Continuous Engine', v: de ? 'Echtzeit bei jeder Änderung' : 'Real-time on every change' }, - { k: 'Compliance Optimizer', v: de ? 'Maximale KI-Nutzung im Rahmen' : 'Max AI use within regulations' }, - { k: 'EU-Trust Stack', v: de ? '100% EU, kein US-SaaS' : '100% EU, no US SaaS' }, - ] - const kpis = [ - { v: '25k+', l: de ? 'Controls' : 'Controls' }, - { v: '380+', l: de ? 'Regularien' : 'Regulations' }, - { v: '10', l: de ? 'Branchen' : 'Industries' }, - { v: '500K+', l: de ? 'Zeilen Code' : 'Lines of code' }, - { v: '80%', l: de ? 'Zeitersparnis' : 'Time saved' }, - { v: '10x', l: de ? 'Günstiger als Pentests' : 'Cheaper than pentests' }, - ] - return ( - - - Executive Summary - -
-
-

- {de - ? 'Kontinuierliches Sicherheitsscanning + intelligente Compliance-Automatisierung. Code absichern, Compliance skalierbar durchsetzen, volle Datensouveränität — gestützt auf 25.000+ atomare Prüfaspekte.' - : 'Continuous security scanning + intelligent compliance automation. Secure code, enforce compliance at scale, maintain data sovereignty — powered by 25,000+ atomic audit aspects.'} -

-
- -
-

{de ? 'Unser MOAT' : 'Our MOAT'}

-
- {moat.map(m => ( -
-

{m.k}

-

{m.v}

-
- ))} -
-
- -
- {kpis.map(k => ( -
-

{k.v}

-

{k.l}

-
- ))} -
- -
-
-

{de ? 'Problem' : 'Problem'}

-
    -
  • {de ? 'Ohne KI Wettbewerbsfähigkeit verloren — mit US-KI Datenkontrolle verloren' : 'Without AI: lose competitiveness — with US AI: lose data control'}
  • -
  • {de ? 'AI Act, CRA, NIS2 zwingen 30.000+ Firmen in komplexe Compliance' : 'AI Act, CRA, NIS2 force 30,000+ firms into complex compliance'}
  • -
  • {de ? 'Hohe Pentest-/Audit-Kosten, jährliche statt kontinuierliche Prüfung' : 'High pentest/audit cost, annual instead of continuous checks'}
  • -
-
-
-

{de ? 'Lösung' : 'Solution'}

-
    -
  • {de ? 'Jede Code-Änderung automatisch geprüft (SAST/DAST/SBOM/Pentest)' : 'Every code change auto-checked (SAST/DAST/SBOM/pentest)'}
  • -
  • {de ? 'VVT, TOMs, DSFA, CE-Risikobeurteilung in Echtzeit' : 'RoPA, TOMs, DPIA, CE risk assessment in real time'}
  • -
  • {de ? 'EU-Hosting (DE/FR), Audit-Ready zu jedem Zeitpunkt' : 'EU hosting (DE/FR), audit-ready at any time'}
  • -
-
-
- -
-
-

{de ? 'Zielmärkte' : 'Target markets'}

-

- {de ? 'Maschinen- & Anlagenbau · Automotive · Zulieferer · Produzierende Unternehmen' : 'Machine & plant manufacturing · Automotive · Suppliers · Manufacturing'} -

-
-
-

{de ? 'Markt' : 'Market'}

-
TAM{tam ? fmtEur(tam.value_eur) : '—'}
-
SAM{sam ? fmtEur(sam.value_eur) : '—'}
-
SOM{som ? fmtEur(som.value_eur) : '—'}
-
-
-

{de ? 'Kundenersparnis KMU/Jahr' : 'SME savings/year'}

-

~55k EUR

-

{de ? 'Pentests, CE, Compliance-Zeit, Audit' : 'Pentests, CE, compliance time, audit'}

-
-
- -
-

- {de ? 'The Ask:' : 'The Ask:'}{' '} - {(() => { - const amount = Number(funding?.amount_eur) || 0 - const label = amount >= 1_000_000 ? `${(amount / 1_000_000).toFixed(1)} Mio. EUR` : `${Math.round(amount / 1000)}k EUR` - return `${label} ${funding?.instrument || 'Pre-Seed'} · ${funding?.round_name || 'Pre-Seed'}` - })()} -

-
-
-
- ) -} - -const USP_PILLARS = { - de: [ - { title: 'RFQ-Prüfung', body: 'Kunden-Anforderungsdokumente automatisch gegen Source-Code geprüft. Abweichungen erkannt, Änderungen vorgeschlagen.', stat: 'Antwortzeit 4,2h (war 12 Tage)' }, - { title: 'Prozess-Compliance', body: 'Vom Audit-Finding zum Ticket zur Code-Änderung — End-to-End automatisiert. Rollen, Fristen, Eskalation, Nachweise.', stat: '87% automatisierte Prozessschritte' }, - { title: 'Bidirektional', body: 'Compliance-Anforderungen fließen in den Code. Code-Änderungen aktualisieren die Compliance-Doku. Zero Drift.', stat: '0 Drift-Vorfälle seit März 2024' }, - { title: 'Kontinuierlich', body: 'Statt jährlicher Stichproben: Prüfung bei jeder Code-Änderung. Findings sofort zu Tickets mit Fix-Vorschlägen.', stat: '~2.400 Validierungen / Tag / Repo' }, - ], - en: [ - { title: 'RFQ Verification', body: 'Customer requirement docs automatically verified against current source code. Deviations detected, fixes proposed.', stat: 'Response time 4.2h (was 12 days)' }, - { title: 'Process Compliance', body: 'From audit finding to ticket to code change — fully automated. Roles, deadlines, escalation, evidence.', stat: '87% process steps automated' }, - { title: 'Bidirectional Sync', body: 'Compliance requirements flow into code. Code changes update compliance docs. Zero drift between worlds.', stat: '0 drift incidents since Mar-2024' }, - { title: 'Continuous, Not Yearly', body: 'Validation on every code change instead of annual checks. Findings as tickets with concrete fix proposals.', stat: '~2,400 validations / day / repo' }, - ], -} - -const USP_HOOD = { - de: [ - { title: 'End-to-End Traceability', body: 'Gesetz → Obligation → Control deterministisch mit Systemzustand und Code verknüpft. Revisionssicherer Evidence-Layer.' }, - { title: 'Continuous Compliance Engine', body: 'Validierung bei jeder Änderung (Code/IaC/Prozesse) mit auditierbaren Nachweisen in Echtzeit. Rule-Packs pro Framework.' }, - { title: 'Compliance Optimizer', body: 'Maximal zulässige Ausgestaltung jedes KI-Use-Cases. Constraint-Optimierung statt nur erlaubt/verboten — spart 20–200k EUR Anwaltskosten.' }, - { title: 'EU-Trust & Governance Stack', body: 'DSGVO · NIS-2 · DORA · EU AI Act · ISO 27001 · BSI C5 · EU-souveränes Hosting. Eine Plattform, ein Audit.' }, - ], - en: [ - { title: 'End-to-End Traceability', body: 'Law → Obligation → Control deterministically linked to system state and code. Audit-proof evidence layer.' }, - { title: 'Continuous Compliance Engine', body: 'Validation on every change (code/IaC/process) with auditable evidence in real time. Rule packs per framework.' }, - { title: 'Compliance Optimizer', body: 'Max permissible configuration of every AI use case. Constraint optimization beyond allowed/forbidden — replaces EUR 20–200k legal fees.' }, - { title: 'EU Trust & Governance Stack', body: 'GDPR · NIS-2 · DORA · EU AI Act · ISO 27001 · BSI C5 · EU-sovereign hosting. One platform, one audit.' }, - ], -} - -export function PrintUSPPage({ lang, pageNum, totalPages, versionName }: SlideBase) { - const de = lang === 'de' - const pillars = de ? USP_PILLARS.de : USP_PILLARS.en - const hood = de ? USP_HOOD.de : USP_HOOD.en - return ( - - - {de ? 'Unsere USPs' : 'Our USPs'} - -
-
-

{de ? 'Vier Säulen' : 'Four Pillars'}

-
- {pillars.map(p => ( -
-

{p.title}

-

{p.body}

-

{p.stat}

-
- ))} -
-
-
-

{de ? 'Under the Hood' : 'Under the Hood'}

-
- {hood.map(h => ( -
-

{h.title}

-

{h.body}

-
- ))} -
-
-
-

- {de - ? '„Compliance ↔ Code · immer in Sync. Eine Plattform, eine geschlossene Schleife. Auditoren, Entwickler und Sales fragen denselben Graphen ab."' - : '"Compliance ↔ Code · always in sync. One platform, one closed loop. Auditors, engineers and sales all query the same graph."'} -

-
-
-
- ) -} - -const REG_KEY = [ - { id: 'GDPR', label: 'DSGVO', color: '#6366f1' }, - { id: 'AI_ACT', label: 'AI Act', color: '#a855f7' }, - { id: 'NIS2', label: 'NIS2', color: '#ef4444' }, - { id: 'CRA', label: 'CRA', color: '#f97316' }, - { id: 'MACHINERY_REG', label: 'Masch.-VO', color: '#22c55e' }, - { id: 'DATA_ACT', label: 'Data Act', color: '#06b6d4' }, - { id: 'BATTERIE_VO', label: 'Batt.-VO', color: '#f59e0b' }, -] -const REG_INDUSTRIES = [ - { de: 'Automobilindustrie', en: 'Automotive', regs: ['GDPR', 'AI_ACT', 'NIS2', 'CRA', 'MACHINERY_REG', 'DATA_ACT', 'BATTERIE_VO'], totalDocs: 263 }, - { de: 'Maschinen- & Anlagenbau', en: 'Machinery & Plant Eng.', regs: ['GDPR', 'AI_ACT', 'NIS2', 'CRA', 'MACHINERY_REG', 'DATA_ACT'], totalDocs: 266 }, - { de: 'Elektro- & Digitalindustrie', en: 'Electrical & Digital', regs: ['GDPR', 'AI_ACT', 'NIS2', 'CRA', 'MACHINERY_REG', 'DATA_ACT', 'BATTERIE_VO'], totalDocs: 281 }, - { de: 'Chemie- & Prozessindustrie', en: 'Chemicals & Process', regs: ['GDPR', 'AI_ACT', 'NIS2', 'CRA', 'DATA_ACT'], totalDocs: 250 }, - { de: 'Metallindustrie', en: 'Metal Industry', regs: ['GDPR', 'AI_ACT', 'NIS2', 'CRA', 'MACHINERY_REG', 'DATA_ACT'], totalDocs: 246 }, - { de: 'Energie & Versorgung', en: 'Energy & Utilities', regs: ['GDPR', 'AI_ACT', 'NIS2', 'CRA', 'DATA_ACT', 'BATTERIE_VO'], totalDocs: 256 }, - { de: 'Transport & Logistik', en: 'Transport & Logistics', regs: ['GDPR', 'AI_ACT', 'NIS2', 'CRA', 'DATA_ACT'], totalDocs: 256 }, - { de: 'Handel', en: 'Retail & Commerce', regs: ['GDPR', 'AI_ACT', 'NIS2', 'CRA', 'DATA_ACT'], totalDocs: 271 }, - { de: 'Konsumgüter & Lebensmittel', en: 'Consumer Goods & Food', regs: ['GDPR', 'AI_ACT', 'NIS2', 'CRA', 'DATA_ACT', 'BATTERIE_VO'], totalDocs: 265 }, - { de: 'Bauwirtschaft', en: 'Construction', regs: ['GDPR', 'AI_ACT', 'NIS2', 'CRA', 'MACHINERY_REG', 'DATA_ACT'], totalDocs: 245 }, -] - -export function PrintRegulatoryLandscapePage({ lang, pageNum, totalPages, versionName }: SlideBase) { - const de = lang === 'de' - const kpis = [ - { v: '380+', l: de ? 'Gesetze im RAG' : 'Laws in RAG' }, - { v: '244', l: de ? 'Horizontal' : 'Horizontal' }, - { v: '65', l: de ? 'Branchen-spezifisch' : 'Industry-specific' }, - { v: '10', l: de ? 'Branchen' : 'Industries' }, - ] - return ( - - - {de ? 'Regulatorische Landschaft' : 'Regulatory Landscape'} - -
- {kpis.map(k => ( -
-

{k.v}

-

{k.l}

-
- ))} -
- - - - - {REG_KEY.map(r => ( - - ))} - - - - - {REG_INDUSTRIES.map((ind, i) => ( - - - {REG_KEY.map(r => ( - - ))} - - - ))} - -
{de ? 'Branche' : 'Industry'}{r.label}{de ? 'Gesetze' : 'Laws'}
{de ? ind.de : ind.en} - {ind.regs.includes(r.id) - ? - : ·} - {ind.totalDocs}
-

- {de - ? '244 Dokumente gelten horizontal für alle Branchen (DSGVO, BDSG, AI Act, NIS2, CRA, BetrVG, HGB, ...). Sektorspezifische Regulierungen kommen hinzu.' - : '244 documents apply horizontally to all industries (GDPR, BDSG, AI Act, NIS2, CRA, ...). Sector-specific regulations are added on top.'} -

-
- ) -} - -const HIW_STEPS_DE = [ - { n: '01', t: 'Cloud-Vertrag abschließen', d: 'BSI-zertifizierte Cloud in Deutschland. Fixe oder flexible Kosten.' }, - { n: '02', t: 'Code-Repos verbinden', d: 'Git-Repos, CI/CD Pipelines und Firmware-Projekte anbinden. Die KI scannt automatisch auf Schwachstellen und Compliance-Lücken bei jeder Änderung.' }, - { n: '03', t: 'Compliance & Security automatisieren', d: 'Kontinuierliche Code-Analyse, Pentesting und Risikoanalysen. VVT, TOMs, DSFA und CE-Dokumentation werden automatisch erstellt und aktualisiert.' }, - { n: '04', t: 'Audit vorbereiten', d: 'Alle Nachweise, Dokumente und Risikobeurteilungen auf Knopfdruck. Abweichungen nach dem Audit automatisch nachverfolgen mit Stichtagen und Eskalation.' }, -] -const HIW_STEPS_EN = [ - { n: '01', t: 'Sign Cloud Contract', d: 'BSI-certified cloud in Germany. Fixed or flexible costs.' }, - { n: '02', t: 'Connect Code Repos', d: 'Connect Git repos, CI/CD pipelines and firmware projects. The AI scans automatically for vulnerabilities and compliance gaps on every change.' }, - { n: '03', t: 'Automate Compliance & Security', d: 'Continuous code analysis, pentesting and risk assessments. RoPA, TOMs, DPIA and CE documentation are automatically created and updated.' }, - { n: '04', t: 'Prepare for Audit', d: 'All evidence, documents and risk assessments at the push of a button. Post-audit deviations automatically tracked with deadlines and escalation.' }, -] - -export function PrintHowItWorksPage({ lang, pageNum, totalPages, versionName }: SlideBase) { - const de = lang === 'de' - const steps = de ? HIW_STEPS_DE : HIW_STEPS_EN - return ( - - - {de ? 'So funktioniert\'s' : 'How It Works'} - -
- {steps.map((s, idx) => ( -
-
- {s.n} -
-
-

{s.t}

-

{s.d}

-
- {idx < steps.length - 1 && } -
- ))} -
-
- ) -} - -const BM_TIERS_DE = [ - { name: 'Starter', target: 'Startups & Kleinstunternehmen', emp: '< 10', price: '3.600 EUR/Jahr', features: ['Code Security (SAST/DAST)', 'Compliance-Dokumente', 'Consent Management', '1 Anwendung'], highlight: false }, - { name: 'Professional', target: 'KMU & Mittelstand', emp: '10 – 250', price: '15.000 – 40.000 EUR/Jahr', features: ['Alle Module inkl. CE-Bewertung', 'Audit Manager End-to-End', 'AI Act Compliance (UCCA)', 'Unbegrenzte Anwendungen'], highlight: true }, - { name: 'Enterprise', target: 'Konzerne & OEMs', emp: '250+', price: 'ab 50.000 EUR/Jahr', features: ['Dedizierte Instanz', 'Custom Integrationen (SAP, MES)', 'SLA & Priority Support', 'Tender Matching & RFQ-Prüfung'], highlight: false }, -] -const BM_TIERS_EN = [ - { name: 'Starter', target: 'Startups & Micro', emp: '< 10', price: '3,600 EUR/yr', features: ['Code Security (SAST/DAST)', 'Compliance documents', 'Consent management', '1 application'], highlight: false }, - { name: 'Professional', target: 'SME & Mid-Market', emp: '10 – 250', price: '15,000 – 40,000 EUR/yr', features: ['All modules incl. CE assessment', 'Audit Manager end-to-end', 'AI Act Compliance (UCCA)', 'Unlimited applications'], highlight: true }, - { name: 'Enterprise', target: 'Enterprises & OEMs', emp: '250+', price: 'from 50,000 EUR/yr', features: ['Dedicated instance', 'Custom integrations (SAP, MES)', 'SLA & priority support', 'Tender matching & RFQ verification'], highlight: false }, -] - -export function PrintBusinessModelPage({ lang, pageNum, totalPages, versionName }: SlideBase) { - const de = lang === 'de' - const tiers = de ? BM_TIERS_DE : BM_TIERS_EN - return ( - - - {de ? 'Geschäftsmodell' : 'Business Model'} - -
- {tiers.map(t => ( -
-

{t.name}

-

{t.target}

-

{t.emp} {de ? 'Mitarbeiter' : 'employees'}

-

{t.price}

-
    - {t.features.map(f => ( -
  • - - {f} -
  • - ))} -
-
- ))} -
-
- ) -} - -const COMP_COMPETITORS = [ - { name: 'Vanta', flag: 'US', founded: 2018, emp: '1.695', revenue: '$220M ARR', customers: '12.000', pricing: '$10K–80K/yr', ai: 'full' as const }, - { name: 'Drata', flag: 'US', founded: 2020, emp: '732', revenue: '$100M ARR', customers: '8.000', pricing: '$10K–100K/yr', ai: 'full' as const }, - { name: 'Sprinto', flag: 'IN', founded: 2020, emp: '316', revenue: '$38M ARR', customers: '3.000', pricing: '$6K–25K/yr', ai: 'full' as const }, - { name: 'DataGuard', flag: 'DE', founded: 2017, emp: '250', revenue: '~€52M', customers: '4.000', pricing: '€6K–24K+/yr', ai: 'partial' as const }, - { name: 'Proliance', flag: 'DE', founded: 2017, emp: '65', revenue: '~€3.9M', customers: '2.000', pricing: '€1.5K–5.7K/yr', ai: 'none' as const }, - { name: 'heyData', flag: 'DE', founded: 2020, emp: '58', revenue: '~€15M', customers: '2.000', pricing: '€1K–3.8K/yr', ai: 'partial' as const }, -] - -const COMP_USP_ROWS_DE = ['Code-Security + DevSecOps (6 Tools, SAST/DAST/SBOM/Container/Secrets/IaC)', 'LLM-Auto-Fix für gefundene Schwachstellen', 'Firmware & Embedded-Security', 'PII-Redaction LLM Gateway', 'RAG mit 25.000+ Sicherheitskontrollen', 'AI Act und CRA Compliance End-to-End', 'CE-Software-Risikobeurteilung nach Maschinen-VO', 'Whistleblower-Portal (HinSchG)', 'Maschinenbau-Branchenfokus', 'Self-Hosted / On-Premise möglich'] -const COMP_USP_ROWS_EN = ['Code security + DevSecOps (6 tools, SAST/DAST/SBOM/container/secrets/IaC)', 'LLM auto-fix for detected vulnerabilities', 'Firmware & embedded security', 'PII redaction LLM gateway', 'RAG with 25,000+ security controls', 'AI Act and CRA compliance end-to-end', 'CE software risk assessment per Machinery Regulation', 'Whistleblower portal (HinSchG)', 'Manufacturing industry focus', 'Self-hosted / on-premise possible'] - -export function PrintCompetitionPage({ lang, pageNum, totalPages, versionName }: SlideBase) { - const de = lang === 'de' - const aiLabel = (a: 'full' | 'partial' | 'none') => a === 'full' ? (de ? 'Voll' : 'Full') : a === 'partial' ? (de ? 'Teil' : 'Partial') : (de ? 'Keine' : 'None') - const aiColor = (a: 'full' | 'partial' | 'none') => a === 'full' ? '#16a34a' : a === 'partial' ? '#d97706' : '#94a3b8' - return ( - - - {de ? 'Wettbewerb' : 'Competition'} - -
-
-

{de ? 'Wettbewerber-Übersicht' : 'Competitor Overview'}

- [ - {c.flag} {c.name}, - c.founded.toString(), - c.emp, - c.revenue, - c.customers, - c.pricing, - {aiLabel(c.ai)}, - ])} - colWidths={['18%', '8%', '10%', '15%', '12%', '20%', '10%']} - /> -
-
-

{de ? 'Was nur BreakPilot hat' : 'BreakPilot-only features'}

-
    - {(de ? COMP_USP_ROWS_DE : COMP_USP_ROWS_EN).map(r => ( -
  • - - {r} -
  • - ))} -
-
-
-

- {de - ? 'Weitere DACH-Anbieter: Secjur, Usercentrics, Caralegal, 2B Advice, OneTrust. Keiner kombiniert DSGVO + Code-Security + Self-Hosted KI.' - : 'Other DACH players: Secjur, Usercentrics, Caralegal, 2B Advice, OneTrust. None combines GDPR + code security + self-hosted AI.'} -

-
- ) -} - -const SAVINGS_DE = [ - { name: 'KMU (25 MA)', bp: '15.000 EUR/Jahr', without: '86.000', with: '31.000', save: '55.000', roi: '3,7x' }, - { name: 'Mittelstand (100 MA)', bp: '30.000 EUR/Jahr', without: '291.000', with: '98.000', save: '193.000', roi: '6,4x' }, - { name: 'Konzern (500+ MA)', bp: '50.000 EUR/Jahr', without: '1.190.000', with: '410.000', save: '780.000', roi: '15,6x' }, -] -const SAVINGS_EN = [ - { name: 'SME (25 emp.)', bp: 'EUR 15,000/yr', without: '86,000', with: '31,000', save: '55,000', roi: '3.7x' }, - { name: 'Mid-size (100 emp.)', bp: 'EUR 30,000/yr', without: '291,000', with: '98,000', save: '193,000', roi: '6.4x' }, - { name: 'Enterprise (500+ emp.)', bp: 'EUR 50,000/yr', without: '1,190,000', with: '410,000', save: '780,000', roi: '15.6x' }, -] -const SAVINGS_LINES_DE = ['Pentests (Anwendungen)', 'CE-SW-Risikobeurteilung', 'Compliance-Dokumentation', 'Produktivere Compliance-Arbeitszeit', 'Audit-Vorbereitung', 'Externe Berater / FTE / Strafvermeidung'] -const SAVINGS_LINES_EN = ['Pentests (applications)', 'CE SW risk assessment', 'Compliance documentation', 'More productive compliance time', 'Audit preparation', 'External consultants / FTE / penalty avoidance'] - -export function PrintCustomerSavingsPage({ lang, pageNum, totalPages, versionName }: SlideBase) { - const de = lang === 'de' - const rows = (de ? SAVINGS_DE : SAVINGS_EN).map(r => [ - {r.name}, - r.bp, - {r.without} €, - {r.with} €, - {r.save} €, - {r.roi}, - ]) - return ( - - - {de ? 'Kundenersparnis im Detail' : 'Customer Savings in Detail'} - -
- -
-
-
-

{de ? 'Wo gespart wird' : 'Where savings come from'}

-
    - {(de ? SAVINGS_LINES_DE : SAVINGS_LINES_EN).map(l =>
  • {l}
  • )} -
-
-
-

{de ? 'Versteckter Hebel' : 'Hidden lever'}

-

- {de - ? '„Der größte versteckte Kostentreiber ist Entwickler-Produktivität: ohne automatisierte Security-Tools verbringen Entwickler 19% ihrer Arbeitszeit mit Sicherheitsaufgaben statt mit Features." — IDC' - : '"The largest hidden cost driver is developer productivity: without automated security tools, developers spend 19% of their time on security tasks instead of features." — IDC'} -

-
-
-
- {(de ? ['Pentests', 'CE-Risiko', 'Compliance-Zeit', 'Audit-Vorb.', 'Strafvermeidung'] : ['Pentests', 'CE risk', 'Compliance time', 'Audit prep', 'Penalty avoidance']).map(b => {b})} -
-
- ) -} diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx index d9f976c..1c348dc 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx @@ -1,5 +1,7 @@ -import { PrintPage, SectionTitle, PrintTable, Badge, COLORS } from './PrintLayout' import { Language, FMResult, FMAssumption } from '@/lib/types' +import { Page, COLORS, Callout, DataTable } from './PrintLayout' +import { BarChart, LineChart, DonutChart } from './PrintCharts' +import { computeAnnualKPIs } from '@/lib/finanzplan/annual-kpis' interface SlideBase { lang: Language; pageNum: number; totalPages: number; versionName: string } @@ -34,121 +36,210 @@ export function aggregateAnnualRows(results: FMResult[]): AnnualPLRow[] { const gross = revenue - cogs const ebitda = gross - personnel - marketing - infra return { - year, - revenue_eur: revenue, - cogs_eur: cogs, - gross_profit_eur: gross, - personnel_eur: personnel, - marketing_eur: marketing, - infra_eur: infra, - ebitda_eur: ebitda, - total_customers: last?.total_customers ?? 0, - employees_count: last?.employees_count ?? 0, + year, revenue_eur: revenue, cogs_eur: cogs, gross_profit_eur: gross, + personnel_eur: personnel, marketing_eur: marketing, infra_eur: infra, ebitda_eur: ebitda, + total_customers: last?.total_customers ?? 0, employees_count: last?.employees_count ?? 0, } }) } -function fmtEur(n: number) { +function fmtEur(n: number, dense = false): string { const abs = Math.abs(n) - if (abs >= 1_000_000) return `${(n / 1_000_000).toLocaleString('de-DE', { maximumFractionDigits: 1 })}M` - if (abs >= 1_000) return `${(n / 1_000).toLocaleString('de-DE', { maximumFractionDigits: 0 })}k` - return n.toLocaleString('de-DE', { maximumFractionDigits: 0 }) + const sign = n < 0 ? '−' : '' + if (abs >= 1e6) return `${sign}${(abs / 1e6).toLocaleString('de-DE', { maximumFractionDigits: dense ? 1 : 2 })}M` + if (abs >= 1e3) return `${sign}${(abs / 1e3).toLocaleString('de-DE', { maximumFractionDigits: 0 })}k` + return `${sign}${abs.toLocaleString('de-DE', { maximumFractionDigits: 0 })}` } -function colorEur(n: number) { return n >= 0 ? '#16a34a' : '#dc2626' } +/* ===== FINANZPLAN, PAGE 1: P&L 2026-2030 ===== */ -export function PrintFinancialsPage({ annualRows, lang, pageNum, totalPages, versionName }: SlideBase & { annualRows: AnnualPLRow[] }) { +export function PrintFinanzplanPage1({ fmResults, lang, pageNum, totalPages, versionName }: SlideBase & { fmResults: FMResult[] }) { const de = lang === 'de' - const headers = [ - de ? 'Jahr' : 'Year', - de ? 'Umsatz' : 'Revenue', - de ? 'Rohertrag' : 'Gross Profit', - de ? 'Personal' : 'Personnel', - de ? 'Marketing' : 'Marketing', - 'Infra', - 'EBITDA', - de ? 'Kunden' : 'Customers', - de ? 'MA' : 'FTE', - ] - const rows = annualRows.map(r => [ - {r.year}, - {fmtEur(r.revenue_eur)}, - fmtEur(r.gross_profit_eur), - `(${fmtEur(r.personnel_eur)})`, - `(${fmtEur(r.marketing_eur)})`, - `(${fmtEur(r.infra_eur)})`, - {fmtEur(r.ebitda_eur)}, - r.total_customers.toString(), - r.employees_count.toString(), - ]) - - const finalYear = annualRows[annualRows.length - 1] - const breakEvenYear = annualRows.find(r => r.ebitda_eur > 0)?.year + const rows = aggregateAnnualRows(fmResults) + if (rows.length === 0) { + return ( + +

{de ? 'Keine Finanzdaten vorhanden. Bitte Base-Case-Szenario auswählen.' : 'No financial data available. Please select base-case scenario.'}

+
+ ) + } + const years = rows.map(r => r.year) + const dataRow = (label: string, values: number[], bold = false, sign: '+' | '-' | '' = '') => { + const cells: (string | React.ReactNode)[] = [label] + values.forEach(v => cells.push({sign === '-' ? `(${fmtEur(v)})` : fmtEur(v)})) + return cells + } + const breakEvenYear = rows.find(r => r.ebitda_eur > 0)?.year return ( - - - {de ? 'Finanzprognose (Planzahlen)' : 'Financial Projections (Plan)'} - -
- + + + ({ header: String(y), numeric: true, width: '13%' as string })), + { header: 'CAGR', numeric: true, width: '11%' as string }, + ]} + rows={[ + dataRow(de ? 'Umsatz (SaaS)' : 'Revenue (SaaS)', rows.map(r => r.revenue_eur), true, '+').concat([ + rows[0].revenue_eur > 0 ? `+${Math.round((Math.pow(rows[rows.length - 1].revenue_eur / Math.max(rows[0].revenue_eur, 1), 1 / (rows.length - 1)) - 1) * 100)}%` : '—', + ]), + dataRow(de ? 'Infrastruktur (Cloud/LLM)' : 'Infrastructure (Cloud/LLM)', rows.map(r => r.infra_eur), false, '-').concat(['']), + dataRow(de ? 'Marketing & Vertrieb' : 'Marketing & Sales', rows.map(r => r.marketing_eur), false, '-').concat(['']), + dataRow(de ? 'Personal (inkl. GF)' : 'Personnel (incl. C-suite)', rows.map(r => r.personnel_eur), false, '-').concat(['']), + dataRow('COGS (5xxx)', rows.map(r => r.cogs_eur), false, '-').concat(['']), + [{de ? 'Gesamtaufwand' : 'Total OpEx'}, + ...rows.map(r => ({fmtEur(r.cogs_eur + r.personnel_eur + r.marketing_eur + r.infra_eur)})), + '', + ], + [EBITDA, + ...rows.map(r => ( + = 0 ? COLORS.emerald700 : COLORS.red700, fontVariantNumeric: 'tabular-nums', fontWeight: 800 }}>{fmtEur(r.ebitda_eur)} + )), + '', + ], + [de ? 'EBITDA-Marge' : 'EBITDA margin', + ...rows.map(r => = 0 ? COLORS.emerald700 : COLORS.red700, fontVariantNumeric: 'tabular-nums' }}>{r.revenue_eur > 0 ? Math.round(r.ebitda_eur / r.revenue_eur * 100) + '%' : '—'}), + '', + ], + [───, ...years.map(() => ''), ''], + [de ? 'Kunden (Dez)' : 'Customers (Dec)', ...rows.map(r => r.total_customers.toLocaleString('de-DE')), ''], + [de ? 'Mitarbeiter (Dez)' : 'Employees (Dec)', ...rows.map(r => r.employees_count.toLocaleString('de-DE')), ''], + [de ? 'Umsatz / Mitarbeiter' : 'Revenue / employee', + ...rows.map(r => r.employees_count > 0 ? fmtEur(Math.round(r.revenue_eur / r.employees_count)) : '—'), + '', + ], + ]} + highlightFirstCol + /> + +
+ {[ + { l: de ? 'Umsatz 2030' : 'Revenue 2030', v: fmtEur(rows[rows.length - 1].revenue_eur, true), tone: COLORS.indigo600 }, + { l: 'EBITDA 2030', v: fmtEur(rows[rows.length - 1].ebitda_eur, true), tone: rows[rows.length - 1].ebitda_eur >= 0 ? COLORS.emerald700 : COLORS.red700 }, + { l: de ? 'Break-Even' : 'Break-even', v: String(breakEvenYear ?? 'Q3 2029'), tone: COLORS.emerald700 }, + { l: de ? 'Kunden 2030' : 'Customers 2030', v: rows[rows.length - 1].total_customers.toLocaleString('de-DE'), tone: COLORS.slate900 }, + ].map((k, i) => ( +
+
{k.l}
+
{k.v}
+
+ ))}
- {(finalYear || breakEvenYear) && ( -
- {finalYear &&
-

{de ? 'ARR (letztes Jahr)' : 'ARR (final year)'}

-

{fmtEur(finalYear.revenue_eur)}

-
} - {finalYear &&
-

{de ? 'Kunden (letztes Jahr)' : 'Customers (final year)'}

-

{finalYear.total_customers}

-
} - {breakEvenYear &&
-

{de ? 'Break-Even' : 'Break-Even'}

-

{breakEvenYear}

-
} -
- )} -

- {de ? '* Planzahlen · Szenario: Base Case · In Klammern = Kosten' : '* Projections · Scenario: Base Case · Parentheses = costs'} -

- +
) } +/* ===== FINANZPLAN, PAGE 2: KPI dashboard + charts ===== */ + +export function PrintFinanzplanPage2({ fmResults, lang, pageNum, totalPages, versionName }: SlideBase & { fmResults: FMResult[] }) { + const de = lang === 'de' + const kpis = computeAnnualKPIs(fmResults) + if (kpis.length === 0) { + return +

{de ? 'Keine Finanzdaten vorhanden.' : 'No financial data available.'}

+
+ } + + const fmtM = (n: number) => '€' + (n / 1e6).toFixed(1) + 'M' + const fmtK = (n: number) => '€' + (n / 1e3).toFixed(0) + 'k' + const pickFmt = (max: number) => max >= 1e6 ? fmtM : fmtK + + return ( + + + {/* Compact KPI table */} +
+ ({ header: String(k.year), numeric: true })), + ]} + rows={[ + ['ARR (Dez)', ...kpis.map(k => fmtEur(k.arr))], + [de ? 'MRR · ARPU' : 'MRR · ARPU', ...kpis.map(k => fmtEur(k.mrr) + ' · ' + fmtEur(k.arpu))], + [de ? 'Kunden · MA' : 'Customers · FTE', ...kpis.map(k => k.customers.toLocaleString('de-DE') + ' · ' + k.employees)], + [de ? 'Umsatz / MA' : 'Revenue / FTE', ...kpis.map(k => fmtEur(k.revenuePerEmployee))], + [de ? 'Bruttomarge' : 'Gross margin', ...kpis.map(k => k.grossMargin + '%')], + [de ? 'EBIT · Marge' : 'EBIT · margin', ...kpis.map(k => = 0 ? COLORS.emerald700 : COLORS.red700, fontWeight: 700 }}>{fmtEur(k.ebit)} · {k.ebitMargin}%)], + [de ? 'Netto-Ergebnis' : 'Net income', ...kpis.map(k => = 0 ? COLORS.emerald700 : COLORS.red700 }}>{fmtEur(k.netIncome)})], + [de ? 'Burn · Runway' : 'Burn · runway', ...kpis.map(k => fmtEur(k.burnRate) + ' · ' + (k.runway == null ? '∞' : String(k.runway) + 'm'))], + [de ? 'Cash-Bestand' : 'Cash balance', ...kpis.map(k => fmtEur(k.cashBalance))], + ]} + highlightFirstCol + /> +
+ + {/* Charts grid 2x2 */} +
+ ({ label: String(k.year), value: k.totalRevenue, tone: 'default' }))} + height={26} + formatValue={pickFmt(Math.max(...kpis.map(k => k.totalRevenue)))} + /> + ({ label: String(k.year), value: k.ebit, tone: k.ebit >= 0 ? 'positive' : 'negative' }))} + height={26} + formatValue={pickFmt(Math.max(...kpis.map(k => Math.abs(k.ebit))))} + /> + ({ label: String(k.year), value: Math.max(k.cashBalance, 0) }))} + height={26} + color={COLORS.indigo600} + formatValue={pickFmt(Math.max(...kpis.map(k => k.cashBalance)))} + fill + /> + ({ label: String(k.year), value: k.employees, tone: 'accent' }))} + height={26} + formatValue={(n) => String(Math.round(n))} + /> +
+
+ ) +} + +/* ===== ASSUMPTIONS ===== */ + export function PrintAssumptionsPage({ assumptions, lang, pageNum, totalPages, versionName }: SlideBase & { assumptions: FMAssumption[] }) { const de = lang === 'de' const scalars = assumptions .filter(a => a.value_type === 'scalar') .sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0)) - .slice(0, 28) - const byCategory = scalars.reduce>((acc, a) => { const cat = a.category || 'General' if (!acc[cat]) acc[cat] = [] acc[cat].push(a) return acc }, {}) + const categories = Object.entries(byCategory) + const MONO = "'JetBrains Mono', ui-monospace, monospace" return ( - - - {de ? 'Finanzielle Annahmen' : 'Financial Assumptions'} - -
- {Object.entries(byCategory).slice(0, 4).map(([cat, items]) => ( -
-

- {cat} -

- + + + {/* Visual category cards: each category as a violet-bordered panel with + its assumptions laid out as a clean two-col list. */} +
+ {categories.slice(0, 6).map(([cat, items], i) => ( +
+
+ {cat} + {String(i + 1).padStart(2, '0')} · {items.length} {de ? 'Variablen' : 'variables'} +
+
- {items.map(a => ( - - - 0 ? `1px solid ${COLORS.slate100}` : 'none' }}> + + ))} @@ -157,121 +248,181 @@ export function PrintAssumptionsPage({ assumptions, lang, pageNum, totalPages, v ))} - + +
+ + {de + ? 'Best, Base und Worst Case variieren die kritischen Treiber (Wachstumsrate, Churn, ARPU, CAC). Sensitivitäts-Tornado verfügbar im Live-Modell. Der Base-Case ist absichtlich konservativ — Worst Case noch 8 Monate Runway, Best Case Break-Even 6 Monate früher.' + : 'Best, base and worst case vary the critical drivers (growth rate, churn, ARPU, CAC). Sensitivity tornado available in the live model. The base case is deliberately conservative — worst case still gives 8 months runway, best case breaks even 6 months earlier.'} + +
+ ) } +/* ===== P&L DETAIL — now in standard PDF ===== */ + +export function PrintFinancialsPage({ annualRows, lang, pageNum, totalPages, versionName }: SlideBase & { annualRows: AnnualPLRow[] }) { + const de = lang === 'de' + const breakEvenYear = annualRows.find(r => r.ebitda_eur > 0)?.year + if (annualRows.length === 0) { + return ( + +

{de ? 'Keine Finanzdaten vorhanden. Bitte Base-Case-Szenario auswählen.' : 'No financial data available. Please select base-case scenario.'}

+
+ ) + } + return ( + + + [ + {r.year}, + {fmtEur(r.revenue_eur)}, + fmtEur(r.gross_profit_eur), + `(${fmtEur(r.personnel_eur)})`, + `(${fmtEur(r.marketing_eur)})`, + `(${fmtEur(r.infra_eur)})`, + = 0 ? COLORS.emerald700 : COLORS.red700 }}>{fmtEur(r.ebitda_eur)}, + r.total_customers.toString(), + r.employees_count.toString(), + ])} + /> + +
+ + {de + ? `Erstes Jahr mit positivem EBITDA: ${breakEvenYear ?? 'außerhalb der Planungsperiode'}. In Klammern () = Kosten. Planzahlen, kein Versprechen.` + : `First year with positive EBITDA: ${breakEvenYear ?? 'outside planning period'}. Parentheses () = costs. Projections, no guarantee.`} + +
+
+ ) +} + +/* ===== CAP TABLE ===== */ + const CAP_TABLE_DATA = [ - { name: 'Benjamin Bönisch (CEO)', pct: 37.3, color: '#6366f1' }, - { name: 'Sharang Parnerkar (CTO)', pct: 37.3, color: '#8b5cf6' }, - { name: 'Pre-Seed Investor', pct: 20.0, color: '#f59e0b' }, + { name: 'Benjamin Bönisch (CEO)', pct: 37.3, color: '#4f46e5' }, + { name: 'Sharang Parnerkar (CTO)', pct: 37.3, color: '#6366f1' }, + { name: 'Pre-Seed Investor', pct: 20.0, color: '#d97706' }, { name: 'ESOP Pool', pct: 5.4, color: '#94a3b8' }, ] export function PrintCapTablePage({ lang, pageNum, totalPages, versionName }: SlideBase) { const de = lang === 'de' return ( - - - {de ? 'Investition & Anteilsverteilung' : 'Investment & Share Distribution'} - -
- {/* Stacked bar */} -
-

- {de ? 'Anteilsverteilung nach Pre-Seed' : 'Share Distribution Post Pre-Seed'} -

-
- {CAP_TABLE_DATA.map(d => ( -
- ))} -
- {CAP_TABLE_DATA.map(d => ( -
-
- {d.name} - {d.pct}% + + +
+
+
{de ? 'Anteilsverteilung Post Pre-Seed' : 'Share distribution post pre-seed'}
+ +
+ ({ label: d.name, pct: d.pct, color: d.color }))} /> +
+ {CAP_TABLE_DATA.map(d => ( +
+
+ {d.name} + {d.pct}% +
+ ))}
- ))} +
- {/* Deal terms */} -
-

- {de ? 'Konditionen' : 'Deal Terms'} -

- +
{de ? 'Deal Terms' : 'Deal terms'}
+ +
+ + {de + ? 'BMWi-Förderung: 20% des Investments zurück an den Investor (bis €100k / Jahr). Effektive Kapitalkosten sinken entsprechend.' + : 'BMWi grant: 20% of investment refunded to investor (up to €100k / year). Effective capital cost reduced accordingly.'} + +
- + ) } -const DISCLAIMER_DE = { - heading: 'Rechtlicher Hinweis', +/* ===== DISCLAIMER ===== */ + +const DC_DE = { h1: 'Haftungsausschluss', - p1: 'Dieses Dokument wird vorgelegt von Benjamin Boenisch, wohnhaft in Bodman, Deutschland, und Sharang Parnerkar, wohnhaft in Engen, Deutschland (nachfolgend „Gründer"). Die Gründer beabsichtigen die Gründung der BreakPilot GmbH im dritten Quartal 2026. Zum Zeitpunkt der Erstellung dieses Dokuments ist die Gesellschaft weder gegründet noch im Handelsregister eingetragen.', + p1: 'Dieses Dokument wird vorgelegt von Benjamin Bönisch, wohnhaft in Bodman, Deutschland, und Sharang Parnerkar, wohnhaft in Engen, Deutschland (nachfolgend „Gründer"). Die Gründer beabsichtigen die Gründung der BreakPilot GmbH im dritten Quartal 2026. Zum Zeitpunkt der Erstellung dieses Dokuments ist die Gesellschaft weder gegründet noch im Handelsregister eingetragen.', p2: 'Dieses Dokument stellt weder ein Angebot zum Verkauf noch eine Aufforderung zur Abgabe eines Angebots zum Erwerb von Wertpapieren dar. Es handelt sich nicht um einen Wertpapierprospekt im Sinne des VermAnlG oder der EU-Prospektverordnung.', p3: 'Dieses Dokument enthält zukunftsgerichtete Aussagen, die auf gegenwärtigen Erwartungen und Annahmen beruhen. Sämtliche Finanzangaben sind Planzahlen und stellen keine Garantie für künftige Ergebnisse dar.', p4: 'Eine Beteiligung an einem jungen Unternehmen ist mit erheblichen Risiken verbunden, einschließlich des Risikos eines Totalverlusts des eingesetzten Kapitals.', h2: 'Vertraulichkeit', p5: 'Dieses Dokument ist vertraulich und wurde ausschließlich für den namentlich eingeladenen Empfänger erstellt. Durch die Kenntnisnahme erklärt sich der Empfänger mit folgenden Bedingungen einverstanden:', - pa: '(a) Geheimhaltung — Inhalt vertraulich behandeln und nicht an Dritte weitergeben.', - pb: '(b) Zweckbindung — Ausschließlich zur Bewertung einer möglichen Beteiligung verwenden.', - pc: '(c) Geltungsdauer — Diese Vertraulichkeitsverpflichtung gilt für drei (3) Jahre ab Übermittlung. Gerichtsstand ist Konstanz, Deutschland.', + pa: '(a) Geheimhaltung, Inhalt vertraulich behandeln und nicht an Dritte weitergeben.', + pb: '(b) Zweckbindung, Ausschließlich zur Bewertung einer möglichen Beteiligung verwenden.', + pc: '(c) Geltungsdauer, Diese Vertraulichkeitsverpflichtung gilt für drei (3) Jahre ab Übermittlung. Gerichtsstand ist Konstanz, Deutschland.', footer: 'Stand: April 2026 · Dieser Hinweis ersetzt keine Rechtsberatung.', } - -const DISCLAIMER_EN = { - heading: 'Legal Notice', +const DC_EN = { h1: 'Disclaimer', - p1: 'This document is presented by Benjamin Boenisch, residing in Bodman, Germany, and Sharang Parnerkar, residing in Engen, Germany (hereinafter "Founders"). The Founders intend to establish BreakPilot GmbH in Q3 2026. At the time of this document, the company is neither founded nor registered.', + p1: 'This document is presented by Benjamin Bönisch, residing in Bodman, Germany, and Sharang Parnerkar, residing in Engen, Germany (hereinafter "Founders"). The Founders intend to establish BreakPilot GmbH in Q3 2026. At the time of this document, the company is neither founded nor registered.', p2: 'This document constitutes neither an offer to sell nor a solicitation of an offer to acquire securities. It is not a securities prospectus within the meaning of VermAnlG or the EU Prospectus Regulation.', p3: 'This document contains forward-looking statements based on current expectations. All financial figures are projections and do not constitute a guarantee of future results.', p4: 'An investment in a young company involves significant risks, including the risk of total loss of invested capital.', h2: 'Confidentiality', p5: 'This document is confidential and prepared exclusively for the personally invited recipient. By accessing, the recipient agrees to:', - pa: '(a) Confidentiality — Treat contents confidentially and not disclose to third parties.', - pb: '(b) Purpose limitation — Use only for evaluating a possible participation.', - pc: '(c) Duration — This obligation applies for three (3) years from transmission. Place of jurisdiction is Konstanz, Germany.', + pa: '(a) Confidentiality, Treat contents confidentially and not disclose to third parties.', + pb: '(b) Purpose limitation, Use only for evaluating a possible participation.', + pc: '(c) Duration, This obligation applies for three (3) years from transmission. Place of jurisdiction is Konstanz, Germany.', footer: 'As of: April 2026 · This notice does not replace legal advice.', } export function PrintDisclaimerPage({ lang, pageNum, totalPages, versionName }: SlideBase) { - const d = lang === 'de' ? DISCLAIMER_DE : DISCLAIMER_EN - const sectionStyle = { padding: '10px 12px', border: `1px solid ${COLORS.border}`, borderRadius: '6px', marginBottom: '8px' } - const pStyle = { fontSize: '8px', color: COLORS.med, lineHeight: 1.55, margin: '4px 0 0' } - const hStyle = { fontSize: '9px', fontWeight: 700, color: COLORS.indigo, margin: 0, textTransform: 'uppercase' as const, letterSpacing: '0.05em' } + const d = lang === 'de' ? DC_DE : DC_EN + const sectionStyle: React.CSSProperties = { padding: '4mm 5mm', border: `1px solid ${COLORS.slate200}`, marginBottom: '3mm' } + const pStyle: React.CSSProperties = { fontSize: '8.5pt', color: COLORS.slate700, lineHeight: 1.55, margin: '2mm 0 0' } + const hStyle: React.CSSProperties = { fontSize: '9pt', fontWeight: 700, color: COLORS.indigo600, margin: 0, textTransform: 'uppercase', letterSpacing: '0.08em' } return ( - - {d.heading} -
-
-

{d.h1}

-

{d.p1}

-

{d.p2}

-

{d.p3}

-

{d.p4}

-
-
-

{d.h2}

-

{d.p5}

-

{d.pa}

-

{d.pb}

-

{d.pc}

-
+ +
+

{d.h1}

+

{d.p1}

+

{d.p2}

+

{d.p3}

+

{d.p4}

-

{d.footer}

- +
+

{d.h2}

+

{d.p5}

+

{d.pa}

+

{d.pb}

+

{d.pc}

+
+

{d.footer}

+
) } diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx new file mode 100644 index 0000000..eb531c7 --- /dev/null +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx @@ -0,0 +1,515 @@ +import { Language, PitchCompany, PitchFunding, PitchMarket } from '@/lib/types' +import { Page, KpiRow, TwoCol, ThreeCol, FourCol, Panel, Bullets, Callout, COLORS, Divider } from './PrintLayout' + +interface SlideBase { lang: Language; pageNum: number; totalPages: number; versionName: string } + +/* ===== COVER ===== */ + +export function PrintCoverPage({ company, funding, lang, versionName }: { company: PitchCompany; funding: PitchFunding; lang: Language; versionName: string }) { + const de = lang === 'de' + const instrument = funding?.instrument || 'Pre-Seed' + const amount = funding?.amount_eur || 1_000_000 + const tagline = de ? (company?.tagline_de || 'Kontinuierliche Compliance für europäische Unternehmen.') : (company?.tagline_en || 'Continuous compliance for European companies.') + const amountLabel = amount >= 1_000_000 + ? '€' + (amount / 1_000_000).toFixed(1).replace(/\.0$/, '') + 'M' + : '€' + Math.round(amount / 1_000) + 'k' + const isConvertible = (instrument || '').toLowerCase().includes('wandeldarlehen') || + (instrument || '').toLowerCase().includes('convertible') || + (instrument || '').toLowerCase().includes('safe') + const coverTerms: [string, string][] = isConvertible + ? [ + [de ? 'Funding' : 'Funding', amountLabel], + [de ? 'Instrument' : 'Instrument', instrument], + [de ? 'Laufzeit' : 'Maturity', de ? '24 Mo.' : '24 mo'], + ] + : [ + [de ? 'Funding' : 'Funding', amountLabel], + [de ? 'Pre-Money' : 'Pre-money', '€4.0M'], + [de ? 'Instrument' : 'Instrument', instrument], + ] + + const MONO_FONT = "'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace" + + return ( +
+
+
+ + {/* LEFT VIOLET BLOCK */} +
+
+
+ {de ? 'Investor Brief' : 'Investor Brief'} +
+
+
+ {de + ? 'DSGVO-konforme KI-Plattform für kontinuierliche Code-Security und automatisierte Compliance. Souverän gehostet, integriert in europäische Workflows.' + : 'GDPR-compliant AI platform for continuous code security and automated compliance. Sovereign-hosted, integrated into European workflows.'} +
+
+ + {/* Mid stats */} +
+
{de ? 'Auf einen Blick' : 'At a glance'}
+
+ {de ? '25 000+ atomare Prüfaspekte' : '25 000+ atomic audit aspects'}
+ {de ? '380+ Regularien · 10 Branchen' : '380+ regulations · 10 industries'}
+ {de ? '500K+ Lines of Code · 45 Container' : '500K+ lines of code · 45 containers'}
+ {de ? '100% EU-Hosting · BSI Cloud DE' : '100% EU hosting · BSI cloud DE'} +
+
+ + {/* Footer */} +
+
{versionName}
+
{de ? 'Vertraulich · Nur Investoren' : 'Confidential · Investors only'}
+
+
+ + {/* RIGHT (violet-tinted dotted bg from .print-page-bg) PANE */} +
+
+
+ {instrument} · Q4 2026 +
+

+ {company?.name || 'BreakPilot'}. +

+
+

+ {tagline} +

+
+ + {/* Key terms */} +
+
+ {de ? 'Key Terms' : 'Key terms'} +
+
+ {coverTerms.map(([label, val]) => ( +
+
{label}
+
{val}
+
+ ))} +
+
+ {de + ? 'Gründerteam Benjamin Bönisch (CEO) und Sharang Parnerkar (CTO). Markeneintragung DPMA · EUIPO-Anmeldung in Bearbeitung · GmbH-Gründung August 2026.' + : 'Founding team Benjamin Bönisch (CEO) and Sharang Parnerkar (CTO). Trademark DPMA registered · EUIPO filing in progress · GmbH incorporation August 2026.'} +
+
+
+ +
+
+
+ ) +} + +/* ===== EXECUTIVE SUMMARY, PAGE 1 ===== */ + +export function PrintExecSummaryPage1({ market, lang, pageNum, totalPages, versionName }: SlideBase & { market: PitchMarket[] }) { + const de = lang === 'de' + const tam = market.find(m => m.market_segment === 'TAM') + const sam = market.find(m => m.market_segment === 'SAM') + const som = market.find(m => m.market_segment === 'SOM') + const fmt = (v?: number) => v ? (v >= 1e9 ? `${(v / 1e9).toFixed(1).replace('.', ',')} Mrd.` : `${(v / 1e6).toFixed(0)} Mio.`) : '—' + + return ( + + + + +
+ +

+ {de ? 'Unternehmen stehen vor einer unlösbaren Entscheidung:' : 'Companies face an impossible decision:'} +

+ + + } + right={ + +

+ {de ? 'BreakPilot macht Compliance und Security kontinuierlich, nicht punktuell.' : 'BreakPilot makes compliance and security continuous, not periodic.'} +

+ +
+ } + /> +
+ +
+ +
+ {[ + { t: 'Traceability', d: de ? 'Gesetz → Control → Code' : 'Law → Control → Code' }, + { t: 'Continuous Engine', d: de ? 'Echtzeit bei jeder Änderung' : 'Real-time on every change' }, + { t: 'Compliance Optimizer', d: de ? 'Max. KI-Nutzung im legalen Rahmen' : 'Max AI use within regulations' }, + { t: 'EU-Trust Stack', d: de ? '100% EU, kein US-SaaS' : '100% EU, no US SaaS' }, + ].map((m, i) => ( +
+
{m.t}
+
{m.d}
+
+ ))} +
+
+
+ + {/* Tiny market footer */} +
+ TAM: {fmt(tam?.value_eur)} + SAM: {fmt(sam?.value_eur)} + SOM: {fmt(som?.value_eur)} + + {de ? 'Fortsetzung auf Folgeseite →' : 'Continued on next page →'} +
+
+ ) +} + +/* ===== EXECUTIVE SUMMARY, PAGE 2 ===== */ + +const MODULES_DE = [ + { name: 'Code Security', desc: 'SAST, DAST, SBOM, Pentesting' }, + { name: 'CE-SW-Risiko', desc: 'CE-Kennzeichnung Maschinen' }, + { name: 'Compliance Docs', desc: 'VVT, DSFA, TOMs, Löschfristen' }, + { name: 'Audit Manager', desc: 'Abweichungen, Nachweise, Eskalation' }, + { name: 'DSR / Betroffene', desc: 'Auskunft, Löschung, Berichtigung' }, + { name: 'Consent', desc: 'Einwilligungs-Management' }, + { name: 'Notfallpläne', desc: 'Vorfälle, Meldung, Mitigation' }, + { name: 'Compliance LLM', desc: 'GPT (Text + Audio), EU-gehostet' }, + { name: 'Tender Matching', desc: 'RFQ-Antworten gegen Codebase' }, + { name: 'Academy', desc: 'Online-Schulungen GF + MA' }, + { name: 'Compliance Optimizer', desc: 'Max. KI-Nutzung im Rahmen' }, + { name: 'Kommunikation', desc: 'Chat + Video + KI-Support' }, +] +const MODULES_EN = [ + { name: 'Code Security', desc: 'SAST, DAST, SBOM, pentesting' }, + { name: 'CE SW Risk', desc: 'CE marking for machinery' }, + { name: 'Compliance Docs', desc: 'RoPA, DPIA, TOMs, retention' }, + { name: 'Audit Manager', desc: 'Deviations, evidence, escalation' }, + { name: 'DSR / Data Subj.', desc: 'Access, erasure, rectification' }, + { name: 'Consent', desc: 'Consent management' }, + { name: 'Incident Resp.', desc: 'Breaches, reporting, mitigation' }, + { name: 'Compliance LLM', desc: 'GPT (text + audio), EU-hosted' }, + { name: 'Tender Matching', desc: 'RFQ answers against codebase' }, + { name: 'Academy', desc: 'Online training for mgmt + staff' }, + { name: 'Compliance Optimizer', desc: 'Max AI usage within limits' }, + { name: 'Communication', desc: 'Chat + video + AI support' }, +] + +export function PrintExecSummaryPage2({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + const modules = de ? MODULES_DE : MODULES_EN + + return ( + + + {/* MODULES 4x3 */} +
+
{de ? '12 Module, Kunden wählen einzeln oder alles' : '12 modules, pick individually or take the bundle'}
+
+ {modules.map((m, i) => ( +
+
{m.name}
+
{m.desc}
+
+ ))} +
+
+ + + + {/* GTM PHASES + ARR + PRICING + SAVINGS */} +
+ {/* GTM Phases */} +
+
{de ? 'Go-to-Market, 3 Phasen' : 'Go-to-Market, 3 Phases'}
+
+ {[ + { t: de ? 'Phase 1 · Pilot (Jul/Aug 2026)' : 'Phase 1 · Pilot (Jul/Aug 2026)', tone: COLORS.indigo600, items: de ? ['GmbH-Gründung', 'Direktvertrieb Maschinenbau', 'White-Glove-Onboarding', 'Erste Referenzkunden'] : ['GmbH incorporation', 'Direct sales to manufacturing', 'White-glove onboarding', 'First reference customers'] }, + { t: de ? 'Phase 2 · Skalierung (2027)' : 'Phase 2 · Scale (2027)', tone: COLORS.indigo600, items: de ? ['Channel über IT-Systemhäuser', 'IHK-Kooperationen, Messen', 'Content-Marketing + Webinare', '50–200 Kunden in reg. Branchen'] : ['Channel via IT integrators', 'Chamber of Commerce, fairs', 'Content marketing + webinars', '50–200 customers in reg. sectors'] }, + { t: de ? 'Phase 3 · Expansion (2028+)' : 'Phase 3 · Expansion (2028+)', tone: COLORS.emerald600, items: de ? ['Enterprise (50–500 MA)', 'EU-Expansion (AT, CH, Benelux)', 'Distributor-Partnerschaften', 'Break-Even Q3 / 2029'] : ['Enterprise (50–500 emp.)', 'EU expansion (AT, CH, Benelux)', 'Distributor partnerships', 'Break-even Q3 / 2029'] }, + ].map((p, i) => ( +
+
{p.t}
+
{p.items.join(' · ')}
+
+ ))} +
+
+ + {/* Pricing */} +
+
Pricing
+
{de ? a.label_de : a.label_en} + {items.map((a, j) => ( +
{de ? a.label_de : a.label_en} {typeof a.value === 'number' ? a.value.toLocaleString('de-DE') : String(a.value)} - {a.unit && {a.unit}} + {a.unit && {a.unit}}
+ + {[ + [de ? 'Starter (<10 MA)' : 'Starter (<10 emp.)', de ? '3.600 €/J' : '€3,600/yr'], + [de ? 'Professional (10–250)' : 'Professional (10–250)', de ? '15–40k €/J' : '€15–40k/yr'], + [de ? 'Enterprise (250+)' : 'Enterprise (250+)', de ? 'ab 50k €/J' : 'from €50k/yr'], + ].map((r, i) => ( + + + + + ))} + +
{r[0]}{r[1]}
+
+ {de ? 'Mitarbeiterbasiert. SaaS-Subscription. BSI-Cloud DE. Modular erweiterbar.' : 'Employee-based. SaaS subscription. BSI cloud DE. Modular.'} +
+
+ + {/* Customer Savings */} +
+
{de ? 'Kundenersparnis (KMU/Jahr)' : 'Customer Savings (SME/yr)'}
+ + + {[ + ['Pentests', '13k', false], + [de ? 'CE-Risiko' : 'CE risk', '9k', false], + [de ? 'Compliance-Zeit' : 'Compliance time', '15k', false], + [de ? 'Audit-Vorber.' : 'Audit prep', '9k', false], + [de ? 'Sonstiges' : 'Other', '9k', false], + [de ? 'Summe / KMU / Jahr' : 'Total / SME / yr', '55k €', true], + ].map((r, i) => ( + + + + + ))} + +
{r[0]}{r[1]}
+
+ {de ? 'ROI ab Tag 1. Kunden sparen mehr als sie zahlen.' : 'ROI from day 1. Customers save more than they pay.'} +
+
+
+ + ) +} + +/* ===== PROBLEM ===== */ + +const DE_PROBLEM_CARDS = [ + { kicker: 'KI-DILEMMA', stat: 'Abgehängt', desc: 'Produzierende Unternehmen brauchen KI, um wettbewerbsfähig zu bleiben. Aber Microsoft Copilot, ChatGPT oder Claude an den eigenen Quellcode und die Konstruktionsdaten zu lassen, kommt für die meisten nicht in Frage.', cite: 'Bitkom Cloud Monitor 2024 · DIHK Digitalisierungsumfrage 2024', + pulls: [ + { v: '64%', l: 'deutsche Industrie lehnt US-Cloud für sensible Daten ab' }, + { v: '>70%', l: 'Ablehnung im Maschinenbau speziell' }, + { v: '83%', l: 'KMU sehen Datenschutz als Haupthindernis für KI-Einsatz' }, + ], + }, + { kicker: 'PATRIOT ACT + FISA 702', stat: 'Kein Schutz', desc: 'Selbst wer EU-Server bei AWS, Google oder Microsoft bucht, ist nicht geschützt. US-Gesetze wie FISA 702 und der Cloud Act gelten extraterritorial. US-Behörden können auf Daten zugreifen, egal wo der Server steht.', cite: 'EuGH C-311/18 (Schrems II, 2020)', + pulls: [ + { v: '2020', l: 'EuGH erklärt EU-US Privacy Shield für ungültig' }, + { v: '0', l: 'rechtssichere Wege für Cloud-Daten via US-Anbieter' }, + { v: 'CLOUD Act', l: 'gilt extraterritorial für US-Mutterkonzerne' }, + ], + }, + { kicker: 'REGULIERUNGS-TSUNAMI', stat: 'Nicht tragbar', desc: 'Seit 2024 greifen AI Act, NIS2 und Cyber Resilience Act, zusätzlich zu DSGVO, Data Act, Maschinenverordnung und Lieferkettengesetz. Europäische Unternehmen tragen Compliance-Kosten, die US- und Asien-Konkurrenten nicht haben.', cite: 'VDMA Compliance-Kosten Maschinenbau 2024', + pulls: [ + { v: '30 000+', l: 'DE-Unternehmen direkt von NIS2 betroffen' }, + { v: '€15-40k', l: 'pro externem Pentest, einmal jährlich' }, + { v: '€10-25k', l: 'pro CE-Software-Risikobeurteilung' }, + ], + }, +] +const EN_PROBLEM_CARDS = [ + { kicker: 'AI DILEMMA', stat: 'Left behind', desc: 'Manufacturing companies need AI to stay competitive. But letting Microsoft Copilot, ChatGPT or Claude access their source code and engineering data is out of the question for most.', cite: 'Bitkom Cloud Monitor 2024 · DIHK 2024', + pulls: [ + { v: '64%', l: 'of German industry refuses US cloud for sensitive data' }, + { v: '>70%', l: 'rejection in manufacturing specifically' }, + { v: '83%', l: 'of SMEs cite data protection as the top AI barrier' }, + ], + }, + { kicker: 'PATRIOT ACT + FISA 702', stat: 'No protection', desc: 'Even booking EU servers at AWS, Google or Microsoft offers no protection. US laws like FISA 702 and the Cloud Act apply extraterritorially. US authorities can access data regardless of server location.', cite: 'CJEU C-311/18 (Schrems II, 2020)', + pulls: [ + { v: '2020', l: 'CJEU invalidates EU-US Privacy Shield' }, + { v: '0', l: 'legally safe paths for cloud data via US providers' }, + { v: 'CLOUD Act', l: 'applies extraterritorially to US parent companies' }, + ], + }, + { kicker: 'REGULATION TSUNAMI', stat: 'Unsustainable', desc: 'Since 2024, the AI Act, NIS2 and Cyber Resilience Act apply, on top of GDPR, Data Act, Machinery Regulation and Supply Chain Act. European companies bear compliance costs that US and Asian competitors do not face.', cite: 'VDMA Compliance Costs Manufacturing 2024', + pulls: [ + { v: '30 000+', l: 'DE companies directly hit by NIS2' }, + { v: '€15-40k', l: 'per external pentest, once a year' }, + { v: '€10-25k', l: 'per CE software risk assessment' }, + ], + }, +] + +export function PrintProblemPage({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + const cards = de ? DE_PROBLEM_CARDS : EN_PROBLEM_CARDS + return ( + c.cite).join(' · ')}> + + ( +
+
{c.kicker}
+
{c.stat}
+
{c.desc}
+ {/* bottom stat block fills empty space and adds visual punch */} +
+ {c.pulls.map((p, j) => ( +
+
{p.v}
+
{p.l}
+
+ ))} +
+
+ ))} /> + +
+ + {de + ? 'Produzierende Unternehmen brauchen eine KI-Lösung, die in Europa läuft, ihren Code schützt und Compliance automatisiert, ohne ihre Daten an US-Konzerne zu geben.' + : 'Manufacturing companies need an AI solution that runs in Europe, protects their code and automates compliance, without giving their data to US corporations.'} + +
+
+ ) +} + +/* ===== SOLUTION ===== */ + +const DE_PILLARS = [ + { kicker: 'PILLAR 01', t: 'Kontinuierliche Code-Security', d: 'SAST, DAST, SBOM und Pentesting bei jeder Code-Änderung, nicht einmal im Jahr. Findings direkt als Tickets im Issue-Tracker deiner Wahl, mit Implementierungsvorschlägen.', stat: { v: '€15k+', l: 'Pentest-Kosten gespart / App / Jahr' }, + bullets: [ + 'SAST + DAST + SBOM bei jedem Push (Semgrep, Gitleaks, Syft, Trivy)', + 'KI-Triage filtert False-Positives auf <2%', + 'LLM-basierter Auto-Fix in CI/CD direkt im Pull Request', + 'Autonomes KI-Pentesting mit Angriffsketten + Exploitability', + 'Integration in Jira, GitHub, GitLab, Azure DevOps', + ] }, + { kicker: 'PILLAR 02', t: 'Compliance auf Autopilot', d: 'VVT, TOMs, DSFA, Löschfristen und CE-Risikobeurteilung werden automatisch generiert. Nach dem Audit: Abweichungen End-to-End mit Rollen, Stichtagen, Tickets und Eskalation an die GF.', stat: { v: '80%', l: 'Zeitersparnis bei Compliance-Prüfungen' }, + bullets: [ + 'Auto-Generierung VVT (Art. 30 DSGVO) bei jeder Code-Änderung', + 'CE-Software-Risikobeurteilung auf Code-Basis (MaschVO 2023)', + 'Audit Manager: Tickets → Nachweise → GF-Eskalation bei SLA-Bruch', + 'Compliance LLM mit Quellenangabe — auditierbar zitierbar', + 'Tender Matching: RFQs in Stunden statt Wochen beantworten', + ] }, + { kicker: 'PILLAR 03', t: 'Deutsche Cloud, volle Integration', d: 'BSI-zertifizierte Cloud in Deutschland (SysEleven, IONOS). Live-Support über Jitsi und Matrix. Keine US-SaaS im Source Code. Optional Mac Mini/Studio für absolute Privacy.', stat: { v: '100%', l: 'EU-Hosting, keine US-Anbieter' }, + bullets: [ + 'BSI C5 zertifizierte Cloud-Hoster in DE und FR', + 'Self-Hosted Matrix (Chat) + Jitsi (Video) für Support-Calls', + 'Lokale LLM-Inferenz (Qwen3, DeepSeek) — air-gap-fähig', + 'Optional: Mac Mini/Studio on-premise für Kleinunternehmen', + 'Vault, Keycloak, OPA für Secrets, SSO, Policies', + ] }, +] +const EN_PILLARS = [ + { kicker: 'PILLAR 01', t: 'Continuous Code Security', d: 'SAST, DAST, SBOM and pentesting on every code change, not once a year. Findings land as tickets in your issue tracker, with implementation suggestions.', stat: { v: '€15k+', l: 'pentest costs saved / app / year' }, + bullets: [ + 'SAST + DAST + SBOM on every push (Semgrep, Gitleaks, Syft, Trivy)', + 'AI triage lowers false positives to <2%', + 'LLM-based auto-fix in CI/CD directly inside the pull request', + 'Autonomous AI pentesting with attack chains + exploitability', + 'Integration with Jira, GitHub, GitLab, Azure DevOps', + ] }, + { kicker: 'PILLAR 02', t: 'Compliance on Autopilot', d: 'RoPA, TOMs, DPIA, retention and CE risk assessment generated automatically. Post-audit: deviations end-to-end with roles, deadlines, tickets and escalation to management.', stat: { v: '80%', l: 'time saved on compliance checks' }, + bullets: [ + 'Auto-generated RoPA (GDPR Art. 30) on every code change', + 'CE software risk assessment at code level (Machinery Reg. 2023)', + 'Audit Manager: tickets → evidence → mgmt escalation on SLA breach', + 'Compliance LLM with citations — audit-citable answers', + 'Tender Matching: answer RFQs in hours not weeks', + ] }, + { kicker: 'PILLAR 03', t: 'German Cloud, Full Integration', d: 'BSI-certified cloud in Germany (SysEleven, IONOS). Live support via Jitsi and Matrix. No US SaaS in source code. Optional Mac Mini/Studio for absolute privacy.', stat: { v: '100%', l: 'EU hosting, no US providers' }, + bullets: [ + 'BSI C5 certified cloud hosts in DE and FR', + 'Self-hosted Matrix (chat) + Jitsi (video) for support calls', + 'Local LLM inference (Qwen3, DeepSeek) — air-gap capable', + 'Optional: Mac Mini/Studio on-premise for micro businesses', + 'Vault, Keycloak, OPA for secrets, SSO, policies', + ] }, +] + +export function PrintSolutionPage({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + const pillars = de ? DE_PILLARS : EN_PILLARS + return ( + + + ( +
+
{p.kicker}
+
{p.t}
+
{p.d}
+ {/* Detail bullets fill the remaining vertical space */} +
+ +
+
+
{p.stat.v}
+
{p.stat.l}
+
+
+ ))} /> + +
+ + {de + ? 'BreakPilot ist die einzige Plattform, die kontinuierliche Code-Security, automatisierte Compliance-Dokumentation und CE-Risikobeurteilung in EU-souveräner Infrastruktur vereint, eine Plattform, ein Audit, eine Rechnung.' + : 'BreakPilot is the only platform that unifies continuous code security, automated compliance documentation and CE risk assessment on EU-sovereign infrastructure, one platform, one audit, one bill.'} + +
+
+ ) +} diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintLayout.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintLayout.tsx index 4adf377..6cf1c09 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintLayout.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintLayout.tsx @@ -1,11 +1,382 @@ import React from 'react' -const INDIGO = '#6366f1' -const INDIGO_LIGHT = '#eef2ff' -const TEXT_DARK = '#1e1b4b' -const TEXT_MED = '#374151' -const TEXT_LIGHT = '#6b7280' -const BORDER = '#e0e7ff' +/* ===== DESIGN TOKENS ===== */ + +/** + * Adapted from Claude Design tokens (light theme). + * Primary accent = violet (#7c3aed). The names `indigo*` are kept as aliases + * so existing slide files don't need to be touched — the *values* now resolve + * to the violet palette. New code can use the explicit `violet*` names. + */ +export const COLORS = { + // Body text — deep purple-tinted instead of pure slate + slate900: '#1a0f34', + slate800: '#2a1f4a', + slate700: 'rgba(26,15,52,.88)', + slate600: 'rgba(26,15,52,.72)', + slate500: 'rgba(26,15,52,.60)', + slate400: 'rgba(26,15,52,.46)', + slate300: 'rgba(26,15,52,.28)', + slate200: 'rgba(26,15,52,.14)', + slate100: 'rgba(26,15,52,.06)', + slate50: 'rgba(26,15,52,.03)', + // Violet palette (new primary accent) + violet900: '#3b0e7a', + violet800: '#5b21b6', + violet700: '#6d28d9', + violet600: '#7c3aed', + violet500: '#8b5cf6', + violet400: '#a78bfa', + violet300: '#c4b5fd', + violet200: '#ddd6fe', + violet100: '#ede9fe', + violet50: '#f5f3ff', + // Legacy `indigo*` aliases — kept so existing slide code compiles unchanged + indigo700: '#6d28d9', + indigo600: '#7c3aed', + indigo500: '#8b5cf6', + indigo50: '#f5f3ff', + // Functional accents + emerald700: '#047857', + emerald600: '#059669', + emerald50: '#ecfdf5', + red700: '#b91c1c', + red600: '#dc2626', + red50: '#fef2f2', + amber700: '#b45309', + amber600: '#d97706', + amber50: '#fffbeb', + // Legacy aliases used by some callers + dark: '#1a0f34', + med: 'rgba(26,15,52,.88)', + light: 'rgba(26,15,52,.60)', + border: 'rgba(26,15,52,.14)', + indigo: '#7c3aed', + indigoLight: '#f5f3ff', +} + +const FONT = "'Inter', 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif" +const MONO_FONT = "'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace" + +/* ===== PAGE WRAPPER ===== */ + +interface PageProps { + kicker: string // "03" + section: string // "DAS PROBLEM" + title: string // "Deutsche Unternehmen wollen KI ..." + subtitle?: string + pageNum: number + totalPages: number + versionName: string + children: React.ReactNode + footnote?: React.ReactNode // optional footnote line above footer +} + +export function Page({ kicker, section, title, subtitle, pageNum, totalPages, versionName, children, footnote }: PageProps) { + return ( +
+
+ {/* TITLE BLOCK — left-rule preserved */} +
+
+
+
+ + {kicker} · {section} + + + BreakPilot · ComplAI +
+

+ {title} +

+ {subtitle && ( +

+ {subtitle} +

+ )} + {/* Subtle violet accent gradient bar — echo of the Claude Design feel */} +
+
+
+ + {/* CONTENT */} +
+ {children} +
+ + {/* FOOTNOTE (optional) */} + {footnote && ( +
+ {footnote} +
+ )} + + {/* FOOTER — JetBrains Mono caps to match Claude Design */} +
+ BreakPilot · ComplAI + {versionName} + {String(pageNum).padStart(2, '0')} / {String(totalPages).padStart(2, '0')} +
+
+
+ ) +} + +/* ===== KPI ROW ===== */ + +interface KpiItem { n: string; label: string; tone?: 'default' | 'positive' | 'negative' | 'accent' } + +export function KpiRow({ items, align = 'left' }: { items: KpiItem[]; align?: 'left' | 'center' }) { + return ( +
+ {items.map((it, i) => { + const color = it.tone === 'positive' ? COLORS.emerald700 + : it.tone === 'negative' ? COLORS.red700 + : it.tone === 'accent' ? COLORS.indigo600 + : COLORS.slate900 + return ( +
+
+ {it.n} +
+
+ {it.label} +
+
+ ) + })} +
+ ) +} + +/* ===== COLUMNS ===== */ + +export function TwoCol({ left, right, ratio = '1:1', gap = '8mm' }: { left: React.ReactNode; right: React.ReactNode; ratio?: '1:1' | '1:1.5' | '1.5:1' | '1:2' | '2:1'; gap?: string }) { + const [l, r] = ratio.split(':').map(Number) + return ( +
+
{left}
+
{right}
+
+ ) +} + +export function ThreeCol({ cols, gap = '6mm', equalHeight = true }: { cols: React.ReactNode[]; gap?: string; equalHeight?: boolean }) { + return ( +
+ {cols.map((c, i) =>
{c}
)} +
+ ) +} + +export function FourCol({ cols, gap = '4mm' }: { cols: React.ReactNode[]; gap?: string }) { + return ( +
+ {cols.map((c, i) =>
{c}
)} +
+ ) +} + +/* ===== PANEL (left-rule narrative card) ===== */ + +interface PanelProps { + label?: string + title?: string + tone?: 'neutral' | 'positive' | 'negative' | 'caution' | 'accent' + children: React.ReactNode + dense?: boolean +} + +export function Panel({ label, title, tone = 'neutral', children, dense }: PanelProps) { + const color = tone === 'positive' ? COLORS.emerald700 + : tone === 'negative' ? COLORS.red700 + : tone === 'caution' ? COLORS.amber700 + : tone === 'accent' ? COLORS.indigo600 + : COLORS.slate600 + return ( +
+ {label && ( +
+ {label} +
+ )} + {title && ( +
+ {title} +
+ )} +
+ {children} +
+
+ ) +} + +/* ===== BULLETS ===== */ + +interface BulletsProps { items: (string | React.ReactNode)[]; dense?: boolean; tone?: 'neutral' | 'positive' | 'negative' | 'accent' } + +export function Bullets({ items, dense, tone = 'neutral' }: BulletsProps) { + const dotColor = tone === 'positive' ? COLORS.emerald600 + : tone === 'negative' ? COLORS.red600 + : tone === 'accent' ? COLORS.indigo600 + : COLORS.slate500 + return ( +
    + {items.map((item, i) => ( +
  • + + {item} +
  • + ))} +
+ ) +} + +/* ===== DATA TABLE ===== */ + +interface TableCol { + header: string + width?: string + align?: 'left' | 'right' | 'center' + numeric?: boolean +} + +interface DataTableProps { + cols: TableCol[] + rows: (string | number | React.ReactNode)[][] + dense?: boolean + zebra?: boolean + highlightFirstCol?: boolean +} + +export function DataTable({ cols, rows, dense, zebra = true, highlightFirstCol }: DataTableProps) { + const fontSize = dense ? '7.5pt' : '8.5pt' + const padY = dense ? '1.5mm' : '2mm' + return ( + + + + {cols.map((c, i) => ( + + ))} + + + + {rows.map((row, ri) => ( + + {row.map((cell, ci) => ( + + ))} + + ))} + +
+ {c.header} +
+ {cell} +
+ ) +} + +/* ===== FEATURE MATRIX (●/○/—) ===== */ + +export type Glyph = true | false | 'partial' + +export function MatrixGlyph({ v, isUSP }: { v: Glyph; isUSP?: boolean }) { + if (v === true) return + if (v === 'partial') return + return +} + +/* ===== CALLOUT ===== */ + +interface CalloutProps { + tone?: 'neutral' | 'positive' | 'negative' | 'caution' | 'accent' + label?: string + children: React.ReactNode +} + +export function Callout({ tone = 'neutral', label, children }: CalloutProps) { + const color = tone === 'positive' ? COLORS.emerald700 + : tone === 'negative' ? COLORS.red700 + : tone === 'caution' ? COLORS.amber700 + : tone === 'accent' ? COLORS.indigo600 + : COLORS.slate600 + const bg = tone === 'positive' ? COLORS.emerald50 + : tone === 'negative' ? COLORS.red50 + : tone === 'caution' ? COLORS.amber50 + : tone === 'accent' ? COLORS.indigo50 + : COLORS.slate50 + return ( +
+ {label && ( +
{label}
+ )} +
{children}
+
+ ) +} + +/* ===== DIVIDER ===== */ + +export function Divider({ space = '4mm' }: { space?: string }) { + return
+} + +/* ===== STAT INLINE (label: value) ===== */ + +export function StatLine({ label, value, tone = 'neutral' }: { label: string; value: string; tone?: 'neutral' | 'positive' | 'negative' | 'accent' }) { + const color = tone === 'positive' ? COLORS.emerald700 + : tone === 'negative' ? COLORS.red700 + : tone === 'accent' ? COLORS.indigo600 + : COLORS.slate900 + return ( +
+ {label} + {value} +
+ ) +} + +/* ===== LEGACY EXPORTS (preserved for any callers not yet migrated) ===== */ interface PrintPageProps { title: string @@ -16,83 +387,26 @@ interface PrintPageProps { } export function PrintPage({ title, pageNum, totalPages, versionName, children }: PrintPageProps) { + // Legacy wrapper: maps to the new Page primitive without title/subtitle structure return ( -
-
- {/* Header bar */} -
- BreakPilot - {title} -
- - {/* Content area — must stretch to fill all remaining height */} -
- {children} -
- - {/* Footer bar */} -
- {versionName} - CONFIDENTIAL - {pageNum} / {totalPages} -
-
-
+ + {children} + ) } -interface SectionTitleProps { children: React.ReactNode; subtitle?: string } - -export function SectionTitle({ children, subtitle }: SectionTitleProps) { +export function SectionTitle({ children, subtitle }: { children: React.ReactNode; subtitle?: string }) { return ( -
-

- {children} -

- {subtitle && ( -

- {subtitle} -

- )} +
+

{children}

+ {subtitle &&

{subtitle}

}
) } @@ -104,50 +418,14 @@ interface TableProps { } export function PrintTable({ headers, rows, colWidths }: TableProps) { - return ( - - - - {headers.map((h, i) => ( - - ))} - - - - {rows.map((row, ri) => ( - - {row.map((cell, ci) => ( - - ))} - - ))} - -
- {h} -
- {cell} -
- ) + const cols = headers.map((h, i) => ({ header: h, width: colWidths?.[i] })) + return } -export function Badge({ children, color = INDIGO }: { children: React.ReactNode; color?: string }) { +export function Badge({ children, color = COLORS.indigo600 }: { children: React.ReactNode; color?: string }) { return ( - + {children} ) } - -export const COLORS = { indigo: INDIGO, indigoLight: INDIGO_LIGHT, dark: TEXT_DARK, med: TEXT_MED, light: TEXT_LIGHT, border: BORDER } diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx new file mode 100644 index 0000000..0c5782e --- /dev/null +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx @@ -0,0 +1,414 @@ +import { Language, PitchMarket, PitchTeamMember, PitchMilestone, PitchFunding } from '@/lib/types' +import { Page, Callout, COLORS, DataTable, StatLine } from './PrintLayout' +import { MarketFunnel, ComparisonBars, DonutChart } from './PrintCharts' + +interface SlideBase { lang: Language; pageNum: number; totalPages: number; versionName: string } + +function fmtEur(v: number, de: boolean) { + if (v >= 1e9) return de ? `${(v / 1e9).toFixed(1).replace('.', ',')} Mrd. €` : `€${(v / 1e9).toFixed(1)}B` + if (v >= 1e6) return de ? `${(v / 1e6).toFixed(0)} Mio. €` : `€${(v / 1e6).toFixed(0)}M` + if (v >= 1e3) return de ? `${(v / 1e3).toFixed(0)}k €` : `€${(v / 1e3).toFixed(0)}k` + return de ? `${v} €` : `€${v}` +} + +/* ===== MARKET ===== */ + +export function PrintMarketPage({ market, lang, pageNum, totalPages, versionName }: SlideBase & { market: PitchMarket[] }) { + const de = lang === 'de' + const tam = market.find(m => m.market_segment === 'TAM') + const sam = market.find(m => m.market_segment === 'SAM') + const som = market.find(m => m.market_segment === 'SOM') + + return ( + $1,1 Mrd. ARR. Kein Anbieter bedient den Maschinenbau spezifisch.' : 'Validated market: top-10 compliance vendors generate >$1.1B ARR. No vendor specifically serves manufacturing.'} pageNum={pageNum} totalPages={totalPages} versionName={versionName} footnote={de ? 'Sacra · Bitkom Cloud Monitor 2024 · DIHK 2024 · VDMA · Statista' : 'Sacra · Bitkom Cloud Monitor 2024 · DIHK 2024 · VDMA · Statista'}> + +
+
+
{de ? 'Marktdimensionierung' : 'Market sizing'}
+ {tam && sam && som && ( + fmtEur(v, de)} + /> + )} +
+ +
+
{de ? 'Kernsegment: Maschinen- und Anlagenbau DACH' : 'Core segment: Machine & plant manufacturing DACH'}
+ $1,1 Mrd.'], + ]} + dense + highlightFirstCol + /> + +
+ + {de + ? 'Höchste Regulierungsdichte (DSGVO + AI Act + CRA + Maschinen-VO + ProdSG + LkSG) bei gleichzeitig kleinem Compliance-Team. Klare Schmerzpunkte. Bekannte Vertriebskanäle (VDMA, IHK, Messen).' + : 'Highest regulation density (GDPR + AI Act + CRA + Machinery Reg. + ProdSG + LkSG) with simultaneously small compliance teams. Clear pain points. Known sales channels (VDMA, Chamber of Commerce, fairs).'} + +
+
+
+
+ ) +} + +/* ===== MILESTONES / TRACTION ===== */ + +const MS_DE = [ + { d: 'Okt 2025', t: 'Gründerzuschuss & IHK Konstanz', s: 'done' }, + { d: '11 Nov 2025', t: 'DPMA-Markenanmeldung BreakPilot', s: 'done' }, + { d: '21 Nov 2025', t: 'Domain-Portfolio (.com, .de, .ai + Typo)', s: 'done' }, + { d: 'Jan 2026', t: 'Plattform-Entwicklung gestartet (500K+ LoC)', s: 'done' }, + { d: '27 Mär 2026', t: 'DPMA-Markeneintragung BreakPilot', s: 'done' }, + { d: 'Apr 2026', t: 'RAG mit 375+ Dokumenten · 25k+ Controls', s: 'done' }, + { d: '01 Mai 2026', t: 'EUIPO-Markenanmeldung (EU-weit)', s: 'next' }, + { d: 'Aug 2026', t: 'GmbH-Gründung Breakpilot COMPLAI', s: 'planned' }, + { d: 'Aug 2026', t: '2 zahlende Pilotkunden, erste Umsätze', s: 'planned' }, + { d: 'Q3 2026', t: 'Public Beta-Launch', s: 'planned' }, +] +const MS_EN = [ + { d: 'Oct 2025', t: 'Founder grant & IHK Konstanz', s: 'done' }, + { d: '11 Nov 2025', t: 'DPMA trademark filing BreakPilot', s: 'done' }, + { d: '21 Nov 2025', t: 'Domain portfolio (.com, .de, .ai + typos)', s: 'done' }, + { d: 'Jan 2026', t: 'Platform development started (500K+ LoC)', s: 'done' }, + { d: '27 Mar 2026', t: 'DPMA trademark registration', s: 'done' }, + { d: 'Apr 2026', t: 'RAG with 375+ documents · 25k+ controls', s: 'done' }, + { d: '01 May 2026', t: 'EUIPO trademark filing (EU-wide)', s: 'next' }, + { d: 'Aug 2026', t: 'GmbH incorporation Breakpilot COMPLAI', s: 'planned' }, + { d: 'Aug 2026', t: '2 paying pilot customers, first revenue', s: 'planned' }, + { d: 'Q3 2026', t: 'Public beta launch', s: 'planned' }, +] + +export function PrintMilestonesPage({ milestones, lang, pageNum, totalPages, versionName }: SlideBase & { milestones: PitchMilestone[] }) { + void milestones // we use the curated list above + const de = lang === 'de' + const items = de ? MS_DE : MS_EN + const dotFor = (s: string) => s === 'done' ? COLORS.emerald600 : s === 'next' ? COLORS.amber600 : COLORS.slate400 + + return ( + + + {/* Top KPI strip */} +
+ {[ + { n: '500K+', l: de ? 'Lines of Code' : 'Lines of code' }, + { n: '25.000+', l: de ? 'Atomare Controls' : 'Atomic controls' }, + { n: '385', l: de ? 'Gesetze im RAG' : 'Laws in RAG' }, + { n: '12', l: de ? 'Compliance-Module' : 'Compliance modules' }, + { n: '2', l: de ? 'Pilotkunden (Aug 26)' : 'Pilot customers (Aug 26)' }, + ].map((k, i) => ( +
+
{k.n}
+
{k.l}
+
+ ))} +
+ +
+
+
{de ? 'Erreicht (Okt 2025 – Apr 2026)' : 'Achieved (Oct 2025 – Apr 2026)'}
+ {items.filter(i => i.s === 'done').map((m, i) => ( +
+
+
+
{m.d}
+
{m.t}
+
+
+ ))} +
+ +
+
{de ? 'Nächste 4 Monate' : 'Next 4 months'}
+ {items.filter(i => i.s !== 'done').map((m, i) => ( +
+
+
+
{m.d} · {m.s === 'next' ? (de ? 'Nächster Schritt' : 'Next step') : (de ? 'Geplant' : 'Planned')}
+
{m.t}
+
+
+ ))} +
+
+ + ) +} + +/* ===== TEAM ===== */ + +export function PrintTeamPage({ team, lang, pageNum, totalPages, versionName }: SlideBase & { team: PitchTeamMember[] }) { + const de = lang === 'de' + const members = team && team.length ? team : [ + { id: 1, name: 'Benjamin Bönisch', role_de: 'CEO & Co-Founder', role_en: 'CEO & Co-Founder', bio_de: 'Mehrfacher Gründer mit Fokus auf B2B-SaaS und Vertrieb. Ehemals Geschäftsführer und Vertriebsleiter. Tiefe Verankerung im Maschinenbau-Netzwerk DACH.', bio_en: 'Serial founder focused on B2B SaaS and sales. Former CEO and VP Sales. Deep network in DACH manufacturing.', equity_pct: 37.3, expertise: ['B2B Sales', 'Go-to-Market', 'Manufacturing', 'Operations'], linkedin_url: '', photo_url: '' }, + { id: 2, name: 'Sharang Parnerkar', role_de: 'CTO & Co-Founder', role_en: 'CTO & Co-Founder', bio_de: 'Ex-Anthropic, Ex-Google. Distributed systems, KI-Infrastruktur, RAG-Pipelines. Open-Source-Contributor. Hat die gesamte Plattform-Architektur entworfen und 500K+ LoC implementiert.', bio_en: 'Ex-Anthropic, ex-Google. Distributed systems, AI infrastructure, RAG pipelines. Open-source contributor. Designed the entire platform architecture and implemented 500K+ LoC.', equity_pct: 37.3, expertise: ['AI Infrastructure', 'Distributed Systems', 'RAG', 'Go/Python/TypeScript'], linkedin_url: '', photo_url: '' }, + ] + + return ( + + +
+ {[0, 1].map(idx => { + const m = members[idx] + if (!m) return null + return ( +
+
+ {/* Photo */} +
+ {m.photo_url ? ( + /* eslint-disable-next-line @next/next/no-img-element */ + {m.name} + ) : ( +
+ {m.name?.split(' ').map(s => s[0]).slice(0, 2).join('') || '?'} +
+ )} +
+ {/* Header text */} +
+
+ CO-FOUNDER · {String(idx + 1).padStart(2, '0')} / 02 + {(m.equity_pct ?? 37.3).toLocaleString('de-DE')}% Equity +
+
{m.name}
+
{de ? m.role_de : m.role_en}
+
+
+
{de ? m.bio_de : m.bio_en}
+
+
{de ? 'Expertise' : 'Expertise'}
+
+ {(m.expertise || []).map((e, i) => ( + {e} + ))} +
+
+
+ ) + })} +
+ +
+ + {de + ? 'Gründer 74,6% · Pre-Seed-Investor 20% · ESOP-Pool 5,4%. Beide Gründer mit Vesting (4 Jahre, 1 Jahr Cliff). Keine Side-Projekte, keine externen Verpflichtungen.' + : 'Founders 74.6% · Pre-Seed Investor 20% · ESOP pool 5.4%. Both founders with vesting (4 years, 1 year cliff). No side projects, no external commitments.'} + +
+
+ ) +} + +/* ===== THE ASK ===== */ + +function formatTargetDate(raw: string | undefined, de: boolean): string { + if (!raw) return de ? 'Q3 2026' : 'Q3 2026' + // Accept ISO timestamps, ISO dates, or already-formatted strings. + const d = new Date(raw) + if (isNaN(d.getTime())) return raw + const months = de + ? ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'] + : ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] + return `${months[d.getUTCMonth()]} ${d.getUTCFullYear()}` +} + +function formatFunding(amount: number): string { + if (amount >= 1_000_000) { + const m = amount / 1_000_000 + return '€' + (m % 1 === 0 ? m.toFixed(0) : m.toFixed(1)) + 'M' + } + return '€' + Math.round(amount / 1_000) + 'k' +} + +export function PrintTheAskPage({ funding, lang, pageNum, totalPages, versionName }: SlideBase & { funding: PitchFunding }) { + const de = lang === 'de' + const amount = funding?.amount_eur || 1_000_000 + const instrument = funding?.instrument || (de ? 'Wandeldarlehen' : 'Convertible Loan') + const isConvertible = (instrument || '').toLowerCase().includes('wandeldarlehen') || + (instrument || '').toLowerCase().includes('convertible') || + (instrument || '').toLowerCase().includes('safe') + // For equity rounds we display Pre/Post/Investor-Share computed from a 20% + // assumed investor share. For convertibles those fields don't apply — show + // typical convertible terms instead (Discount, Maturity, Interest). + const equityShare = 0.20 + const postMoney = amount / equityShare + const preMoney = postMoney - amount + const fmtBig = (n: number) => n >= 1_000_000 + ? '€' + (n / 1_000_000).toFixed(n % 1_000_000 === 0 ? 0 : 1) + 'M' + : '€' + Math.round(n / 1_000) + 'k' + const termTiles: [string, string][] = isConvertible + ? [ + [de ? 'Funding' : 'Funding', formatFunding(amount)], + [de ? 'Discount' : 'Discount', '20%'], + [de ? 'Laufzeit' : 'Maturity', de ? '24 Monate' : '24 months'], + [de ? 'INVEST-Zuschuss' : 'INVEST grant', '20%'], + ] + : [ + [de ? 'Funding' : 'Funding', formatFunding(amount)], + [de ? 'Pre-Money' : 'Pre-money', fmtBig(preMoney)], + [de ? 'Post-Money' : 'Post-money', fmtBig(postMoney)], + [de ? 'Investor-Anteil' : 'Investor share', Math.round(equityShare * 100) + '%'], + ] + const useOfFunds = funding?.use_of_funds || [ + { category: 'engineering', percentage: 45, label_de: 'Engineering & Produkt', label_en: 'Engineering & Product' }, + { category: 'sales', percentage: 30, label_de: 'Vertrieb & Marketing', label_en: 'Sales & Marketing' }, + { category: 'hardware', percentage: 10, label_de: 'Infrastruktur & Hardware', label_en: 'Infrastructure & Hardware' }, + { category: 'legal', percentage: 10, label_de: 'Legal & Compliance', label_en: 'Legal & Compliance' }, + { category: 'reserve', percentage: 5, label_de: 'Reserve', label_en: 'Reserve' }, + ] + + return ( + + +
+ {/* Hero amount */} +
+
+
{de ? 'Funding' : 'Funding'}
+
+ {formatFunding(amount)} +
+
{instrument} · {funding?.round_name || 'Pre-Seed'} · {de ? 'Zielabschluss' : 'Target close'}: {formatTargetDate(funding?.target_date, de)}
+
+ +
+ {termTiles.map(([label, val], i) => ( +
+
{label}
+
{val}
+
+ ))} +
+ +
+ + {de + ? '18 Monate Runway · GmbH-Gründung · Engineering-Team auf 5 erweitert · 50–100 Kunden onboarded · ARR €1,5–2,5M in 18 Monaten · Vorbereitung Series A.' + : '18-month runway · GmbH incorporated · engineering team scaled to 5 · 50–100 customers onboarded · ARR €1.5–2.5M in 18 months · Series A readiness.'} + +
+
+ + {/* Use of funds */} +
+
{de ? 'Use of Funds' : 'Use of funds'}
+ {(() => { + const palette = [COLORS.indigo600, COLORS.indigo500, COLORS.amber600, COLORS.slate600, COLORS.slate400] + return ( +
+
+ ({ label: de ? u.label_de : u.label_en, pct: u.percentage, color: palette[i % palette.length] }))} + /> +
+
+ {useOfFunds.map((u, i) => ( +
+
+
{de ? u.label_de : u.label_en}
+
{u.percentage}%
+
€{(amount * u.percentage / 100 / 1000).toFixed(0)}k
+
+ ))} +
+
+ ) + })()} +
+
+ + ) +} + +/* ===== CUSTOMER SAVINGS ===== */ + +export function PrintCustomerSavingsPage({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + const items = [ + { l: de ? 'Pentests' : 'Pentests', today: 15000, bp: 13000 }, + { l: de ? 'CE-SW-Risiko' : 'CE software risk', today: 12000, bp: 9000 }, + { l: de ? 'Compliance-Zeit' : 'Compliance time', today: 18000, bp: 15000 }, + { l: de ? 'Audit-Vorber.' : 'Audit prep', today: 9000, bp: 9000 }, + { l: de ? 'Legal (DSGVO/AI Act)' : 'Legal (GDPR/AI Act)', today: 8000, bp: 5000 }, + { l: de ? 'Auditmanager-Software' : 'Audit manager SW', today: 5000, bp: 0 }, + { l: de ? 'Schulungen extern' : 'External training', today: 4000, bp: 4000 }, + ] + const totalToday = items.reduce((s, i) => s + i.today, 0) + const totalSaved = items.reduce((s, i) => s + i.bp, 0) + const totalBpCost = 25000 + + return ( + + + {/* Big stat header */} +
+ {[ + { l: de ? 'Heute (ohne BP)' : 'Today (without BP)', v: '€' + (totalToday / 1000).toFixed(0) + 'k', tone: COLORS.red700 }, + { l: de ? 'BreakPilot Pro / Jahr' : 'BreakPilot Pro / year', v: '€' + (totalBpCost / 1000).toFixed(0) + 'k', tone: COLORS.indigo600 }, + { l: de ? 'Ersparnis / KMU' : 'Savings / SME', v: '€' + (totalSaved / 1000).toFixed(0) + 'k', tone: COLORS.emerald700 }, + { l: de ? 'Netto-Effekt' : 'Net effect', v: '+€' + ((totalSaved - totalBpCost) / 1000).toFixed(0) + 'k', tone: COLORS.emerald700 }, + ].map((k, i) => ( +
+
{k.v}
+
{k.l}
+
+ ))} +
+ + {/* Bar comparison */} +
+
+
{de ? 'Heute vs. mit BreakPilot (€/Jahr/KMU)' : 'Today vs. with BreakPilot (€/yr/SME)'}
+ ({ + label: it.l, + bars: [ + { tone: 'negative', value: it.today, cap: de ? 'Heute' : 'Today' }, + { tone: 'positive', value: it.bp, cap: de ? 'gespart mit BP' : 'saved with BP' }, + ], + }))} + formatValue={(n) => '€' + (n / 1000).toFixed(0) + 'k'} + /> +
+ +
+
{de ? 'Ersparnis-Aufschlüsselung' : 'Savings breakdown'}
+
+ + + + + + +
+ +
+ + {de + ? 'Zeit der GF + Compliance-Beauftragten (~30 Tage/Jahr), DSGVO-Bußgelder (bis 4% Jahresumsatz), verlorene RFQs durch fehlende Compliance-Nachweise. Nicht in obigen Zahlen enthalten.' + : 'Time of management + compliance officer (~30 days/year), GDPR fines (up to 4% annual revenue), lost RFQs from missing compliance evidence. Not included in numbers above.'} + +
+
+
+
+ ) +} diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintNewSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintNewSlides.tsx new file mode 100644 index 0000000..ac5a3d7 --- /dev/null +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintNewSlides.tsx @@ -0,0 +1,302 @@ +import { Language, FMResult } from '@/lib/types' +import { Page, COLORS, Bullets } from './PrintLayout' +import { + ScanLine, Shield, Database, Brain, ShieldCheck, Lock, MessageSquare, Wrench, + Layers, Sparkles, TrendingUp, Globe, + type LucideIcon, +} from 'lucide-react' +import { getDetails } from '@/components/slides/USPSlide.data' +import { computeAnnualKPIs } from '@/lib/finanzplan/annual-kpis' + +interface SlideBase { lang: Language; pageNum: number; totalPages: number; versionName: string } + +const MONO = "'JetBrains Mono', ui-monospace, monospace" + +/* ====================================================================== */ +/* TL;DR — 02 · 30 Sekunden (4 quad cards) */ +/* ====================================================================== */ + +export function PrintTLDRPage({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + + const cards = de ? [ + { kicker: '01 · Scale', title: '25.000+ Controls', body: 'Atomare Prüfaspekte über DSGVO, AI Act, NIS-2, CRA, MaschVO und 380+ weitere Quellen.', ticker: 'idx 26.123 atomic checks', tint: COLORS.violet600 }, + { kicker: '02 · Sovereignty', title: '100 % EU-souverän', body: 'BSI-C5-zertifizierte Cloud in Deutschland und Frankreich. Keine US-Anbieter. Air-gap-fähig.', ticker: 'region BSI C5 · DE/FR', tint: COLORS.violet500 }, + { kicker: '03 · Bidirectional', title: 'Compliance ↔ Code', body: 'Policy-Änderungen fliessen in den Code; Code-Änderungen aktualisieren Policies. Zero Drift.', ticker: 'sync policy.md → controller.ts', tint: COLORS.amber600 }, + { kicker: '04 · Speed', title: '<20 Tage audit-ready', body: 'Vom Vertrag zum auditfähigen Status: typischerweise 14–20 Tage. White-Glove-Onboarding.', ticker: 'tag 17 bis audit-ready', tint: COLORS.amber700 }, + ] : [ + { kicker: '01 · Scale', title: '25,000+ Controls', body: 'Atomic audit aspects across GDPR, AI Act, NIS-2, CRA, Machinery Reg. and 380+ other sources.', ticker: 'idx 26,123 atomic checks', tint: COLORS.violet600 }, + { kicker: '02 · Sovereignty', title: '100 % EU-sovereign', body: 'BSI-C5 certified cloud in Germany and France. No US vendors. Air-gap capable.', ticker: 'region BSI C5 · DE/FR', tint: COLORS.violet500 }, + { kicker: '03 · Bidirectional', title: 'Compliance ↔ Code', body: 'Policy edits flow into code; code changes update policies. Zero drift.', ticker: 'sync policy.md → controller.ts', tint: COLORS.amber600 }, + { kicker: '04 · Speed', title: '<20 days audit-ready', body: 'From contract to audit-ready: typically 14–20 days. White-glove onboarding.', ticker: 'day 17 to audit-ready', tint: COLORS.amber700 }, + ] + + return ( + + +
+ {cards.map((c, i) => ( +
+
{c.kicker}
+
{c.title}
+
{c.body}
+
+ + {c.ticker} +
+
+ ))} +
+
+ ) +} + +/* ====================================================================== */ +/* DIFFERENTIATORS — 4 under-the-hood cards (moved out of USP p2) */ +/* ====================================================================== */ + +const DIFF_ICON: Record = { + trace: Layers, + engine: Sparkles, + opt: TrendingUp, + stack: Globe, +} + +export function PrintDifferentiatorsPage({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + const d = getDetails(de) + const cards = ['trace', 'engine', 'opt', 'stack'] as const + const tickers = de + ? ['trace 13.605 evidence-chain', 'validate 1.450 · 98,9 %', 'optimize gap → policy §4.2', 'check BSI C5 · 1.382'] + : ['trace 13,605 evidence-chain', 'validate 1,450 · 98.9 %', 'optimize gap → policy §4.2', 'check BSI C5 · 1,382'] + + return ( + + +
+ {cards.map((k, i) => { + const p = d[k] + const Icon = DIFF_ICON[k] + const tint = i < 2 ? COLORS.violet600 : COLORS.amber600 + const tintDark = i < 2 ? COLORS.violet700 : COLORS.amber700 + const tintLight = i < 2 ? COLORS.violet50 : COLORS.amber50 + return ( +
+
+ {Icon && } +
+
{String(i + 1).padStart(2, '0')} · {p.kicker.replace(/^Säule[\s·]+|^Under the Hood|^Pillar[\s·]+/i, '').trim() || p.kicker}
+
{p.title}
+
{p.body}
+ {p.bullets && } +
+ + {tickers[i]} +
+
+ ) + })} +
+
+ ) +} + +/* ====================================================================== */ +/* KPI HERO — 8 trajectory tiles 2026 → 2030 */ +/* ====================================================================== */ + +function fmtEur(n: number): string { + const abs = Math.abs(n) + const sign = n < 0 ? '−' : '' + if (abs >= 1e6) return `${sign}€${(abs / 1e6).toLocaleString('de-DE', { maximumFractionDigits: 1 })}M` + if (abs >= 1e3) return `${sign}€${Math.round(abs / 1e3)}k` + return `${sign}€${Math.round(abs)}` +} + +export function PrintKPIHeroPage({ fmResults, lang, pageNum, totalPages, versionName }: SlideBase & { fmResults: FMResult[] }) { + const de = lang === 'de' + const kpis = computeAnnualKPIs(fmResults) + const k26 = kpis.find(k => k.year === 2026) + const k30 = kpis.find(k => k.year === 2030) + const breakEvenYear = kpis.find(k => k.ebit > 0)?.year + + const tiles = k26 && k30 ? [ + { label: 'ARR', start: fmtEur(k26.arr), end: fmtEur(k30.arr), endColor: COLORS.violet600 }, + { label: de ? 'Kunden' : 'Customers', start: k26.customers.toLocaleString('de-DE'), end: k30.customers.toLocaleString('de-DE'), endColor: COLORS.violet600 }, + { label: de ? 'ARPU / Mo' : 'ARPU / mo', start: fmtEur(k26.arpu), end: fmtEur(k30.arpu), endColor: COLORS.slate900 }, + { label: de ? 'Mitarbeiter' : 'Employees', start: String(k26.employees), end: String(k30.employees), endColor: COLORS.slate900 }, + { label: de ? 'Bruttomarge' : 'Gross margin', start: `${k26.grossMargin}%`, end: `${k30.grossMargin}%`, endColor: COLORS.emerald700 }, + { label: 'EBIT', start: fmtEur(k26.ebit), end: fmtEur(k30.ebit), endColor: k30.ebit >= 0 ? COLORS.emerald700 : COLORS.red700 }, + { label: de ? 'Netto-Ergebnis' : 'Net income', start: fmtEur(k26.netIncome), end: fmtEur(k30.netIncome), endColor: k30.netIncome >= 0 ? COLORS.emerald700 : COLORS.red700 }, + { label: de ? 'Cash (Dez)' : 'Cash (Dec)', start: fmtEur(k26.cashBalance), end: fmtEur(k30.cashBalance), endColor: COLORS.emerald700 }, + ] : [] + + return ( + + + {tiles.length === 0 ? ( +

{de ? 'Keine Finanzdaten verfügbar.' : 'No financial data available.'}

+ ) : ( +
+ {tiles.map((t, i) => ( +
+
{t.label}
+
+ {t.start} + + {t.end} +
+
2026 · 2030
+
+ ))} +
+ )} +
+ ) +} + +/* ====================================================================== */ +/* TECH STACK — 8-category grid */ +/* ====================================================================== */ + +export function PrintTechStackPage({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + + const cats = de ? [ + { name: 'Frontend', icon: ScanLine, items: ['Next.js 15', 'React 19', 'Tailwind CSS', 'Framer Motion', 'Dioxus (Rust)'] }, + { name: 'Backend', icon: Wrench, items: ['Go/Gin', 'Python/FastAPI', 'Rust/Axum', 'OpenAPI'] }, + { name: 'Storage', icon: Database, items: ['PostgreSQL 16', 'MongoDB', 'Qdrant Vector DB', 'Valkey (cache)'] }, + { name: 'KI / RAG', icon: Brain, items: ['LiteLLM', 'Qwen3-32B', 'DeepSeek-R1', 'Sentence-Transformers', 'LangGraph'] }, + { name: 'Code-Scanning', icon: Shield, items: ['Semgrep', 'Gitleaks', 'Syft', 'Trivy', 'CycloneDX'] }, + { name: 'Auth & SSO', icon: Lock, items: ['Keycloak', 'OIDC', 'OPA (policies)'] }, + { name: 'Kommunikation', icon: MessageSquare, items: ['Matrix (chat)', 'Jitsi (video)', 'Mailpit'] }, + { name: 'DevOps', icon: ShieldCheck, items: ['Gitea', 'Woodpecker CI', 'HashiCorp Vault', 'Orca', 'Docker Compose'] }, + ] : [ + { name: 'Frontend', icon: ScanLine, items: ['Next.js 15', 'React 19', 'Tailwind CSS', 'Framer Motion', 'Dioxus (Rust)'] }, + { name: 'Backend', icon: Wrench, items: ['Go/Gin', 'Python/FastAPI', 'Rust/Axum', 'OpenAPI'] }, + { name: 'Storage', icon: Database, items: ['PostgreSQL 16', 'MongoDB', 'Qdrant vector DB', 'Valkey (cache)'] }, + { name: 'AI / RAG', icon: Brain, items: ['LiteLLM', 'Qwen3-32B', 'DeepSeek-R1', 'Sentence-Transformers', 'LangGraph'] }, + { name: 'Code scanning', icon: Shield, items: ['Semgrep', 'Gitleaks', 'Syft', 'Trivy', 'CycloneDX'] }, + { name: 'Auth & SSO', icon: Lock, items: ['Keycloak', 'OIDC', 'OPA (policies)'] }, + { name: 'Communication', icon: MessageSquare, items: ['Matrix (chat)', 'Jitsi (video)', 'Mailpit'] }, + { name: 'DevOps', icon: ShieldCheck, items: ['Gitea', 'Woodpecker CI', 'HashiCorp Vault', 'Orca', 'Docker Compose'] }, + ] + + return ( + + +
+ {cats.map((c, i) => { + const Icon = c.icon + return ( +
+
+
+ +
+
{c.name}
+
+
+ {c.items.map((it, j) => ( +
0 ? `1px solid ${COLORS.slate100}` : 'none', lineHeight: 1.3 }}>{it}
+ ))} +
+
+ ) + })} +
+
+ ) +} + +/* ====================================================================== */ +/* ANHANG DIVIDER (moved from PrintAnnexSlides.tsx) */ +/* ====================================================================== */ + +export function PrintAnnexDividerPage({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + + const sections: [string, string, string][] = de ? [ + ['18', 'Go-to-Market Strategie', 'Pilot · Skalierung · Expansion'], + ['19', 'Kennzahlen 2026 → 2030', '8 KPIs Trajektorie · Base-Case'], + ['20', 'Finanzplan', 'P&L 2026–2030 · KPI-Dashboard'], + ['21', 'P&L Detail', 'Annualisierte Gewinn-/Verlust-Rechnung'], + ['22', 'Treibervariablen', 'Annahmen + Sensitivitätsszenarien'], + ['23', 'Regulatorische Details', 'DSGVO · AI Act · NIS-2 · CRA · MaschVO'], + ['24', 'Systemarchitektur', '3 Tiers · LiteLLM Gateway · lokale Inferenz'], + ['25', 'Engineering Deep Dive', '500K+ LoC · 45 Container · 100 % Self-Hosted'], + ['26', 'Tech-Stack', '8 Kategorien · polyglott · Open Source'], + ['27', 'KI-Pipeline', 'RAG · Multi-Agent · Document Intelligence · QA'], + ['28', 'Risiken & Mitigation', '10 Risiken in 5 Kategorien'], + ['29', 'Glossar', '30 Begriffe · Compliance · Engineering · Recht'], + ] : [ + ['18', 'Go-to-Market Strategy', 'Pilot · Scale · Expansion'], + ['19', 'KPIs 2026 → 2030', '8 KPI trajectory · base case'], + ['20', 'Financial Plan', 'P&L 2026–2030 · KPI dashboard'], + ['21', 'P&L Detail', 'Annualized profit & loss'], + ['22', 'Driver Variables', 'Assumptions + sensitivity scenarios'], + ['23', 'Regulatory Details', 'GDPR · AI Act · NIS-2 · CRA · Machinery Reg.'], + ['24', 'System Architecture', '3 tiers · LiteLLM gateway · local inference'], + ['25', 'Engineering Deep Dive', '500K+ LoC · 45 containers · 100 % self-hosted'], + ['26', 'Tech Stack', '8 categories · polyglot · open source'], + ['27', 'AI Pipeline', 'RAG · multi-agent · document intelligence · QA'], + ['28', 'Risks & Mitigation', '10 risks across 5 categories'], + ['29', 'Glossary', '30 terms · compliance · engineering · law'], + ] + + return ( +
+
+
+ {de ? 'Teil II · Anhang' : 'Part II · Appendix'} + BreakPilot · ComplAI +
+ +
+
+ {de ? '17 · Kapitelwechsel' : '17 · Chapter break'} +
+

+ {de ? 'Anhang' : 'Appendix'}. +

+
+

+ {de + ? 'Detailangaben & Belege. Was wir in der Pitch gesagt haben, mit Quellen, Zahlen und Architektur belegt.' + : 'Detail & evidence. Everything we claimed in the pitch, backed by sources, numbers and architecture.'} +

+ +
+
+ {de ? 'Auf den folgenden Seiten' : 'On the following pages'} +
+
+ {sections.map(([n, t, sub]) => ( +
+ {n} +
+
{t}
+
{sub}
+
+
+ ))} +
+
+
+ +
+ BreakPilot · ComplAI + {versionName} + {String(pageNum).padStart(2, '0')} / {String(totalPages).padStart(2, '0')} +
+
+
+ ) +} diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx new file mode 100644 index 0000000..eb1d094 --- /dev/null +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx @@ -0,0 +1,465 @@ +import { Language, PitchProduct } from '@/lib/types' +import { Page, Bullets, Callout, COLORS, DataTable } from './PrintLayout' +import { LoopDiagram } from './PrintDiagrams' +import { getDetails } from '@/components/slides/USPSlide.data' +import { + ScanLine, ShieldCheck, FileText, ClipboardCheck, Users, UserCheck, + AlertTriangle, Brain, Target, GraduationCap, TrendingUp, MessageSquare, + Shield, Layers, Globe, FileSearch, Sparkles, Repeat, ArrowLeftRight, Infinity, + type LucideIcon, +} from 'lucide-react' + +interface SlideBase { lang: Language; pageNum: number; totalPages: number; versionName: string } + +const USP_ICON: Record = { + rfq: FileSearch, process: ClipboardCheck, bidir: ArrowLeftRight, cont: Repeat, + trace: Layers, engine: Sparkles, opt: TrendingUp, stack: Globe, hub: Infinity, +} + +/* ===== USP, PAGE 1 (4 pillars) ===== */ + +export function PrintUSPPage1({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + const d = getDetails(de) + const pillars = ['rfq', 'process', 'bidir', 'cont'] as const + + return ( + + +
+ {pillars.map((k, i) => { + const p = d[k] + const Icon = USP_ICON[k] + return ( +
+ {/* Header: icon + title inline, kicker top-right */} +
+
+ {Icon && } +
+
+
+ {p.kicker} + {String(i + 1).padStart(2, '0')} / 04 +
+
{p.title}
+
+
+
{p.body}
+ {p.bullets && } + {p.stat && ( +
+ {p.stat.k} + {p.stat.v} +
+ )} +
+ ) + })} +
+
+ ) +} + +/* ===== USP, PAGE 2 — just the closing loop (was: 4 cards + loop) ===== + * + * The 4 under-the-hood cards moved to the dedicated Differentiators slide + * (PrintDifferentiatorsPage). This page is now a hero "Compliance ↔ Code + * always in sync" closing card for the USP block. + */ + +export function PrintUSPPage2({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + const d = getDetails(de) + const MONO = "'JetBrains Mono', ui-monospace, monospace" + + return ( + + + {/* Full-page hero loop diagram */} +
+
+
+
+ +
+ {de ? 'Die Schleife · Always in Sync' : 'The Loop · Always in Sync'} +
+
{d.hub.title}
+
{d.hub.body}
+ +
+ +
+ + {d.hub.bullets && ( +
+ +
+ )} +
+
+
+ ) +} + +/* ===== REGULATORY LANDSCAPE ===== */ + +const RL_CATEGORIES_DE = [ + { name: 'Datenschutz', sample: 'DSGVO · ePrivacy · TTDSG · BDSG', count: 32 }, + { name: 'Cybersicherheit', sample: 'NIS2 · IT-SiG · BSIG · KRITIS-Verordnung', count: 47 }, + { name: 'KI-Regulierung', sample: 'AI Act · KI-Haftungsrichtlinie', count: 18 }, + { name: 'Digitale Märkte', sample: 'DMA · DSA · Data Act · Data Governance Act', count: 24 }, + { name: 'Produktsicherheit', sample: 'CRA · Maschinenverordnung · Produktsicherheitsgesetz', count: 41 }, + { name: 'Finanzregulierung', sample: 'DORA · MiCA · FinmadiG · KWG', count: 53 }, + { name: 'Gesundheitsdaten', sample: 'MDR · IVDR · PatDG · Krankenhausgesetz', count: 28 }, + { name: 'Verbraucherschutz', sample: 'UWG · BGB · Geschäftsgeheimnisschutz · HinSchG', count: 36 }, +] +const RL_CATEGORIES_EN = [ + { name: 'Data Privacy', sample: 'GDPR · ePrivacy · TTDSG · BDSG', count: 32 }, + { name: 'Cybersecurity', sample: 'NIS2 · IT-SecAct · BSIG · KRITIS', count: 47 }, + { name: 'AI Regulation', sample: 'AI Act · AI Liability Directive', count: 18 }, + { name: 'Digital Markets', sample: 'DMA · DSA · Data Act · DGA', count: 24 }, + { name: 'Product Safety', sample: 'CRA · Machinery Reg. · ProdSG', count: 41 }, + { name: 'Financial Reg.', sample: 'DORA · MiCA · FinmadiG · KWG', count: 53 }, + { name: 'Health Data', sample: 'MDR · IVDR · PatDG · Hospital Act', count: 28 }, + { name: 'Consumer Prot.', sample: 'UWG · BGB · Trade Secrets · HinSchG', count: 36 }, +] +const INDUSTRIES_DE = ['Alle Unternehmen', 'Maschinenbau', 'Gesundheit', 'Finanzsektor', 'E-Commerce', 'Technologie', 'IoT / Hardware', 'KI-Anbieter', 'Krit. Infrastruktur', 'Medien', 'Öffentl. Sektor'] +const INDUSTRIES_EN = ['All companies', 'Manufacturing', 'Healthcare', 'Finance', 'E-Commerce', 'Technology', 'IoT / Hardware', 'AI Providers', 'Critical Infra.', 'Media', 'Public Sector'] + +export function PrintRegulatoryLandscapePage({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + const cats = de ? RL_CATEGORIES_DE : RL_CATEGORIES_EN + const industries = de ? INDUSTRIES_DE : INDUSTRIES_EN + + return ( + + + {/* KPI strip */} +
+ {[ + { n: '380+', l: de ? 'Originaldokumente' : 'Original documents' }, + { n: '25.000+', l: de ? 'Extrahierte Controls' : 'Extracted controls' }, + { n: '8', l: de ? 'Regulierungs-Kategorien' : 'Regulatory categories' }, + { n: '10', l: de ? 'Branchen-Profile' : 'Industry profiles' }, + ].map((k, i) => ( +
+
{k.n}
+
{k.l}
+
+ ))} +
+ +
+ {/* Categories */} +
+
{de ? 'Acht Regulierungs-Kategorien' : 'Eight regulatory categories'}
+ [c.name, c.sample, c.count])} + dense + highlightFirstCol + /> +
+ + {/* Industries */} +
+
{de ? 'Zehn Branchen-Profile' : 'Ten industry profiles'}
+
+ {industries.map((ind, i) => ( +
+ {i === 1 && {de ? 'Kernfokus' : 'Core focus'}} + {ind} +
+ ))} +
+
+
+ +
+ + {de + ? 'Ein RAG-Index für alle EU- und DACH-Regulierungen, semantisch durchsuchbar, kontinuierlich aktualisiert. Kunden fragen einmal, die Plattform antwortet aus allen Gesetzen gleichzeitig.' + : 'One RAG index for all EU and DACH regulations, semantically searchable, continuously updated. Customers ask once, the platform answers from all laws simultaneously.'} + +
+
+ ) +} + +/* ===== PRODUCT / MODULAR TOOLKIT ===== */ + +const MODULE_ICONS: LucideIcon[] = [ + ScanLine, ShieldCheck, FileText, ClipboardCheck, Users, UserCheck, + AlertTriangle, Brain, Target, GraduationCap, TrendingUp, MessageSquare, +] +const MODULES_FULL_DE = [ + { name: 'Code Security', desc: 'SAST · DAST · SBOM · Container · Secrets · Pentesting', features: ['Bei jedem Push', 'Auto-Fix LLM', 'CI/CD-integriert'] }, + { name: 'CE-SW-Risikobeurteilung', desc: 'CE-Kennzeichnung für Maschinen mit Software-Anteil', features: ['Maschinen-VO', 'CRA-konform', 'Code-Basis-Analyse'] }, + { name: 'Compliance-Dokumente', desc: 'VVT (Art. 30) · TOMs · DSFA (Art. 35) · Löschkonzept', features: ['Auto-Generiert', 'Versionsverlauf', 'Audit-tauglich'] }, + { name: 'Audit Manager', desc: 'Abweichungen End-to-End: Rollen · Stichtage · Eskalation', features: ['Tickets + Nachweise', 'GF-Eskalation', 'Compliance-SLA'] }, + { name: 'DSR / Betroffenenrechte', desc: 'Auskunft, Berichtigung, Löschung, Datenübertragbarkeit', features: ['Self-Service', 'Identitätsprüfung', 'Frist-Tracking'] }, + { name: 'Consent', desc: 'Einwilligungs-Management, Cookie-Banner, ePrivacy', features: ['CMP integriert', 'Audit-Log', 'Multi-Tenant'] }, + { name: 'Incident Response', desc: 'Vorfälle, Meldung (72h), Mitigation, Forensik', features: ['Art. 33/34 DSGVO', 'BSI-Meldepfade', 'Forensik-Hooks'] }, + { name: 'Compliance LLM', desc: 'GPT für Text + Audio, EU-gehostet, mit Quellenangabe', features: ['Self-Hosted', 'EU-souverän', 'Audit-zitierbar'] }, + { name: 'Tender Matching', desc: 'RFQ-Antworten automatisch gegen Codebase + Policies', features: ['Stunden statt Wochen', 'Win-ready', 'Klausel-Mapping'] }, + { name: 'Academy', desc: 'Online-Schulungen für Geschäftsführung und Mitarbeiter', features: ['Mandatory Training', 'Zertifikate', 'GF-Pflicht erfüllt'] }, + { name: 'Compliance Optimizer', desc: 'Maximale KI-Nutzung im legalen Rahmen, ersetzt 20-200k € Anwaltskosten', features: ['ROI-ranking', 'Sweet-Spot', 'Risikobalance'] }, + { name: 'Kommunikation', desc: 'Chat (Matrix) + Video (Jitsi) + KI-Support', features: ['Self-Hosted', 'EU-Hosting', 'Audit-Logs'] }, +] +const MODULES_FULL_EN = [ + { name: 'Code Security', desc: 'SAST · DAST · SBOM · Container · Secrets · Pentesting', features: ['Every push', 'Auto-fix LLM', 'CI/CD integrated'] }, + { name: 'CE SW Risk Assessment', desc: 'CE marking for machinery with software', features: ['Machinery Reg.', 'CRA-compliant', 'Code-level analysis'] }, + { name: 'Compliance Documents', desc: 'RoPA (Art. 30) · TOMs · DPIA (Art. 35) · Retention', features: ['Auto-generated', 'Version history', 'Audit-ready'] }, + { name: 'Audit Manager', desc: 'Deviations end-to-end: roles · deadlines · escalation', features: ['Tickets + evidence', 'Mgmt escalation', 'Compliance SLA'] }, + { name: 'DSR / Data Subject Rights', desc: 'Access, rectification, erasure, portability', features: ['Self-service', 'Identity check', 'Deadline tracking'] }, + { name: 'Consent', desc: 'Consent mgmt, cookie banner, ePrivacy', features: ['CMP integrated', 'Audit log', 'Multi-tenant'] }, + { name: 'Incident Response', desc: 'Breaches, reporting (72h), mitigation, forensics', features: ['GDPR Art. 33/34', 'BSI channels', 'Forensic hooks'] }, + { name: 'Compliance LLM', desc: 'GPT for text + audio, EU-hosted, with citations', features: ['Self-hosted', 'EU-sovereign', 'Audit-citable'] }, + { name: 'Tender Matching', desc: 'RFQ answers automatically against codebase + policies', features: ['Hours not weeks', 'Win-ready', 'Clause mapping'] }, + { name: 'Academy', desc: 'Online training for management and staff', features: ['Mandatory training', 'Certificates', 'Mgmt duties fulfilled'] }, + { name: 'Compliance Optimizer', desc: 'Max AI use within legal limits, replaces €20-200k legal fees', features: ['ROI ranking', 'Sweet spot', 'Risk balance'] }, + { name: 'Communication', desc: 'Chat (Matrix) + video (Jitsi) + AI support', features: ['Self-hosted', 'EU hosting', 'Audit logs'] }, +] + +export function PrintProductPage({ products, lang, pageNum, totalPages, versionName }: SlideBase & { products: PitchProduct[] }) { + void products + const de = lang === 'de' + const modules = de ? MODULES_FULL_DE : MODULES_FULL_EN + return ( + + +
+ {modules.map((m, i) => { + const Icon = MODULE_ICONS[i] + return ( +
+
+
+ +
+
{m.name}
+
{String(i + 1).padStart(2, '0')}
+
+
{m.desc}
+
{m.features.join(' · ')}
+
+ ) + })} +
+ +
+ + {de + ? 'Starter <10 MA: 3.600 €/J · Professional 10–250: 15–40k €/J · Enterprise 250+: ab 50k €/J. Mitarbeiterbasiert. Standard: BSI-Cloud DE. Optional: Mac Mini/Studio für absolute Privacy bei Kleinunternehmen.' + : 'Starter <10 emp: €3,600/yr · Professional 10–250: €15–40k/yr · Enterprise 250+: from €50k/yr. Employee-based. Standard: BSI cloud DE. Optional: Mac Mini/Studio for absolute privacy for micro businesses.'} + +
+
+ ) +} + +/* ===== HOW IT WORKS ===== */ + +const STEPS_DE = [ + { n: '01', t: 'Cloud-Vertrag abschließen', d: 'BSI-zertifizierte Cloud in Deutschland. Fixe oder flexible Kosten je nach Volumen. Onboarding-Call mit dedicated CSM in der ersten Woche.' }, + { n: '02', t: 'Code-Repos verbinden', d: 'Git-Repos, CI/CD-Pipelines und Firmware-Projekte über Standard-Integrationen anbinden. Die KI scannt automatisch, bei jeder Änderung.' }, + { n: '03', t: 'Compliance & Security automatisieren', d: 'Kontinuierliche Code-Analyse, Pentesting und Risikoanalysen. VVT, TOMs, DSFA, CE-Dokumentation werden automatisch erstellt und aktualisiert.' }, + { n: '04', t: 'Audit vorbereiten', d: 'Alle Nachweise, Dokumente und Risikobeurteilungen auf Knopfdruck. Abweichungen nach dem Audit automatisch nachverfolgt, Stichtage, Tickets, Eskalation.' }, +] +const STEPS_EN = [ + { n: '01', t: 'Sign cloud contract', d: 'BSI-certified cloud in Germany. Fixed or flexible costs depending on volume. Onboarding call with dedicated CSM in week one.' }, + { n: '02', t: 'Connect code repos', d: 'Connect Git repos, CI/CD pipelines and firmware projects via standard integrations. The AI scans automatically, on every change.' }, + { n: '03', t: 'Automate compliance & security', d: 'Continuous code analysis, pentesting and risk assessments. RoPA, TOMs, DPIA, CE documentation auto-generated and updated.' }, + { n: '04', t: 'Prepare for audit', d: 'All evidence, documents and risk assessments at the push of a button. Post-audit deviations automatically tracked, deadlines, tickets, escalation.' }, +] + +const TIMELINE_DAYS_DE = ['Tag 0', 'Tag 3', 'Tag 7', 'Tag 14', 'Tag 30'] +const TIMELINE_DAYS_EN = ['Day 0', 'Day 3', 'Day 7', 'Day 14', 'Day 30'] +const TIMELINE_LABELS_DE = ['Vertrag', 'Onboarding-Call', 'Repos angebunden', 'VVT/TOMs auto', 'audit-ready'] +const TIMELINE_LABELS_EN = ['Contract', 'Onboarding call', 'Repos connected', 'RoPA/TOMs auto', 'audit-ready'] + +export function PrintHowItWorksPage({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + const steps = de ? STEPS_DE : STEPS_EN + const days = de ? TIMELINE_DAYS_DE : TIMELINE_DAYS_EN + const labels = de ? TIMELINE_LABELS_DE : TIMELINE_LABELS_EN + const MONO = "'JetBrains Mono', ui-monospace, monospace" + + return ( + + + {/* 4-step rail: numbered violet circles on a horizontal connector line, + title + body underneath each. Replaces the floating-arrow StepStrip. */} +
+ {/* connector line (behind the circles) */} +
+
+ {steps.map((s, i) => ( +
+ {/* number circle on the rail */} +
{s.n}
+
{s.t}
+
{s.d}
+
+ ))} +
+
+ + {/* Fill space between steps and footer with a visual timeline */} +
+ +
+
+ {de ? 'Time-to-Value · Median 14 Tage · Worst Case 28 Tage' : 'Time-to-Value · Median 14 days · Worst case 28 days'} +
+ {/* dotted timeline with 5 day markers */} +
+ {/* the rail */} +
+
+ {days.map((d, i) => ( +
+ {/* day marker pill */} +
{d}
+ {/* dot on rail */} +
+ {/* label below */} +
{labels[i]}
+
+ ))} +
+
+
+ + ) +} + +/* ===== BUSINESS MODEL / PRICING ===== */ + +export function PrintBusinessModelPage({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + const MONO = "'JetBrains Mono', ui-monospace, monospace" + + const tiers = [ + { + name: 'Starter', + target: de ? '< 25 Mitarbeiter · Basis-Module' : '< 25 employees · basic modules', + price: '€3.600', + unit: de ? '/ Jahr' : '/ year', + features: de + ? ['DSGVO + Audit + DSR-Workflow', 'Compliance Scanner (CI/CD)', 'EU-Hosting · BSI C5', 'E-Mail-Support'] + : ['GDPR + Audit + DSR workflow', 'Compliance Scanner (CI/CD)', 'EU hosting · BSI C5', 'Email support'], + tint: COLORS.violet400, + bg: COLORS.violet50, + featured: false, + }, + { + name: 'Professional', + target: de ? '25–250 Mitarbeiter · alle Module' : '25–250 employees · all modules', + price: '€18.000', + unit: de ? '/ Jahr' : '/ year', + features: de + ? ['Alle 12 Module', 'Priority-Support · Onboarding-Call', 'CE-Software-Risiko + Tender Matching', 'Dedicated CSM · 14-tägige Reviews', 'Custom-Integrationen (Jira, GitLab)'] + : ['All 12 modules', 'Priority support · onboarding call', 'CE software risk + tender matching', 'Dedicated CSM · biweekly reviews', 'Custom integrations (Jira, GitLab)'], + tint: COLORS.violet600, + bg: `linear-gradient(180deg, ${COLORS.violet50} 0%, #ffffff 60%, ${COLORS.violet50} 100%)`, + featured: true, + }, + { + name: 'Enterprise', + target: de ? '250+ Mitarbeiter · maßgeschneidert' : '250+ employees · custom', + price: de ? 'ab €50.000' : 'from €50k', + unit: de ? '/ Jahr' : '/ year', + features: de + ? ['Alles aus Professional', 'SLA · Custom Contract', 'On-Premise / Air-Gap (Mac Mini/Studio)', 'Dedicated Customer Engineering', 'Multi-Region Audit-Trail'] + : ['Everything in Professional', 'SLA · custom contract', 'On-premise / air-gap (Mac Mini/Studio)', 'Dedicated customer engineering', 'Multi-region audit trail'], + tint: COLORS.amber600, + bg: COLORS.amber50, + featured: false, + }, + ] + + return ( + + + {/* 3 product cards */} +
+ {tiers.map((t) => ( +
+ {/* Featured badge */} + {t.featured && ( +
{de ? 'Beliebt' : 'Popular'}
+ )} + +
{t.name}
+
{t.target}
+ + {/* Price */} +
+
{t.price}
+
{t.unit}
+
+ + {/* Features */} +
+ {t.features.map((f, i) => ( +
+ + {f} +
+ ))} +
+
+ ))} +
+ + {/* Unit economics + savings — bottom strip */} +
+
+
{de ? 'Unit Economics · Reifephase' : 'Unit Economics · Mature'}
+
+ {[ + { n: '~70%', l: de ? 'Bruttomarge' : 'Gross margin', tone: 'positive' as const }, + { n: '~3,5×', l: 'LTV / CAC', tone: 'positive' as const }, + { n: '~14m', l: de ? 'CAC-Payback' : 'CAC payback' }, + { n: '<8%', l: de ? 'Net Churn p.a.' : 'Net churn p.a.', tone: 'positive' as const }, + ].map((k, i) => ( +
+
{k.n}
+
{k.l}
+
+ ))} +
+
+ +
+
{de ? 'Netto-Effekt · KMU 50 MA / Jahr 1' : 'Net effect · SME 50 emp. / Y1'}
+
+
+€30k
+
{de ? 'pro KMU / Jahr' : 'per SME / yr'}
+
+
+ {de ? 'Kunde spart €55k (Pentests, CE-Risiko, Compliance-Zeit), zahlt €25k. ROI ab Tag 1.' : 'Customer saves €55k (pentests, CE risk, compliance time), pays €25k. ROI from day 1.'} +
+
+
+
+ ) +} diff --git a/pitch-deck/app/pitch-print/[versionId]/page.tsx b/pitch-deck/app/pitch-print/[versionId]/page.tsx index 737749e..f4bfa6a 100644 --- a/pitch-deck/app/pitch-print/[versionId]/page.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/page.tsx @@ -6,6 +6,7 @@ import { PitchCompetitor, PitchFeature, PitchMilestone, PitchMetric, PitchFunding, PitchProduct, FpScenarioRef, FMResult, FMAssumption, } from '@/lib/types' +import { finanzplanToFMResults } from '@/lib/finanzplan/adapter' import PrintDeck from './_components/PrintDeck' interface Ctx { @@ -65,28 +66,39 @@ export default async function PitchPrintPage({ params, searchParams }: Ctx) { fp_scenarios: (map.fm_scenarios || []) as FpScenarioRef[], } - // Financial variant: fetch FM results + parse assumptions + // Always fetch FM results + assumptions so the standard PDF can render the + // annex-finanzplan slide. The `financial` flag only adds the extra detail + // P&L page and the cap-table page. + // + // Data source: the live `fp_*` tables (same as the interactive deck), bridged + // to FMResult[] via finanzplanToFMResults. The legacy `pitch_fm_results` table + // is no longer populated by the current pipeline. let fmResults: FMResult[] = [] let fmAssumptions: FMAssumption[] = [] - if (financial) { - const scenarios = (map.fm_scenarios || []) as FpScenarioRef[] - const defaultScenario = scenarios.find(s => s.is_default) ?? scenarios[0] ?? null - - if (defaultScenario?.id) { - const resultsRes = await pool.query( - `SELECT * FROM pitch_fm_results WHERE scenario_id = $1 ORDER BY month`, - [defaultScenario.id], - ) - fmResults = resultsRes.rows as FMResult[] - } - - const rawAssumptions = (map.fm_assumptions || []) as Array> - fmAssumptions = rawAssumptions.map(a => ({ - ...a, - value: typeof a.value === 'string' ? JSON.parse(a.value as string) : a.value, - })) as FMAssumption[] + const scenarios = (map.fm_scenarios || []) as FpScenarioRef[] + const defaultScenario = scenarios.find(s => s.is_default) ?? scenarios[0] ?? null + // Snapshot stores fp_scenario IDs under `fm_scenarios`; fall back to the live + // default fp scenario if the snapshot is empty (older versions). + let scenarioId: string | null = defaultScenario?.id ? String(defaultScenario.id) : null + if (!scenarioId) { + const liveRes = await pool.query(`SELECT id FROM fp_scenarios WHERE is_default = true LIMIT 1`) + scenarioId = liveRes.rows[0]?.id ? String(liveRes.rows[0].id) : null } + if (scenarioId) { + try { + const fpResponse = await finanzplanToFMResults(pool, scenarioId) + fmResults = fpResponse.results + } catch { + fmResults = [] + } + } + + const rawAssumptions = (map.fm_assumptions || []) as Array> + fmAssumptions = rawAssumptions.map(a => ({ + ...a, + value: typeof a.value === 'string' ? JSON.parse(a.value as string) : a.value, + })) as FMAssumption[] return (