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