From 269464943e55817f768f4524d14c31438446edf2 Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Thu, 30 Apr 2026 14:05:42 +0200 Subject: [PATCH] fix(pitch-deck): restore complete USPSlide with all helper functions The previously committed version was missing useIsLight hook, all sub-components (PillarRow, ColHeader, CentralHub, BridgeConnectors, FeatureCard, DetailModal, StarField, ticker components) and their data/types. Only the main component shell was present, causing a CI build failure on type-check. Co-Authored-By: Claude Sonnet 4.6 --- pitch-deck/components/slides/USPSlide.tsx | 590 +++++++++++++++++++++- 1 file changed, 589 insertions(+), 1 deletion(-) diff --git a/pitch-deck/components/slides/USPSlide.tsx b/pitch-deck/components/slides/USPSlide.tsx index 8e7ae49..1e1e6be 100644 --- a/pitch-deck/components/slides/USPSlide.tsx +++ b/pitch-deck/components/slides/USPSlide.tsx @@ -1,9 +1,11 @@ 'use client' -import { useState } from 'react' +import { useState, useEffect, useRef, useMemo } from 'react' +import { motion, AnimatePresence } from 'framer-motion' import { Language } from '@/lib/types' import GradientText from '../ui/GradientText' import FadeInView from '../ui/FadeInView' +import { X } from 'lucide-react' interface USPSlideProps { lang: Language } @@ -30,6 +32,592 @@ const CSS_KF = ` ` // ── Light mode hook ─────────────────────────────────────────────────────────── +function useIsLight() { + const [isLight, setIsLight] = useState(false) + useEffect(() => { + const check = () => setIsLight(document.documentElement.classList.contains('theme-light')) + check() + const obs = new MutationObserver(check) + obs.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] }) + return () => obs.disconnect() + }, []) + return isLight +} + +// ── Ticker ──────────────────────────────────────────────────────────────────── +function useTicker(fn: () => void, min = 180, max = 420, skip = 0.1) { + const ref = useRef(fn) + ref.current = fn + useEffect(() => { + let t: ReturnType + const loop = () => { + if (Math.random() > skip) ref.current() + t = setTimeout(loop, min + Math.random() * (max - min)) + } + loop() + return () => clearTimeout(t) + }, [min, max, skip]) +} + +function TickerShell({ tint, isLight, children }: { tint: string; isLight: boolean; children: React.ReactNode }) { + return ( +
{children}
+ ) +} + +function TickTrace({ tint, isLight }: { tint: string; isLight: boolean }) { + const [n, setN] = useState(12748) + useTicker(() => setN(v => v + 1 + Math.floor(Math.random() * 3)), 250, 500) + return ( + + + trace + {n.toLocaleString()} + evidence-chain + + ) +} + +function TickEngine({ tint, isLight }: { tint: string; isLight: boolean }) { + const [v, setV] = useState(428) + const [rate, setRate] = useState(99.4) + useTicker(() => { + setV(x => x + 1 + Math.floor(Math.random() * 4)) + setRate(r => Math.max(97, Math.min(99.9, r + (Math.random() - 0.5) * 0.3))) + }, 220, 420) + return ( + + + validate + {v.toLocaleString()} + {rate.toFixed(1)}% + + ) +} + +function TickOptimizer({ tint, isLight }: { tint: string; isLight: boolean }) { + const ops = ['ROI: 2.418 € / dev', 'gap → policy §4.2', 'dedup 128 tickets', 'sweet-spot: 22 KLOC', 'tradeoff: speed↔risk'] + const [i, setI] = useState(0) + useTicker(() => setI(x => (x + 1) % ops.length), 900, 1600, 0.05) + return ( + + + optimize + {ops[i]} + + ) +} + +function TickStack({ tint, isLight }: { tint: string; isLight: boolean }) { + const regs = ['DSGVO', 'NIS-2', 'DORA', 'EU AI Act', 'ISO 27001', 'BSI C5'] + const [i, setI] = useState(0) + const [c, setC] = useState(1208) + useTicker(() => { setI(x => (x + 1) % regs.length); setC(v => v + Math.floor(Math.random() * 3)) }, 800, 1400, 0.05) + return ( + + + check + {regs[i]} + · + {c.toLocaleString()} + + ) +} + +// ── Data ────────────────────────────────────────────────────────────────────── +interface DetailItem { + tint: string + icon: string + kicker: string + title: string + body: string + bullets?: string[] + stat?: { k: string; v: string } +} + +function getDetails(de: boolean): Record { + return { + rfq: { + tint: '#a78bfa', icon: '⇄', + kicker: de ? 'Säule · Compliance' : 'Pillar · Compliance', + title: de ? 'RFQ-Prüfung' : 'RFQ Verification', + body: de + ? 'Kunden-Anforderungsdokumente werden automatisch gegen den aktuellen Source-Code geprüft. Abweichungen werden erkannt, Änderungen vorgeschlagen und auf Wunsch direkt im Code umgesetzt — ohne manuelles Nacharbeiten.' + : 'Customer requirement documents are automatically verified against current source code. Deviations are detected, changes proposed and implemented directly in code on request — no manual rework needed.', + bullets: de + ? ['Klauseln automatisch gegen SBOM, SAST-Findings und Policy-Docs abgeglichen', 'Lücken mit konkreten Implementierungsvorschlägen markiert', 'RFQ-Antworten in Stunden statt Wochen'] + : ['Auto-match clauses against SBOM, SAST findings and policy docs', 'Flag gaps with concrete implementation proposals', 'Win-ready RFQ replies in hours, not weeks'], + stat: { k: de ? 'Ø Antwortzeit' : 'avg response time', v: de ? '4,2h (war 12 Tage)' : '4.2h (was 12 days)' }, + }, + process: { + tint: '#c084fc', icon: '⟲', + kicker: de ? 'Säule · Compliance' : 'Pillar · Compliance', + title: de ? 'Prozess-Compliance' : 'Process Compliance', + body: de + ? 'Vom Audit-Finding über das Ticket bis zur Code-Änderung läuft der gesamte Prozess automatisiert durch. Rollen, Fristen und Eskalation werden End-to-End verwaltet. Nachweise werden automatisch generiert und archiviert.' + : 'From audit finding to ticket to code change, the entire process runs automatically. Roles, deadlines and escalation are managed end-to-end. Evidence is automatically generated and archived.', + bullets: de + ? ['Finding → Ticket → PR → Nachweis in einem Thread', 'SLA-Tracking pro Control mit Auto-Eskalation', 'Unveränderliches Audit-Log, pro Änderung signiert'] + : ['Finding → ticket → PR → evidence in one thread', 'SLA tracking per control with auto-escalation', 'Immutable audit log signed per change'], + stat: { k: de ? 'automatisierte Prozessschritte' : 'process steps automated', v: '87%' }, + }, + bidir: { + tint: '#fbbf24', icon: '⟷', + kicker: de ? 'Säule · Code' : 'Pillar · Code', + title: de ? 'Bidirektional' : 'Bidirectional Sync', + body: de + ? 'Compliance-Anforderungen fliessen direkt in den Code. Umgekehrt aktualisieren Code-Änderungen automatisch die Compliance-Dokumentation. Beide Seiten sind immer synchron — kein Informationsverlust zwischen Audit und Entwicklung.' + : 'Compliance requirements flow directly into code. Conversely, code changes automatically update compliance documentation. Both sides always stay in sync — no information loss between audit and development.', + bullets: de + ? ['Policy ↔ Code-Mapping via semantischem Diff', 'Git-nativ: jede Änderung als PR', 'Zero Drift zwischen Audit-Artefakten und Realität'] + : ['Policy ↔ code mapping via semantic diff', 'Git-native: every change shipped as a PR', 'Zero drift between audit artefacts and reality'], + stat: { k: de ? 'Drift-Vorfälle' : 'drift incidents', v: de ? '0 seit März 2024' : '0 since Mar-2024' }, + }, + cont: { + tint: '#f59e0b', icon: '◎', + kicker: de ? 'Säule · Code' : 'Pillar · Code', + title: de ? 'Kontinuierlich' : 'Continuous, Not Yearly', + body: de + ? 'Klassische Compliance prüft einmal im Jahr und hofft auf das Beste. Unsere Plattform prüft bei jeder Code-Änderung. Findings werden sofort zu Tickets mit konkreten Implementierungsvorschlägen im Issue-Tracker der Wahl.' + : 'Traditional compliance checks once a year and hopes for the best. Our platform checks on every code change. Findings immediately become tickets with concrete implementation proposals in the issue tracker of choice.', + bullets: de + ? ['CI-integrierte Validierung bei jedem Push', 'Fix-Vorschläge generiert, nicht nur gemeldet', 'Compliance-Frische: Minuten statt Monate'] + : ['CI-integrated validation on each push', 'Fix suggestions generated, not just reported', 'Compliance freshness: minutes, not months'], + stat: { k: de ? 'Validierungen / Tag' : 'validations / day', v: '~2.400 / repo' }, + }, + trace: { + tint: '#a78bfa', icon: '⇄', + kicker: de ? 'Under the Hood' : 'Under the Hood', + title: de ? 'End-to-End Rückverfolgbarkeit' : 'End-to-End Traceability', + body: de + ? 'Regulatorische Anforderungen (Gesetz → Obligation → Control) deterministisch mit realem Systemzustand und Code verknüpft — inklusive revisionssicherem Evidence-Layer.' + : 'Regulatory requirements (law → obligation → control) deterministically linked to real system state and code — including audit-proof evidence layer.', + bullets: de + ? ['Versionierter Evidence-Chain, unveränderlich gespeichert', 'Ein Klick von Klausel bis Codezeile', 'Signierte Attestierungen pro Build'] + : ['Versioned evidence chain stored immutably', 'One-click drill from clause to line of code', 'Signed attestations per build'], + }, + engine: { + tint: '#c084fc', icon: '◉', + kicker: de ? 'Under the Hood' : 'Under the Hood', + title: de ? 'Continuous Compliance Engine' : 'Continuous Compliance Engine', + body: de + ? 'Statt punktueller Audits: Validierung bei jeder Änderung (Code, Infrastruktur, Prozesse) mit auditierbaren Nachweisen in Echtzeit.' + : 'Instead of point-in-time audits: validation on every change (code, infrastructure, processes) with auditable evidence in real time.', + bullets: de + ? ['Rule-Packs pro Framework (NIS-2, DORA, …)', 'Verarbeitet Code, IaC und Prozess-Events', 'Findings automatisch ans richtige Team geroutet'] + : ['Rule packs per framework (NIS-2, DORA, …)', 'Handles code, infra-as-code, and process events', 'Findings routed to the right team automatically'], + }, + opt: { + tint: '#fbbf24', icon: '✦', + kicker: de ? 'Under the Hood' : 'Under the Hood', + title: de ? 'Compliance Optimizer' : 'Compliance Optimizer', + body: de + ? 'Nicht nur „erlaubt/verboten", sondern die maximal zulässige Ausgestaltung jedes KI-Use-Cases. Deterministische Constraint-Optimierung zeigt den Sweet Spot zwischen Regulierung und Innovation — ersetzt 20–200k EUR Anwaltskosten.' + : 'Not just "allowed/forbidden" but the maximum permissible configuration of every AI use case. Deterministic constraint optimization shows the sweet spot between regulation and innovation — replaces EUR 20–200k in legal fees.', + bullets: de + ? ['ROI-Ranking jedes offenen Findings', 'Abwägung zwischen Liefergeschwindigkeit und Restrisiko', 'Low-Hanging-Wins zuerst'] + : ['ROI-ranks every open finding', 'Balances speed of delivery with residual risk', 'Highlights low-hanging wins first'], + }, + stack: { + tint: '#f59e0b', icon: '◎', + kicker: de ? 'Under the Hood' : 'Under the Hood', + title: de ? 'EU-Trust & Governance Stack' : 'EU Trust & Governance Stack', + body: de + ? 'Souveräne, DSGVO-/AI-Act-konforme Architektur (EU-Hosting, Isolation, Betriebsrat-Fähigkeit) — Marktzugang, den US-Lösungen strukturell nicht erreichen.' + : 'Sovereign, GDPR/AI Act compliant architecture (EU hosting, isolation, works council capability) — market access that US solutions structurally cannot achieve.', + bullets: de + ? ['DSGVO · NIS-2 · DORA · EU AI Act · ISO 27001 · BSI C5', 'EU-souveränes Hosting und Key-Management', 'Eine Plattform, ein Audit, eine Rechnung'] + : ['DSGVO · NIS-2 · DORA · EU AI Act · ISO 27001 · BSI C5', 'EU-sovereign hosting and key-management', 'One platform, one audit, one bill'], + }, + hub: { + tint: '#a78bfa', icon: '∞', + kicker: de ? 'Die Schleife' : 'The Loop', + title: de ? 'Compliance ↔ Code · Immer in Sync' : 'Compliance ↔ Code · Always in sync', + body: de + ? 'Die Plattform ist eine einzige geschlossene Schleife. Jede Policy-Änderung fliesst in den Code; jede Code-Änderung fliesst in die Policy zurück.' + : 'The platform is a single closed loop. Every policy change ripples into code; every code change ripples back into policy. That\'s the USP in one diagram.', + bullets: de + ? ['Single Source of Truth, zwei Oberflächen', 'Echtzeit-Sync, kein Batch-Abgleich', 'Auditoren, Entwickler und Sales fragen denselben Graphen ab'] + : ['Single source of truth, two surfaces', 'Real-time sync, not batch reconciliation', 'Auditors, engineers and sales all query the same graph'], + }, + } +} + +// ── Pillar row ──────────────────────────────────────────────────────────────── +function PillarRow({ side, title, body, tint, onClick, active, isLight }: { + side: 'left' | 'right' + title: string; body: string; tint: string + onClick: () => void; active: boolean; isLight: boolean +}) { + const [hover, setHover] = useState(false) + const lit = hover || active + const isLeft = side === 'left' + return ( +
setHover(true)} + onMouseLeave={() => setHover(false)} + style={{ + display: 'flex', alignItems: 'flex-start', gap: 12, + flexDirection: isLeft ? 'row-reverse' : 'row', + textAlign: isLeft ? 'right' : 'left', + padding: '10px 14px', borderRadius: 10, cursor: 'pointer', + transition: 'transform .25s, background .25s, box-shadow .25s', + background: lit + ? `linear-gradient(${isLeft ? '270deg' : '90deg'}, ${tint}24 0%, ${tint}0a 70%, transparent 100%)` + : 'transparent', + boxShadow: lit + ? `0 10px 30px ${tint}26, inset 0 0 0 1px ${tint}44` + : 'inset 0 0 0 1px transparent', + transform: lit ? (isLeft ? 'translateX(-3px)' : 'translateX(3px)') : 'translateX(0)', + }} + > +
+
+
+ {title} + {isLeft ? '‹' : '›'} +
+
{body}
+
+
+ ) +} + +// ── Column header ───────────────────────────────────────────────────────────── +function ColHeader({ side, label, color, icon, sub, isLight }: { + side: 'left' | 'right'; label: string; color: string; icon: string; sub: string; isLight: boolean +}) { + const isLeft = side === 'left' + return ( +
+
{icon}
+
+
{label}
+
{sub}
+
+
+ ) +} + +// ── Central hub ─────────────────────────────────────────────────────────────── +function CentralHub({ caption, isLight }: { caption: string; isLight: boolean }) { + return ( +
+
+
+
+ + + +
+
{caption}
+
+ ) +} + +// ── Bridge SVG connectors ───────────────────────────────────────────────────── +function BridgeConnectors({ isLight }: { isLight: boolean }) { + const rfpY = 130 + const sub2Y = 250 + const hubCx = 500 + const hubR = 72 + return ( + + + + + + + + + + + + + + + + + + + + {([rfpY, sub2Y] as number[]).map(y => ( + + + + + + + ))} + + + + + + + + + + + ) +} + +// ── Under-the-hood feature card ─────────────────────────────────────────────── +function FeatureCard({ icon, title, body, tint, Ticker, onClick, active, isLight }: { + icon: string; title: string; body: string; tint: string + Ticker: React.ComponentType<{ tint: string; isLight: boolean }> + onClick: () => void; active: boolean; isLight: boolean +}) { + const [hover, setHover] = useState(false) + const lit = hover || active + return ( +
setHover(true)} + onMouseLeave={() => setHover(false)} + style={{ + position: 'relative', padding: '13px 15px', + background: isLight + ? lit + ? `linear-gradient(180deg, ${tint}18 0%, ${tint}08 55%, rgba(248,250,252,.95) 100%)` + : 'linear-gradient(180deg, #ffffff, #f8fafc)' + : `linear-gradient(180deg, ${tint}${lit ? '2a' : '1a'} 0%, ${tint}07 55%, rgba(14,8,28,.85) 100%)`, + border: `1px solid ${lit ? tint : isLight ? 'rgba(0,0,0,.1)' : tint + '4a'}`, + borderRadius: 12, + boxShadow: lit + ? `0 18px 40px ${tint}33, 0 0 0 1px ${tint}66, inset 0 1px 0 ${tint}60` + : isLight + ? '0 2px 8px rgba(0,0,0,.08), inset 0 1px 0 rgba(255,255,255,.8)' + : `0 10px 24px rgba(0,0,0,.4), inset 0 1px 0 ${tint}35`, + minWidth: 0, cursor: 'pointer', + transform: lit ? 'translateY(-3px)' : 'translateY(0)', + transition: 'transform .25s, box-shadow .25s, background .25s, border-color .25s', + }} + > +
+ {icon} + {title} + +
+
{body}
+ +
+ ) +} + +// ── Detail modal ────────────────────────────────────────────────────────────── +function DetailModal({ item, onClose, isLight }: { item: DetailItem | null; onClose: () => void; isLight: boolean }) { + useEffect(() => { + if (!item) return + const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose() } + window.addEventListener('keydown', onKey) + return () => window.removeEventListener('keydown', onKey) + }, [item, onClose]) + + return ( + + {item && ( + + e.stopPropagation()} + style={{ + width: 560, maxWidth: '88%', + background: isLight + ? `linear-gradient(180deg, ${item.tint}10 0%, rgba(255,255,255,.98) 50%, rgba(248,250,252,.99) 100%)` + : `linear-gradient(180deg, ${item.tint}18 0%, rgba(20,10,40,.96) 50%, rgba(14,8,28,.98) 100%)`, + border: `1px solid ${item.tint}${isLight ? '44' : '66'}`, + borderRadius: 16, + boxShadow: isLight + ? `0 20px 60px rgba(0,0,0,.12), 0 0 40px ${item.tint}18, inset 0 1px 0 rgba(255,255,255,.9)` + : `0 30px 80px rgba(0,0,0,.6), 0 0 60px ${item.tint}33, inset 0 1px 0 ${item.tint}55`, + padding: '22px 26px', + color: isLight ? '#1a1a2e' : '#ece9f7', + }} + > +
+
{item.icon}
+
+
+ {item.kicker} +
+
{item.title}
+
+ +
+
+ {item.body} +
+ {item.bullets && ( +
+ {item.bullets.map((b, i) => ( +
+ + {b} +
+ ))} +
+ )} + {item.stat && ( +
+ + {item.stat.k} + {item.stat.v} +
+ )} +
+
+ )} +
+ ) +} + +// ── Star field ──────────────────────────────────────────────────────────────── +function StarField({ isLight }: { isLight: boolean }) { + const stars = useMemo(() => { + let s = 41 + const r = () => { s = (s * 9301 + 49297) % 233280; return s / 233280 } + return Array.from({ length: 90 }, () => ({ x: r() * 100, y: r() * 100, size: r() * 1.4 + 0.3, op: r() * 0.5 + 0.15 })) + }, []) + if (isLight) return null + return ( +
+ {stars.map((st, i) => ( +
+ ))} +
+ ) +} + +// ── Main slide ──────────────────────────────────────────────────────────────── export default function USPSlide({ lang }: USPSlideProps) { const de = lang === 'de' const isLight = useIsLight()