fix(pitch-print): port Claude Design tokens — violet, Inter+JBMono, dotted bg
Build pitch-deck / build-push-deploy (push) Successful in 1m50s
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 33s
CI / test-python-voice (push) Successful in 30s
CI / test-bqas (push) Successful in 27s

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 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-05-20 11:23:58 +02:00
parent cd23ebc3ba
commit 8b5b9905a7
3 changed files with 121 additions and 84 deletions
@@ -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 (
<div className="print-page-break">
<div className="print-page" style={{ width: '297mm', height: '210mm', background: '#ffffff', color: COLORS.slate900, fontFamily: "'Plus Jakarta Sans', system-ui, sans-serif", boxSizing: 'border-box', margin: '0 auto 24px', boxShadow: '0 4px 24px rgba(15,23,42,0.10)', overflow: 'hidden', padding: 0 }}>
{/*
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.
*/}
<div className="print-page print-page-bg" style={{ width: '297mm', height: '210mm', color: COLORS.slate900, fontFamily: "'Inter', system-ui, sans-serif", boxSizing: 'border-box', margin: '0 auto 24px', boxShadow: '0 4px 24px rgba(59,26,122,0.10)', overflow: 'hidden', padding: 0 }}>
<div style={{ width: '100%', height: '100%', display: 'grid', gridTemplateColumns: '95mm 1fr' }}>
{/* LEFT INDIGO BLOCK */}
{/* LEFT VIOLET BLOCK */}
<div style={{
background: COLORS.indigo600,
background: `linear-gradient(180deg, ${COLORS.violet700} 0%, ${COLORS.violet600} 60%, ${COLORS.violet700} 100%)`,
color: '#ffffff',
padding: '16mm 12mm',
display: 'flex',
@@ -53,10 +49,10 @@ export function PrintCoverPage({ company, funding, lang, versionName }: { compan
printColorAdjust: 'exact',
}}>
<div>
<div style={{ fontSize: '8pt', fontWeight: 700, letterSpacing: '0.18em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.75)' }}>
<div style={{ fontFamily: MONO_FONT, fontSize: '7.5pt', fontWeight: 700, letterSpacing: '0.22em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.78)' }}>
{de ? 'Investor Brief' : 'Investor Brief'}
</div>
<div style={{ marginTop: '6mm', height: '1px', background: 'rgba(255,255,255,0.35)', width: '32mm', WebkitPrintColorAdjust: 'exact', printColorAdjust: 'exact' }} />
<div style={{ marginTop: '6mm', height: '1px', background: 'rgba(255,255,255,0.4)', width: '32mm', WebkitPrintColorAdjust: 'exact', printColorAdjust: 'exact' }} />
<div style={{ marginTop: '6mm', fontSize: '11pt', color: '#ffffff', lineHeight: 1.5, fontWeight: 500 }}>
{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
</div>
{/* Mid stats */}
<div style={{ paddingTop: '8mm', borderTop: '1px solid rgba(255,255,255,0.25)' }}>
<div style={{ fontSize: '8pt', fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.75)', marginBottom: '4mm' }}>{de ? 'Auf einen Blick' : 'At a glance'}</div>
<div style={{ fontSize: '9.5pt', color: '#ffffff', lineHeight: 1.7, fontWeight: 500 }}>
{de ? '25 000 + atomare Prüfaspekte' : '25 000 + atomic audit aspects'}<br />
{de ? '380 + Regularien · 10 Branchen' : '380 + regulations · 10 industries'}<br />
{de ? '500 K + Lines of Code · 45 Container' : '500 K + lines of code · 45 containers'}<br />
{de ? '100 % EU-Hosting · BSI Cloud DE' : '100 % EU hosting · BSI cloud DE'}
<div style={{ paddingTop: '8mm', borderTop: '1px solid rgba(255,255,255,0.3)' }}>
<div style={{ fontFamily: MONO_FONT, fontSize: '7.5pt', fontWeight: 700, letterSpacing: '0.18em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.78)', marginBottom: '4mm' }}>{de ? 'Auf einen Blick' : 'At a glance'}</div>
<div style={{ fontFamily: MONO_FONT, fontSize: '8.5pt', color: '#ffffff', lineHeight: 1.85, fontWeight: 500 }}>
{de ? '25 000+ atomare Prüfaspekte' : '25 000+ atomic audit aspects'}<br />
{de ? '380+ Regularien · 10 Branchen' : '380+ regulations · 10 industries'}<br />
{de ? '500K+ Lines of Code · 45 Container' : '500K+ lines of code · 45 containers'}<br />
{de ? '100% EU-Hosting · BSI Cloud DE' : '100% EU hosting · BSI cloud DE'}
</div>
</div>
{/* Footer */}
<div>
<div style={{ fontSize: '7pt', letterSpacing: '0.16em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.6)', fontWeight: 700 }}>{versionName}</div>
<div style={{ marginTop: '2mm', fontSize: '7pt', letterSpacing: '0.16em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.6)', fontWeight: 700 }}>{de ? 'Vertraulich · Nur Investoren' : 'Confidential · Investors only'}</div>
<div style={{ fontFamily: MONO_FONT, fontSize: '7pt', letterSpacing: '0.2em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.65)', fontWeight: 700 }}>{versionName}</div>
<div style={{ fontFamily: MONO_FONT, marginTop: '2mm', fontSize: '7pt', letterSpacing: '0.2em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.65)', fontWeight: 700 }}>{de ? 'Vertraulich · Nur Investoren' : 'Confidential · Investors only'}</div>
</div>
</div>
{/* RIGHT WHITE PANE */}
<div style={{ padding: '18mm 16mm', display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minWidth: 0 }}>
{/* RIGHT (violet-tinted dotted bg from .print-page-bg) PANE */}
<div className="print-page-bg" style={{ padding: '18mm 16mm', display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minWidth: 0 }}>
<div>
<div style={{ fontSize: '10pt', fontWeight: 700, color: COLORS.indigo600, textTransform: 'uppercase', letterSpacing: '0.16em' }}>
<div style={{ fontFamily: MONO_FONT, fontSize: '9pt', fontWeight: 700, color: COLORS.violet600, textTransform: 'uppercase', letterSpacing: '0.22em' }}>
{instrument} &middot; Q4 2026
</div>
<h1 style={{ fontSize: '60pt', fontWeight: 800, color: COLORS.slate900, lineHeight: 0.95, letterSpacing: '-0.03em', margin: '8mm 0 4mm' }}>
@@ -99,18 +95,18 @@ export function PrintCoverPage({ company, funding, lang, versionName }: { compan
{/* Key terms */}
<div>
<div style={{ fontSize: '7.5pt', fontWeight: 700, color: COLORS.slate500, textTransform: 'uppercase', letterSpacing: '0.12em', marginBottom: '3mm', paddingBottom: '2mm', borderBottom: `1px solid ${COLORS.slate200}` }}>
<div style={{ fontFamily: MONO_FONT, fontSize: '7.5pt', fontWeight: 700, color: COLORS.violet600, textTransform: 'uppercase', letterSpacing: '0.2em', marginBottom: '3mm', paddingBottom: '2mm', borderBottom: `1px solid ${COLORS.slate200}` }}>
{de ? 'Key Terms' : 'Key terms'}
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '5mm' }}>
{coverTerms.map(([label, val]) => (
<div key={label}>
<div style={{ fontSize: '7pt', color: COLORS.slate500, textTransform: 'uppercase', letterSpacing: '0.12em', fontWeight: 700 }}>{label}</div>
<div style={{ fontSize: '16pt', fontWeight: 800, color: COLORS.slate900, marginTop: '1.5mm', fontVariantNumeric: 'tabular-nums', letterSpacing: '-0.01em', lineHeight: 1.1 }}>{val}</div>
<div style={{ fontFamily: MONO_FONT, fontSize: '7pt', color: COLORS.slate500, textTransform: 'uppercase', letterSpacing: '0.18em', fontWeight: 700 }}>{label}</div>
<div style={{ fontSize: '17pt', fontWeight: 800, color: COLORS.slate900, marginTop: '2mm', fontVariantNumeric: 'tabular-nums', letterSpacing: '-0.015em', lineHeight: 1.05 }}>{val}</div>
</div>
))}
</div>
<div style={{ marginTop: '5mm', fontSize: '8pt', color: COLORS.slate500, lineHeight: 1.5 }}>
<div style={{ marginTop: '5mm', fontSize: '8.5pt', color: COLORS.slate600, lineHeight: 1.5 }}>
{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.'}
@@ -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 (
<div className="print-page-break">
<div className="print-page" style={{
<div className="print-page print-page-bg" style={{
width: '297mm',
height: '210mm',
background: '#ffffff',
color: COLORS.slate900,
fontFamily: FONT,
display: 'flex',
@@ -66,28 +86,31 @@ export function Page({ kicker, section, title, subtitle, pageNum, totalPages, ve
padding: '11mm 14mm 8mm 14mm',
// screen-only decoration
margin: '0 auto 24px',
boxShadow: '0 4px 24px rgba(15,23,42,0.10)',
boxShadow: '0 4px 24px rgba(59,26,122,0.10)',
WebkitPrintColorAdjust: 'exact',
printColorAdjust: 'exact',
}}>
{/* TITLE BLOCK */}
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '8mm', borderLeft: `3px solid ${COLORS.indigo600}`, paddingLeft: '7mm', marginBottom: '6mm', flexShrink: 0 }}>
{/* TITLE BLOCK — left-rule preserved */}
<div style={{ display: 'flex', alignItems: 'stretch', gap: '7mm', marginBottom: '5mm', flexShrink: 0 }}>
<div style={{ width: '3px', background: COLORS.violet600, WebkitPrintColorAdjust: 'exact', printColorAdjust: 'exact', alignSelf: 'stretch', minHeight: '14mm' }} />
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ display: 'flex', alignItems: 'baseline', gap: '4mm', marginBottom: '2mm' }}>
<span style={{ fontSize: '8pt', fontWeight: 700, letterSpacing: '0.14em', color: COLORS.indigo600, textTransform: 'uppercase' }}>
<span className="print-mono" style={{ fontFamily: MONO_FONT, fontSize: '7.5pt', fontWeight: 700, letterSpacing: '0.18em', color: COLORS.violet600, textTransform: 'uppercase' }}>
{kicker} &middot; {section}
</span>
<span style={{ flex: 1, height: '1px', background: COLORS.slate200, alignSelf: 'center' }} />
<span style={{ fontSize: '7.5pt', color: COLORS.slate500, fontWeight: 500 }}>BreakPilot &middot; {versionName}</span>
<span style={{ flex: 1, height: '1px', background: `linear-gradient(90deg, ${COLORS.violet400}, transparent 80%)`, alignSelf: 'center', WebkitPrintColorAdjust: 'exact', printColorAdjust: 'exact' }} />
<span className="print-mono" style={{ fontFamily: MONO_FONT, fontSize: '7pt', color: COLORS.slate500, fontWeight: 500, letterSpacing: '0.06em' }}>BreakPilot &middot; ComplAI</span>
</div>
<h1 style={{ fontSize: '22pt', fontWeight: 800, color: COLORS.slate900, margin: 0, lineHeight: 1.1, letterSpacing: '-0.01em' }}>
<h1 style={{ fontSize: '22pt', fontWeight: 800, color: COLORS.slate900, margin: 0, lineHeight: 1.1, letterSpacing: '-0.015em' }}>
{title}
</h1>
{subtitle && (
<p style={{ fontSize: '10pt', color: COLORS.slate600, margin: '2mm 0 0', fontWeight: 400, lineHeight: 1.4, maxWidth: '210mm' }}>
<p style={{ fontSize: '10pt', color: COLORS.slate600, margin: '2mm 0 0', fontWeight: 400, lineHeight: 1.45, maxWidth: '210mm' }}>
{subtitle}
</p>
)}
{/* Subtle violet accent gradient bar — echo of the Claude Design feel */}
<div style={{ marginTop: '3mm', height: '2px', width: '100%', background: `linear-gradient(90deg, ${COLORS.violet700} 0%, ${COLORS.violet400} 50%, ${COLORS.violet700} 100%)`, opacity: 0.85, WebkitPrintColorAdjust: 'exact', printColorAdjust: 'exact' }} />
</div>
</div>
@@ -103,10 +126,10 @@ export function Page({ kicker, section, title, subtitle, pageNum, totalPages, ve
</div>
)}
{/* FOOTER */}
<div style={{ flexShrink: 0, marginTop: '3mm', paddingTop: '2mm', borderTop: `1px solid ${COLORS.slate200}`, display: 'flex', alignItems: 'center', justifyContent: 'space-between', fontSize: '7.5pt', color: COLORS.slate500 }}>
<span>BreakPilot &middot; {versionName}</span>
<span style={{ fontWeight: 700, letterSpacing: '0.12em', color: COLORS.slate600 }}>CONFIDENTIAL</span>
{/* FOOTER — JetBrains Mono caps to match Claude Design */}
<div className="print-mono" style={{ fontFamily: MONO_FONT, flexShrink: 0, marginTop: '3mm', paddingTop: '2mm', 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>
+39 -21
View File
@@ -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;
}