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 && ( +
+ +
+ )}