feat(pitch-deck): USP font sizes match Solution slide, product modules updated
All checks were successful
Build pitch-deck / build-push-deploy (push) Successful in 1m4s
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 31s
CI / test-python-voice (push) Successful in 32s
CI / test-bqas (push) Successful in 30s
All checks were successful
Build pitch-deck / build-push-deploy (push) Successful in 1m4s
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 31s
CI / test-python-voice (push) Successful in 32s
CI / test-bqas (push) Successful in 30s
USP slide: - Title/subtitle same as Solution (text-4xl/text-lg) - Card titles: text-base font-bold (was text-xs) - Card descriptions: text-sm text-white/50 (was text-[10px]) - Circle text: text-sm (was text-[11px]/text-[9px]) - Cards 240px wide with GlassCard wrapper Product slide: - "Integration in Kundenprozesse" → "AI Act Compliance" (UCCA, Betriebsrat) - "Cookie-Generator" → "Tender Matching" (RFQ gegen Codebase) - Remove "FR" badge from deployment options Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,9 +24,9 @@ const MODULES = [
|
|||||||
{ icon: UserCheck, color: '#14b8a6', de: 'Consent Management', en: 'Consent Management', descDe: 'Einwilligungen, Cookie-Banner, Widerruf', descEn: 'Consent, cookie banner, withdrawal' },
|
{ icon: UserCheck, color: '#14b8a6', de: 'Consent Management', en: 'Consent Management', descDe: 'Einwilligungen, Cookie-Banner, Widerruf', descEn: 'Consent, cookie banner, withdrawal' },
|
||||||
{ icon: AlertTriangle, color: '#f59e0b', de: 'Notfallpläne', en: 'Incident Response', descDe: 'Datenschutzvorfälle, Meldepflichten, Eskalation', descEn: 'Data breaches, reporting obligations, escalation' },
|
{ icon: AlertTriangle, color: '#f59e0b', de: 'Notfallpläne', en: 'Incident Response', descDe: 'Datenschutzvorfälle, Meldepflichten, Eskalation', descEn: 'Data breaches, reporting obligations, escalation' },
|
||||||
{ icon: Brain, color: '#a855f7', de: 'Compliance LLM', en: 'Compliance LLM', descDe: 'GPT für Text und Audio — sicher in der EU', descEn: 'GPT for text and audio — securely in EU' },
|
{ icon: Brain, color: '#a855f7', de: 'Compliance LLM', en: 'Compliance LLM', descDe: 'GPT für Text und Audio — sicher in der EU', descEn: 'GPT for text and audio — securely in EU' },
|
||||||
{ icon: Shield, color: '#8b5cf6', de: 'Cookie-Generator', en: 'Cookie Generator', descDe: 'Cookie-Banner, Consent-Konfiguration', descEn: 'Cookie banner, consent configuration' },
|
{ icon: Shield, color: '#8b5cf6', de: 'Tender Matching', en: 'Tender Matching', descDe: 'Kundenanfragen (RFQ) gegen Codebase prüfen', descEn: 'Verify customer RFQs against codebase' },
|
||||||
{ icon: GraduationCap, color: '#ec4899', de: 'Academy', en: 'Academy', descDe: 'Online-Schulungen für GF und Mitarbeiter', descEn: 'Online training for management and employees' },
|
{ icon: GraduationCap, color: '#ec4899', de: 'Academy', en: 'Academy', descDe: 'Online-Schulungen für GF und Mitarbeiter', descEn: 'Online training for management and employees' },
|
||||||
{ icon: Puzzle, color: '#0ea5e9', de: 'Integration in Kundenprozesse', en: 'Process Integration', descDe: 'Ticketsysteme, Workflows', descEn: 'Ticket systems, workflows' },
|
{ icon: Puzzle, color: '#0ea5e9', de: 'AI Act Compliance', en: 'AI Act Compliance', descDe: 'UCCA, Use-Case-Bewertung, Betriebsratsmodul', descEn: 'UCCA, use case assessment, works council module' },
|
||||||
{ icon: CheckCircle2, color: '#22c55e', de: 'Sichere Kommunikation', en: 'Secure Communication', descDe: 'Chat + Video mit AI Notetaker', descEn: 'Chat + video with AI notetaker' },
|
{ icon: CheckCircle2, color: '#22c55e', de: 'Sichere Kommunikation', en: 'Secure Communication', descDe: 'Chat + Video mit AI Notetaker', descEn: 'Chat + video with AI notetaker' },
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -109,7 +109,6 @@ export default function ProductSlide({ lang }: ProductSlideProps) {
|
|||||||
<p className="text-[10px] text-white/50 leading-relaxed">{i.product.cloudDesc}</p>
|
<p className="text-[10px] text-white/50 leading-relaxed">{i.product.cloudDesc}</p>
|
||||||
<div className="flex gap-2 mt-2">
|
<div className="flex gap-2 mt-2">
|
||||||
<span className="text-[9px] bg-blue-500/15 text-blue-300 px-2 py-0.5 rounded-full">BSI DE</span>
|
<span className="text-[9px] bg-blue-500/15 text-blue-300 px-2 py-0.5 rounded-full">BSI DE</span>
|
||||||
<span className="text-[9px] bg-blue-500/15 text-blue-300 px-2 py-0.5 rounded-full">FR</span>
|
|
||||||
<span className="text-[9px] bg-blue-500/15 text-blue-300 px-2 py-0.5 rounded-full">{de ? 'Fix oder flexibel' : 'Fixed or flexible'}</span>
|
<span className="text-[9px] bg-blue-500/15 text-blue-300 px-2 py-0.5 rounded-full">{de ? 'Fix oder flexibel' : 'Fixed or flexible'}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import { Language } from '@/lib/types'
|
import { Language } from '@/lib/types'
|
||||||
import GradientText from '../ui/GradientText'
|
import GradientText from '../ui/GradientText'
|
||||||
import FadeInView from '../ui/FadeInView'
|
import FadeInView from '../ui/FadeInView'
|
||||||
|
import GlassCard from '../ui/GlassCard'
|
||||||
import {
|
import {
|
||||||
FileCheck,
|
FileCheck,
|
||||||
Code,
|
Code,
|
||||||
@@ -35,8 +36,6 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
|||||||
{
|
{
|
||||||
icon: GitPullRequest,
|
icon: GitPullRequest,
|
||||||
color: 'text-indigo-400',
|
color: 'text-indigo-400',
|
||||||
border: 'border-indigo-500/20',
|
|
||||||
bg: 'bg-indigo-500/10',
|
|
||||||
label: de ? 'RFQ-Prüfung' : 'RFQ Verification',
|
label: de ? 'RFQ-Prüfung' : 'RFQ Verification',
|
||||||
desc: de
|
desc: de
|
||||||
? 'Kunden-Anforderungsdokumente werden automatisiert gegen die aktuelle Source-Code-Umsetzung geprüft. Abweichungen werden erkannt, Änderungen vorgeschlagen und auf Wunsch direkt im Code umgesetzt — ohne manuelles Nacharbeiten.'
|
? 'Kunden-Anforderungsdokumente werden automatisiert gegen die aktuelle Source-Code-Umsetzung geprüft. Abweichungen werden erkannt, Änderungen vorgeschlagen und auf Wunsch direkt im Code umgesetzt — ohne manuelles Nacharbeiten.'
|
||||||
@@ -45,8 +44,6 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
|||||||
{
|
{
|
||||||
icon: ArrowLeftRight,
|
icon: ArrowLeftRight,
|
||||||
color: 'text-purple-400',
|
color: 'text-purple-400',
|
||||||
border: 'border-purple-500/20',
|
|
||||||
bg: 'bg-purple-500/10',
|
|
||||||
label: de ? 'Bidirektional' : 'Bidirectional',
|
label: de ? 'Bidirektional' : 'Bidirectional',
|
||||||
desc: de
|
desc: 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-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.'
|
||||||
@@ -55,8 +52,6 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
|||||||
{
|
{
|
||||||
icon: Zap,
|
icon: Zap,
|
||||||
color: 'text-amber-400',
|
color: 'text-amber-400',
|
||||||
border: 'border-amber-500/20',
|
|
||||||
bg: 'bg-amber-500/10',
|
|
||||||
label: de ? 'Prozess-Compliance' : 'Process Compliance',
|
label: de ? 'Prozess-Compliance' : 'Process Compliance',
|
||||||
desc: de
|
desc: 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.'
|
? '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.'
|
||||||
@@ -65,8 +60,6 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
|||||||
{
|
{
|
||||||
icon: Shield,
|
icon: Shield,
|
||||||
color: 'text-emerald-400',
|
color: 'text-emerald-400',
|
||||||
border: 'border-emerald-500/20',
|
|
||||||
bg: 'bg-emerald-500/10',
|
|
||||||
label: de ? 'Kontinuierlich' : 'Continuous',
|
label: de ? 'Kontinuierlich' : 'Continuous',
|
||||||
desc: de
|
desc: 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.'
|
? '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.'
|
||||||
@@ -76,42 +69,35 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{/* Title */}
|
<FadeInView className="text-center mb-8">
|
||||||
<FadeInView className="text-center mb-2">
|
<h2 className="text-4xl md:text-5xl font-bold mb-3">
|
||||||
<h2 className="text-4xl md:text-5xl font-bold mb-1">
|
|
||||||
<GradientText>USP</GradientText>
|
<GradientText>USP</GradientText>
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-sm text-white/50 max-w-3xl mx-auto">{subtitle}</p>
|
<p className="text-lg text-white/50 max-w-3xl mx-auto">{subtitle}</p>
|
||||||
</FadeInView>
|
</FadeInView>
|
||||||
|
|
||||||
<FadeInView delay={0.2}>
|
<FadeInView delay={0.2}>
|
||||||
<div className="relative max-w-6xl mx-auto" style={{ height: '480px' }}>
|
<div className="relative max-w-6xl mx-auto" style={{ height: '440px' }}>
|
||||||
|
|
||||||
{/* ===== CENTER: Large circle ===== */}
|
{/* CENTER: Large circle */}
|
||||||
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2" style={{ width: '380px', height: '380px' }}>
|
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2" style={{ width: '380px', height: '380px' }}>
|
||||||
|
|
||||||
{/* Outer spinning dashed ring */}
|
|
||||||
<div className="absolute inset-0 rounded-full border-2 border-dashed border-indigo-500/20 animate-[spin_20s_linear_infinite]" />
|
<div className="absolute inset-0 rounded-full border-2 border-dashed border-indigo-500/20 animate-[spin_20s_linear_infinite]" />
|
||||||
|
|
||||||
{/* Inner ring */}
|
|
||||||
<div className="absolute inset-4 rounded-full border border-white/[0.06] bg-white/[0.015]" />
|
<div className="absolute inset-4 rounded-full border border-white/[0.06] bg-white/[0.015]" />
|
||||||
|
|
||||||
{/* Center hub: Infinity symbol */}
|
|
||||||
<div className="absolute inset-0 flex items-center justify-center z-10">
|
<div className="absolute inset-0 flex items-center justify-center z-10">
|
||||||
<div className="w-20 h-20 rounded-full bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center shadow-xl shadow-indigo-500/30">
|
<div className="w-20 h-20 rounded-full bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center shadow-xl shadow-indigo-500/30">
|
||||||
<span className="text-3xl font-black text-white">∞</span>
|
<span className="text-3xl font-black text-white">∞</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Left half: Compliance */}
|
<div className="absolute left-7 top-1/2 -translate-y-1/2 w-[120px] z-10">
|
||||||
<div className="absolute left-8 top-1/2 -translate-y-1/2 w-[120px] z-10">
|
|
||||||
<div className="flex items-center gap-1.5 mb-2">
|
<div className="flex items-center gap-1.5 mb-2">
|
||||||
<FileCheck className="w-4 h-4 text-indigo-400" />
|
<FileCheck className="w-4 h-4 text-indigo-400" />
|
||||||
<span className="text-xs font-bold text-indigo-400">Compliance</span>
|
<span className="text-sm font-bold text-indigo-400">Compliance</span>
|
||||||
</div>
|
</div>
|
||||||
<ul className="space-y-1.5">
|
<ul className="space-y-1.5">
|
||||||
{complianceItems.map((item, idx) => (
|
{complianceItems.map((item, idx) => (
|
||||||
<li key={idx} className="flex items-center gap-1.5 text-[11px] text-white/50">
|
<li key={idx} className="flex items-center gap-1.5 text-sm text-white/50">
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-indigo-400 shrink-0" />
|
<span className="w-1.5 h-1.5 rounded-full bg-indigo-400 shrink-0" />
|
||||||
{item}
|
{item}
|
||||||
</li>
|
</li>
|
||||||
@@ -119,15 +105,14 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Right half: Code */}
|
<div className="absolute right-7 top-1/2 -translate-y-1/2 w-[120px] z-10">
|
||||||
<div className="absolute right-8 top-1/2 -translate-y-1/2 w-[120px] z-10">
|
|
||||||
<div className="flex items-center gap-1.5 mb-2">
|
<div className="flex items-center gap-1.5 mb-2">
|
||||||
<Code className="w-4 h-4 text-purple-400" />
|
<Code className="w-4 h-4 text-purple-400" />
|
||||||
<span className="text-xs font-bold text-purple-400">Code & Security</span>
|
<span className="text-sm font-bold text-purple-400">Code</span>
|
||||||
</div>
|
</div>
|
||||||
<ul className="space-y-1.5">
|
<ul className="space-y-1.5">
|
||||||
{codeItems.map((item, idx) => (
|
{codeItems.map((item, idx) => (
|
||||||
<li key={idx} className="flex items-center gap-1.5 text-[11px] text-white/50">
|
<li key={idx} className="flex items-center gap-1.5 text-sm text-white/50">
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-purple-400 shrink-0" />
|
<span className="w-1.5 h-1.5 rounded-full bg-purple-400 shrink-0" />
|
||||||
{item}
|
{item}
|
||||||
</li>
|
</li>
|
||||||
@@ -135,73 +120,38 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 4 directional arrows */}
|
|
||||||
<div className="absolute top-[12%] left-[12%] text-indigo-400/60 text-lg z-20">◀</div>
|
<div className="absolute top-[12%] left-[12%] text-indigo-400/60 text-lg z-20">◀</div>
|
||||||
<div className="absolute top-[12%] right-[12%] text-purple-400/60 text-lg z-20">▶</div>
|
<div className="absolute top-[12%] right-[12%] text-purple-400/60 text-lg z-20">▶</div>
|
||||||
<div className="absolute bottom-[12%] left-[12%] text-amber-400/60 text-lg z-20">◀</div>
|
<div className="absolute bottom-[12%] left-[12%] text-amber-400/60 text-lg z-20">◀</div>
|
||||||
<div className="absolute bottom-[12%] right-[12%] text-emerald-400/60 text-lg z-20">▶</div>
|
<div className="absolute bottom-[12%] right-[12%] text-emerald-400/60 text-lg z-20">▶</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* ===== CARDS: 4 corners, spread out ===== */}
|
{/* 4 CORNER CARDS */}
|
||||||
|
{capabilities.map((cap, idx) => {
|
||||||
{/* Top Left */}
|
const Icon = cap.icon
|
||||||
<div className="absolute top-0 left-0 w-[220px]">
|
const posClass = idx === 0 ? 'top-0 left-0'
|
||||||
{(() => { const Icon = capabilities[0].icon; const cap = capabilities[0]; return (
|
: idx === 1 ? 'top-0 right-0'
|
||||||
<div className={`border ${cap.border} ${cap.bg} rounded-xl p-4`}>
|
: idx === 2 ? 'bottom-0 left-0'
|
||||||
|
: 'bottom-0 right-0'
|
||||||
|
return (
|
||||||
|
<div key={idx} className={`absolute ${posClass} w-[240px]`}>
|
||||||
|
<GlassCard hover={false} className="p-4" delay={0}>
|
||||||
<div className="flex items-center gap-2 mb-2">
|
<div className="flex items-center gap-2 mb-2">
|
||||||
<Icon className={`w-5 h-5 ${cap.color}`} />
|
<Icon className={`w-5 h-5 ${cap.color}`} />
|
||||||
<span className={`text-sm font-bold ${cap.color}`}>{cap.label}</span>
|
<h3 className={`text-base font-bold ${cap.color}`}>{cap.label}</h3>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-white/50 leading-relaxed">{cap.desc}</p>
|
<p className="text-sm text-white/50 leading-relaxed">{cap.desc}</p>
|
||||||
</div>
|
</GlassCard>
|
||||||
)})()}
|
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
|
||||||
{/* Top Right */}
|
{/* SVG connection lines */}
|
||||||
<div className="absolute top-0 right-0 w-[220px]">
|
|
||||||
{(() => { const Icon = capabilities[1].icon; const cap = capabilities[1]; return (
|
|
||||||
<div className={`border ${cap.border} ${cap.bg} rounded-xl p-4`}>
|
|
||||||
<div className="flex items-center gap-2 mb-2">
|
|
||||||
<Icon className={`w-5 h-5 ${cap.color}`} />
|
|
||||||
<span className={`text-sm font-bold ${cap.color}`}>{cap.label}</span>
|
|
||||||
</div>
|
|
||||||
<p className="text-xs text-white/50 leading-relaxed">{cap.desc}</p>
|
|
||||||
</div>
|
|
||||||
)})()}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Bottom Left */}
|
|
||||||
<div className="absolute bottom-0 left-0 w-[220px]">
|
|
||||||
{(() => { const Icon = capabilities[2].icon; const cap = capabilities[2]; return (
|
|
||||||
<div className={`border ${cap.border} ${cap.bg} rounded-xl p-4`}>
|
|
||||||
<div className="flex items-center gap-2 mb-2">
|
|
||||||
<Icon className={`w-5 h-5 ${cap.color}`} />
|
|
||||||
<span className={`text-sm font-bold ${cap.color}`}>{cap.label}</span>
|
|
||||||
</div>
|
|
||||||
<p className="text-xs text-white/50 leading-relaxed">{cap.desc}</p>
|
|
||||||
</div>
|
|
||||||
)})()}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Bottom Right */}
|
|
||||||
<div className="absolute bottom-0 right-0 w-[220px]">
|
|
||||||
{(() => { const Icon = capabilities[3].icon; const cap = capabilities[3]; return (
|
|
||||||
<div className={`border ${cap.border} ${cap.bg} rounded-xl p-4`}>
|
|
||||||
<div className="flex items-center gap-2 mb-2">
|
|
||||||
<Icon className={`w-5 h-5 ${cap.color}`} />
|
|
||||||
<span className={`text-sm font-bold ${cap.color}`}>{cap.label}</span>
|
|
||||||
</div>
|
|
||||||
<p className="text-xs text-white/50 leading-relaxed">{cap.desc}</p>
|
|
||||||
</div>
|
|
||||||
)})()}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Dashed connection lines from circle to cards */}
|
|
||||||
<svg className="absolute inset-0 w-full h-full pointer-events-none z-0" preserveAspectRatio="none" viewBox="0 0 100 100">
|
<svg className="absolute inset-0 w-full h-full pointer-events-none z-0" preserveAspectRatio="none" viewBox="0 0 100 100">
|
||||||
<line x1="32" y1="28" x2="22" y2="18" stroke="rgba(99,102,241,0.15)" strokeWidth="0.3" strokeDasharray="1 1" />
|
<line x1="30" y1="25" x2="22" y2="15" stroke="rgba(99,102,241,0.15)" strokeWidth="0.3" strokeDasharray="1 1" />
|
||||||
<line x1="68" y1="28" x2="78" y2="18" stroke="rgba(168,85,247,0.15)" strokeWidth="0.3" strokeDasharray="1 1" />
|
<line x1="70" y1="25" x2="78" y2="15" stroke="rgba(168,85,247,0.15)" strokeWidth="0.3" strokeDasharray="1 1" />
|
||||||
<line x1="32" y1="72" x2="22" y2="82" stroke="rgba(245,158,11,0.15)" strokeWidth="0.3" strokeDasharray="1 1" />
|
<line x1="30" y1="75" x2="22" y2="85" stroke="rgba(245,158,11,0.15)" strokeWidth="0.3" strokeDasharray="1 1" />
|
||||||
<line x1="68" y1="72" x2="78" y2="82" stroke="rgba(16,185,129,0.15)" strokeWidth="0.3" strokeDasharray="1 1" />
|
<line x1="70" y1="75" x2="78" y2="85" stroke="rgba(16,185,129,0.15)" strokeWidth="0.3" strokeDasharray="1 1" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</FadeInView>
|
</FadeInView>
|
||||||
|
|||||||
Reference in New Issue
Block a user