From 0d5ebcd27aa07bc0485e984fd60017044ec38c03 Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Tue, 19 May 2026 18:43:35 +0200 Subject: [PATCH 01/11] feat(pitch-print): redesign PDF investor brief from scratch Throws away the screen-deck-derived print system. Builds a new institutional-research aesthetic: - 12-col grid on A4 landscape, hairline rules, no colored bars, no icons - 3-color discipline: indigo (structural), emerald (positive), red (problem) - Plus Jakarta Sans 800 for hero numerals + titles; tabular numerals everywhere - 1-to-1 content parity with the interactive deck: full USP (8 cards), full competition matrix (45 features, 12 AppSec features, 8+6 competitor profiles), Finanzplan P&L grid + KPI dashboard, full glossary - 2-page slides where content demands (Exec Summary, USP, Competition, Finanzplan) - 28 base pages; +1 for Financial detail; +1 for Cap Table (suppressed on Wandeldarlehen) Files: - New: PrintIntroSlides, PrintProductSlides, PrintMarketSlides, PrintCompetitionSlides - Rewritten: PrintLayout (new primitives Page/KpiRow/TwoCol/ThreeCol/DataTable/MatrixGlyph/Callout), PrintAnnexSlides, PrintFinancialSlides, PrintDeck - Removed: PrintCoreSlides.tsx, PrintExtraSlides.tsx (obsolete) - print.css now sets Plus Jakarta Sans as the print font family - All files under 500 LOC cap Co-Authored-By: Claude Opus 4.7 --- .../_components/PrintAnnexSlides.tsx | 830 +++++++++--------- .../_components/PrintCompetitionSlides.tsx | 190 ++++ .../_components/PrintCoreSlides.tsx | 301 ------- .../[versionId]/_components/PrintDeck.tsx | 137 ++- .../_components/PrintExtraSlides.tsx | 480 ---------- .../_components/PrintFinancialSlides.tsx | 469 ++++++---- .../_components/PrintIntroSlides.tsx | 368 ++++++++ .../[versionId]/_components/PrintLayout.tsx | 491 ++++++++--- .../_components/PrintMarketSlides.tsx | 393 +++++++++ .../_components/PrintProductSlides.tsx | 339 +++++++ pitch-deck/app/pitch-print/print.css | 20 +- 11 files changed, 2514 insertions(+), 1504 deletions(-) create mode 100644 pitch-deck/app/pitch-print/[versionId]/_components/PrintCompetitionSlides.tsx delete mode 100644 pitch-deck/app/pitch-print/[versionId]/_components/PrintCoreSlides.tsx delete mode 100644 pitch-deck/app/pitch-print/[versionId]/_components/PrintExtraSlides.tsx create mode 100644 pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx create mode 100644 pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx create mode 100644 pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx index 2ec8c29..999e726 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx @@ -1,478 +1,500 @@ -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' 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'] }, -] +/* ===== 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}

+ + + ( +
+
+ {p.n} + {p.kpi}
- ))} -
-

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

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

{p.title}

-

{p.period}

-
- {p.team}{p.arr} -
-
    - {p.items.map(i =>
  • {i}
  • )} -
+
{p.t}
+
{p.subtitle}
+
+
- ))} -
-
-
-

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 + ? '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.'} +
-

- {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 -
- ))} -
- - )} -

- {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.'} -

- - ) -} +/* ===== ANNEX REGULATORY ===== */ -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'] }, - ], -} +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}
  • )} -
-
- ))} -
-
- ) -} + -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}

+
+ {/* PRODUCT TIER */} +
+
{de ? 'Produkt-Schicht' : 'Product Tier'}
+
+ {[ + { t: 'CERTifAI', s: de ? 'GenAI Mandantenportal' : 'GenAI Tenant Portal', tech: 'Rust · Dioxus · MongoDB · Keycloak · SearXNG · LangGraph', services: ['LiteLLM Dashboard', 'LibreChat + SSO', 'LangGraph Agents', 'MCP Hub'] }, + { t: 'COMPLAI', s: de ? 'Compliance & Audit' : 'Compliance & Audit', tech: 'Next.js 15 · FastAPI · Go/Gin · PostgreSQL · Qdrant · Valkey', services: [de ? 'DSGVO/AI Act/NIS2 (25k+ Controls)' : 'GDPR/AI Act/NIS2 (25k+ controls)', de ? 'RAG (380+ Quellen)' : 'RAG (380+ sources)', de ? 'Control Pipeline (LLM)' : 'Control pipeline (LLM)', 'MCP Client'] }, + { t: 'Compliance Scanner', s: de ? 'Code-Sicherheit' : 'Code Security', tech: 'Rust · Axum · MongoDB · Semgrep · Gitleaks · Syft', services: ['SAST · SBOM · CVE Pipeline', de ? 'KI-Triage (False Positives)' : 'AI Triage (false positives)', de ? 'KI-Pentest (autonom)' : 'AI Pentest (autonomous)', 'MCP Server'] }, + ].map((p, i) => ( +
+
{p.t}
+
{p.s}
+
{p.tech}
+
+ {p.services.map((s, j) => ( +
0 ? `1px solid ${COLORS.slate100}` : 'none' }}>· {s}
+ ))} +
+
+ ))}
- ))} -
-
-
-

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

-
- {langs.map(l =>
)} -
- {langs.map(l => ( -
- - - {l.lang} - - {l.loc}{l.pct}% -
- ))}
+ + {/* PROXY TIER */} +
+
{de ? 'Gateway-Schicht (KI-Proxy mit Guardrails)' : 'Gateway Tier (AI proxy with guardrails)'}
+
+
+ LiteLLM Proxy + {de ? 'KI-Gateway · Bearer-Auth · Rate-Limiting · PII-Filter · Spend-Tracking' : 'AI gateway · bearer auth · rate limiting · PII filter · spend tracking'} +
+
+
· {de ? 'Token-Budget pro Mandant' : 'Per-tenant token budget'}
+
· {de ? 'PII-Guardrails alle Anfragen' : 'PII guardrails on all requests'}
+
· {de ? 'Anonyme EU-Web-Suche (SearXNG)' : 'Anonymous EU web search (SearXNG)'}
+
· {de ? 'Namespace-Isolierung pro API-Key' : 'Namespace isolation per API key'}
+
· {de ? 'Failover-Routing zwischen Modellen' : 'Failover routing between models'}
+
+
+
+ + {/* INFERENCE TIER */}
-

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

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

{t.l}

-

{t.d}

+
{de ? 'Inferenz-Schicht (lokal, air-gap-fähig)' : 'Inference Tier (local, air-gap capable)'}
+
+ {[ + { t: de ? 'LLM Inferenz' : 'LLM Inference', tech: 'Qwen3-32B · Qwen3-Coder-30B · DeepSeek-R1-8B · Ollama', desc: de ? 'Vollständig lokal, air-gap fähig, GPU-optimiert. Daten verlassen nie den Server.' : 'Fully local, air-gap capable, GPU-optimized. Data never leaves the server.' }, + { t: 'Embeddings', tech: 'bge-m3 · Qdrant Vector DB · Sentence-Transformers', desc: de ? 'RAG mit 380+ Rechtsquellen indexiert, multilinguale Einbettungen, lokal.' : 'RAG with 380+ legal sources indexed, multilingual embeddings, local.' }, + { t: de ? 'KI-Tools' : 'AI Tools', tech: 'SearXNG · MCP Protocol · Semgrep API · Gitleaks API', desc: de ? 'Anonymisierte EU-Web-Suche, MCP-Integration für Audit-Dokumente und Code-Findings.' : 'Anonymized EU web search, MCP integration for audit docs and code findings.' }, + ].map((p, i) => ( +
+
{p.t}
+
{p.tech}
+
{p.desc}
))}
-

- {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 ENGINEERING ===== */ + +export function PrintEngineeringPage({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + return ( + + +
+ {[ + { 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 ? 'Tech-Stack pro Schicht' : 'Tech stack per layer'}
+ +
+ +
+
{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.'} + +
+
+
+
+ ) } +/* ===== 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 ? 'RAG-Pipeline (4 Stufen)' : 'RAG Pipeline (4 stages)'}

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

{s.t}

-

{s.d}

-
- ))} -
-
-

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

-
    - {agents.map(a => ( -
  • - - {a} -
  • +
    {de ? 'Pipeline-Fluss' : 'Pipeline flow'}
    +
    + {[ + { n: '01', t: 'Ingestion', d: de ? 'Rohdokumente (PDF, HTML, XML, Word) → Pass 0a OCR → Pass 0b Strukturierung. Markdown + Metadaten.' : 'Raw docs (PDF, HTML, XML, Word) → Pass 0a OCR → Pass 0b structuring. Markdown + metadata.', kpi: '385 docs' }, + { n: '02', t: 'Chunking + Embed', d: de ? 'Semantisches Chunking, Sentence-Transformers (bge-m3), Qdrant Vector DB, Multi-Index.' : 'Semantic chunking, sentence-transformers (bge-m3), Qdrant vector DB, multi-index.', kpi: '~280k chunks' }, + { n: '03', t: 'Control Extraction', d: de ? 'BatchDedup → LLM-Extraktor (Qwen3-32B) → Strukturierte Controls mit Quellenangabe + Confidence.' : 'BatchDedup → LLM extractor (Qwen3-32B) → structured controls with source + confidence.', kpi: '25k+ controls' }, + { n: '04', t: 'Quality Assurance', d: de ? 'BQAS (Batch Quality Assessment System): Cross-Validation, Inkonsistenz-Detection, Audit-Sampling.' : 'BQAS (Batch Quality Assessment System): cross-validation, inconsistency detection, audit sampling.', kpi: '>99% precision' }, + ].map((s, i) => ( +
    +
    + {s.n} + {s.kpi} +
    +
    {s.t}
    +
    {s.d}
    +
    ))} -
-

- {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.'} -

+
+
+ + {/* Agent system */} +
+
+
{de ? 'Multi-Agent-System (LangGraph)' : 'Multi-Agent System (LangGraph)'}
+ +
+ +
+
{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} +
+ ))} +
+
-
+ ) } -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/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..47609fb 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx @@ -3,23 +3,31 @@ 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 { + PrintFinanzplanPage1, PrintFinanzplanPage2, PrintAssumptionsPage, + PrintFinancialsPage, PrintCapTablePage, PrintDisclaimerPage, + aggregateAnnualRows, +} from './PrintFinancialSlides' + +export { aggregateAnnualRows } interface PrintDeckProps { pitchData: PitchData @@ -31,46 +39,50 @@ 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 hasFinancialDetail = financial && annualRows.length > 0 const de = lang === 'de' + // Base standard PDF: 28 pages (25 slides, 3 of them 2-page: exec-summary, usp, competition; finanzplan annex is 2 pages) + // 1 (exec1) + 1 (exec2) + 1 (cover) + 1 (problem) + 1 (solution) + 2 (usp) + 1 (regL) + 1 (product) + + // 1 (how) + 1 (market) + 1 (bm) + 1 (traction) + 2 (competition) + 1 (team) + 1 (ask) + 1 (savings) + + // 1 (strategy) + 2 (finanzplan) + 1 (assumptions) + 1 (regulatory) + 1 (architecture) + 1 (engineering) + + // 1 (aipipeline) + 1 (risks) + 1 (glossary) + 1 (disclaimer) = 28 + const BASE_PAGES = 28 + const totalPages = BASE_PAGES + (hasFinancialDetail ? 1 : 0) + (hasCapTable ? 1 : 0) + 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. */} +
+ {/* SLIDE_ORDER from lib/slide-order.ts, minus 3 interactive-only slides: + intro-presenter, ai-qa, annex-sdk-demo */} - {/* 1. executive-summary */} - - {/* 2. cover (page 2 — uses its own layout; assign sequential number) */} + {/* 1. executive-summary (2 pages) */} + + + + {/* 2. cover */} {(() => { n += 1; return })()} + {/* 3. problem */} + {/* 4. solution */} - {/* 5. usp */} - + + {/* 5. usp (2 pages) */} + + + {/* 6. regulatory-landscape */} - {/* 7. product */} + + {/* 7. product / modular-toolkit */} + {/* 8. how-it-works */} + {/* 9. market */} - {/* 10. business-model */} + + {/* 10. business-model / pricing */} - {/* 11. traction (uses milestones table) */} + + {/* 11. traction (uses milestones) */} - {/* 12. competition */} - + + {/* 12. competition (2 pages) */} + + + {/* 13. team */} + {/* 14. the-ask */} + {/* 15. customer-savings */} + {/* 16. annex-strategy */} - {/* 17. annex-finanzplan */} - - {/* Financial-only: detailed P&L table */} - {hasFinancials && } + + {/* 17. annex-finanzplan (2 pages) */} + + + + {/* Financial-only: detail P&L */} + {hasFinancialDetail && } + {/* 18. annex-assumptions */} + {/* 19. annex-regulatory */} + {/* 20. annex-architecture */} + {/* 21. annex-engineering */} + {/* 22. annex-aipipeline */} + {/* 23. risks */} + {/* 24. annex-glossary */} - {/* Financial-only: cap table */} + + {/* Financial-only: cap-table (suppressed for Wandeldarlehen) */} {hasCapTable && } + {/* 25. legal-disclaimer */}
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..572185c 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx @@ -1,5 +1,6 @@ -import { PrintPage, SectionTitle, PrintTable, Badge, COLORS } from './PrintLayout' import { Language, FMResult, FMAssumption } from '@/lib/types' +import { Page, COLORS, Callout, DataTable } from './PrintLayout' +import { computeAnnualKPIs } from '@/lib/finanzplan/annual-kpis' interface SlideBase { lang: Language; pageNum: number; totalPages: number; versionName: string } @@ -34,121 +35,231 @@ 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 maxRev = Math.max(...kpis.map(k => k.totalRevenue), 1) + const maxEmp = Math.max(...kpis.map(k => k.employees), 1) + + return ( + + + {/* KPI table */} +
+ ({ header: String(k.year), numeric: true, width: '15.2%' as string })), + ]} + rows={[ + ['ARR (Dez)', ...kpis.map(k => fmtEur(k.arr))], + ['MRR (Dez)', ...kpis.map(k => fmtEur(k.mrr))], + [de ? 'ARPU (€/Monat)' : 'ARPU (€/mo)', ...kpis.map(k => fmtEur(k.arpu))], + [de ? 'Kunden' : 'Customers', ...kpis.map(k => k.customers.toLocaleString('de-DE'))], + [de ? 'Mitarbeiter' : 'Employees', ...kpis.map(k => k.employees.toLocaleString('de-DE'))], + [de ? 'Umsatz / MA' : 'Revenue / FTE', ...kpis.map(k => fmtEur(k.revenuePerEmployee))], + [de ? 'Bruttomarge %' : 'Gross margin %', ...kpis.map(k => k.grossMargin + '%')], + [de ? 'EBIT' : 'EBIT', ...kpis.map(k => = 0 ? COLORS.emerald700 : COLORS.red700, fontWeight: 700 }}>{fmtEur(k.ebit)})], + [de ? 'EBIT-Marge' : 'EBIT margin', ...kpis.map(k => = 0 ? COLORS.emerald700 : COLORS.red700 }}>{k.ebitMargin}%)], + [de ? 'Steuern (~30%)' : 'Taxes (~30%)', ...kpis.map(k => fmtEur(k.taxes))], + [de ? 'Netto-Ergebnis' : 'Net income', ...kpis.map(k => = 0 ? COLORS.emerald700 : COLORS.red700 }}>{fmtEur(k.netIncome)})], + [de ? 'Burn-Rate (Dez)' : 'Burn rate (Dec)', ...kpis.map(k => fmtEur(k.burnRate))], + [de ? 'Runway (Monate)' : 'Runway (months)', ...kpis.map(k => k.runway == null ? '∞' : String(k.runway))], + [de ? 'Cash-Bestand (Dez)' : 'Cash balance (Dec)', ...kpis.map(k => fmtEur(k.cashBalance))], + ]} + highlightFirstCol + /> +
+ + {/* Charts */} +
+ {/* Revenue chart */} +
+
{de ? 'Umsatz-Wachstum (Mio. €)' : 'Revenue growth (€M)'}
+
+ {kpis.map((k, i) => { + const h = (k.totalRevenue / maxRev) * 100 + return ( +
+
{(k.totalRevenue / 1e6).toFixed(1)}
+
+
+ ) + })} +
+
+ {kpis.map((k, i) => ( +
{k.year}
+ ))} +
+
+ + {/* Headcount + customers chart */} +
+
{de ? 'Mitarbeiter & Kunden' : 'Employees & customers'}
+
+ {kpis.map((k, i) => { + const h = (k.employees / maxEmp) * 100 + return ( +
+
+ {k.employees} +
+ {k.customers}c +
+
+
+ ) + })} +
+
+ {kpis.map((k, i) => ( +
{k.year}
+ ))} +
+
+ {de ? 'Mitarbeiter (FTE)' : 'Employees (FTE)'} + {de ? 'Zahl unten: Kunden' : 'Number below: customers'} +
+
+
+ + ) +} + +/* ===== 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) return ( - - - {de ? 'Finanzielle Annahmen' : 'Financial Assumptions'} - -
- {Object.entries(byCategory).slice(0, 4).map(([cat, items]) => ( + + +
+ {categories.slice(0, 6).map(([cat, items]) => (
-

- {cat} -

- +
{cat}
+
{items.map(a => ( - - + ))} @@ -157,121 +268,173 @@ export function PrintAssumptionsPage({ assumptions, lang, pageNum, totalPages, v ))} - + +
+ + {de + ? 'Drei Szenarien, Best/Base/Worst, variieren um Wachstumsrate, Churn, ARPU und CAC. Sensitivitäts-Tornado verfügbar im Live-Modell. Base-Case ist absichtlich konservativ angesetzt.' + : 'Three scenarios, best/base/worst, vary growth rate, churn, ARPU and CAC. Sensitivity tornado available in live model. Base case is deliberately conservative.'} + +
+ ) } +/* ===== FINANCIAL DETAIL (financial-only extra page) ===== */ + +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 + 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'} -

-
+ + +
+
+
{de ? 'Anteilsverteilung Post Pre-Seed' : 'Share distribution post pre-seed'}
+
{CAP_TABLE_DATA.map(d => ( -
+
))}
{CAP_TABLE_DATA.map(d => ( -
-
- {d.name} - {d.pct}% +
+
+ {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..a132830 --- /dev/null +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx @@ -0,0 +1,368 @@ +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 tagline = de ? (company?.tagline_de || 'Kontinuierliche Compliance für europäische Unternehmen.') : (company?.tagline_en || 'Continuous compliance for European companies.') + return ( +
+
+ {/* TOP META */} +
+ BreakPilot · Investor Brief + {versionName} +
+ + {/* HERO */} +
+

+ {instrument} · Q4 2026 +

+

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

+

+ {tagline} +

+
+

+ {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.'} +

+
+ + {/* META GRID */} +
+ {([ + [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}

+
+ ))} +
+ + {/* FOOTER */} +
+ {de ? 'Vertraulich, Nur für Investoren' : 'Confidential, For Investor Use Only'} + CONFIDENTIAL +
+
+
+ ) +} + +/* ===== 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} + {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. Wer auf US-KI verzichtet, verliert den Anschluss. Wer sie nutzt, riskiert seine Datensouveränität.', cite: 'Bitkom Cloud Monitor 2024 · DIHK Digitalisierungsumfrage 2024' }, + { 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. Das Schrems-II-Urteil des EuGH hat das bestätigt.', cite: 'EuGH C-311/18 (Schrems II, 2020)' }, + { 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. Pentests 15-40k €, CE-Risiko 10-25k €. KMU können das allein nicht mehr stemmen.', cite: 'VDMA Compliance-Kosten Maschinenbau 2024' }, +] +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. Those avoiding US AI fall behind. Those using it risk their data sovereignty.', cite: 'Bitkom Cloud Monitor 2024 · DIHK 2024' }, + { 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. The Schrems II ruling by the CJEU confirmed this.', cite: 'CJEU C-311/18 (Schrems II, 2020)' }, + { 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. Pentests €15-40k, CE risk €10-25k. SMEs can no longer handle this alone.', cite: 'VDMA Compliance Costs Manufacturing 2024' }, +] + +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}
+
+ ))} /> + +
+ + {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' } }, + { kicker: 'PILLAR 02', t: 'Compliance auf Autopilot', d: 'VVT, TOMs, DSFA, Löschfristen, CE-Risikobeurteilung automatisch. Nach dem Audit: Abweichungen End-to-End, Rollen, Stichtage, Tickets, Nachweise, Eskalation an GF.', stat: { v: '80%', l: 'Zeitersparnis bei Compliance-Prüfungen' } }, + { kicker: 'PILLAR 03', t: 'Deutsche Cloud, volle Integration', d: 'BSI-zertifizierte Cloud in Deutschland. 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' } }, +] +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 as tickets in the issue tracker of your choice, with implementation suggestions.', stat: { v: '€15k+', l: 'pentest costs saved / app / year' } }, + { kicker: 'PILLAR 02', t: 'Compliance on Autopilot', d: 'RoPA, TOMs, DPIA, retention policies, CE risk assessment automatically. Post-audit: deviations end-to-end, roles, deadlines, tickets, evidence, escalation to management.', stat: { v: '80%', l: 'time saved on compliance checks' } }, + { kicker: 'PILLAR 03', t: 'German Cloud, Full Integration', d: 'BSI-certified cloud in Germany. 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' } }, +] + +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}
+
+
{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..0d308f8 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintLayout.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintLayout.tsx @@ -1,11 +1,359 @@ 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 ===== */ + +export const COLORS = { + slate900: '#0f172a', + slate800: '#1e293b', + slate700: '#334155', + slate600: '#475569', + slate500: '#64748b', + slate400: '#94a3b8', + slate300: '#cbd5e1', + slate200: '#e2e8f0', + slate100: '#f1f5f9', + slate50: '#f8fafc', + indigo700: '#4338ca', + indigo600: '#4f46e5', + indigo500: '#6366f1', + indigo50: '#eef2ff', + emerald700: '#047857', + emerald600: '#059669', + emerald50: '#ecfdf5', + red700: '#b91c1c', + red600: '#dc2626', + red50: '#fef2f2', + amber700: '#b45309', + amber600: '#d97706', + amber50: '#fffbeb', + // legacy aliases for migrating callers + dark: '#0f172a', + med: '#334155', + light: '#64748b', + border: '#e2e8f0', + indigo: '#4f46e5', + indigoLight: '#eef2ff', +} + +const FONT = "'Plus Jakarta Sans', 'Inter', system-ui, -apple-system, sans-serif" + +/* ===== 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 */} +
+
+
+ + {kicker} · {section} + + + BreakPilot · {versionName} +
+

+ {title} +

+ {subtitle && ( +

+ {subtitle} +

+ )} +
+
+ + {/* CONTENT */} +
+ {children} +
+ + {/* FOOTNOTE (optional) */} + {footnote && ( +
+ {footnote} +
+ )} + + {/* FOOTER */} +
+ BreakPilot · {versionName} + CONFIDENTIAL + {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 +364,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 +395,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..6d121d6 --- /dev/null +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx @@ -0,0 +1,393 @@ +import { Language, PitchMarket, PitchTeamMember, PitchMilestone, PitchFunding } from '@/lib/types' +import { Page, TwoCol, Bullets, Callout, COLORS, DataTable, StatLine } from './PrintLayout' + +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'}> + + {/* TAM/SAM/SOM as nested rectangles */} +
+
+
{de ? 'Marktdimensionierung' : 'Market sizing'}
+ + {/* TAM */} + {tam && ( +
+
+ TAM · {de ? 'Total Addressable Market' : 'Total Addressable Market'} + +{tam.growth_rate_pct ?? 14}% p.a. +
+
{fmtEur(tam.value_eur, de)}
+
{de ? 'Globaler Compliance- und GRC-Markt (alle Branchen, alle Größen).' : 'Global compliance and GRC market (all industries, all sizes).'}
+
+ )} + + {/* SAM */} + {sam && ( +
+
+ SAM · {de ? 'Serviceable Addressable' : 'Serviceable Addressable'} + +{sam.growth_rate_pct ?? 18}% p.a. +
+
{fmtEur(sam.value_eur, de)}
+
{de ? 'DACH + EU: regulierte Branchen, KMU + Enterprise.' : 'DACH + EU: regulated industries, SMB + enterprise.'}
+
+ )} + + {/* SOM */} + {som && ( +
+
+ SOM · {de ? 'Kernmarkt 5 Jahre' : 'Core market 5 yrs'} + +{som.growth_rate_pct ?? 25}% p.a. +
+
{fmtEur(som.value_eur, de)}
+
{de ? 'Anlagen- und Maschinenbau DACH, unser Kernsegment.' : 'Machine & plant manufacturing DACH, our core segment.'}
+
+ )} +
+ + {/* Segment context */} +
+
{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 ( + + + +
+ CO-FOUNDER · 01 / 02 + Equity {members[0]?.equity_pct ?? 37.3}% +
+
{members[0]?.name || 'Benjamin Bönisch'}
+
{de ? (members[0]?.role_de || 'CEO & Co-Founder') : (members[0]?.role_en || 'CEO & Co-Founder')}
+
{de ? (members[0]?.bio_de) : (members[0]?.bio_en)}
+
+
{de ? 'Expertise' : 'Expertise'}
+
+ {(members[0]?.expertise || []).map((e, i) => ( + {e} + ))} +
+
+
+ } right={ +
+
+ CO-FOUNDER · 02 / 02 + Equity {members[1]?.equity_pct ?? 37.3}% +
+
{members[1]?.name || 'Sharang Parnerkar'}
+
{de ? (members[1]?.role_de || 'CTO & Co-Founder') : (members[1]?.role_en || 'CTO & Co-Founder')}
+
{de ? (members[1]?.bio_de) : (members[1]?.bio_en)}
+
+
{de ? 'Expertise' : 'Expertise'}
+
+ {(members[1]?.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 ===== */ + +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 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'}
+
+ €{(amount / 1_000_000).toFixed(1)}M +
+
{instrument} · {funding?.round_name || 'Pre-Seed'} · {de ? 'Zielabschluss' : 'Target close'}: {funding?.target_date || 'Q3 2026'}
+
+ +
+ {[ + { l: de ? 'Pre-Money' : 'Pre-money', v: '€4.0M' }, + { l: de ? 'Post-Money' : 'Post-money', v: '€5.0M' }, + { l: de ? 'Investor-Anteil' : 'Investor share', v: '20%' }, + ].map((k, i) => ( +
+
{k.l}
+
{k.v}
+
+ ))} +
+ +
+ + {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'}
+ {/* Horizontal bar */} +
+ {useOfFunds.map((u, i) => { + const colors = [COLORS.indigo600, COLORS.indigo500, COLORS.amber600, COLORS.slate600, COLORS.slate400] + return ( +
+ ) + })} +
+ {useOfFunds.map((u, i) => { + const colors = [COLORS.indigo600, COLORS.indigo500, COLORS.amber600, COLORS.slate600, COLORS.slate400] + return ( +
+
+
{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' + return ( + + +
+
+
{de ? 'Was der Kunde heute bezahlt (ohne BreakPilot)' : 'What customer pays today (without BreakPilot)'}
+ {de ? 'Summe heute' : 'Today total'}, €71.000, ''], + ]} + dense + /> + +
+ + {de + ? 'Zeit der GF + Compliance-Beauftragten (~30 Tage/Jahr), DSGVO-Bußgelder bei Fehlern (bis zu 4% Jahresumsatz), verlorene RFQs durch fehlende Compliance-Nachweise.' + : 'Time of management + compliance officer (~30 days/year), GDPR fines on errors (up to 4% annual revenue), lost RFQs due to missing compliance evidence.'} + +
+
+ +
+
{de ? 'Mit BreakPilot' : 'With BreakPilot'}
+ {de ? 'BreakPilot Pro' : 'BreakPilot Pro'}, €25.000, ''], + [{de ? 'Gesamt-Ersparnis' : 'Total savings'}, '', €55.000], + ]} + dense + /> + +
+
{de ? 'Netto-Effekt Jahr 1' : 'Net effect year 1'}
+
+
+€30k
+
{de ? 'pro KMU / Jahr' : 'per SME / year'}
+
+
{de ? 'Kunde spart €55k, zahlt €25k. ROI ab Tag 1. Zusätzlich: keine Bußgelder, RFQ-Win-Rate ↑, Schlaf-Frieden für die GF.' : 'Customer saves €55k, pays €25k. ROI from day 1. Plus: no fines, RFQ win-rate ↑, peace of mind for management.'}
+
+
+
+
+ ) +} 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..229f9d9 --- /dev/null +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx @@ -0,0 +1,339 @@ +import { Language, PitchProduct } from '@/lib/types' +import { Page, TwoCol, ThreeCol, FourCol, Bullets, Callout, COLORS, Divider, DataTable, StatLine } from './PrintLayout' +import { getDetails } from '@/components/slides/USPSlide.data' + +interface SlideBase { lang: Language; pageNum: number; totalPages: number; versionName: string } + +/* ===== 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] + return ( +
+
+ {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 (under the hood + closing loop) ===== */ + +export function PrintUSPPage2({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + const d = getDetails(de) + const cards = ['trace', 'engine', 'opt', 'stack'] as const + + return ( + + +
+ {cards.map(k => { + const p = d[k] + return ( +
+
{p.kicker}
+
{p.title}
+
{p.body}
+ {p.bullets && } +
+ ) + })} +
+ +
+ +
{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 MODULES_FULL_DE = [ + { name: 'Code Security', icon: '◇', desc: 'SAST · DAST · SBOM · Container · Secrets · Pentesting', features: ['Bei jedem Push', 'Auto-Fix LLM', 'CI/CD-integriert'] }, + { name: 'CE-SW-Risikobeurteilung', icon: '◇', desc: 'CE-Kennzeichnung für Maschinen mit Software-Anteil', features: ['Maschinen-VO', 'CRA-konform', 'Code-Basis-Analyse'] }, + { name: 'Compliance-Dokumente', icon: '◇', desc: 'VVT (Art. 30) · TOMs · DSFA (Art. 35) · Löschkonzept', features: ['Auto-Generiert', 'Versionsverlauf', 'Audit-tauglich'] }, + { name: 'Audit Manager', icon: '◇', desc: 'Abweichungen End-to-End: Rollen · Stichtage · Eskalation', features: ['Tickets + Nachweise', 'GF-Eskalation', 'Compliance-SLA'] }, + { name: 'DSR / Betroffenenrechte', icon: '◇', desc: 'Auskunft, Berichtigung, Löschung, Datenübertragbarkeit', features: ['Self-Service', 'Identitätsprüfung', 'Frist-Tracking'] }, + { name: 'Consent', icon: '◇', desc: 'Einwilligungs-Management, Cookie-Banner, ePrivacy', features: ['CMP integriert', 'Audit-Log', 'Multi-Tenant'] }, + { name: 'Incident Response', icon: '◇', desc: 'Vorfälle, Meldung (72h), Mitigation, Forensik', features: ['Art. 33/34 DSGVO', 'BSI-Meldepfade', 'Forensik-Hooks'] }, + { name: 'Compliance LLM', icon: '◇', desc: 'GPT für Text + Audio, EU-gehostet, mit Quellenangabe', features: ['Self-Hosted', 'EU-souverän', 'Audit-zitierbar'] }, + { name: 'Tender Matching', icon: '◇', desc: 'RFQ-Antworten automatisch gegen Codebase + Policies', features: ['Stunden statt Wochen', 'Win-ready', 'Klausel-Mapping'] }, + { name: 'Academy', icon: '◇', desc: 'Online-Schulungen für Geschäftsführung und Mitarbeiter', features: ['Mandatory Training', 'Zertifikate', 'GF-Pflicht erfüllt'] }, + { name: 'Compliance Optimizer', icon: '◇', desc: 'Maximale KI-Nutzung im legalen Rahmen, ersetzt 20-200k € Anwaltskosten', features: ['ROI-ranking', 'Sweet-Spot', 'Risikobalance'] }, + { name: 'Kommunikation', icon: '◇', desc: 'Chat (Matrix) + Video (Jitsi) + KI-Support', features: ['Self-Hosted', 'EU-Hosting', 'Audit-Logs'] }, +] +const MODULES_FULL_EN = [ + { name: 'Code Security', icon: '◇', desc: 'SAST · DAST · SBOM · Container · Secrets · Pentesting', features: ['Every push', 'Auto-fix LLM', 'CI/CD integrated'] }, + { name: 'CE SW Risk Assessment', icon: '◇', desc: 'CE marking for machinery with software', features: ['Machinery Reg.', 'CRA-compliant', 'Code-level analysis'] }, + { name: 'Compliance Documents', icon: '◇', desc: 'RoPA (Art. 30) · TOMs · DPIA (Art. 35) · Retention', features: ['Auto-generated', 'Version history', 'Audit-ready'] }, + { name: 'Audit Manager', icon: '◇', desc: 'Deviations end-to-end: roles · deadlines · escalation', features: ['Tickets + evidence', 'Mgmt escalation', 'Compliance SLA'] }, + { name: 'DSR / Data Subject Rights', icon: '◇', desc: 'Access, rectification, erasure, portability', features: ['Self-service', 'Identity check', 'Deadline tracking'] }, + { name: 'Consent', icon: '◇', desc: 'Consent mgmt, cookie banner, ePrivacy', features: ['CMP integrated', 'Audit log', 'Multi-tenant'] }, + { name: 'Incident Response', icon: '◇', desc: 'Breaches, reporting (72h), mitigation, forensics', features: ['GDPR Art. 33/34', 'BSI channels', 'Forensic hooks'] }, + { name: 'Compliance LLM', icon: '◇', desc: 'GPT for text + audio, EU-hosted, with citations', features: ['Self-hosted', 'EU-sovereign', 'Audit-citable'] }, + { name: 'Tender Matching', icon: '◇', desc: 'RFQ answers automatically against codebase + policies', features: ['Hours not weeks', 'Win-ready', 'Clause mapping'] }, + { name: 'Academy', icon: '◇', desc: 'Online training for management and staff', features: ['Mandatory training', 'Certificates', 'Mgmt duties fulfilled'] }, + { name: 'Compliance Optimizer', icon: '◇', desc: 'Max AI use within legal limits, replaces €20-200k legal fees', features: ['ROI ranking', 'Sweet spot', 'Risk balance'] }, + { name: 'Communication', icon: '◇', 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) => ( +
+
+
{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 Kleinstunternehmen.' + : '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.' }, +] + +export function PrintHowItWorksPage({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + const steps = de ? STEPS_DE : STEPS_EN + return ( + + + {/* horizontal step flow */} +
+ {steps.map((s, i) => ( +
+ {i < steps.length - 1 && ( +
+ )} +
{s.n}
+
{s.t}
+
{s.d}
+
+ ))} +
+ +
+ + {de + ? 'Tag 0: Vertrag · Tag 3: Onboarding-Call · Tag 7: erste Repos angebunden · Tag 14: erste automatische VVT/TOMs · Tag 30: audit-ready Status erreicht.' + : 'Day 0: contract · Day 3: onboarding call · Day 7: first repos connected · Day 14: first automated RoPA/TOMs · Day 30: audit-ready status achieved.'} + +
+ + ) +} + +/* ===== BUSINESS MODEL / PRICING ===== */ + +export function PrintBusinessModelPage({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + return ( + + +
+
+
{de ? 'Pricing-Tiers' : 'Pricing tiers'}
+ + +
+
{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 ? 'Was der Kunde zahlt vs. spart (KMU 50 MA, Jahr 1)' : 'What customer pays vs. saves (SME 50 emp., year 1)'}
+
+ + + + + + +
+
+
{de ? 'Netto-Effekt Jahr 1' : 'Net effect year 1'}
+
+€30.000
+
{de ? 'Kunde spart €55k, zahlt €25k. ROI ab Tag 1.' : 'Customer saves €55k, pays €25k. ROI from day 1.'}
+
+
+
+
+ ) +} diff --git a/pitch-deck/app/pitch-print/print.css b/pitch-deck/app/pitch-print/print.css index f343933..0712054 100644 --- a/pitch-deck/app/pitch-print/print.css +++ b/pitch-deck/app/pitch-print/print.css @@ -24,12 +24,14 @@ min-height: 0 !important; overflow: visible !important; background: #ffffff !important; - color: #000000 !important; + color: #0f172a !important; margin: 0 !important; padding: 0 !important; + font-family: 'Plus Jakarta Sans', 'Inter', system-ui, -apple-system, sans-serif !important; -webkit-print-color-adjust: exact; -moz-print-color-adjust: exact; print-color-adjust: exact; + font-variant-numeric: tabular-nums; } .no-print { @@ -41,6 +43,7 @@ margin: 0 !important; display: block !important; overflow: visible !important; + font-family: 'Plus Jakarta Sans', 'Inter', system-ui, sans-serif !important; } /* @@ -73,8 +76,23 @@ margin: 0 !important; box-shadow: none !important; background: #ffffff !important; + font-family: 'Plus Jakarta Sans', 'Inter', system-ui, sans-serif !important; + color: #0f172a !important; -webkit-print-color-adjust: exact; -moz-print-color-adjust: exact; print-color-adjust: exact; } + + /* Tabular numerals everywhere — institutional research aesthetic */ + .print-page table, + .print-page .num, + .print-page .kpi { + font-variant-numeric: tabular-nums; + } +} + +/* Screen preview: apply Plus Jakarta Sans to print pages even on screen */ +.print-page, .print-page-break { + font-family: 'Plus Jakarta Sans', 'Inter', system-ui, sans-serif; + font-variant-numeric: tabular-nums; } From bb85ee2e27cc21bac50638d5cd7f2ce218711c55 Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Wed, 20 May 2026 09:31:28 +0200 Subject: [PATCH 02/11] fix(pitch-print): page count, Finanzplan loading, visual energy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bug fixes plus the requested visual rework — the deck now looks like a pitch deck, not a research paper. Bugs: - BASE_PAGES corrected from 28 to 29; disclaimer no longer shows "29/28" - fmResults + fmAssumptions now load for the standard PDF, not only when financial=true; Finanzplan annex + KPI dashboard now render Visual rework (per user: "graphic elements, not just text"): - Cover: split layout — indigo block left (tagline + hero stats + version meta), white block right with oversized title and key terms - Modules: 12 lucide icons in indigo-50 tiles (ScanLine, ShieldCheck, FileText, ClipboardCheck, Users, UserCheck, AlertTriangle, Brain, Target, GraduationCap, TrendingUp, MessageSquare) - USP cards: icon-led card heads with FileSearch/ArrowLeftRight/Repeat/Layers/etc.; LoopDiagram SVG on the closing "Compliance ↔ Code" hub - How It Works: StepStrip primitive with visible right-arrows between steps - Market: nested-rectangle MarketFunnel (TAM > SAM > SOM) replaces three stacked boxes - Customer Savings: 4 hero KPIs + ComparisonBars (today vs. with BP) per cost item - The Ask: DonutChart for use-of-funds - Cap Table: DonutChart for equity distribution - Finanzplan p2: 2×2 chart grid — Revenue (bars), EBIT (bars, tone by sign), Cash balance (line+area), Headcount (bars) - Architecture: ArchitectureDiagram primitive (3 tiers, vertical arrows between tiers) - AI Pipeline: PipelineFlow primitive (4 stages, horizontal arrows) - Team: founder photos (32×32mm) added; falls back to initials if photo_url missing New primitives: - PrintCharts.tsx — BarChart, LineChart, ComparisonBars, DonutChart, ProgressBar, MarketFunnel - PrintDiagrams.tsx — FlowNode, VArrow, HArrow, StepStrip, ArchitectureDiagram, LoopDiagram, PipelineFlow All files under 500 LOC cap. Co-Authored-By: Claude Opus 4.7 --- .../_components/PrintAnnexSlides.tsx | 105 ++----- .../[versionId]/_components/PrintCharts.tsx | 267 +++++++++++++++++ .../[versionId]/_components/PrintDeck.tsx | 13 +- .../[versionId]/_components/PrintDiagrams.tsx | 263 +++++++++++++++++ .../_components/PrintFinancialSlides.tsx | 137 ++++----- .../_components/PrintIntroSlides.tsx | 123 +++++--- .../_components/PrintMarketSlides.tsx | 277 ++++++++---------- .../_components/PrintProductSlides.tsx | 150 ++++++---- .../app/pitch-print/[versionId]/page.tsx | 35 ++- 9 files changed, 937 insertions(+), 433 deletions(-) create mode 100644 pitch-deck/app/pitch-print/[versionId]/_components/PrintCharts.tsx create mode 100644 pitch-deck/app/pitch-print/[versionId]/_components/PrintDiagrams.tsx diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx index 999e726..ecaca0c 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx @@ -1,5 +1,6 @@ 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 } @@ -158,68 +159,31 @@ export function PrintRegulatoryPage({ lang, pageNum, totalPages, versionName }: export function PrintArchitecturePage({ lang, pageNum, totalPages, versionName }: SlideBase) { const de = lang === 'de' return ( - - -
- {/* PRODUCT TIER */} -
-
{de ? 'Produkt-Schicht' : 'Product Tier'}
-
- {[ - { t: 'CERTifAI', s: de ? 'GenAI Mandantenportal' : 'GenAI Tenant Portal', tech: 'Rust · Dioxus · MongoDB · Keycloak · SearXNG · LangGraph', services: ['LiteLLM Dashboard', 'LibreChat + SSO', 'LangGraph Agents', 'MCP Hub'] }, - { t: 'COMPLAI', s: de ? 'Compliance & Audit' : 'Compliance & Audit', tech: 'Next.js 15 · FastAPI · Go/Gin · PostgreSQL · Qdrant · Valkey', services: [de ? 'DSGVO/AI Act/NIS2 (25k+ Controls)' : 'GDPR/AI Act/NIS2 (25k+ controls)', de ? 'RAG (380+ Quellen)' : 'RAG (380+ sources)', de ? 'Control Pipeline (LLM)' : 'Control pipeline (LLM)', 'MCP Client'] }, - { t: 'Compliance Scanner', s: de ? 'Code-Sicherheit' : 'Code Security', tech: 'Rust · Axum · MongoDB · Semgrep · Gitleaks · Syft', services: ['SAST · SBOM · CVE Pipeline', de ? 'KI-Triage (False Positives)' : 'AI Triage (false positives)', de ? 'KI-Pentest (autonom)' : 'AI Pentest (autonomous)', 'MCP Server'] }, - ].map((p, i) => ( -
-
{p.t}
-
{p.s}
-
{p.tech}
-
- {p.services.map((s, j) => ( -
0 ? `1px solid ${COLORS.slate100}` : 'none' }}>· {s}
- ))} -
-
- ))} -
-
- - {/* PROXY TIER */} -
-
{de ? 'Gateway-Schicht (KI-Proxy mit Guardrails)' : 'Gateway Tier (AI proxy with guardrails)'}
-
-
- LiteLLM Proxy - {de ? 'KI-Gateway · Bearer-Auth · Rate-Limiting · PII-Filter · Spend-Tracking' : 'AI gateway · bearer auth · rate limiting · PII filter · spend tracking'} -
-
-
· {de ? 'Token-Budget pro Mandant' : 'Per-tenant token budget'}
-
· {de ? 'PII-Guardrails alle Anfragen' : 'PII guardrails on all requests'}
-
· {de ? 'Anonyme EU-Web-Suche (SearXNG)' : 'Anonymous EU web search (SearXNG)'}
-
· {de ? 'Namespace-Isolierung pro API-Key' : 'Namespace isolation per API key'}
-
· {de ? 'Failover-Routing zwischen Modellen' : 'Failover routing between models'}
-
-
-
- - {/* INFERENCE TIER */} -
-
{de ? 'Inferenz-Schicht (lokal, air-gap-fähig)' : 'Inference Tier (local, air-gap capable)'}
-
- {[ - { t: de ? 'LLM Inferenz' : 'LLM Inference', tech: 'Qwen3-32B · Qwen3-Coder-30B · DeepSeek-R1-8B · Ollama', desc: de ? 'Vollständig lokal, air-gap fähig, GPU-optimiert. Daten verlassen nie den Server.' : 'Fully local, air-gap capable, GPU-optimized. Data never leaves the server.' }, - { t: 'Embeddings', tech: 'bge-m3 · Qdrant Vector DB · Sentence-Transformers', desc: de ? 'RAG mit 380+ Rechtsquellen indexiert, multilinguale Einbettungen, lokal.' : 'RAG with 380+ legal sources indexed, multilingual embeddings, local.' }, - { t: de ? 'KI-Tools' : 'AI Tools', tech: 'SearXNG · MCP Protocol · Semgrep API · Gitleaks API', desc: de ? 'Anonymisierte EU-Web-Suche, MCP-Integration für Audit-Dokumente und Code-Findings.' : 'Anonymized EU web search, MCP integration for audit docs and code findings.' }, - ].map((p, i) => ( -
-
{p.t}
-
{p.tech}
-
{p.desc}
-
- ))} -
-
-
+ + ) } @@ -318,23 +282,14 @@ export function PrintAIPipelinePage({ lang, pageNum, totalPages, versionName }: {/* Pipeline flow */}
{de ? 'Pipeline-Fluss' : 'Pipeline flow'}
-
- {[ + 99% precision' }, - ].map((s, i) => ( -
-
- {s.n} - {s.kpi} -
-
{s.t}
-
{s.d}
-
- ))} -
+ ]} + />
{/* Agent system */} 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/PrintDeck.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx index 47609fb..8a15d6f 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx @@ -46,12 +46,13 @@ export default function PrintDeck({ pitchData, versionName, fmResults, fmAssumpt const hasFinancialDetail = financial && annualRows.length > 0 const de = lang === 'de' - // Base standard PDF: 28 pages (25 slides, 3 of them 2-page: exec-summary, usp, competition; finanzplan annex is 2 pages) - // 1 (exec1) + 1 (exec2) + 1 (cover) + 1 (problem) + 1 (solution) + 2 (usp) + 1 (regL) + 1 (product) + - // 1 (how) + 1 (market) + 1 (bm) + 1 (traction) + 2 (competition) + 1 (team) + 1 (ask) + 1 (savings) + - // 1 (strategy) + 2 (finanzplan) + 1 (assumptions) + 1 (regulatory) + 1 (architecture) + 1 (engineering) + - // 1 (aipipeline) + 1 (risks) + 1 (glossary) + 1 (disclaimer) = 28 - const BASE_PAGES = 28 + // Base standard PDF: 29 physical pages. + // 2 (exec) + 1 (cover) + 1 (problem) + 1 (solution) + 2 (usp) + 1 (regL) + + // 1 (product) + 1 (how) + 1 (market) + 1 (bm) + 1 (milestones) + 2 (competition) + + // 1 (team) + 1 (ask) + 1 (savings) + 1 (strategy) + 2 (finanzplan) + + // 1 (assumptions) + 1 (regulatory) + 1 (architecture) + 1 (engineering) + + // 1 (aipipeline) + 1 (risks) + 1 (glossary) + 1 (disclaimer) = 29 + const BASE_PAGES = 29 const totalPages = BASE_PAGES + (hasFinancialDetail ? 1 : 0) + (hasCapTable ? 1 : 0) useEffect(() => { 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..cd22da9 --- /dev/null +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintDiagrams.tsx @@ -0,0 +1,263 @@ +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' + return ( +
+ {/* PRODUCT TIER */} +
+
{de ? 'Produkt-Schicht' : 'Product Tier'}
+
+ {product.map((p, i) => ( + + ))} +
+
+ + {/* Down arrows between product and proxy */} +
+ {[0, 1, 2].map(i => )} +
+ + {/* PROXY */} +
+
+
+
+ {de ? 'Gateway' : 'Gateway'} + {proxy.title} + {proxy.subtitle} +
+
+
+ {proxy.features.map((f, i) => ( +
{f}
+ ))} +
+
+
+ + {/* Down arrows between proxy and inference */} +
+ {[0, 1, 2].map(i => )} +
+ + {/* INFERENCE TIER */} +
+
{de ? 'Inferenz-Schicht (lokal, air-gap-fähig)' : 'Inference Tier (local, air-gap capable)'}
+
+ {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/PrintFinancialSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx index 572185c..20a0f1a 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx @@ -1,5 +1,6 @@ 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 } @@ -140,91 +141,64 @@ export function PrintFinanzplanPage2({ fmResults, lang, pageNum, totalPages, ver } - const maxRev = Math.max(...kpis.map(k => k.totalRevenue), 1) - const maxEmp = Math.max(...kpis.map(k => k.employees), 1) + 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 ( - + - {/* KPI table */} -
+ {/* Compact KPI table */} +
({ header: String(k.year), numeric: true, width: '15.2%' as string })), + { header: de ? 'KPI' : 'KPI', width: '22%' }, + ...kpis.map(k => ({ header: String(k.year), numeric: true })), ]} rows={[ ['ARR (Dez)', ...kpis.map(k => fmtEur(k.arr))], - ['MRR (Dez)', ...kpis.map(k => fmtEur(k.mrr))], - [de ? 'ARPU (€/Monat)' : 'ARPU (€/mo)', ...kpis.map(k => fmtEur(k.arpu))], - [de ? 'Kunden' : 'Customers', ...kpis.map(k => k.customers.toLocaleString('de-DE'))], - [de ? 'Mitarbeiter' : 'Employees', ...kpis.map(k => k.employees.toLocaleString('de-DE'))], + [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' : 'EBIT', ...kpis.map(k => = 0 ? COLORS.emerald700 : COLORS.red700, fontWeight: 700 }}>{fmtEur(k.ebit)})], - [de ? 'EBIT-Marge' : 'EBIT margin', ...kpis.map(k => = 0 ? COLORS.emerald700 : COLORS.red700 }}>{k.ebitMargin}%)], - [de ? 'Steuern (~30%)' : 'Taxes (~30%)', ...kpis.map(k => fmtEur(k.taxes))], - [de ? 'Netto-Ergebnis' : 'Net income', ...kpis.map(k => = 0 ? COLORS.emerald700 : COLORS.red700 }}>{fmtEur(k.netIncome)})], - [de ? 'Burn-Rate (Dez)' : 'Burn rate (Dec)', ...kpis.map(k => fmtEur(k.burnRate))], - [de ? 'Runway (Monate)' : 'Runway (months)', ...kpis.map(k => k.runway == null ? '∞' : String(k.runway))], - [de ? 'Cash-Bestand (Dez)' : 'Cash balance (Dec)', ...kpis.map(k => fmtEur(k.cashBalance))], + [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 */} -
- {/* Revenue chart */} -
-
{de ? 'Umsatz-Wachstum (Mio. €)' : 'Revenue growth (€M)'}
-
- {kpis.map((k, i) => { - const h = (k.totalRevenue / maxRev) * 100 - return ( -
-
{(k.totalRevenue / 1e6).toFixed(1)}
-
-
- ) - })} -
-
- {kpis.map((k, i) => ( -
{k.year}
- ))} -
-
- - {/* Headcount + customers chart */} -
-
{de ? 'Mitarbeiter & Kunden' : 'Employees & customers'}
-
- {kpis.map((k, i) => { - const h = (k.employees / maxEmp) * 100 - return ( -
-
- {k.employees} -
- {k.customers}c -
-
-
- ) - })} -
-
- {kpis.map((k, i) => ( -
{k.year}
- ))} -
-
- {de ? 'Mitarbeiter (FTE)' : 'Employees (FTE)'} - {de ? 'Zahl unten: Kunden' : 'Number below: customers'} -
-
+ {/* 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))} + />
) @@ -341,18 +315,19 @@ export function PrintCapTablePage({ lang, pageNum, totalPages, versionName }: Sl
{de ? 'Anteilsverteilung Post Pre-Seed' : 'Share distribution post pre-seed'}
-
- {CAP_TABLE_DATA.map(d => ( -
- ))} -
- {CAP_TABLE_DATA.map(d => ( -
-
- {d.name} - {d.pct}% + +
+ ({ label: d.name, pct: d.pct, color: d.color }))} /> +
+ {CAP_TABLE_DATA.map(d => ( +
+
+ {d.name} + {d.pct}% +
+ ))}
- ))} +
diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx index a132830..9b6a424 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx @@ -8,54 +8,95 @@ interface SlideBase { lang: Language; pageNum: number; totalPages: number; versi 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.') return (
-
- {/* TOP META */} -
- BreakPilot · Investor Brief - {versionName} -
+
- {/* HERO */} -
-

- {instrument} · Q4 2026 -

-

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

-

- {tagline} -

-
-

- {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.'} -

-
- - {/* META GRID */} -
- {([ - [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}

+ {/* LEFT INDIGO 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.'} +
+
+ + {/* Hero stat */} +
+
+ {de ? '25 000 + atomare Prüfaspekte' : '25 000 + atomic audit aspects'} +
+
+ {de ? '380 + Regularien · 10 Branchen' : '380 + regulations · 10 industries'} +
+
+ {de ? '500 K + Lines of Code · 45 Container' : '500 K + lines of code · 45 containers'} +
+
+ + {/* Bottom: version + confidential */} +
+
{versionName}
+
{de ? 'Vertraulich · Nur Investoren' : 'Confidential · Investors only'}
+
- {/* FOOTER */} -
- {de ? 'Vertraulich, Nur für Investoren' : 'Confidential, For Investor Use Only'} - CONFIDENTIAL + {/* RIGHT WHITE PANE */} +
+
+
+ {instrument} · Q4 2026 +
+

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

+
+

+ {tagline} +

+
+ + {/* Key terms */} +
+
+ {de ? 'Key Terms' : 'Key terms'} +
+
+ {([ + [de ? 'Funding' : 'Funding', '€' + (amount / 1_000_000).toFixed(1) + 'M'], + [de ? 'Pre-Money' : 'Pre-money', '€4.0M'], + [de ? 'Instrument' : 'Instrument', instrument], + [de ? 'Standort' : 'HQ', company?.hq_city || 'Bodman'], + ] as [string, string][]).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.'} +
+
diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx index 6d121d6..e368173 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx @@ -1,5 +1,6 @@ import { Language, PitchMarket, PitchTeamMember, PitchMilestone, PitchFunding } from '@/lib/types' -import { Page, TwoCol, Bullets, Callout, COLORS, DataTable, StatLine } from './PrintLayout' +import { Page, Callout, COLORS, DataTable, StatLine } from './PrintLayout' +import { MarketFunnel, ComparisonBars, DonutChart } from './PrintCharts' interface SlideBase { lang: Language; pageNum: number; totalPages: number; versionName: string } @@ -21,49 +22,19 @@ export function PrintMarketPage({ market, lang, pageNum, totalPages, versionName 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'}> - {/* TAM/SAM/SOM as nested rectangles */} -
+
{de ? 'Marktdimensionierung' : 'Market sizing'}
- - {/* TAM */} - {tam && ( -
-
- TAM · {de ? 'Total Addressable Market' : 'Total Addressable Market'} - +{tam.growth_rate_pct ?? 14}% p.a. -
-
{fmtEur(tam.value_eur, de)}
-
{de ? 'Globaler Compliance- und GRC-Markt (alle Branchen, alle Größen).' : 'Global compliance and GRC market (all industries, all sizes).'}
-
- )} - - {/* SAM */} - {sam && ( -
-
- SAM · {de ? 'Serviceable Addressable' : 'Serviceable Addressable'} - +{sam.growth_rate_pct ?? 18}% p.a. -
-
{fmtEur(sam.value_eur, de)}
-
{de ? 'DACH + EU: regulierte Branchen, KMU + Enterprise.' : 'DACH + EU: regulated industries, SMB + enterprise.'}
-
- )} - - {/* SOM */} - {som && ( -
-
- SOM · {de ? 'Kernmarkt 5 Jahre' : 'Core market 5 yrs'} - +{som.growth_rate_pct ?? 25}% p.a. -
-
{fmtEur(som.value_eur, de)}
-
{de ? 'Anlagen- und Maschinenbau DACH, unser Kernsegment.' : 'Machine & plant manufacturing DACH, our core segment.'}
-
+ {tam && sam && som && ( + fmtEur(v, de)} + /> )}
- {/* Segment context */}
{de ? 'Kernsegment: Maschinen- und Anlagenbau DACH' : 'Core segment: Machine & plant manufacturing DACH'}
- -
- CO-FOUNDER · 01 / 02 - Equity {members[0]?.equity_pct ?? 37.3}% -
-
{members[0]?.name || 'Benjamin Bönisch'}
-
{de ? (members[0]?.role_de || 'CEO & Co-Founder') : (members[0]?.role_en || 'CEO & Co-Founder')}
-
{de ? (members[0]?.bio_de) : (members[0]?.bio_en)}
-
-
{de ? 'Expertise' : 'Expertise'}
-
- {(members[0]?.expertise || []).map((e, i) => ( - {e} - ))} +
+ {[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} + ))} +
+
-
-
- } right={ -
-
- CO-FOUNDER · 02 / 02 - Equity {members[1]?.equity_pct ?? 37.3}% -
-
{members[1]?.name || 'Sharang Parnerkar'}
-
{de ? (members[1]?.role_de || 'CTO & Co-Founder') : (members[1]?.role_en || 'CTO & Co-Founder')}
-
{de ? (members[1]?.bio_de) : (members[1]?.bio_en)}
-
-
{de ? 'Expertise' : 'Expertise'}
-
- {(members[1]?.expertise || []).map((e, i) => ( - {e} - ))} -
-
-
- } /> + ) + })} +
@@ -292,27 +267,31 @@ export function PrintTheAskPage({ funding, lang, pageNum, totalPages, versionNam {/* Use of funds */}
-
{de ? 'Use of Funds' : 'Use of Funds'}
- {/* Horizontal bar */} -
- {useOfFunds.map((u, i) => { - const colors = [COLORS.indigo600, COLORS.indigo500, COLORS.amber600, COLORS.slate600, COLORS.slate400] - return ( -
- ) - })} -
- {useOfFunds.map((u, i) => { - const colors = [COLORS.indigo600, COLORS.indigo500, COLORS.amber600, COLORS.slate600, COLORS.slate400] +
{de ? 'Use of Funds' : 'Use of funds'}
+ {(() => { + const palette = [COLORS.indigo600, COLORS.indigo500, COLORS.amber600, COLORS.slate600, COLORS.slate400] return ( -
-
-
{de ? u.label_de : u.label_en}
-
{u.percentage}%
-
€{(amount * u.percentage / 100 / 1000).toFixed(0)}k
+
+
+ ({ 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
+
+ ))} +
) - })} + })()}
@@ -323,68 +302,70 @@ export function PrintTheAskPage({ funding, lang, pageNum, totalPages, versionNam 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 ( - + -
-
-
{de ? 'Was der Kunde heute bezahlt (ohne BreakPilot)' : 'What customer pays today (without BreakPilot)'}
- {de ? 'Summe heute' : 'Today total'}, €71.000, ''], - ]} - dense - /> - -
- - {de - ? 'Zeit der GF + Compliance-Beauftragten (~30 Tage/Jahr), DSGVO-Bußgelder bei Fehlern (bis zu 4% Jahresumsatz), verlorene RFQs durch fehlende Compliance-Nachweise.' - : 'Time of management + compliance officer (~30 days/year), GDPR fines on errors (up to 4% annual revenue), lost RFQs due to missing compliance evidence.'} - + {/* 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 ? 'Mit BreakPilot' : 'With BreakPilot'}
- {de ? 'BreakPilot Pro' : 'BreakPilot Pro'}, €25.000, ''], - [{de ? 'Gesamt-Ersparnis' : 'Total savings'}, '', €55.000], - ]} - dense - /> +
{de ? 'Ersparnis-Aufschlüsselung' : 'Savings breakdown'}
+
+ + + + + + +
-
-
{de ? 'Netto-Effekt Jahr 1' : 'Net effect year 1'}
-
-
+€30k
-
{de ? 'pro KMU / Jahr' : 'per SME / year'}
-
-
{de ? 'Kunde spart €55k, zahlt €25k. ROI ab Tag 1. Zusätzlich: keine Bußgelder, RFQ-Win-Rate ↑, Schlaf-Frieden für die GF.' : 'Customer saves €55k, pays €25k. ROI from day 1. Plus: no fines, RFQ win-rate ↑, peace of mind for management.'}
+
+ + {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/PrintProductSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx index 229f9d9..07b7282 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx @@ -1,9 +1,21 @@ import { Language, PitchProduct } from '@/lib/types' -import { Page, TwoCol, ThreeCol, FourCol, Bullets, Callout, COLORS, Divider, DataTable, StatLine } from './PrintLayout' +import { Page, Bullets, Callout, COLORS, DataTable, StatLine } from './PrintLayout' +import { StepStrip, 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) { @@ -17,19 +29,25 @@ export function PrintUSPPage1({ lang, pageNum, totalPages, versionName }: SlideB
{pillars.map((k, i) => { const p = d[k] + const Icon = USP_ICON[k] return ( -
-
- {p.kicker} - {String(i + 1).padStart(2, '0')} / 04 +
+
+
+ {Icon && } +
+
+
{p.kicker}
+
{String(i + 1).padStart(2, '0')} / 04
+
-
{p.title}
+
{p.title}
{p.body}
{p.bullets && } {p.stat && (
{p.stat.k} - {p.stat.v} + {p.stat.v}
)}
@@ -50,28 +68,32 @@ export function PrintUSPPage2({ lang, pageNum, totalPages, versionName }: SlideB return ( -
+
{cards.map(k => { const p = d[k] + const Icon = USP_ICON[k] return (
-
{p.kicker}
-
{p.title}
-
{p.body}
+
+ {Icon && } + {p.kicker} +
+
{p.title}
+
{p.body}
{p.bullets && }
) })}
-
- -
{d.hub.title}
-
{d.hub.body}
- {d.hub.bullets && ( -
- )} -
+
+
+ + {de ? 'Die Schleife' : 'The Loop'} +
+
{d.hub.title}
+
{d.hub.body}
+
) @@ -168,33 +190,37 @@ export function PrintRegulatoryLandscapePage({ lang, pageNum, totalPages, versio /* ===== 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', icon: '◇', desc: 'SAST · DAST · SBOM · Container · Secrets · Pentesting', features: ['Bei jedem Push', 'Auto-Fix LLM', 'CI/CD-integriert'] }, - { name: 'CE-SW-Risikobeurteilung', icon: '◇', desc: 'CE-Kennzeichnung für Maschinen mit Software-Anteil', features: ['Maschinen-VO', 'CRA-konform', 'Code-Basis-Analyse'] }, - { name: 'Compliance-Dokumente', icon: '◇', desc: 'VVT (Art. 30) · TOMs · DSFA (Art. 35) · Löschkonzept', features: ['Auto-Generiert', 'Versionsverlauf', 'Audit-tauglich'] }, - { name: 'Audit Manager', icon: '◇', desc: 'Abweichungen End-to-End: Rollen · Stichtage · Eskalation', features: ['Tickets + Nachweise', 'GF-Eskalation', 'Compliance-SLA'] }, - { name: 'DSR / Betroffenenrechte', icon: '◇', desc: 'Auskunft, Berichtigung, Löschung, Datenübertragbarkeit', features: ['Self-Service', 'Identitätsprüfung', 'Frist-Tracking'] }, - { name: 'Consent', icon: '◇', desc: 'Einwilligungs-Management, Cookie-Banner, ePrivacy', features: ['CMP integriert', 'Audit-Log', 'Multi-Tenant'] }, - { name: 'Incident Response', icon: '◇', desc: 'Vorfälle, Meldung (72h), Mitigation, Forensik', features: ['Art. 33/34 DSGVO', 'BSI-Meldepfade', 'Forensik-Hooks'] }, - { name: 'Compliance LLM', icon: '◇', desc: 'GPT für Text + Audio, EU-gehostet, mit Quellenangabe', features: ['Self-Hosted', 'EU-souverän', 'Audit-zitierbar'] }, - { name: 'Tender Matching', icon: '◇', desc: 'RFQ-Antworten automatisch gegen Codebase + Policies', features: ['Stunden statt Wochen', 'Win-ready', 'Klausel-Mapping'] }, - { name: 'Academy', icon: '◇', desc: 'Online-Schulungen für Geschäftsführung und Mitarbeiter', features: ['Mandatory Training', 'Zertifikate', 'GF-Pflicht erfüllt'] }, - { name: 'Compliance Optimizer', icon: '◇', desc: 'Maximale KI-Nutzung im legalen Rahmen, ersetzt 20-200k € Anwaltskosten', features: ['ROI-ranking', 'Sweet-Spot', 'Risikobalance'] }, - { name: 'Kommunikation', icon: '◇', desc: 'Chat (Matrix) + Video (Jitsi) + KI-Support', features: ['Self-Hosted', 'EU-Hosting', 'Audit-Logs'] }, + { 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', icon: '◇', desc: 'SAST · DAST · SBOM · Container · Secrets · Pentesting', features: ['Every push', 'Auto-fix LLM', 'CI/CD integrated'] }, - { name: 'CE SW Risk Assessment', icon: '◇', desc: 'CE marking for machinery with software', features: ['Machinery Reg.', 'CRA-compliant', 'Code-level analysis'] }, - { name: 'Compliance Documents', icon: '◇', desc: 'RoPA (Art. 30) · TOMs · DPIA (Art. 35) · Retention', features: ['Auto-generated', 'Version history', 'Audit-ready'] }, - { name: 'Audit Manager', icon: '◇', desc: 'Deviations end-to-end: roles · deadlines · escalation', features: ['Tickets + evidence', 'Mgmt escalation', 'Compliance SLA'] }, - { name: 'DSR / Data Subject Rights', icon: '◇', desc: 'Access, rectification, erasure, portability', features: ['Self-service', 'Identity check', 'Deadline tracking'] }, - { name: 'Consent', icon: '◇', desc: 'Consent mgmt, cookie banner, ePrivacy', features: ['CMP integrated', 'Audit log', 'Multi-tenant'] }, - { name: 'Incident Response', icon: '◇', desc: 'Breaches, reporting (72h), mitigation, forensics', features: ['GDPR Art. 33/34', 'BSI channels', 'Forensic hooks'] }, - { name: 'Compliance LLM', icon: '◇', desc: 'GPT for text + audio, EU-hosted, with citations', features: ['Self-hosted', 'EU-sovereign', 'Audit-citable'] }, - { name: 'Tender Matching', icon: '◇', desc: 'RFQ answers automatically against codebase + policies', features: ['Hours not weeks', 'Win-ready', 'Clause mapping'] }, - { name: 'Academy', icon: '◇', desc: 'Online training for management and staff', features: ['Mandatory training', 'Certificates', 'Mgmt duties fulfilled'] }, - { name: 'Compliance Optimizer', icon: '◇', desc: 'Max AI use within legal limits, replaces €20-200k legal fees', features: ['ROI ranking', 'Sweet spot', 'Risk balance'] }, - { name: 'Communication', icon: '◇', desc: 'Chat (Matrix) + video (Jitsi) + AI support', features: ['Self-hosted', 'EU hosting', 'Audit logs'] }, + { 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[] }) { @@ -205,16 +231,22 @@ export function PrintProductPage({ products, lang, pageNum, totalPages, versionN
- {modules.map((m, i) => ( -
-
-
{m.name}
-
{String(i + 1).padStart(2, '0')}
+ {modules.map((m, i) => { + const Icon = MODULE_ICONS[i] + return ( +
+
+
+ +
+
{m.name}
+
{String(i + 1).padStart(2, '0')}
+
+
{m.desc}
+
{m.features.join(' · ')}
-
{m.desc}
-
{m.features.join(' · ')}
-
- ))} + ) + })}
@@ -249,18 +281,8 @@ export function PrintHowItWorksPage({ lang, pageNum, totalPages, versionName }: return ( - {/* horizontal step flow */} -
- {steps.map((s, i) => ( -
- {i < steps.length - 1 && ( -
- )} -
{s.n}
-
{s.t}
-
{s.d}
-
- ))} +
+
diff --git a/pitch-deck/app/pitch-print/[versionId]/page.tsx b/pitch-deck/app/pitch-print/[versionId]/page.tsx index 737749e..1c92a2d 100644 --- a/pitch-deck/app/pitch-print/[versionId]/page.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/page.tsx @@ -65,29 +65,28 @@ 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. 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 + 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[] + return ( Date: Wed, 20 May 2026 10:01:53 +0200 Subject: [PATCH 03/11] fix(pitch-print): cover layout, Finanzplan data source, target_date MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three critical fixes after reviewing the rendered PDF: Cover (was: indigo block collapsed to top, white content stacked below): - The .print-page class in print.css forces flex-direction: column !important, which broke the horizontal split. Wrap the cover content in a single grid container — the column-flex parent then has only one child so direction is irrelevant. Indigo block now runs full-height on the left. - Title reduced 88pt -> 60pt so "BreakPilot ComplAI." fits without wrapping. - Funding amount formatter now handles sub-€1M cases (€200k vs €0.2M). Finanzplan (was: "nicht verfügbar" on both pages 20-21): - page.tsx was querying the legacy pitch_fm_results table which isn't populated by the current pipeline. The interactive deck reads from fp_* tables. - Wire in lib/finanzplan/adapter.ts (finanzplanToFMResults) which bridges the live fp_* tables to FMResult[] — same source the interactive deck uses. - Fall back to live default fp_scenario if the version snapshot's fm_scenarios is empty. - adapter.ts: populate total_customers + new_customers from fp_kunden_summary (was hardcoded 0). The Ask: - target_date was rendering as raw ISO timestamp "2026-08-01T00:00:00.000Z"; now formatted as "Aug 2026" (locale-aware). - Hero funding amount uses same sub-€1M formatter. Co-Authored-By: Claude Opus 4.7 --- .../_components/PrintIntroSlides.tsx | 162 ++++++++++-------- .../_components/PrintMarketSlides.tsx | 25 ++- .../app/pitch-print/[versionId]/page.tsx | 25 ++- pitch-deck/lib/finanzplan/adapter.ts | 9 +- 4 files changed, 133 insertions(+), 88 deletions(-) diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx index 9b6a424..fd1c27f 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx @@ -10,93 +10,103 @@ export function PrintCoverPage({ company, funding, lang, versionName }: { compan 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' + return (
-
+
+ {/* + The .print-page class in print.css forces flex-direction: column !important, + which would collapse a horizontal flex split. We sidestep that by putting a + single full-size grid container as the only child — the column-flex parent + has just one item so direction no longer matters. + */} +
- {/* LEFT INDIGO BLOCK */} -
-
-
- {de ? 'Investor Brief' : 'Investor Brief'} + {/* LEFT INDIGO 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.'} +
-
-
- {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 ? '500 K + Lines of Code · 45 Container' : '500 K + 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'}
- {/* Hero stat */} -
-
- {de ? '25 000 + atomare Prüfaspekte' : '25 000 + atomic audit aspects'} + {/* RIGHT WHITE PANE */} +
+
+
+ {instrument} · Q4 2026 +
+

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

+
+

+ {tagline} +

-
- {de ? '380 + Regularien · 10 Branchen' : '380 + regulations · 10 industries'} -
-
- {de ? '500 K + Lines of Code · 45 Container' : '500 K + lines of code · 45 containers'} + + {/* Key terms */} +
+
+ {de ? 'Key Terms' : 'Key terms'} +
+
+ {([ + [de ? 'Funding' : 'Funding', amountLabel], + [de ? 'Pre-Money' : 'Pre-money', '€4.0M'], + [de ? 'Instrument' : 'Instrument', instrument], + [de ? 'Standort' : 'HQ', company?.hq_city || 'Bodman'], + ] as [string, string][]).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.'} +
- {/* Bottom: version + confidential */} -
-
{versionName}
-
{de ? 'Vertraulich · Nur Investoren' : 'Confidential · Investors only'}
-
-
- - {/* RIGHT WHITE PANE */} -
-
-
- {instrument} · Q4 2026 -
-

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

-
-

- {tagline} -

-
- - {/* Key terms */} -
-
- {de ? 'Key Terms' : 'Key terms'} -
-
- {([ - [de ? 'Funding' : 'Funding', '€' + (amount / 1_000_000).toFixed(1) + 'M'], - [de ? 'Pre-Money' : 'Pre-money', '€4.0M'], - [de ? 'Instrument' : 'Instrument', instrument], - [de ? 'Standort' : 'HQ', company?.hq_city || 'Bodman'], - ] as [string, string][]).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.'} -
-
diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx index e368173..bab42b5 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx @@ -217,6 +217,25 @@ export function PrintTeamPage({ team, lang, pageNum, totalPages, versionName }: /* ===== 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 @@ -230,7 +249,7 @@ export function PrintTheAskPage({ funding, lang, pageNum, totalPages, versionNam ] return ( - +
{/* Hero amount */} @@ -238,9 +257,9 @@ export function PrintTheAskPage({ funding, lang, pageNum, totalPages, versionNam
{de ? 'Funding' : 'Funding'}
- €{(amount / 1_000_000).toFixed(1)}M + {formatFunding(amount)}
-
{instrument} · {funding?.round_name || 'Pre-Seed'} · {de ? 'Zielabschluss' : 'Target close'}: {funding?.target_date || 'Q3 2026'}
+
{instrument} · {funding?.round_name || 'Pre-Seed'} · {de ? 'Zielabschluss' : 'Target close'}: {formatTargetDate(funding?.target_date, de)}
diff --git a/pitch-deck/app/pitch-print/[versionId]/page.tsx b/pitch-deck/app/pitch-print/[versionId]/page.tsx index 1c92a2d..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 { @@ -68,17 +69,29 @@ export default async function PitchPrintPage({ params, searchParams }: Ctx) { // 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[] = [] 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[] + // 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> diff --git a/pitch-deck/lib/finanzplan/adapter.ts b/pitch-deck/lib/finanzplan/adapter.ts index ca9c3b5..13dcd5d 100644 --- a/pitch-deck/lib/finanzplan/adapter.ts +++ b/pitch-deck/lib/finanzplan/adapter.ts @@ -17,18 +17,20 @@ export async function finanzplanToFMResults(pool: Pool, scenarioId?: string): Pr } // Load computed data - const [personalRes, liquidRes, betriebRes, umsatzRes, materialRes, investRes] = await Promise.all([ + const [personalRes, liquidRes, betriebRes, umsatzRes, materialRes, investRes, kundenRes] = await Promise.all([ pool.query("SELECT * FROM fp_personalkosten WHERE scenario_id = $1 ORDER BY sort_order", [sid]), pool.query("SELECT * FROM fp_liquiditaet WHERE scenario_id = $1 ORDER BY sort_order", [sid]), pool.query("SELECT * FROM fp_betriebliche_aufwendungen WHERE scenario_id = $1 ORDER BY sort_order", [sid]), pool.query("SELECT * FROM fp_umsatzerloese WHERE scenario_id = $1 AND section = 'revenue' AND row_label = 'GESAMTUMSATZ' LIMIT 1", [sid]), pool.query("SELECT * FROM fp_materialaufwand WHERE scenario_id = $1 AND row_label = 'SUMME' LIMIT 1", [sid]), pool.query("SELECT * FROM fp_investitionen WHERE scenario_id = $1 ORDER BY sort_order", [sid]), + pool.query("SELECT * FROM fp_kunden_summary WHERE scenario_id = $1 AND row_label = 'Bestandskunden gesamt' LIMIT 1", [sid]), ]) const personal = personalRes.rows const liquid = liquidRes.rows const betrieb = betriebRes.rows + const customersByMonth = (kundenRes.rows[0]?.values as MonthlyValues) || emptyMonthly() // Helper to sum a field across personnel function sumPersonalField(field: string): MonthlyValues { @@ -92,9 +94,9 @@ export async function finanzplanToFMResults(pool: Pool, scenarioId?: string): Pr month: m, year, month_in_year: month, - new_customers: 0, + new_customers: Math.max((customersByMonth[`m${m}`] || 0) - prevCustomers, 0), churned_customers: 0, - total_customers: 0, + total_customers: Math.round(customersByMonth[`m${m}`] || 0), mrr_eur: Math.round(rev / 1), // monthly arr_eur: Math.round(rev * 12), revenue_eur: Math.round(rev), @@ -113,6 +115,7 @@ export async function finanzplanToFMResults(pool: Pool, scenarioId?: string): Pr cash_balance_eur: Math.round(cash), cumulative_revenue_eur: Math.round(cumulativeRevenue), }) + prevCustomers = customersByMonth[`m${m}`] || 0 } // Summary From cd23ebc3ba7b2118cdf24cec86874c48d802c6b5 Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Wed, 20 May 2026 10:10:58 +0200 Subject: [PATCH 04/11] fix(pitch-print): density on Problem/Solution/Strategy, Ask reconciliation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per user review of the rendered PDF. Problem: empty bottom-third on each card → added a bottom stat block per column showing 3 pulled-out data points (e.g. "64% · 70% · 83%") with red hero numerals. Description text trimmed since the stats now carry the punch. Solution: pillar bodies were short, leaving large gaps between description and the green stat at the bottom. Added 5 detail bullets per pillar (specific tools, frameworks, behaviours) in the previously empty middle. Stat at the bottom now reads as a real KPI tile, not a floating value. Strategy: phase KPI was a tiny corner tag. Promoted it to a bottom "Outcome" block with side-by-side 14pt numerals matching the phase tone (2 Kunden / ARR €40k etc.). The bullets get more breathing room above. The Ask reconciliation (was showing nonsense €4M pre / €5M post / 20% investor share for a €200k Wandeldarlehen): detect convertible/SAFE/ Wandeldarlehen and swap the tiles to Funding / Discount / Maturity / INVEST-grant. Equity rounds compute Pre/Post from amount × 20% assumed investor share. Same conditional applied to the cover key-terms grid. Pricing label "Was der Kunde zahlt vs. spart (KMU 50 MA, Jahr 1)" was wrapping "1)" onto its own line — switched to a slash-separated form ("Kunde zahlt vs. spart · KMU 50 MA · Jahr 1") that fits on one line. Co-Authored-By: Claude Opus 4.7 --- .../_components/PrintAnnexSlides.tsx | 34 +++-- .../_components/PrintIntroSlides.tsx | 144 +++++++++++++++--- .../_components/PrintMarketSlides.tsx | 37 ++++- .../_components/PrintProductSlides.tsx | 2 +- 4 files changed, 175 insertions(+), 42 deletions(-) diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx index ecaca0c..3b73ed1 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx @@ -81,19 +81,29 @@ export function PrintStrategyPage({ lang, pageNum, totalPages, versionName }: Sl return ( - ( -
-
- {p.n} - {p.kpi} + { + // Split "2 Kunden · ARR €40k" into pieces for a richer outcome block + const kpiParts = p.kpi.split(' · ') + return ( +
+ {p.n} +
{p.t}
+
{p.subtitle}
+
+ +
+ {/* 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}
+ ))} +
+
-
{p.t}
-
{p.subtitle}
-
- -
-
- ))} /> + ) + })} />
diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx index fd1c27f..66ddd43 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx @@ -13,6 +13,22 @@ export function PrintCoverPage({ company, funding, lang, versionName }: { compan 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 ? 'Standort' : 'HQ', company?.hq_city || 'Bodman'], + ] + : [ + [de ? 'Funding' : 'Funding', amountLabel], + [de ? 'Pre-Money' : 'Pre-money', '€4.0M'], + [de ? 'Instrument' : 'Instrument', instrument], + [de ? 'Standort' : 'HQ', company?.hq_city || 'Bodman'], + ] return (
@@ -87,12 +103,7 @@ export function PrintCoverPage({ company, funding, lang, versionName }: { compan {de ? 'Key Terms' : 'Key terms'}
- {([ - [de ? 'Funding' : 'Funding', amountLabel], - [de ? 'Pre-Money' : 'Pre-money', '€4.0M'], - [de ? 'Instrument' : 'Instrument', instrument], - [de ? 'Standort' : 'HQ', company?.hq_city || 'Bodman'], - ] as [string, string][]).map(([label, val]) => ( + {coverTerms.map(([label, val]) => (
{label}
{val}
@@ -341,14 +352,50 @@ export function PrintExecSummaryPage2({ lang, pageNum, totalPages, versionName } /* ===== 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. Wer auf US-KI verzichtet, verliert den Anschluss. Wer sie nutzt, riskiert seine Datensouveränität.', cite: 'Bitkom Cloud Monitor 2024 · DIHK Digitalisierungsumfrage 2024' }, - { 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. Das Schrems-II-Urteil des EuGH hat das bestätigt.', cite: 'EuGH C-311/18 (Schrems II, 2020)' }, - { 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. Pentests 15-40k €, CE-Risiko 10-25k €. KMU können das allein nicht mehr stemmen.', cite: 'VDMA Compliance-Kosten Maschinenbau 2024' }, + { 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. Those avoiding US AI fall behind. Those using it risk their data sovereignty.', cite: 'Bitkom Cloud Monitor 2024 · DIHK 2024' }, - { 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. The Schrems II ruling by the CJEU confirmed this.', cite: 'CJEU C-311/18 (Schrems II, 2020)' }, - { 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. Pentests €15-40k, CE risk €10-25k. SMEs can no longer handle this alone.', cite: 'VDMA Compliance Costs Manufacturing 2024' }, + { 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) { @@ -361,7 +408,16 @@ export function PrintProblemPage({ lang, pageNum, totalPages, versionName }: Sli
{c.kicker}
{c.stat}
-
{c.desc}
+
{c.desc}
+ {/* bottom stat block fills empty space and adds visual punch */} +
+ {c.pulls.map((p, j) => ( +
+
{p.v}
+
{p.l}
+
+ ))} +
))} /> @@ -379,14 +435,56 @@ export function PrintProblemPage({ lang, pageNum, totalPages, versionName }: Sli /* ===== 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' } }, - { kicker: 'PILLAR 02', t: 'Compliance auf Autopilot', d: 'VVT, TOMs, DSFA, Löschfristen, CE-Risikobeurteilung automatisch. Nach dem Audit: Abweichungen End-to-End, Rollen, Stichtage, Tickets, Nachweise, Eskalation an GF.', stat: { v: '80%', l: 'Zeitersparnis bei Compliance-Prüfungen' } }, - { kicker: 'PILLAR 03', t: 'Deutsche Cloud, volle Integration', d: 'BSI-zertifizierte Cloud in Deutschland. 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' } }, + { 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 Kleinstunternehmen', + '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 as tickets in the issue tracker of your choice, with implementation suggestions.', stat: { v: '€15k+', l: 'pentest costs saved / app / year' } }, - { kicker: 'PILLAR 02', t: 'Compliance on Autopilot', d: 'RoPA, TOMs, DPIA, retention policies, CE risk assessment automatically. Post-audit: deviations end-to-end, roles, deadlines, tickets, evidence, escalation to management.', stat: { v: '80%', l: 'time saved on compliance checks' } }, - { kicker: 'PILLAR 03', t: 'German Cloud, Full Integration', d: 'BSI-certified cloud in Germany. 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' } }, + { 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) { @@ -399,8 +497,12 @@ export function PrintSolutionPage({ lang, pageNum, totalPages, versionName }: Sl
{p.kicker}
{p.t}
-
{p.d}
-
+
{p.d}
+ {/* Detail bullets fill the remaining vertical space */} +
+ +
+
{p.stat.v}
{p.stat.l}
diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx index bab42b5..0c5782e 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintMarketSlides.tsx @@ -240,6 +240,31 @@ export function PrintTheAskPage({ funding, lang, pageNum, totalPages, versionNam 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' }, @@ -262,15 +287,11 @@ export function PrintTheAskPage({ funding, lang, pageNum, totalPages, versionNam
{instrument} · {funding?.round_name || 'Pre-Seed'} · {de ? 'Zielabschluss' : 'Target close'}: {formatTargetDate(funding?.target_date, de)}
-
- {[ - { l: de ? 'Pre-Money' : 'Pre-money', v: '€4.0M' }, - { l: de ? 'Post-Money' : 'Post-money', v: '€5.0M' }, - { l: de ? 'Investor-Anteil' : 'Investor share', v: '20%' }, - ].map((k, i) => ( +
+ {termTiles.map(([label, val], i) => (
-
{k.l}
-
{k.v}
+
{label}
+
{val}
))}
diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx index 07b7282..959382c 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx @@ -340,7 +340,7 @@ export function PrintBusinessModelPage({ lang, pageNum, totalPages, versionName
-
{de ? 'Was der Kunde zahlt vs. spart (KMU 50 MA, Jahr 1)' : 'What customer pays vs. saves (SME 50 emp., year 1)'}
+
{de ? 'Kunde zahlt vs. spart · KMU 50 MA · Jahr 1' : 'Customer pays vs. saves · SME 50 emp. · Y1'}
From 8b5b9905a774d0278a0db400ba52b1a36514a70c Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Wed, 20 May 2026 11:23:58 +0200 Subject: [PATCH 05/11] =?UTF-8?q?fix(pitch-print):=20port=20Claude=20Desig?= =?UTF-8?q?n=20tokens=20=E2=80=94=20violet,=20Inter+JBMono,=20dotted=20bg?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adapts the visual language from the Claude Design reference (light theme) while preserving our left-rule Page header and split-block cover. Color palette: indigo (#4f46e5) → violet (#7c3aed) as primary accent across all slides. COLORS.indigo* aliases kept so the existing 9 slide files inherit the new palette without edits. New explicit COLORS.violet50..900 names available for future code. Body text shifted from pure slate to deep purple-tinted (#1a0f34) per Claude tokens.fg. Typography: - Body / headings: Inter (was Plus Jakarta Sans) - Mono utility: JetBrains Mono — applied to kicker tags, page numbers, footer, the "At a glance" stat block on the cover, and the cover key-term labels - Mono class .print-mono added to print.css Background: - New .print-page-bg utility paints a violet-tinted radial gradient (white → #f5efff → #ebdfff) with a subtle 24px dotted grid SVG overlay - Applied to every Page and the cover's right pane Page chrome: - Kicker label switched to JetBrains Mono with wider letter-spacing (0.18em) - Right-of-kicker rule fades violet→transparent (was flat slate) - New 2px violet gradient bar (700→400→700) below the title/subtitle — the Claude Design "purple bar" accent, scaled down for print - Footer restyled: mono caps "BREAKPILOT · COMPLAI" left, version (violet) middle, page number right Cover: - Left block now a violet vertical gradient (was flat indigo) - All small labels ("Investor Brief", "Auf einen Blick", "Confidential", "Key Terms", and the term labels) restyled to JetBrains Mono with wider tracking - Right pane carries the violet-tinted dotted bg, matching the rest of the deck Co-Authored-By: Claude Opus 4.7 --- .../_components/PrintIntroSlides.tsx | 50 +++++----- .../[versionId]/_components/PrintLayout.tsx | 95 ++++++++++++------- pitch-deck/app/pitch-print/print.css | 60 ++++++++---- 3 files changed, 121 insertions(+), 84 deletions(-) diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx index 66ddd43..d9d6c7f 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx @@ -30,20 +30,16 @@ export function PrintCoverPage({ company, funding, lang, versionName }: { compan [de ? 'Standort' : 'HQ', company?.hq_city || 'Bodman'], ] + const MONO_FONT = "'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace" + return (
-
- {/* - The .print-page class in print.css forces flex-direction: column !important, - which would collapse a horizontal flex split. We sidestep that by putting a - single full-size grid container as the only child — the column-flex parent - has just one item so direction no longer matters. - */} +
- {/* LEFT INDIGO BLOCK */} + {/* 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.' @@ -65,27 +61,27 @@ export function PrintCoverPage({ company, funding, lang, versionName }: { compan
{/* 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 ? '500 K + Lines of Code · 45 Container' : '500 K + lines of code · 45 containers'}
- {de ? '100 % EU-Hosting · BSI Cloud DE' : '100 % EU hosting · BSI cloud DE'} +
+
{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'}
+
{versionName}
+
{de ? 'Vertraulich · Nur Investoren' : 'Confidential · Investors only'}
- {/* RIGHT WHITE PANE */} -
+ {/* RIGHT (violet-tinted dotted bg from .print-page-bg) PANE */} +
-
+
{instrument} · Q4 2026

@@ -99,18 +95,18 @@ export function PrintCoverPage({ company, funding, lang, versionName }: { compan {/* Key terms */}
-
+
{de ? 'Key Terms' : 'Key terms'}
{coverTerms.map(([label, val]) => (
-
{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.'} diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintLayout.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintLayout.tsx index 0d308f8..6cf1c09 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintLayout.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintLayout.tsx @@ -2,21 +2,41 @@ import React from 'react' /* ===== 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 = { - slate900: '#0f172a', - slate800: '#1e293b', - slate700: '#334155', - slate600: '#475569', - slate500: '#64748b', - slate400: '#94a3b8', - slate300: '#cbd5e1', - slate200: '#e2e8f0', - slate100: '#f1f5f9', - slate50: '#f8fafc', - indigo700: '#4338ca', - indigo600: '#4f46e5', - indigo500: '#6366f1', - indigo50: '#eef2ff', + // 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', @@ -26,16 +46,17 @@ export const COLORS = { amber700: '#b45309', amber600: '#d97706', amber50: '#fffbeb', - // legacy aliases for migrating callers - dark: '#0f172a', - med: '#334155', - light: '#64748b', - border: '#e2e8f0', - indigo: '#4f46e5', - indigoLight: '#eef2ff', + // 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 = "'Plus Jakarta Sans', 'Inter', system-ui, -apple-system, sans-serif" +const FONT = "'Inter', 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif" +const MONO_FONT = "'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace" /* ===== PAGE WRAPPER ===== */ @@ -54,10 +75,9 @@ interface PageProps { export function Page({ kicker, section, title, subtitle, pageNum, totalPages, versionName, children, footnote }: PageProps) { return (
-
- {/* TITLE BLOCK */} -
+ {/* TITLE BLOCK — left-rule preserved */} +
+
- + {kicker} · {section} - - BreakPilot · {versionName} + + BreakPilot · ComplAI
-

+

{title}

{subtitle && ( -

+

{subtitle}

)} + {/* Subtle violet accent gradient bar — echo of the Claude Design feel */} +
@@ -103,10 +126,10 @@ export function Page({ kicker, section, title, subtitle, pageNum, totalPages, ve
)} - {/* FOOTER */} -
- BreakPilot · {versionName} - CONFIDENTIAL + {/* FOOTER — JetBrains Mono caps to match Claude Design */} +
+ BreakPilot · ComplAI + {versionName} {String(pageNum).padStart(2, '0')} / {String(totalPages).padStart(2, '0')}
diff --git a/pitch-deck/app/pitch-print/print.css b/pitch-deck/app/pitch-print/print.css index 0712054..5897fe1 100644 --- a/pitch-deck/app/pitch-print/print.css +++ b/pitch-deck/app/pitch-print/print.css @@ -1,9 +1,30 @@ +/* Fonts: Inter (body/headings) + JetBrains Mono (kickers, tickers, page numbers). + Plus Jakarta Sans is still loaded by globals.css; we don't need it for print. */ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600;700&display=swap'); + /* Named page — must be outside @media print */ @page slide-page { size: A4 landscape; margin: 0; } +/* + * Page background: violet-tinted radial gradient with a faint dotted-grid + * overlay (printed via two layered background-images on .print-page). + * + * The radial mimics Claude Design's `radial-gradient(ellipse at 50% 12%, #fff 0%, #f5efff 55%, #ebdfff 100%)`. + * The dots are a tiny SVG repeat tile at 24px pitch, ~6% slate, so the grid is + * just barely visible — same role as the dot-grid in the design reference. + */ +.print-page-bg { + background-color: #ffffff; + background-image: + url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Ccircle cx='1' cy='1' r='0.6' fill='%23a78bfa' fill-opacity='0.18'/%3E%3C/svg%3E"), + radial-gradient(ellipse at 50% 8%, #ffffff 0%, #f5efff 55%, #ebdfff 100%); + background-repeat: repeat, no-repeat; + background-size: 24px 24px, cover; +} + @media screen { body { background: #d1d5db; } } @@ -14,20 +35,15 @@ margin: 0; } - /* - * globals.css sets html,body { height:100%; overflow:hidden; background:#0a0a1a }. - * In print mode that clips all content to one viewport height and renders a black - * background. Override everything here. - */ html, body { height: auto !important; min-height: 0 !important; overflow: visible !important; background: #ffffff !important; - color: #0f172a !important; + color: #1a0f34 !important; margin: 0 !important; padding: 0 !important; - font-family: 'Plus Jakarta Sans', 'Inter', system-ui, -apple-system, sans-serif !important; + font-family: 'Inter', 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif !important; -webkit-print-color-adjust: exact; -moz-print-color-adjust: exact; print-color-adjust: exact; @@ -43,13 +59,10 @@ margin: 0 !important; display: block !important; overflow: visible !important; - font-family: 'Plus Jakarta Sans', 'Inter', system-ui, sans-serif !important; + font-family: 'Inter', system-ui, sans-serif !important; } - /* - * Block wrapper: carries the height AND the page break. - * height:210mm on display:block is reliable in both Chrome and Firefox. - */ + /* Block wrapper carries the height + page break. */ .print-page-break { page: slide-page; display: block !important; @@ -75,24 +88,29 @@ overflow: hidden !important; margin: 0 !important; box-shadow: none !important; - background: #ffffff !important; - font-family: 'Plus Jakarta Sans', 'Inter', system-ui, sans-serif !important; - color: #0f172a !important; + font-family: 'Inter', system-ui, sans-serif !important; + color: #1a0f34 !important; -webkit-print-color-adjust: exact; -moz-print-color-adjust: exact; print-color-adjust: exact; } - /* Tabular numerals everywhere — institutional research aesthetic */ - .print-page table, - .print-page .num, - .print-page .kpi { + /* Tabular numerals everywhere */ + .print-page table, .print-page .num, .print-page .kpi { font-variant-numeric: tabular-nums; } + + /* Mono utility — for kickers, page numbers, tickers, code-style tags */ + .print-mono { + font-family: 'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace !important; + } } -/* Screen preview: apply Plus Jakarta Sans to print pages even on screen */ +/* Screen preview: same fonts, applied to print-page on screen too */ .print-page, .print-page-break { - font-family: 'Plus Jakarta Sans', 'Inter', system-ui, sans-serif; + font-family: 'Inter', system-ui, sans-serif; font-variant-numeric: tabular-nums; } +.print-mono { + font-family: 'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace; +} From 12a9fe1810f25b0b62c5aa216531fce64cd3f454 Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Wed, 20 May 2026 11:57:58 +0200 Subject: [PATCH 06/11] fix(pitch-print): drop Standort/HQ from cover key terms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 3-column grid now: Funding · Pre-Money/Maturity · Instrument. Co-Authored-By: Claude Opus 4.7 --- .../pitch-print/[versionId]/_components/PrintIntroSlides.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx index d9d6c7f..4db6990 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx @@ -21,13 +21,11 @@ export function PrintCoverPage({ company, funding, lang, versionName }: { compan [de ? 'Funding' : 'Funding', amountLabel], [de ? 'Instrument' : 'Instrument', instrument], [de ? 'Laufzeit' : 'Maturity', de ? '24 Mo.' : '24 mo'], - [de ? 'Standort' : 'HQ', company?.hq_city || 'Bodman'], ] : [ [de ? 'Funding' : 'Funding', amountLabel], [de ? 'Pre-Money' : 'Pre-money', '€4.0M'], [de ? 'Instrument' : 'Instrument', instrument], - [de ? 'Standort' : 'HQ', company?.hq_city || 'Bodman'], ] const MONO_FONT = "'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace" @@ -98,7 +96,7 @@ export function PrintCoverPage({ company, funding, lang, versionName }: { compan
{de ? 'Key Terms' : 'Key terms'}
-
+
{coverTerms.map(([label, val]) => (
{label}
From f1814fe8ecec36fa60cb2d76ad9b6ebf85b8cb0f Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Wed, 20 May 2026 12:08:50 +0200 Subject: [PATCH 07/11] fix(pitch-print): USP overflow, How It Works rail, Assumptions, Architecture layer cards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Five fixes per user review: 1. USP p1 overflow (stats were getting clipped). Tightened card spacing: - icon tile 12mm → 9mm, moved inline next to title - mono kicker for "SÄULE · COMPLIANCE" tags - reduced paddings, title 13pt → 12pt, body 8.5pt → 8pt - violet replaces indigo (already by alias, but explicit here) 2. USP p2 closing loop: was a plain tinted callout, now a 2-col hero panel - left: violet circle around ∞, mono "DIE SCHLEIFE · ALWAYS IN SYNC", bold headline (14pt), body - right: white card containing the LoopDiagram with violet outline - gradient violet→white→violet background for the panel 3. How It Works: replaced the floating-arrow StepStrip with a real horizontal-rail timeline: - Violet gradient connector line behind 4 numbered circles - Each circle is a 14mm violet disc with the step number - Title + body below each circle Replaced the Time-to-Value callout with a dotted-rail timeline: - 5 day markers (Tag 0/3/7/14/30) as violet pill chips on a dashed rail - Stop label below each - Mono header reads "Time-to-Value · Median 14 Tage · Worst Case 28 Tage" 4. Assumptions slide: - "Skalare Annahmen" → "Treibervariablen des Finanzplans" (plain language) - subtitle rewritten to explain the three-scenario sensitivity setup instead of referencing internal fp_assumptions tables - each category now a violet-bordered card with mono kicker + variable count, italic instead of bare table - sensitivity callout expanded with concrete runway impact numbers 5. Architecture diagram: layer chips per Claude Design pattern. - Each tier wrapped in a tinted rounded card (violet for product + inference, amber for gateway) - "01 · APPLICATION LAYER" mono pill with italic sub-label ("User-facing services") next to it - Gateway layer carries the LiteLLM Proxy title inline with subtitle - Connector arrows kept between layers Also fixes "Kleinstunternehmen" → "Kleinunternehmen" typo in solution pillar 03 and the product pricing-logic callout. Co-Authored-By: Claude Opus 4.7 --- .../[versionId]/_components/PrintDiagrams.tsx | 74 ++++++------ .../_components/PrintFinancialSlides.tsx | 32 ++--- .../_components/PrintIntroSlides.tsx | 2 +- .../_components/PrintProductSlides.tsx | 110 +++++++++++++----- 4 files changed, 138 insertions(+), 80 deletions(-) diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintDiagrams.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintDiagrams.tsx index cd22da9..7fdf77b 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintDiagrams.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintDiagrams.tsx @@ -127,59 +127,61 @@ export function ArchitectureDiagram({ 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} +
+ ) + + const productLayerBg = `linear-gradient(135deg, ${COLORS.violet50} 0%, #ffffff 50%, ${COLORS.violet50} 100%)` + const proxyLayerBg = `linear-gradient(135deg, ${COLORS.amber50} 0%, #fffaf0 50%, ${COLORS.amber50} 100%)` + return ( -
- {/* PRODUCT TIER */} -
-
{de ? 'Produkt-Schicht' : 'Product Tier'}
+
+ {/* APPLICATION (PRODUCT) LAYER */} +
+
{product.map((p, i) => ( - + ))}
- {/* Down arrows between product and proxy */} -
- {[0, 1, 2].map(i => )} + {/* connectors */} +
+ {[0, 1, 2].map(i => )}
- {/* PROXY */} -
-
-
-
- {de ? 'Gateway' : 'Gateway'} - {proxy.title} - {proxy.subtitle} -
-
-
- {proxy.features.map((f, i) => ( -
{f}
- ))} -
+ {/* GATEWAY LAYER */} +
+ +
+ {proxy.title} + {proxy.subtitle} +
+
+ {proxy.features.map((f, i) => ( +
{f}
+ ))}
- {/* Down arrows between proxy and inference */} -
+ {/* connectors */} +
{[0, 1, 2].map(i => )}
- {/* INFERENCE TIER */} -
-
{de ? 'Inferenz-Schicht (lokal, air-gap-fähig)' : 'Inference Tier (local, air-gap capable)'}
+ {/* INFRASTRUCTURE (INFERENCE) LAYER */} +
+
{inference.map((p, i) => ( - + ))}
diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx index 20a0f1a..af5f00a 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx @@ -219,21 +219,27 @@ export function PrintAssumptionsPage({ assumptions, lang, pageNum, totalPages, v }, {}) const categories = Object.entries(byCategory) + const MONO = "'JetBrains Mono', ui-monospace, monospace" return ( - + -
- {categories.slice(0, 6).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 => ( - + {items.map((a, j) => ( + 0 ? `1px solid ${COLORS.slate100}` : 'none' }}> ))} @@ -243,11 +249,11 @@ export function PrintAssumptionsPage({ assumptions, lang, pageNum, totalPages, v ))} -
- +
+ {de - ? 'Drei Szenarien, Best/Base/Worst, variieren um Wachstumsrate, Churn, ARPU und CAC. Sensitivitäts-Tornado verfügbar im Live-Modell. Base-Case ist absichtlich konservativ angesetzt.' - : 'Three scenarios, best/base/worst, vary growth rate, churn, ARPU and CAC. Sensitivity tornado available in live model. Base case is deliberately conservative.'} + ? '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.'}
diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx index 4db6990..eb531c7 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintIntroSlides.tsx @@ -450,7 +450,7 @@ const DE_PILLARS = [ '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 Kleinstunternehmen', + 'Optional: Mac Mini/Studio on-premise für Kleinunternehmen', 'Vault, Keycloak, OPA für Secrets, SSO, Policies', ] }, ] diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx index 959382c..3baae15 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx @@ -1,6 +1,6 @@ import { Language, PitchProduct } from '@/lib/types' import { Page, Bullets, Callout, COLORS, DataTable, StatLine } from './PrintLayout' -import { StepStrip, LoopDiagram } from './PrintDiagrams' +import { LoopDiagram } from './PrintDiagrams' import { getDetails } from '@/components/slides/USPSlide.data' import { ScanLine, ShieldCheck, FileText, ClipboardCheck, Users, UserCheck, @@ -26,28 +26,31 @@ export function PrintUSPPage1({ lang, pageNum, totalPages, versionName }: SlideB return ( -
+
{pillars.map((k, i) => { const p = d[k] const Icon = USP_ICON[k] return ( -
-
-
- {Icon && } +
+ {/* Header: icon + title inline, kicker top-right */} +
+
+ {Icon && }
-
-
{p.kicker}
-
{String(i + 1).padStart(2, '0')} / 04
+
+
+ {p.kicker} + {String(i + 1).padStart(2, '0')} / 04 +
+
{p.title}
-
{p.title}
-
{p.body}
+
{p.body}
{p.bullets && } {p.stat && ( -
- {p.stat.k} - {p.stat.v} +
+ {p.stat.k} + {p.stat.v}
)}
@@ -86,14 +89,21 @@ export function PrintUSPPage2({ lang, pageNum, totalPages, versionName }: SlideB })}
-
-
- - {de ? 'Die Schleife' : 'The Loop'} + {/* Closing loop: violet-tinted hero panel with the diagram on the right */} +
+
+
+
+ +
+ {de ? 'Die Schleife · Always in Sync' : 'The Loop · Always in Sync'} +
+
{d.hub.title}
+
{d.hub.body}
+
+
+
-
{d.hub.title}
-
{d.hub.body}
-
) @@ -252,7 +262,7 @@ export function PrintProductPage({ products, lang, pageNum, totalPages, versionN
{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 Kleinstunternehmen.' + ? '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.'}
@@ -275,22 +285,62 @@ const STEPS_EN = [ { 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}
+
+ ))} +
-
- - {de - ? 'Tag 0: Vertrag · Tag 3: Onboarding-Call · Tag 7: erste Repos angebunden · Tag 14: erste automatische VVT/TOMs · Tag 30: audit-ready Status erreicht.' - : 'Day 0: contract · Day 3: onboarding call · Day 7: first repos connected · Day 14: first automated RoPA/TOMs · Day 30: audit-ready status achieved.'} - + {/* 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]}
+
+ ))} +
+
) From cb46372e52af7b4b3e72180af4483a67355d576d Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Wed, 20 May 2026 12:25:56 +0200 Subject: [PATCH 08/11] =?UTF-8?q?fix(pitch-print):=20architecture=20diagra?= =?UTF-8?q?m=20overflow=20=E2=80=94=20compact=20ServiceNode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Infrastructure layer was being cut off (only the chip showed; the 3 inference service cards never rendered). Root cause: each tier was double-wrapped — an outer tinted layer card AND inner bordered FlowNode cards — which inflated the total height past A4 landscape. Replaces inner FlowNode (border + padding + footer rule) with a new flat ServiceNode used only inside the tinted layer wrappers: - no own border / no own padding - title 11pt → 10pt, kicker 7pt → 6pt - caps inner items to 4 max - mono tech footer in 6pt with hairline separator Also tightened the connectors between tiers: was a 12mm row of three VArrow SVGs each with its own padding, now a 5mm row of three compact down-arrow SVGs. Saves ~14mm of vertical space. Layer chip sizing reduced (7.5pt → 7pt, padding 1.5mm → 1mm) so each chip takes less of its layer card. Result: all three layers fit on one A4 landscape page with the LLM Inference / Embeddings / AI Tools cards visible. Co-Authored-By: Claude Opus 4.7 --- .../[versionId]/_components/PrintDiagrams.tsx | 81 +++++++++++++------ 1 file changed, 57 insertions(+), 24 deletions(-) diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintDiagrams.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintDiagrams.tsx index 7fdf77b..c27628b 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintDiagrams.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintDiagrams.tsx @@ -131,57 +131,90 @@ export function ArchitectureDiagram({ /** Layer pill: "01 · APPLICATION LAYER" + sub-label */ const LayerChip = ({ n, label, sub, tint }: { n: string; label: string; sub: string; tint: string }) => ( -
- {n} · {label} - {sub} +
+ {n} · {label} + {sub}
) - const productLayerBg = `linear-gradient(135deg, ${COLORS.violet50} 0%, #ffffff 50%, ${COLORS.violet50} 100%)` - const proxyLayerBg = `linear-gradient(135deg, ${COLORS.amber50} 0%, #fffaf0 50%, ${COLORS.amber50} 100%)` + /** + * 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) => ( - + ))}
- {/* connectors */} -
- {[0, 1, 2].map(i => )} + {/* compact connector strip */} +
+ {[0, 1, 2].map(i => ( +
+ + + + +
+ ))}
- {/* GATEWAY LAYER */} -
+ {/* GATEWAY LAYER — compact: title row + features in 1 row */} +
-
- {proxy.title} - {proxy.subtitle} +
+ {proxy.title} + {proxy.subtitle}
-
+
{proxy.features.map((f, i) => ( -
{f}
+
{f}
))}
- {/* connectors */} -
- {[0, 1, 2].map(i => )} + {/* compact connector strip */} +
+ {[0, 1, 2].map(i => ( +
+ + + + +
+ ))}
{/* INFRASTRUCTURE (INFERENCE) LAYER */} -
+
-
+
{inference.map((p, i) => ( - + ))}
From d1b55cd65bbf78e648077bfce0a7cd47817c622b Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Wed, 20 May 2026 12:54:31 +0200 Subject: [PATCH 09/11] feat(pitch-print): redesign Pricing slide as 3 distinct product cards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pricing slide previously rendered as a 4-column DataTable buried below unit economics — the 3 tiers were hard to find. Rebuilt as the Claude Design PREISE pattern: three prominent product cards side by side. Each card: - Mono tier label kicker (STARTER / PROFESSIONAL / ENTERPRISE) at top - Target audience line ("<25 Mitarbeiter · Basis-Module" etc.) - Hero price (€3.600 / €18.000 / ab €50.000) + /Jahr unit - 4–5 feature checkmarks (green ✓) - Tinted background per tier: violet-50 for Starter, white-gradient for featured Professional, amber-50 for Enterprise Professional card carries: - 2px violet border (vs 1px on others) - Drop shadow - "BELIEBT" / "POPULAR" pill badge floating above its top edge in violet Below the 3 cards, a compact 2-col footer: - left: 4 Unit Economics tiles (~70% gross margin, ~3.5× LTV/CAC, etc.) - right: emerald net-effect callout (+€30k per SME / yr) Co-Authored-By: Claude Opus 4.7 --- .../_components/PrintProductSlides.tsx | 148 ++++++++++++------ 1 file changed, 104 insertions(+), 44 deletions(-) diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx index 3baae15..da39017 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx @@ -1,5 +1,5 @@ import { Language, PitchProduct } from '@/lib/types' -import { Page, Bullets, Callout, COLORS, DataTable, StatLine } from './PrintLayout' +import { Page, Bullets, Callout, COLORS, DataTable } from './PrintLayout' import { LoopDiagram } from './PrintDiagrams' import { getDetails } from '@/components/slides/USPSlide.data' import { @@ -350,59 +350,119 @@ export function PrintHowItWorksPage({ lang, pageNum, totalPages, versionName }: 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 ( - + -
-
-
{de ? 'Pricing-Tiers' : 'Pricing tiers'}
- + {/* 3 product cards */} +
+ {tiers.map((t) => ( +
+ {/* Featured badge */} + {t.featured && ( +
{de ? 'Beliebt' : 'Popular'}
+ )} -
-
{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}
+
{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 ? 'Kunde zahlt vs. spart · KMU 50 MA · Jahr 1' : 'Customer pays vs. saves · SME 50 emp. · Y1'}
-
- - - - - - +
+
{de ? 'Netto-Effekt · KMU 50 MA / Jahr 1' : 'Net effect · SME 50 emp. / Y1'}
+
+
+€30k
+
{de ? 'pro KMU / Jahr' : 'per SME / yr'}
-
-
{de ? 'Netto-Effekt Jahr 1' : 'Net effect year 1'}
-
+€30.000
-
{de ? 'Kunde spart €55k, zahlt €25k. ROI ab Tag 1.' : 'Customer saves €55k, pays €25k. ROI from day 1.'}
+
+ {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.'}
From ad61fd37797173526bc5ace26279dd71e39a9106 Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Wed, 20 May 2026 12:58:53 +0200 Subject: [PATCH 10/11] feat(pitch-print): add Anhang divider slide before appendix block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Investors arriving at slide 16 (Customer Savings) currently jump straight into annex-strategy without any chapter break — they don't know the main pitch has ended and the appendix has started. Adds PrintAnnexDividerPage that sits between customer-savings and annex-strategy. Layout: Part II · Anhang BreakPilot · ComplAI ───────────────────────────────────────────────────────── 16 · Kapitelwechsel Anhang. (giant violet-dotted title, 74pt) ──────── Detail & Belege. (15pt lead) Auf den folgenden Seiten 17 GTM Strategie 20 Reg. Details 23 KI-Pipeline 18 Finanzplan 21 Architektur 24 Risiken 19 Treibervariablen 22 Engineering 25 Glossar ───────────────────────────────────────────────────────── BREAKPILOT · COMPLAI WANDELDARLEHEN 16 / 30 Uses .print-page-bg so the violet-tinted dotted background reads as the same chapter as the rest of the deck. Footer matches the standard Page primitive. BASE_PAGES bumped 29 → 30. Bilingual (DE/EN). Co-Authored-By: Claude Opus 4.7 --- .../_components/PrintAnnexSlides.tsx | 102 ++++++++++++++++++ .../[versionId]/_components/PrintDeck.tsx | 16 +-- 2 files changed, 112 insertions(+), 6 deletions(-) diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx index 3b73ed1..19e5e1d 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx @@ -4,6 +4,108 @@ import { ArchitectureDiagram, PipelineFlow } from './PrintDiagrams' interface SlideBase { lang: Language; pageNum: number; totalPages: number; versionName: string } +/* ===== ANHANG DIVIDER ===== */ + +/** + * Chapter-break slide that sits between the main pitch and the appendix. + * Bypasses the standard Page chrome to render as a hero divider, but keeps + * a footer row consistent with all other slides. + */ +export function PrintAnnexDividerPage({ lang, pageNum, totalPages, versionName }: SlideBase) { + const de = lang === 'de' + const MONO = "'JetBrains Mono', ui-monospace, monospace" + + const sections: [string, string, string][] = de ? [ + ['17', 'Go-to-Market Strategie', 'Pilot · Skalierung · Expansion'], + ['18', 'Finanzplan', 'P&L 2026–2030 · KPI-Dashboard'], + ['19', 'Treibervariablen', 'Annahmen + Sensitivitätsszenarien'], + ['20', 'Regulatorische Details', 'DSGVO · AI Act · NIS-2 · CRA · MaschVO'], + ['21', 'Systemarchitektur', '3 Tiers · LiteLLM Gateway · lokale Inferenz'], + ['22', 'Engineering Deep Dive', '500K+ LoC · 45 Container · 100 % Self-Hosted'], + ['23', 'KI-Pipeline', 'RAG · Multi-Agent · Document Intelligence · QA'], + ['24', 'Risiken & Mitigation', '10 Risiken in 5 Kategorien'], + ['25', 'Glossar', '30 Begriffe · Compliance · Engineering · Recht'], + ] : [ + ['17', 'Go-to-Market Strategy', 'Pilot · Scale · Expansion'], + ['18', 'Financial Plan', 'P&L 2026–2030 · KPI dashboard'], + ['19', 'Driver Variables', 'Assumptions + sensitivity scenarios'], + ['20', 'Regulatory Details', 'GDPR · AI Act · NIS-2 · CRA · Machinery Reg.'], + ['21', 'System Architecture', '3 tiers · LiteLLM gateway · local inference'], + ['22', 'Engineering Deep Dive', '500K+ LoC · 45 containers · 100 % self-hosted'], + ['23', 'AI Pipeline', 'RAG · multi-agent · document intelligence · QA'], + ['24', 'Risks & Mitigation', '10 risks across 5 categories'], + ['25', 'Glossary', '30 terms · compliance · engineering · law'], + ] + + return ( +
+
+ + {/* Top meta row */} +
+ {de ? 'Teil II · Anhang' : 'Part II · Appendix'} + BreakPilot · ComplAI +
+ + {/* Hero */} +
+
+ {de ? '16 · Kapitelwechsel' : '16 · 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.'} +

+ + {/* What's coming */} +
+
+ {de ? 'Auf den folgenden Seiten' : 'On the following pages'} +
+
+ {sections.map(([n, t, sub]) => ( +
+ {n} +
+
{t}
+
{sub}
+
+
+ ))} +
+
+
+ + {/* Footer (matches Page primitive) */} +
+ BreakPilot · ComplAI + {versionName} + {String(pageNum).padStart(2, '0')} / {String(totalPages).padStart(2, '0')} +
+
+
+ ) +} + /* ===== STRATEGY / GO-TO-MARKET ===== */ export function PrintStrategyPage({ lang, pageNum, totalPages, versionName }: SlideBase) { diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx index 8a15d6f..34b68ff 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx @@ -18,6 +18,7 @@ import { PrintCompetitionPage1, PrintCompetitionPage2, } from './PrintCompetitionSlides' import { + PrintAnnexDividerPage, PrintStrategyPage, PrintRegulatoryPage, PrintArchitecturePage, PrintEngineeringPage, PrintAIPipelinePage, PrintRisksPage, PrintGlossaryPage, } from './PrintAnnexSlides' @@ -46,13 +47,13 @@ export default function PrintDeck({ pitchData, versionName, fmResults, fmAssumpt const hasFinancialDetail = financial && annualRows.length > 0 const de = lang === 'de' - // Base standard PDF: 29 physical pages. + // Base standard PDF: 30 physical pages. // 2 (exec) + 1 (cover) + 1 (problem) + 1 (solution) + 2 (usp) + 1 (regL) + // 1 (product) + 1 (how) + 1 (market) + 1 (bm) + 1 (milestones) + 2 (competition) + - // 1 (team) + 1 (ask) + 1 (savings) + 1 (strategy) + 2 (finanzplan) + - // 1 (assumptions) + 1 (regulatory) + 1 (architecture) + 1 (engineering) + - // 1 (aipipeline) + 1 (risks) + 1 (glossary) + 1 (disclaimer) = 29 - const BASE_PAGES = 29 + // 1 (team) + 1 (ask) + 1 (savings) + 1 (anhang-divider) + 1 (strategy) + + // 2 (finanzplan) + 1 (assumptions) + 1 (regulatory) + 1 (architecture) + + // 1 (engineering) + 1 (aipipeline) + 1 (risks) + 1 (glossary) + 1 (disclaimer) = 30 + const BASE_PAGES = 30 const totalPages = BASE_PAGES + (hasFinancialDetail ? 1 : 0) + (hasCapTable ? 1 : 0) useEffect(() => { @@ -144,7 +145,10 @@ export default function PrintDeck({ pitchData, versionName, fmResults, fmAssumpt {/* 15. customer-savings */} - {/* 16. annex-strategy */} + {/* 16. ANHANG divider — chapter break before the appendix block */} + + + {/* 17. annex-strategy */} {/* 17. annex-finanzplan (2 pages) */} From b4043b20b2c4fdd62922225554492c769e844d5f Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Wed, 20 May 2026 13:11:02 +0200 Subject: [PATCH 11/11] feat(pitch-print): TL;DR + Differentiators + KPIs + Tech Stack + P&L promoted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the 5 slides flagged as missing vs Claude Design (30 slides). Standard PDF now matches Claude's slide count and structure. New slides (PrintNewSlides.tsx): - TL;DR / 30 SEKUNDEN — 4 quad cards (Scale / Sovereignty / Bidirectional / Speed) with mono kicker, hero stat, body and ticker line. Slot 3, after the exec summary. - Differentiators — 4 under-the-hood cards (Traceability / Engine / Optimizer / EU-Trust-Stack) extracted from USP p2. Slot 9, after USP. Each card has the lucide icon in a violet/amber tile, full body + bullets, and the mono ticker line. - KPIs (Trajektorie 2026 → 2030) — 8 hero tiles showing year-1 → year-5 transitions (ARR, customers, ARPU, employees, gross margin, EBIT, net income, cash). Derived live from computeAnnualKPIs(fmResults). Slot 23. - Tech Stack — 8-category grid (Frontend / Backend / Storage / AI-RAG / Code-Scanning / Auth / Comms / DevOps), each with lucide icon tile + category label + monospaced tech list. Slot 31, after Engineering. USP p2 redesigned: now hero-sized closing loop only (the 4 cards moved to Differentiators). Bigger LoopDiagram in a violet-tinted hero panel, 12mm inner padding, more room for the hub body + bullets. P&L Detail (PrintFinancialsPage) promoted from financial-only to standard PDF. Kicker now 21 (was '17b'), subtitle rewritten ('Annualisierte GuV', no longer 'Investor-only'). Empty-data fallback added so it doesn't crash if fmResults isn't populated. Anhang divider moved from PrintAnnexSlides.tsx to PrintNewSlides.tsx (was pushing PrintAnnexSlides over the 500-LOC cap). Section list inside the divider updated for the new numbering — now 12 sections from #18 GTM down to #29 Glossary. PrintDeck.tsx: BASE_PAGES bumped 30 → 35. Render order updated; hasFinancialDetail flag removed (P&L always rendered); cap-table is the only remaining financial-only conditional and stays suppressed for Wandeldarlehen. Co-Authored-By: Claude Opus 4.7 --- .../_components/PrintAnnexSlides.tsx | 103 +----- .../[versionId]/_components/PrintDeck.tsx | 102 +++--- .../_components/PrintFinancialSlides.tsx | 11 +- .../_components/PrintNewSlides.tsx | 302 ++++++++++++++++++ .../_components/PrintProductSlides.tsx | 60 ++-- 5 files changed, 401 insertions(+), 177 deletions(-) create mode 100644 pitch-deck/app/pitch-print/[versionId]/_components/PrintNewSlides.tsx diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx index 19e5e1d..7fc6fa9 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintAnnexSlides.tsx @@ -4,107 +4,8 @@ import { ArchitectureDiagram, PipelineFlow } from './PrintDiagrams' interface SlideBase { lang: Language; pageNum: number; totalPages: number; versionName: string } -/* ===== ANHANG DIVIDER ===== */ - -/** - * Chapter-break slide that sits between the main pitch and the appendix. - * Bypasses the standard Page chrome to render as a hero divider, but keeps - * a footer row consistent with all other slides. - */ -export function PrintAnnexDividerPage({ lang, pageNum, totalPages, versionName }: SlideBase) { - const de = lang === 'de' - const MONO = "'JetBrains Mono', ui-monospace, monospace" - - const sections: [string, string, string][] = de ? [ - ['17', 'Go-to-Market Strategie', 'Pilot · Skalierung · Expansion'], - ['18', 'Finanzplan', 'P&L 2026–2030 · KPI-Dashboard'], - ['19', 'Treibervariablen', 'Annahmen + Sensitivitätsszenarien'], - ['20', 'Regulatorische Details', 'DSGVO · AI Act · NIS-2 · CRA · MaschVO'], - ['21', 'Systemarchitektur', '3 Tiers · LiteLLM Gateway · lokale Inferenz'], - ['22', 'Engineering Deep Dive', '500K+ LoC · 45 Container · 100 % Self-Hosted'], - ['23', 'KI-Pipeline', 'RAG · Multi-Agent · Document Intelligence · QA'], - ['24', 'Risiken & Mitigation', '10 Risiken in 5 Kategorien'], - ['25', 'Glossar', '30 Begriffe · Compliance · Engineering · Recht'], - ] : [ - ['17', 'Go-to-Market Strategy', 'Pilot · Scale · Expansion'], - ['18', 'Financial Plan', 'P&L 2026–2030 · KPI dashboard'], - ['19', 'Driver Variables', 'Assumptions + sensitivity scenarios'], - ['20', 'Regulatory Details', 'GDPR · AI Act · NIS-2 · CRA · Machinery Reg.'], - ['21', 'System Architecture', '3 tiers · LiteLLM gateway · local inference'], - ['22', 'Engineering Deep Dive', '500K+ LoC · 45 containers · 100 % self-hosted'], - ['23', 'AI Pipeline', 'RAG · multi-agent · document intelligence · QA'], - ['24', 'Risks & Mitigation', '10 risks across 5 categories'], - ['25', 'Glossary', '30 terms · compliance · engineering · law'], - ] - - return ( -
-
- - {/* Top meta row */} -
- {de ? 'Teil II · Anhang' : 'Part II · Appendix'} - BreakPilot · ComplAI -
- - {/* Hero */} -
-
- {de ? '16 · Kapitelwechsel' : '16 · 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.'} -

- - {/* What's coming */} -
-
- {de ? 'Auf den folgenden Seiten' : 'On the following pages'} -
-
- {sections.map(([n, t, sub]) => ( -
- {n} -
-
{t}
-
{sub}
-
-
- ))} -
-
-
- - {/* Footer (matches Page primitive) */} -
- BreakPilot · ComplAI - {versionName} - {String(pageNum).padStart(2, '0')} / {String(totalPages).padStart(2, '0')} -
-
-
- ) -} +/* The Anhang divider lives in PrintNewSlides.tsx so this file stays under + * the 500-LOC cap. */ /* ===== STRATEGY / GO-TO-MARKET ===== */ diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx index 34b68ff..85a299d 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintDeck.tsx @@ -18,10 +18,13 @@ import { PrintCompetitionPage1, PrintCompetitionPage2, } from './PrintCompetitionSlides' import { - PrintAnnexDividerPage, PrintStrategyPage, PrintRegulatoryPage, PrintArchitecturePage, PrintEngineeringPage, PrintAIPipelinePage, PrintRisksPage, PrintGlossaryPage, } from './PrintAnnexSlides' +import { + PrintTLDRPage, PrintDifferentiatorsPage, PrintKPIHeroPage, + PrintTechStackPage, PrintAnnexDividerPage, +} from './PrintNewSlides' import { PrintFinanzplanPage1, PrintFinanzplanPage2, PrintAssumptionsPage, PrintFinancialsPage, PrintCapTablePage, PrintDisclaimerPage, @@ -44,17 +47,21 @@ export default function PrintDeck({ pitchData, versionName, fmResults, fmAssumpt (pitchData.funding?.instrument || '').toLowerCase().includes('convertible') const hasCapTable = financial && !isWandeldarlehen const annualRows = aggregateAnnualRows(fmResults) - const hasFinancialDetail = financial && annualRows.length > 0 + const hasFinancialData = annualRows.length > 0 const de = lang === 'de' - // Base standard PDF: 30 physical pages. - // 2 (exec) + 1 (cover) + 1 (problem) + 1 (solution) + 2 (usp) + 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) + - // 2 (finanzplan) + 1 (assumptions) + 1 (regulatory) + 1 (architecture) + - // 1 (engineering) + 1 (aipipeline) + 1 (risks) + 1 (glossary) + 1 (disclaimer) = 30 - const BASE_PAGES = 30 - const totalPages = BASE_PAGES + (hasFinancialDetail ? 1 : 0) + (hasCapTable ? 1 : 0) + // 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) @@ -93,96 +100,109 @@ export default function PrintDeck({ pitchData, versionName, fmResults, fmAssumpt
-
- {/* SLIDE_ORDER from lib/slide-order.ts, minus 3 interactive-only slides: - intro-presenter, ai-qa, annex-sdk-demo */} +
+ {/* PITCH (slides 01–17) */} - {/* 1. executive-summary (2 pages) */} + {/* 01–02 executive-summary (2 pages) */} - {/* 2. cover */} + {/* 03 TL;DR — 30 Sekunden */} + + + {/* 04 cover */} {(() => { n += 1; return })()} - {/* 3. problem */} + {/* 05 problem */} - {/* 4. solution */} + {/* 06 solution */} - {/* 5. usp (2 pages) */} + {/* 07–08 usp (2 pages) */} - {/* 6. regulatory-landscape */} + {/* 09 differentiators */} + + + {/* 10 regulatory-landscape */} - {/* 7. product / modular-toolkit */} + {/* 11 product / modular-toolkit */} - {/* 8. how-it-works */} + {/* 12 how-it-works */} - {/* 9. market */} + {/* 13 market */} - {/* 10. business-model / pricing */} + {/* 14 business-model / pricing */} - {/* 11. traction (uses milestones) */} + {/* 15 traction (milestones) */} - {/* 12. competition (2 pages) */} + {/* 16–17 competition (2 pages) */} - {/* 13. team */} + {/* 18 team */} - {/* 14. the-ask */} + {/* 19 the-ask */} - {/* 15. customer-savings */} + {/* 20 customer-savings */} - {/* 16. ANHANG divider — chapter break before the appendix block */} + {/* 21 ANHANG divider — chapter break before the appendix */} - {/* 17. annex-strategy */} + {/* APPENDIX (slides 22–35) */} + + {/* 22 annex-strategy */} - {/* 17. annex-finanzplan (2 pages) */} + {/* 23 KPIs — 2026 → 2030 trajectory */} + + + {/* 24–25 annex-finanzplan (2 pages) */} - {/* Financial-only: detail P&L */} - {hasFinancialDetail && } + {/* 26 P&L detail (was financial-only; now standard) */} + - {/* 18. annex-assumptions */} + {/* 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 (suppressed for Wandeldarlehen) */} {hasCapTable && } - {/* 25. legal-disclaimer */} + {/* 35 legal-disclaimer */}
diff --git a/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx b/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx index af5f00a..1c348dc 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintFinancialSlides.tsx @@ -260,13 +260,20 @@ export function PrintAssumptionsPage({ assumptions, lang, pageNum, totalPages, v ) } -/* ===== FINANCIAL DETAIL (financial-only extra page) ===== */ +/* ===== 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 ( - + + +
+ {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 index da39017..eb1d094 100644 --- a/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx +++ b/pitch-deck/app/pitch-print/[versionId]/_components/PrintProductSlides.tsx @@ -61,48 +61,42 @@ export function PrintUSPPage1({ lang, pageNum, totalPages, versionName }: SlideB ) } -/* ===== USP, PAGE 2 (under the hood + closing loop) ===== */ +/* ===== 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 cards = ['trace', 'engine', 'opt', 'stack'] as const + const MONO = "'JetBrains Mono', ui-monospace, monospace" return ( - + -
- {cards.map(k => { - const p = d[k] - const Icon = USP_ICON[k] - return ( -
-
- {Icon && } - {p.kicker} -
-
{p.title}
-
{p.body}
- {p.bullets && } + {/* Full-page hero loop diagram */} +
+
+
+
+
- ) - })} -
- - {/* Closing loop: violet-tinted hero panel with the diagram on the right */} -
-
-
-
- -
- {de ? 'Die Schleife · Always in Sync' : 'The Loop · Always in Sync'} + {de ? 'Die Schleife · Always in Sync' : 'The Loop · Always in Sync'}
-
{d.hub.title}
-
{d.hub.body}
-
-
- +
{d.hub.title}
+
{d.hub.body}
+ +
+ +
+ + {d.hub.bullets && ( +
+ +
+ )}
{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}}