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

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:
Sharang Parnerkar
2026-05-20 12:58:53 +02:00
parent d1b55cd65b
commit ad61fd3779
2 changed files with 112 additions and 6 deletions
@@ -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 20262030 · 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 20262030 · 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 &middot; 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 &middot; 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 ===== */
export function PrintStrategyPage({ lang, pageNum, totalPages, versionName }: SlideBase) {
@@ -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 */}
<PrintCustomerSavingsPage {...p()} />
{/* 16. annex-strategy */}
{/* 16. ANHANG divider — chapter break before the appendix block */}
<PrintAnnexDividerPage {...p()} />
{/* 17. annex-strategy */}
<PrintStrategyPage {...p()} />
{/* 17. annex-finanzplan (2 pages) */}