feat(pitch-print): add Anhang divider slide before appendix block
Build pitch-deck / build-push-deploy (push) Successful in 2m5s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 35s
CI / test-python-voice (push) Successful in 35s
CI / test-bqas (push) Successful in 31s
Build pitch-deck / build-push-deploy (push) Successful in 2m5s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 35s
CI / test-python-voice (push) Successful in 35s
CI / test-bqas (push) Successful in 31s
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 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,108 @@ import { ArchitectureDiagram, PipelineFlow } from './PrintDiagrams'
|
|||||||
|
|
||||||
interface SlideBase { lang: Language; pageNum: number; totalPages: number; versionName: string }
|
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 (
|
||||||
|
<div className="print-page-break">
|
||||||
|
<div className="print-page print-page-bg" style={{
|
||||||
|
width: '297mm',
|
||||||
|
height: '210mm',
|
||||||
|
color: COLORS.slate900,
|
||||||
|
fontFamily: "'Inter', system-ui, sans-serif",
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
padding: '14mm 18mm',
|
||||||
|
margin: '0 auto 24px',
|
||||||
|
boxShadow: '0 4px 24px rgba(59,26,122,0.10)',
|
||||||
|
overflow: 'hidden',
|
||||||
|
WebkitPrintColorAdjust: 'exact',
|
||||||
|
printColorAdjust: 'exact',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
}}>
|
||||||
|
|
||||||
|
{/* Top meta row */}
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', borderBottom: `1px solid ${COLORS.slate200}`, paddingBottom: '3mm' }}>
|
||||||
|
<span style={{ fontFamily: MONO, fontSize: '7.5pt', fontWeight: 700, color: COLORS.violet600, textTransform: 'uppercase', letterSpacing: '0.22em' }}>{de ? 'Teil II · Anhang' : 'Part II · Appendix'}</span>
|
||||||
|
<span style={{ fontFamily: MONO, fontSize: '7pt', color: COLORS.slate500, letterSpacing: '0.16em', textTransform: 'uppercase', fontWeight: 700 }}>BreakPilot · ComplAI</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Hero */}
|
||||||
|
<div style={{ flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'center', maxWidth: '260mm' }}>
|
||||||
|
<div style={{ fontFamily: MONO, fontSize: '10pt', fontWeight: 700, color: COLORS.violet600, textTransform: 'uppercase', letterSpacing: '0.3em', marginBottom: '6mm' }}>
|
||||||
|
{de ? '16 · Kapitelwechsel' : '16 · Chapter break'}
|
||||||
|
</div>
|
||||||
|
<h1 style={{ fontSize: '74pt', fontWeight: 800, color: COLORS.slate900, lineHeight: 0.95, letterSpacing: '-0.035em', margin: 0 }}>
|
||||||
|
{de ? 'Anhang' : 'Appendix'}<span style={{ color: COLORS.violet600 }}>.</span>
|
||||||
|
</h1>
|
||||||
|
<div style={{ height: '3px', width: '60mm', background: `linear-gradient(90deg, ${COLORS.violet700} 0%, ${COLORS.violet400} 50%, ${COLORS.violet700} 100%)`, marginTop: '6mm', marginBottom: '8mm', WebkitPrintColorAdjust: 'exact', printColorAdjust: 'exact' }} />
|
||||||
|
<p style={{ fontSize: '15pt', fontWeight: 500, color: COLORS.slate700, lineHeight: 1.3, margin: 0, letterSpacing: '-0.008em', maxWidth: '230mm' }}>
|
||||||
|
{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.'}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* What's coming */}
|
||||||
|
<div style={{ marginTop: '12mm' }}>
|
||||||
|
<div style={{ fontFamily: MONO, fontSize: '8pt', fontWeight: 700, color: COLORS.slate500, textTransform: 'uppercase', letterSpacing: '0.18em', marginBottom: '4mm' }}>
|
||||||
|
{de ? 'Auf den folgenden Seiten' : 'On the following pages'}
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '5mm 8mm' }}>
|
||||||
|
{sections.map(([n, t, sub]) => (
|
||||||
|
<div key={n} style={{ display: 'flex', alignItems: 'flex-start', gap: '4mm' }}>
|
||||||
|
<span style={{ fontFamily: MONO, fontSize: '14pt', fontWeight: 800, color: COLORS.violet600, lineHeight: 1, fontVariantNumeric: 'tabular-nums', letterSpacing: '-0.02em', minWidth: '11mm' }}>{n}</span>
|
||||||
|
<div style={{ flex: 1, minWidth: 0 }}>
|
||||||
|
<div style={{ fontSize: '10pt', fontWeight: 700, color: COLORS.slate900, lineHeight: 1.2 }}>{t}</div>
|
||||||
|
<div style={{ fontSize: '7.5pt', color: COLORS.slate600, marginTop: '0.5mm', lineHeight: 1.35 }}>{sub}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Footer (matches Page primitive) */}
|
||||||
|
<div className="print-mono" style={{ fontFamily: MONO, paddingTop: '3mm', borderTop: `1px solid ${COLORS.slate200}`, display: 'flex', alignItems: 'center', justifyContent: 'space-between', fontSize: '7pt', color: COLORS.slate500, letterSpacing: '0.16em', textTransform: 'uppercase', fontWeight: 700 }}>
|
||||||
|
<span>BreakPilot · ComplAI</span>
|
||||||
|
<span style={{ color: COLORS.violet600 }}>{versionName}</span>
|
||||||
|
<span style={{ fontVariantNumeric: 'tabular-nums' }}>{String(pageNum).padStart(2, '0')} / {String(totalPages).padStart(2, '0')}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/* ===== STRATEGY / GO-TO-MARKET ===== */
|
/* ===== STRATEGY / GO-TO-MARKET ===== */
|
||||||
|
|
||||||
export function PrintStrategyPage({ lang, pageNum, totalPages, versionName }: SlideBase) {
|
export function PrintStrategyPage({ lang, pageNum, totalPages, versionName }: SlideBase) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
PrintCompetitionPage1, PrintCompetitionPage2,
|
PrintCompetitionPage1, PrintCompetitionPage2,
|
||||||
} from './PrintCompetitionSlides'
|
} from './PrintCompetitionSlides'
|
||||||
import {
|
import {
|
||||||
|
PrintAnnexDividerPage,
|
||||||
PrintStrategyPage, PrintRegulatoryPage, PrintArchitecturePage,
|
PrintStrategyPage, PrintRegulatoryPage, PrintArchitecturePage,
|
||||||
PrintEngineeringPage, PrintAIPipelinePage, PrintRisksPage, PrintGlossaryPage,
|
PrintEngineeringPage, PrintAIPipelinePage, PrintRisksPage, PrintGlossaryPage,
|
||||||
} from './PrintAnnexSlides'
|
} from './PrintAnnexSlides'
|
||||||
@@ -46,13 +47,13 @@ export default function PrintDeck({ pitchData, versionName, fmResults, fmAssumpt
|
|||||||
const hasFinancialDetail = financial && annualRows.length > 0
|
const hasFinancialDetail = financial && annualRows.length > 0
|
||||||
const de = lang === 'de'
|
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) +
|
// 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 (product) + 1 (how) + 1 (market) + 1 (bm) + 1 (milestones) + 2 (competition) +
|
||||||
// 1 (team) + 1 (ask) + 1 (savings) + 1 (strategy) + 2 (finanzplan) +
|
// 1 (team) + 1 (ask) + 1 (savings) + 1 (anhang-divider) + 1 (strategy) +
|
||||||
// 1 (assumptions) + 1 (regulatory) + 1 (architecture) + 1 (engineering) +
|
// 2 (finanzplan) + 1 (assumptions) + 1 (regulatory) + 1 (architecture) +
|
||||||
// 1 (aipipeline) + 1 (risks) + 1 (glossary) + 1 (disclaimer) = 29
|
// 1 (engineering) + 1 (aipipeline) + 1 (risks) + 1 (glossary) + 1 (disclaimer) = 30
|
||||||
const BASE_PAGES = 29
|
const BASE_PAGES = 30
|
||||||
const totalPages = BASE_PAGES + (hasFinancialDetail ? 1 : 0) + (hasCapTable ? 1 : 0)
|
const totalPages = BASE_PAGES + (hasFinancialDetail ? 1 : 0) + (hasCapTable ? 1 : 0)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -144,7 +145,10 @@ export default function PrintDeck({ pitchData, versionName, fmResults, fmAssumpt
|
|||||||
{/* 15. customer-savings */}
|
{/* 15. customer-savings */}
|
||||||
<PrintCustomerSavingsPage {...p()} />
|
<PrintCustomerSavingsPage {...p()} />
|
||||||
|
|
||||||
{/* 16. annex-strategy */}
|
{/* 16. ANHANG divider — chapter break before the appendix block */}
|
||||||
|
<PrintAnnexDividerPage {...p()} />
|
||||||
|
|
||||||
|
{/* 17. annex-strategy */}
|
||||||
<PrintStrategyPage {...p()} />
|
<PrintStrategyPage {...p()} />
|
||||||
|
|
||||||
{/* 17. annex-finanzplan (2 pages) */}
|
{/* 17. annex-finanzplan (2 pages) */}
|
||||||
|
|||||||
Reference in New Issue
Block a user