refactor: Consolidate standalone services into admin-v2, add new SDK modules
Remove standalone services (ai-compliance-sdk root, developer-portal, dsms-gateway, dsms-node, night-scheduler) and legacy compliance/dsgvo pages. Add new SDK pipeline modules (academy, document-crawler, dsb-portal, incidents, whistleblower, reporting, sso, multi-tenant, industry-templates). Add drafting engine, legal corpus files (AT/CH/DE), pitch-deck, blog and Förderantrag pages. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
40
pitch-deck/components/slides/AIQASlide.tsx
Normal file
40
pitch-deck/components/slides/AIQASlide.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
'use client'
|
||||
|
||||
import { Language } from '@/lib/types'
|
||||
import { t } from '@/lib/i18n'
|
||||
import { Bot } from 'lucide-react'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import ChatInterface from '../ui/ChatInterface'
|
||||
import LiveIndicator from '../ui/LiveIndicator'
|
||||
|
||||
interface AIQASlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
export default function AIQASlide({ lang }: AIQASlideProps) {
|
||||
const i = t(lang)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FadeInView className="text-center mb-8">
|
||||
<div className="flex items-center justify-center gap-3 mb-4">
|
||||
<div className="w-12 h-12 rounded-xl bg-indigo-500/20 flex items-center justify-center">
|
||||
<Bot className="w-6 h-6 text-indigo-400" />
|
||||
</div>
|
||||
<LiveIndicator />
|
||||
</div>
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-3">
|
||||
<GradientText>{i.aiqa.title}</GradientText>
|
||||
</h2>
|
||||
<p className="text-lg text-white/50 max-w-2xl mx-auto">{i.aiqa.subtitle}</p>
|
||||
</FadeInView>
|
||||
|
||||
<FadeInView delay={0.3}>
|
||||
<div className="max-w-3xl mx-auto bg-white/[0.04] border border-white/10 rounded-2xl p-6">
|
||||
<ChatInterface lang={lang} />
|
||||
</div>
|
||||
</FadeInView>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
200
pitch-deck/components/slides/AnnexAIStackSlide.tsx
Normal file
200
pitch-deck/components/slides/AnnexAIStackSlide.tsx
Normal file
@@ -0,0 +1,200 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language } from '@/lib/types'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import { Brain, Cpu, Zap, ArrowRight } from 'lucide-react'
|
||||
|
||||
interface AnnexAIStackSlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
export default function AnnexAIStackSlide({ lang }: AnnexAIStackSlideProps) {
|
||||
const roadmapSteps = [
|
||||
{
|
||||
year: '2026',
|
||||
model: 'Qwen 32B',
|
||||
label: lang === 'de' ? 'Foundation' : 'Foundation',
|
||||
},
|
||||
{
|
||||
year: '2027',
|
||||
model: 'Multi-Model 70B',
|
||||
label: lang === 'de' ? 'Skalierung' : 'Scaling',
|
||||
},
|
||||
{
|
||||
year: '2028',
|
||||
model: 'Fine-Tuned 100B+',
|
||||
label: 'Enterprise',
|
||||
},
|
||||
{
|
||||
year: '2030',
|
||||
model: '1000B Agent Network',
|
||||
label: lang === 'de' ? 'Volle Autonomie' : 'Full Autonomy',
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="h-screen w-full flex items-center justify-center bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950 text-white p-8">
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<FadeInView>
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-5xl font-bold mb-4">
|
||||
<GradientText>
|
||||
{lang === 'de' ? 'KI-Stack & LLM-Architektur' : 'AI Stack & LLM Architecture'}
|
||||
</GradientText>
|
||||
</h2>
|
||||
<p className="text-xl text-slate-400">
|
||||
{lang === 'de' ? 'Von 32B zu 1000B Parametern' : 'From 32B to 1000B parameters'}
|
||||
</p>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
{/* LLM Evolution Roadmap */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.2, duration: 0.6 }}
|
||||
className="mb-12"
|
||||
>
|
||||
<div className="flex items-center justify-between gap-2 mb-12">
|
||||
{roadmapSteps.map((step, index) => (
|
||||
<div key={step.year} className="flex items-center flex-1">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ delay: 0.3 + index * 0.1, duration: 0.5 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-4 flex-1"
|
||||
>
|
||||
<div className="text-sm text-blue-400 font-semibold mb-1">{step.year}</div>
|
||||
<div className="text-base font-bold mb-1">{step.model}</div>
|
||||
<div className="text-xs text-slate-400">{step.label}</div>
|
||||
</motion.div>
|
||||
|
||||
{index < roadmapSteps.length - 1 && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: -10 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.4 + index * 0.1, duration: 0.5 }}
|
||||
className="mx-2"
|
||||
>
|
||||
<ArrowRight className="w-5 h-5 text-blue-400" />
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* Bottom Section: 2-column grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{/* Left Card - Multi-Model Router */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.6, duration: 0.6 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-6"
|
||||
>
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="bg-blue-500/20 p-3 rounded-lg">
|
||||
<Brain className="w-6 h-6 text-blue-400" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold">
|
||||
{lang === 'de' ? 'Multi-Model Router' : 'Multi-Model Router'}
|
||||
</h3>
|
||||
</div>
|
||||
<ul className="space-y-3 text-slate-300">
|
||||
<li className="flex items-start gap-2">
|
||||
<span className="text-blue-400 mt-1">•</span>
|
||||
<span>
|
||||
{lang === 'de'
|
||||
? 'Automatische Modellauswahl basierend auf Aufgabe'
|
||||
: 'Automatic model selection based on task'}
|
||||
</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<span className="text-blue-400 mt-1">•</span>
|
||||
<span>
|
||||
{lang === 'de'
|
||||
? 'Einfache Anfragen → kleineres Modell (schnell, günstig)'
|
||||
: 'Simple queries → smaller model (fast, cheap)'}
|
||||
</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<span className="text-blue-400 mt-1">•</span>
|
||||
<span>
|
||||
{lang === 'de'
|
||||
? 'Komplexe Analysen → größeres Modell (präzise)'
|
||||
: 'Complex analysis → larger model (accurate)'}
|
||||
</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<span className="text-green-400 mt-1">•</span>
|
||||
<span className="font-semibold text-green-400">
|
||||
{lang === 'de'
|
||||
? 'Kostenoptimierung: 60% günstiger als immer großes Modell'
|
||||
: 'Cost optimization: 60% cheaper than always using large model'}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</motion.div>
|
||||
|
||||
{/* Right Card - Inference Optimization */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: 20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.7, duration: 0.6 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-6"
|
||||
>
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="bg-purple-500/20 p-3 rounded-lg">
|
||||
<Zap className="w-6 h-6 text-purple-400" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold">
|
||||
{lang === 'de' ? 'Inference-Optimierung' : 'Inference Optimization'}
|
||||
</h3>
|
||||
</div>
|
||||
<ul className="space-y-3 text-slate-300">
|
||||
<li className="flex items-start gap-2">
|
||||
<span className="text-purple-400 mt-1">•</span>
|
||||
<span>
|
||||
{lang === 'de'
|
||||
? 'Apple Neural Engine Beschleunigung'
|
||||
: 'Apple Neural Engine acceleration'}
|
||||
</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<span className="text-purple-400 mt-1">•</span>
|
||||
<span>
|
||||
{lang === 'de'
|
||||
? 'Quantisierung (INT4/INT8) für schnellere Inferenz'
|
||||
: 'Quantization (INT4/INT8) for faster inference'}
|
||||
</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<span className="text-purple-400 mt-1">•</span>
|
||||
<span>Context window: 32k tokens</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<span className="text-purple-400 mt-1">•</span>
|
||||
<span>
|
||||
{lang === 'de'
|
||||
? 'Durchschn. Antwortzeit: <2s für einfache Anfragen'
|
||||
: 'Avg response time: <2s for simple queries'}
|
||||
</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<span className="text-green-400 mt-1">•</span>
|
||||
<span className="font-semibold text-green-400">
|
||||
{lang === 'de'
|
||||
? 'GPU vs Apple Silicon: Apple 3x besseres Preis-/Leistungsverhältnis für Inferenz'
|
||||
: 'GPU vs Apple Silicon: Apple 3x better price/performance for inference'}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
147
pitch-deck/components/slides/AnnexAgentArchSlide.tsx
Normal file
147
pitch-deck/components/slides/AnnexAgentArchSlide.tsx
Normal file
@@ -0,0 +1,147 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language } from '@/lib/types'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import { Brain, GraduationCap, ClipboardCheck, Scale, Bell, Database, MessageSquare, Archive } from 'lucide-react'
|
||||
|
||||
interface AnnexAgentArchSlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
export default function AnnexAgentArchSlide({ lang }: AnnexAgentArchSlideProps) {
|
||||
const agents = [
|
||||
{
|
||||
name: lang === 'de' ? 'Tutor Agent' : 'Tutor Agent',
|
||||
icon: GraduationCap,
|
||||
color: 'text-blue-400',
|
||||
position: 'col-start-1 row-start-1'
|
||||
},
|
||||
{
|
||||
name: lang === 'de' ? 'Grader Agent' : 'Grader Agent',
|
||||
icon: ClipboardCheck,
|
||||
color: 'text-green-400',
|
||||
position: 'col-start-3 row-start-1'
|
||||
},
|
||||
{
|
||||
name: lang === 'de' ? 'Quality Judge' : 'Quality Judge',
|
||||
icon: Scale,
|
||||
color: 'text-purple-400',
|
||||
position: 'col-start-1 row-start-3'
|
||||
},
|
||||
{
|
||||
name: lang === 'de' ? 'Alert Agent' : 'Alert Agent',
|
||||
icon: Bell,
|
||||
color: 'text-amber-400',
|
||||
position: 'col-start-3 row-start-3'
|
||||
}
|
||||
]
|
||||
|
||||
const features = [
|
||||
{
|
||||
icon: Archive,
|
||||
title: lang === 'de' ? 'Session Management' : 'Session Management',
|
||||
desc: lang === 'de' ? 'Persistent state, auto-recovery, checkpoints' : 'Persistent state, auto-recovery, checkpoints'
|
||||
},
|
||||
{
|
||||
icon: Database,
|
||||
title: lang === 'de' ? 'Shared Brain' : 'Shared Brain',
|
||||
desc: lang === 'de' ? 'Long-term memory, knowledge graph, context sharing' : 'Long-term memory, knowledge graph, context sharing'
|
||||
},
|
||||
{
|
||||
icon: MessageSquare,
|
||||
title: lang === 'de' ? 'Message Bus' : 'Message Bus',
|
||||
desc: lang === 'de' ? 'Real-time inter-agent communication, priority routing' : 'Real-time inter-agent communication, priority routing'
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<FadeInView>
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-4">
|
||||
<GradientText>
|
||||
{lang === 'de' ? 'Compliance Agent Architektur' : 'Compliance Agent Architecture'}
|
||||
</GradientText>
|
||||
</h2>
|
||||
<p className="text-xl text-white/60">
|
||||
{lang === 'de' ? 'Multi-Agent System für autonome Compliance' : 'Multi-agent system for autonomous compliance'}
|
||||
</p>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
{/* Agent Architecture Diagram */}
|
||||
<FadeInView delay={0.2}>
|
||||
<div className="mb-12 grid grid-cols-3 grid-rows-3 gap-4 max-w-4xl mx-auto">
|
||||
{/* Top agents */}
|
||||
{agents.slice(0, 2).map((agent, idx) => (
|
||||
<motion.div
|
||||
key={agent.name}
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ delay: 0.3 + idx * 0.1 }}
|
||||
className={`${agent.position} bg-white/[0.04] border border-white/[0.06] rounded-xl p-4 text-center`}
|
||||
>
|
||||
<agent.icon className={`w-10 h-10 mx-auto mb-2 ${agent.color}`} />
|
||||
<h3 className="text-sm font-semibold text-white/90">{agent.name}</h3>
|
||||
</motion.div>
|
||||
))}
|
||||
|
||||
{/* Center Orchestrator */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ delay: 0.5 }}
|
||||
className="col-start-2 row-start-2 bg-gradient-to-br from-indigo-500/20 to-purple-500/20 border-2 border-indigo-400/30 rounded-xl p-6 text-center relative"
|
||||
>
|
||||
<Brain className="w-12 h-12 mx-auto mb-2 text-indigo-400" />
|
||||
<h3 className="text-lg font-bold text-white">Orchestrator</h3>
|
||||
<p className="text-xs text-white/60 mt-1">
|
||||
{lang === 'de' ? 'Koordiniert alle Agents' : 'Coordinates all agents'}
|
||||
</p>
|
||||
|
||||
{/* Connection lines */}
|
||||
<div className="absolute -top-4 left-1/2 w-0.5 h-4 bg-indigo-400/30" />
|
||||
<div className="absolute -bottom-4 left-1/2 w-0.5 h-4 bg-indigo-400/30" />
|
||||
<div className="absolute -left-4 top-1/2 h-0.5 w-4 bg-indigo-400/30" />
|
||||
<div className="absolute -right-4 top-1/2 h-0.5 w-4 bg-indigo-400/30" />
|
||||
</motion.div>
|
||||
|
||||
{/* Bottom agents */}
|
||||
{agents.slice(2, 4).map((agent, idx) => (
|
||||
<motion.div
|
||||
key={agent.name}
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ delay: 0.6 + idx * 0.1 }}
|
||||
className={`${agent.position} bg-white/[0.04] border border-white/[0.06] rounded-xl p-4 text-center`}
|
||||
>
|
||||
<agent.icon className={`w-10 h-10 mx-auto mb-2 ${agent.color}`} />
|
||||
<h3 className="text-sm font-semibold text-white/90">{agent.name}</h3>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
{/* Features */}
|
||||
<FadeInView delay={0.8}>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
{features.map((feature, idx) => (
|
||||
<motion.div
|
||||
key={feature.title}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.9 + idx * 0.1 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-4"
|
||||
>
|
||||
<feature.icon className="w-8 h-8 text-indigo-400 mb-3" />
|
||||
<h3 className="text-lg font-semibold text-white/90 mb-2">{feature.title}</h3>
|
||||
<p className="text-sm text-white/60">{feature.desc}</p>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</FadeInView>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
145
pitch-deck/components/slides/AnnexAgentRAGSlide.tsx
Normal file
145
pitch-deck/components/slides/AnnexAgentRAGSlide.tsx
Normal file
@@ -0,0 +1,145 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language } from '@/lib/types'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import { FileText, Layers, Tag, RefreshCw } from 'lucide-react'
|
||||
|
||||
interface AnnexAgentRAGSlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
export default function AnnexAgentRAGSlide({ lang }: AnnexAgentRAGSlideProps) {
|
||||
const regulations = [
|
||||
{
|
||||
name: 'DSGVO',
|
||||
articles: lang === 'de' ? '99 Artikel' : '99 Articles',
|
||||
recitals: lang === 'de' ? '173 Erwägungsgründe' : '173 Recitals',
|
||||
color: 'from-blue-500/20 to-blue-600/20',
|
||||
border: 'border-blue-400/30'
|
||||
},
|
||||
{
|
||||
name: 'AI Act',
|
||||
articles: lang === 'de' ? '113 Artikel' : '113 Articles',
|
||||
recitals: lang === 'de' ? '180 Erwägungsgründe' : '180 Recitals',
|
||||
color: 'from-purple-500/20 to-purple-600/20',
|
||||
border: 'border-purple-400/30'
|
||||
},
|
||||
{
|
||||
name: 'NIS2',
|
||||
articles: lang === 'de' ? '46 Artikel' : '46 Articles',
|
||||
recitals: lang === 'de' ? '144 Erwägungsgründe' : '144 Recitals',
|
||||
color: 'from-green-500/20 to-green-600/20',
|
||||
border: 'border-green-400/30'
|
||||
}
|
||||
]
|
||||
|
||||
const chunkingDetails = [
|
||||
{
|
||||
icon: Layers,
|
||||
label: lang === 'de' ? 'Chunk-Größe' : 'Chunk size',
|
||||
value: lang === 'de' ? '512 Tokens mit 64 Token Überlappung' : '512 tokens with 64 token overlap'
|
||||
},
|
||||
{
|
||||
icon: Tag,
|
||||
label: lang === 'de' ? 'Metadaten-Tagging' : 'Metadata tagging',
|
||||
value: lang === 'de' ? 'Artikelnummer, Abschnitt, Verordnung, Sprache' : 'Article number, section, regulation, language'
|
||||
},
|
||||
{
|
||||
icon: FileText,
|
||||
label: lang === 'de' ? 'Hierarchisches Chunking' : 'Hierarchical chunking',
|
||||
value: lang === 'de' ? 'Artikel → Absatz → Satz' : 'Article → Paragraph → Sentence'
|
||||
},
|
||||
{
|
||||
icon: RefreshCw,
|
||||
label: lang === 'de' ? 'Update-Workflow' : 'Update workflow',
|
||||
value: lang === 'de' ? 'Automatische Re-Indizierung bei Gesetzesänderungen' : 'Automatic re-indexing on law changes'
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<FadeInView>
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-4">
|
||||
<GradientText>
|
||||
{lang === 'de' ? 'Rechtsdokumente im RAG' : 'Legal Documents in RAG'}
|
||||
</GradientText>
|
||||
</h2>
|
||||
<p className="text-xl text-white/60">
|
||||
{lang === 'de' ? 'Wie Gesetze in die KI gelangen' : 'How laws enter the AI'}
|
||||
</p>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
{/* Regulations */}
|
||||
<FadeInView delay={0.2}>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12">
|
||||
{regulations.map((reg, idx) => (
|
||||
<motion.div
|
||||
key={reg.name}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.3 + idx * 0.1 }}
|
||||
className={`bg-gradient-to-br ${reg.color} border ${reg.border} rounded-xl p-6 text-center`}
|
||||
>
|
||||
<h3 className="text-2xl font-bold text-white mb-4">{reg.name}</h3>
|
||||
<div className="space-y-2">
|
||||
<div className="bg-white/[0.08] rounded-lg p-3">
|
||||
<p className="text-lg font-semibold text-white/90">{reg.articles}</p>
|
||||
</div>
|
||||
<div className="bg-white/[0.08] rounded-lg p-3">
|
||||
<p className="text-lg font-semibold text-white/90">{reg.recitals}</p>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
{/* Chunking Strategy */}
|
||||
<FadeInView delay={0.6}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.7 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-6"
|
||||
>
|
||||
<h3 className="text-2xl font-bold text-white/90 mb-6 text-center">
|
||||
{lang === 'de' ? 'Chunking-Strategie' : 'Chunking Strategy'}
|
||||
</h3>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
|
||||
{chunkingDetails.map((detail, idx) => (
|
||||
<motion.div
|
||||
key={detail.label}
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.8 + idx * 0.1 }}
|
||||
className="flex items-start gap-4"
|
||||
>
|
||||
<detail.icon className="w-6 h-6 text-indigo-400 flex-shrink-0 mt-1" />
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold text-white/80 mb-1">{detail.label}</h4>
|
||||
<p className="text-sm text-white/60">{detail.value}</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 1.2 }}
|
||||
className="text-center pt-4 border-t border-white/[0.06]"
|
||||
>
|
||||
<p className="text-lg font-semibold text-indigo-400">
|
||||
{lang === 'de' ? 'Aktuell: 15.000+ Chunks indiziert' : 'Currently: 15,000+ chunks indexed'}
|
||||
</p>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</FadeInView>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
162
pitch-deck/components/slides/AnnexAgentWorkflowSlide.tsx
Normal file
162
pitch-deck/components/slides/AnnexAgentWorkflowSlide.tsx
Normal file
@@ -0,0 +1,162 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language } from '@/lib/types'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import { Upload, ScanLine, Search, AlertTriangle, FileText, UserCheck, ShieldCheck } from 'lucide-react'
|
||||
|
||||
interface AnnexAgentWorkflowSlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
export default function AnnexAgentWorkflowSlide({ lang }: AnnexAgentWorkflowSlideProps) {
|
||||
const workflowSteps = [
|
||||
{
|
||||
icon: Upload,
|
||||
title: 'Upload',
|
||||
desc: lang === 'de' ? 'Dokument-Upload (Verträge, Richtlinien, Aufzeichnungen)' : 'Document upload (contracts, policies, records)',
|
||||
color: 'text-blue-400'
|
||||
},
|
||||
{
|
||||
icon: ScanLine,
|
||||
title: 'OCR',
|
||||
desc: lang === 'de' ? 'Automatische Textextraktion (PaddleOCR)' : 'Automatic text extraction (PaddleOCR)',
|
||||
color: 'text-purple-400'
|
||||
},
|
||||
{
|
||||
icon: Search,
|
||||
title: lang === 'de' ? 'Analyse' : 'Analysis',
|
||||
desc: lang === 'de' ? 'KI analysiert gegen DSGVO/AI Act/NIS2' : 'AI analyzes against DSGVO/AI Act/NIS2',
|
||||
color: 'text-indigo-400'
|
||||
},
|
||||
{
|
||||
icon: AlertTriangle,
|
||||
title: lang === 'de' ? 'Risikobewertung' : 'Risk Assessment',
|
||||
desc: lang === 'de' ? 'Automatische Risikoklassifizierung (niedrig/mittel/hoch/kritisch)' : 'Automatic risk classification (low/medium/high/critical)',
|
||||
color: 'text-amber-400'
|
||||
},
|
||||
{
|
||||
icon: FileText,
|
||||
title: lang === 'de' ? 'Report-Generierung' : 'Report Generation',
|
||||
desc: lang === 'de' ? 'DSFA, VVT, TOM Dokumente automatisch erstellt' : 'DSFA, VVT, TOM documents auto-generated',
|
||||
color: 'text-green-400'
|
||||
},
|
||||
{
|
||||
icon: UserCheck,
|
||||
title: lang === 'de' ? 'Human Review' : 'Human Review',
|
||||
desc: lang === 'de' ? 'Experte prüft und genehmigt' : 'Expert reviews and approves',
|
||||
color: 'text-cyan-400'
|
||||
}
|
||||
]
|
||||
|
||||
const humanInLoopFeatures = [
|
||||
lang === 'de' ? 'KI schlägt vor, Mensch entscheidet' : 'AI suggests, human decides',
|
||||
lang === 'de' ? 'Kritische Entscheidungen erfordern Genehmigung' : 'Critical decisions require approval',
|
||||
lang === 'de' ? 'Audit-Trail für alle Aktionen' : 'Audit trail for all actions',
|
||||
lang === 'de' ? 'Compliance Officer immer in Kontrolle' : 'Compliance officer always in control'
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<FadeInView>
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-4">
|
||||
<GradientText>
|
||||
{lang === 'de' ? 'Autonomer Compliance-Workflow' : 'Autonomous Compliance Workflow'}
|
||||
</GradientText>
|
||||
</h2>
|
||||
<p className="text-xl text-white/60">
|
||||
{lang === 'de' ? 'End-to-End: Vom Upload bis zum fertigen Report' : 'End-to-end: From upload to finished report'}
|
||||
</p>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
{/* Workflow Steps */}
|
||||
<div className="lg:col-span-2">
|
||||
<FadeInView delay={0.2}>
|
||||
<div className="space-y-4">
|
||||
{workflowSteps.map((step, idx) => (
|
||||
<motion.div
|
||||
key={step.title}
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.3 + idx * 0.1 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-4 relative"
|
||||
>
|
||||
<div className="flex items-start gap-4">
|
||||
<div className={`p-3 bg-white/[0.06] rounded-lg ${step.color}`}>
|
||||
<step.icon className="w-6 h-6" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<span className="text-xs font-bold text-white/40">
|
||||
{lang === 'de' ? 'SCHRITT' : 'STEP'} {idx + 1}
|
||||
</span>
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-white/90 mb-1">{step.title}</h3>
|
||||
<p className="text-sm text-white/60">{step.desc}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Connection line to next step */}
|
||||
{idx < workflowSteps.length - 1 && (
|
||||
<div className="absolute left-8 -bottom-4 w-0.5 h-4 bg-gradient-to-b from-white/[0.2] to-transparent" />
|
||||
)}
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</FadeInView>
|
||||
</div>
|
||||
|
||||
{/* Human-in-the-Loop */}
|
||||
<div className="lg:col-span-1">
|
||||
<FadeInView delay={0.9}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 1.0 }}
|
||||
className="bg-gradient-to-br from-indigo-500/20 to-purple-500/20 border border-indigo-400/30 rounded-xl p-6 sticky top-8"
|
||||
>
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<ShieldCheck className="w-8 h-8 text-indigo-400" />
|
||||
<h3 className="text-xl font-bold text-white">
|
||||
{lang === 'de' ? 'Human-in-the-Loop' : 'Human-in-the-Loop'}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<ul className="space-y-4">
|
||||
{humanInLoopFeatures.map((feature, idx) => (
|
||||
<motion.li
|
||||
key={idx}
|
||||
initial={{ opacity: 0, x: -10 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 1.1 + idx * 0.1 }}
|
||||
className="flex items-start gap-3"
|
||||
>
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-indigo-400 mt-2 flex-shrink-0" />
|
||||
<p className="text-sm text-white/80">{feature}</p>
|
||||
</motion.li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 1.5 }}
|
||||
className="mt-6 pt-6 border-t border-white/[0.1]"
|
||||
>
|
||||
<p className="text-xs text-center text-white/60 italic">
|
||||
{lang === 'de'
|
||||
? 'KI automatisiert Routine, Mensch behält Kontrolle über kritische Entscheidungen'
|
||||
: 'AI automates routine, human retains control over critical decisions'}
|
||||
</p>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</FadeInView>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
146
pitch-deck/components/slides/AnnexDevOpsSlide.tsx
Normal file
146
pitch-deck/components/slides/AnnexDevOpsSlide.tsx
Normal file
@@ -0,0 +1,146 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { GitBranch, Code, Hammer, TestTube, Rocket, ArrowRight, Container, GitMerge, Activity, Bell } from 'lucide-react'
|
||||
import { Language } from '@/lib/types'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
|
||||
interface AnnexDevOpsSlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
export default function AnnexDevOpsSlide({ lang }: AnnexDevOpsSlideProps) {
|
||||
const pipelineSteps = [
|
||||
{ name: 'Code', icon: GitBranch, color: 'from-blue-400 to-blue-600' },
|
||||
{ name: 'Gitea', icon: Code, color: 'from-green-400 to-green-600' },
|
||||
{ name: 'Woodpecker CI', icon: Hammer, color: 'from-orange-400 to-orange-600' },
|
||||
{ name: 'Build', icon: Container, color: 'from-purple-400 to-purple-600' },
|
||||
{ name: 'Test', icon: TestTube, color: 'from-pink-400 to-pink-600' },
|
||||
{ name: 'Deploy', icon: Rocket, color: 'from-cyan-400 to-cyan-600' }
|
||||
]
|
||||
|
||||
const devOpsTools = [
|
||||
{
|
||||
title: 'Woodpecker CI',
|
||||
icon: Hammer,
|
||||
accentColor: 'from-orange-400 to-orange-600',
|
||||
items: [
|
||||
lang === 'de' ? 'Open-Source CI/CD (Apache 2.0)' : 'Open-source CI/CD (Apache 2.0)',
|
||||
lang === 'de' ? 'Docker-native Builds' : 'Docker-native builds',
|
||||
lang === 'de' ? 'Automatische Tests bei jedem Commit' : 'Automatic testing on every commit',
|
||||
lang === 'de' ? 'Build-Zeit: ~3 min' : 'Build time: ~3 min'
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Docker Compose',
|
||||
icon: Container,
|
||||
accentColor: 'from-blue-400 to-blue-600',
|
||||
items: [
|
||||
lang === 'de' ? '30+ Services orchestriert' : '30+ services orchestrated',
|
||||
lang === 'de' ? 'Health Checks für alle Container' : 'Health checks for all containers',
|
||||
lang === 'de' ? 'Automatischer Neustart bei Fehler' : 'Automatic restart on failure',
|
||||
lang === 'de' ? 'Ressourcenlimits konfiguriert' : 'Resource limits configured'
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Gitea',
|
||||
icon: GitMerge,
|
||||
accentColor: 'from-green-400 to-green-600',
|
||||
items: [
|
||||
lang === 'de' ? 'Self-hosted Git Server' : 'Self-hosted Git server',
|
||||
lang === 'de' ? 'Keine GitHub/GitLab Abhängigkeit' : 'No GitHub/GitLab dependency',
|
||||
lang === 'de' ? 'Issue Tracking integriert' : 'Issue tracking integrated',
|
||||
lang === 'de' ? 'Mirror zu externem Backup' : 'Mirror to external backup'
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Monitoring',
|
||||
icon: Activity,
|
||||
accentColor: 'from-purple-400 to-purple-600',
|
||||
items: [
|
||||
lang === 'de' ? 'Night Scheduler für Auto-Shutdown' : 'Night Scheduler for auto-shutdown',
|
||||
lang === 'de' ? 'Container Health Monitoring' : 'Container health monitoring',
|
||||
lang === 'de' ? 'Log-Aggregation' : 'Log aggregation',
|
||||
lang === 'de' ? 'Alerting bei Fehlern' : 'Alerting on failures'
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<FadeInView>
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-5xl font-bold mb-4">
|
||||
<GradientText>
|
||||
{lang === 'de' ? 'DevOps & CI/CD' : 'DevOps & CI/CD'}
|
||||
</GradientText>
|
||||
</h2>
|
||||
<p className="text-xl text-white/60">
|
||||
{lang === 'de'
|
||||
? 'Automatisierte Entwicklungs- und Deployment-Pipeline'
|
||||
: 'Automated development and deployment pipeline'}
|
||||
</p>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
{/* CI/CD Pipeline Visualization */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.1 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-6 mb-8"
|
||||
>
|
||||
<h3 className="text-lg font-semibold mb-6 text-white/90 text-center">
|
||||
{lang === 'de' ? 'CI/CD Pipeline' : 'CI/CD Pipeline'}
|
||||
</h3>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
{pipelineSteps.map((step, index) => (
|
||||
<div key={step.name} className="flex items-center gap-2">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ delay: 0.2 + index * 0.1 }}
|
||||
className="flex flex-col items-center"
|
||||
>
|
||||
<div className={`w-16 h-16 rounded-lg bg-gradient-to-br ${step.color} flex items-center justify-center mb-2`}>
|
||||
<step.icon className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<span className="text-xs text-white/70 text-center">{step.name}</span>
|
||||
</motion.div>
|
||||
{index < pipelineSteps.length - 1 && (
|
||||
<ArrowRight className="w-5 h-5 text-white/30 flex-shrink-0" />
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* DevOps Tools Grid */}
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
{devOpsTools.map((tool, index) => (
|
||||
<motion.div
|
||||
key={tool.title}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.8 + index * 0.1 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-4"
|
||||
>
|
||||
<div className={`w-12 h-12 rounded-lg bg-gradient-to-br ${tool.accentColor} flex items-center justify-center mb-4`}>
|
||||
<tool.icon className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold mb-4 text-white">{tool.title}</h3>
|
||||
<ul className="space-y-2">
|
||||
{tool.items.map((item, itemIndex) => (
|
||||
<li key={itemIndex} className="text-sm text-white/70 flex items-start">
|
||||
<span className="mr-2 text-white/40">•</span>
|
||||
<span>{item}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
97
pitch-deck/components/slides/AnnexInfraSlide.tsx
Normal file
97
pitch-deck/components/slides/AnnexInfraSlide.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language } from '@/lib/types'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import { Server, Container, ShieldOff, Calculator } from 'lucide-react'
|
||||
|
||||
interface AnnexInfraSlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
export default function AnnexInfraSlide({ lang }: AnnexInfraSlideProps) {
|
||||
const title = lang === 'de' ? 'Infrastruktur & Self-Hosting' : 'Infrastructure & Self-Hosting'
|
||||
const subtitle = lang === 'de' ? 'Warum wir auf eigene Hardware setzen' : 'Why we rely on our own hardware'
|
||||
|
||||
const sections = [
|
||||
{
|
||||
icon: Server,
|
||||
title: 'Apple Silicon Hardware',
|
||||
items: [
|
||||
'Mac Mini M2 (Starter), Mac Mini M4 Pro (Business), Mac Studio M4 Max (Enterprise)',
|
||||
'Unified Memory: 16GB / 48GB / 128GB',
|
||||
'Neural Engine for ML inference'
|
||||
]
|
||||
},
|
||||
{
|
||||
icon: Container,
|
||||
title: 'Docker Architecture',
|
||||
items: [
|
||||
'30+ Microservices in Docker Compose',
|
||||
'Automatic health monitoring',
|
||||
'Zero-downtime updates via rolling restarts'
|
||||
]
|
||||
},
|
||||
{
|
||||
icon: ShieldOff,
|
||||
title: lang === 'de' ? 'Why No Cloud?' : 'Why No Cloud?',
|
||||
items: [
|
||||
lang === 'de' ? 'Data sovereignty: No data leaves the company' : 'Data sovereignty: No data leaves the company',
|
||||
lang === 'de' ? 'No recurring cloud costs (AWS/Azure)' : 'No recurring cloud costs (AWS/Azure)',
|
||||
lang === 'de' ? 'BSI-TR-03161 compliance easier on-premise' : 'BSI-TR-03161 compliance easier on-premise',
|
||||
lang === 'de' ? 'DSGVO Art. 28: No third-party processors' : 'DSGVO Art. 28: No third-party processors'
|
||||
]
|
||||
},
|
||||
{
|
||||
icon: Calculator,
|
||||
title: 'Cost Comparison',
|
||||
items: [
|
||||
lang === 'de' ? 'Self-Hosted: EUR 599 hardware + EUR 149/mo' : 'Self-Hosted: EUR 599 hardware + EUR 149/mo',
|
||||
lang === 'de' ? 'Cloud equivalent: EUR 800-1200/mo (AWS)' : 'Cloud equivalent: EUR 800-1200/mo (AWS)',
|
||||
lang === 'de' ? 'Break-even after 4-5 months' : 'Break-even after 4-5 months',
|
||||
lang === 'de' ? '70% cheaper over 3 years' : '70% cheaper over 3 years'
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<FadeInView delay={0}>
|
||||
<h2 className="text-4xl md:text-5xl font-bold text-center mb-4">
|
||||
<GradientText>{title}</GradientText>
|
||||
</h2>
|
||||
<p className="text-xl text-center text-white/60 mb-12">{subtitle}</p>
|
||||
</FadeInView>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{sections.map((section, idx) => {
|
||||
const Icon = section.icon
|
||||
return (
|
||||
<motion.div
|
||||
key={idx}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5, delay: 0.2 + idx * 0.1 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-4"
|
||||
>
|
||||
<div className="flex items-start gap-3 mb-3">
|
||||
<div className="p-2 bg-purple-500/10 rounded-lg">
|
||||
<Icon className="w-6 h-6 text-purple-400" />
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold text-white mt-1">{section.title}</h3>
|
||||
</div>
|
||||
<ul className="space-y-2">
|
||||
{section.items.map((item, itemIdx) => (
|
||||
<li key={itemIdx} className="text-white/70 text-sm leading-relaxed">
|
||||
{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</motion.div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
204
pitch-deck/components/slides/AnnexRAGSlide.tsx
Normal file
204
pitch-deck/components/slides/AnnexRAGSlide.tsx
Normal file
@@ -0,0 +1,204 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Database, FileSearch, Layers, BarChart3, FileUp, ScanLine, Brain } from 'lucide-react'
|
||||
import { Language } from '@/lib/types'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
|
||||
interface AnnexRAGSlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
export default function AnnexRAGSlide({ lang }: AnnexRAGSlideProps) {
|
||||
const pipelineSteps = [
|
||||
{
|
||||
icon: FileUp,
|
||||
labelDE: 'Dokument Upload',
|
||||
labelEN: 'Document Upload'
|
||||
},
|
||||
{
|
||||
icon: ScanLine,
|
||||
labelDE: 'OCR Verarbeitung',
|
||||
labelEN: 'OCR Processing'
|
||||
},
|
||||
{
|
||||
icon: Layers,
|
||||
labelDE: 'Chunking',
|
||||
labelEN: 'Chunking'
|
||||
},
|
||||
{
|
||||
icon: Brain,
|
||||
labelDE: 'Embedding',
|
||||
labelEN: 'Embedding'
|
||||
},
|
||||
{
|
||||
icon: Database,
|
||||
labelDE: 'Vector Store',
|
||||
labelEN: 'Vector Store'
|
||||
}
|
||||
]
|
||||
|
||||
const features = [
|
||||
{
|
||||
titleDE: 'Qdrant Vector DB',
|
||||
titleEN: 'Qdrant Vector DB',
|
||||
icon: Database,
|
||||
pointsDE: [
|
||||
'High-performance vector search',
|
||||
'Hybrid search: semantisch + keyword',
|
||||
'Filter nach Metadaten (Typ, Datum, Vorschrift)',
|
||||
'99.2% Retrieval-Genauigkeit'
|
||||
],
|
||||
pointsEN: [
|
||||
'High-performance vector search',
|
||||
'Hybrid search: semantic + keyword',
|
||||
'Filters by metadata (document type, date, regulation)',
|
||||
'99.2% retrieval accuracy'
|
||||
]
|
||||
},
|
||||
{
|
||||
titleDE: 'Embedding Pipeline',
|
||||
titleEN: 'Embedding Pipeline',
|
||||
icon: FileSearch,
|
||||
pointsDE: [
|
||||
'PaddleOCR für Dokumentenscanning',
|
||||
'Chunk-Größe: 512 Tokens, Overlap: 64',
|
||||
'Sentence-Transformers für Embedding',
|
||||
'Automatische Spracherkennung'
|
||||
],
|
||||
pointsEN: [
|
||||
'PaddleOCR for document scanning',
|
||||
'Chunk size: 512 tokens, overlap: 64',
|
||||
'Sentence-Transformers for embedding',
|
||||
'Automatic language detection'
|
||||
]
|
||||
},
|
||||
{
|
||||
titleDE: 'Hybrid Search',
|
||||
titleEN: 'Hybrid Search',
|
||||
icon: Layers,
|
||||
pointsDE: [
|
||||
'Kombiniert dense + sparse Vektoren',
|
||||
'BM25 für Keyword-Matching',
|
||||
'Cosine-Similarity für semantische Suche',
|
||||
'Re-Ranking für optimale Ergebnisse'
|
||||
],
|
||||
pointsEN: [
|
||||
'Combines dense + sparse vectors',
|
||||
'BM25 for keyword matching',
|
||||
'Cosine similarity for semantic search',
|
||||
'Re-ranking for optimal results'
|
||||
]
|
||||
},
|
||||
{
|
||||
titleDE: 'Retrieval Metrics',
|
||||
titleEN: 'Retrieval Metrics',
|
||||
icon: BarChart3,
|
||||
pointsDE: [
|
||||
'Precision@5: 94.3%',
|
||||
'Recall@10: 97.1%',
|
||||
'MRR: 0.89',
|
||||
'Avg. Latenz: 120ms'
|
||||
],
|
||||
pointsEN: [
|
||||
'Precision@5: 94.3%',
|
||||
'Recall@10: 97.1%',
|
||||
'MRR: 0.89',
|
||||
'Avg latency: 120ms'
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
{/* Header */}
|
||||
<FadeInView>
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-4">
|
||||
<GradientText>
|
||||
{lang === 'de' ? 'RAG Pipeline & Vektordatenbank' : 'RAG Pipeline & Vector Database'}
|
||||
</GradientText>
|
||||
</h2>
|
||||
<p className="text-xl text-white/60">
|
||||
{lang === 'de'
|
||||
? 'Präzise Antworten durch intelligentes Retrieval'
|
||||
: 'Precise answers through intelligent retrieval'}
|
||||
</p>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
{/* Pipeline Visualization */}
|
||||
<FadeInView delay={0.2}>
|
||||
<div className="mb-12">
|
||||
<div className="relative flex items-center justify-between gap-2">
|
||||
{pipelineSteps.map((step, index) => {
|
||||
const Icon = step.icon
|
||||
return (
|
||||
<div key={index} className="flex items-center flex-1">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ delay: 0.3 + index * 0.1 }}
|
||||
className="flex-1"
|
||||
>
|
||||
<div className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-4 text-center hover:bg-white/[0.06] transition-all duration-300">
|
||||
<Icon className="w-8 h-8 mx-auto mb-2 text-blue-400" />
|
||||
<p className="text-sm text-white/80">
|
||||
{lang === 'de' ? step.labelDE : step.labelEN}
|
||||
</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{index < pipelineSteps.length - 1 && (
|
||||
<motion.div
|
||||
initial={{ scaleX: 0 }}
|
||||
animate={{ scaleX: 1 }}
|
||||
transition={{ delay: 0.4 + index * 0.1, duration: 0.3 }}
|
||||
className="flex-shrink-0 mx-2 origin-left"
|
||||
>
|
||||
<div className="h-0.5 w-8 bg-gradient-to-r from-blue-500 to-purple-500" />
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
{/* Feature Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{features.map((feature, index) => {
|
||||
const Icon = feature.icon
|
||||
return (
|
||||
<motion.div
|
||||
key={index}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.6 + index * 0.1 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-4 hover:bg-white/[0.06] transition-all duration-300"
|
||||
>
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<div className="p-2 bg-blue-500/10 rounded-lg">
|
||||
<Icon className="w-5 h-5 text-blue-400" />
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-white">
|
||||
{lang === 'de' ? feature.titleDE : feature.titleEN}
|
||||
</h3>
|
||||
</div>
|
||||
<ul className="space-y-2">
|
||||
{(lang === 'de' ? feature.pointsDE : feature.pointsEN).map((point, idx) => (
|
||||
<li key={idx} className="text-sm text-white/70 flex items-start">
|
||||
<span className="text-blue-400 mr-2">•</span>
|
||||
<span>{point}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</motion.div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
142
pitch-deck/components/slides/AnnexRoadmap2027Slide.tsx
Normal file
142
pitch-deck/components/slides/AnnexRoadmap2027Slide.tsx
Normal file
@@ -0,0 +1,142 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language } from '@/lib/types'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import { Users, Target, TrendingUp, Award } from 'lucide-react'
|
||||
|
||||
interface AnnexRoadmap2027SlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
export default function AnnexRoadmap2027Slide({ lang }: AnnexRoadmap2027SlideProps) {
|
||||
const quarters = [
|
||||
{
|
||||
quarter: 'Q1 2027',
|
||||
accent: 'from-blue-500 to-cyan-500',
|
||||
items: [
|
||||
lang === 'de' ? 'Multi-Model Router Launch' : 'Multi-Model Router launch',
|
||||
lang === 'de' ? 'RAG 2.0 mit Advanced Retrieval' : 'RAG 2.0 with advanced retrieval',
|
||||
lang === 'de' ? '15 zahlende Kunden' : '15 paying customers',
|
||||
lang === 'de' ? 'Team: 3 Personen' : 'Team: 3 people'
|
||||
]
|
||||
},
|
||||
{
|
||||
quarter: 'Q2 2027',
|
||||
accent: 'from-indigo-500 to-blue-500',
|
||||
items: [
|
||||
lang === 'de' ? 'Auto Compliance-Scan Feature' : 'Auto Compliance-Scan feature',
|
||||
lang === 'de' ? 'Kunden Self-Service Portal' : 'Customer self-service portal',
|
||||
lang === 'de' ? '25 zahlende Kunden' : '25 paying customers',
|
||||
lang === 'de' ? 'Erster Enterprise Pilot' : 'First enterprise pilot'
|
||||
]
|
||||
},
|
||||
{
|
||||
quarter: 'Q3 2027',
|
||||
accent: 'from-purple-500 to-indigo-500',
|
||||
items: [
|
||||
lang === 'de' ? 'Echtzeit-Monitoring Dashboard' : 'Real-time monitoring dashboard',
|
||||
lang === 'de' ? 'API für Partner-Integrationen' : 'API for partner integrations',
|
||||
lang === 'de' ? '35 zahlende Kunden' : '35 paying customers',
|
||||
lang === 'de' ? 'Team: 4 Personen' : 'Team: 4 people'
|
||||
]
|
||||
},
|
||||
{
|
||||
quarter: 'Q4 2027',
|
||||
accent: 'from-violet-500 to-purple-500',
|
||||
items: [
|
||||
lang === 'de' ? 'Series A Vorbereitung' : 'Series A preparation',
|
||||
lang === 'de' ? 'Due Diligence Package bereit' : 'Due diligence package ready',
|
||||
lang === 'de' ? '50+ zahlende Kunden' : '50+ paying customers',
|
||||
'ARR: EUR 90k'
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
const metrics = [
|
||||
{
|
||||
icon: Target,
|
||||
label: lang === 'de' ? 'Zielkunden' : 'Target Customers',
|
||||
value: '50+'
|
||||
},
|
||||
{
|
||||
icon: TrendingUp,
|
||||
label: lang === 'de' ? 'Ziel ARR' : 'Target ARR',
|
||||
value: 'EUR 90k'
|
||||
},
|
||||
{
|
||||
icon: Users,
|
||||
label: lang === 'de' ? 'Team-Größe' : 'Team Size',
|
||||
value: '4'
|
||||
},
|
||||
{
|
||||
icon: Award,
|
||||
label: lang === 'de' ? 'Key Milestone' : 'Key Milestone',
|
||||
value: 'Series A Ready'
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<FadeInView>
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-5xl font-bold mb-4">
|
||||
<GradientText>
|
||||
{lang === 'de' ? 'Roadmap 2027' : 'Roadmap 2027'}
|
||||
</GradientText>
|
||||
</h2>
|
||||
<p className="text-xl text-gray-400">
|
||||
{lang === 'de'
|
||||
? 'Product-Market Fit & Series A Vorbereitung'
|
||||
: 'Product-Market Fit & Series A Preparation'}
|
||||
</p>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||
{quarters.map((quarter, index) => (
|
||||
<motion.div
|
||||
key={quarter.quarter}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: index * 0.1 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-4"
|
||||
>
|
||||
<div className={`bg-gradient-to-r ${quarter.accent} text-white text-sm font-bold px-3 py-1 rounded-lg inline-block mb-4`}>
|
||||
{quarter.quarter}
|
||||
</div>
|
||||
<ul className="space-y-3">
|
||||
{quarter.items.map((item, i) => (
|
||||
<li key={i} className="text-sm text-gray-300 flex items-start">
|
||||
<span className="text-blue-400 mr-2">•</span>
|
||||
<span>{item}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.5 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-6"
|
||||
>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-6">
|
||||
{metrics.map((metric, index) => {
|
||||
const Icon = metric.icon
|
||||
return (
|
||||
<div key={index} className="text-center">
|
||||
<Icon className="w-8 h-8 text-blue-400 mx-auto mb-2" />
|
||||
<p className="text-sm text-gray-400 mb-1">{metric.label}</p>
|
||||
<p className="text-2xl font-bold text-white">{metric.value}</p>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
142
pitch-deck/components/slides/AnnexRoadmap2028Slide.tsx
Normal file
142
pitch-deck/components/slides/AnnexRoadmap2028Slide.tsx
Normal file
@@ -0,0 +1,142 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language } from '@/lib/types'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import { Users, Target, TrendingUp, Globe } from 'lucide-react'
|
||||
|
||||
interface AnnexRoadmap2028SlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
export default function AnnexRoadmap2028Slide({ lang }: AnnexRoadmap2028SlideProps) {
|
||||
const quarters = [
|
||||
{
|
||||
quarter: 'Q1 2028',
|
||||
accent: 'from-blue-500 to-cyan-500',
|
||||
items: [
|
||||
lang === 'de' ? 'Federated Learning über Kunden' : 'Federated Learning across customers',
|
||||
lang === 'de' ? 'Multi-Tenant Architektur' : 'Multi-tenant architecture',
|
||||
lang === 'de' ? '80 zahlende Kunden' : '80 paying customers',
|
||||
lang === 'de' ? 'Series A Abschluss (EUR 2-3M)' : 'Series A close (EUR 2-3M)'
|
||||
]
|
||||
},
|
||||
{
|
||||
quarter: 'Q2 2028',
|
||||
accent: 'from-indigo-500 to-blue-500',
|
||||
items: [
|
||||
lang === 'de' ? 'API Marketplace Launch' : 'API Marketplace launch',
|
||||
lang === 'de' ? 'Partner Ökosystem Start' : 'Partner ecosystem start',
|
||||
lang === 'de' ? '120 zahlende Kunden' : '120 paying customers',
|
||||
lang === 'de' ? 'Team: 6 Personen' : 'Team: 6 people'
|
||||
]
|
||||
},
|
||||
{
|
||||
quarter: 'Q3 2028',
|
||||
accent: 'from-purple-500 to-indigo-500',
|
||||
items: [
|
||||
lang === 'de' ? 'Enterprise Tier Launch' : 'Enterprise tier launch',
|
||||
lang === 'de' ? 'DACH Expansion (Österreich, Schweiz)' : 'DACH expansion (Austria, Switzerland)',
|
||||
lang === 'de' ? '160 zahlende Kunden' : '160 paying customers',
|
||||
lang === 'de' ? 'Team: 7 Personen' : 'Team: 7 people'
|
||||
]
|
||||
},
|
||||
{
|
||||
quarter: 'Q4 2028',
|
||||
accent: 'from-violet-500 to-purple-500',
|
||||
items: [
|
||||
lang === 'de' ? 'Volle DACH Abdeckung' : 'Full DACH coverage',
|
||||
lang === 'de' ? '200+ zahlende Kunden' : '200+ paying customers',
|
||||
'ARR: EUR 360k',
|
||||
lang === 'de' ? 'Team: 8 Personen' : 'Team: 8 people'
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
const metrics = [
|
||||
{
|
||||
icon: Target,
|
||||
label: lang === 'de' ? 'Zielkunden' : 'Target Customers',
|
||||
value: '200+'
|
||||
},
|
||||
{
|
||||
icon: TrendingUp,
|
||||
label: lang === 'de' ? 'Ziel ARR' : 'Target ARR',
|
||||
value: 'EUR 360k'
|
||||
},
|
||||
{
|
||||
icon: Users,
|
||||
label: lang === 'de' ? 'Team-Größe' : 'Team Size',
|
||||
value: '8'
|
||||
},
|
||||
{
|
||||
icon: Globe,
|
||||
label: lang === 'de' ? 'Key Milestone' : 'Key Milestone',
|
||||
value: lang === 'de' ? 'DACH Expansion' : 'DACH Expansion'
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<FadeInView>
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-5xl font-bold mb-4">
|
||||
<GradientText>
|
||||
{lang === 'de' ? 'Roadmap 2028' : 'Roadmap 2028'}
|
||||
</GradientText>
|
||||
</h2>
|
||||
<p className="text-xl text-gray-400">
|
||||
{lang === 'de'
|
||||
? 'Enterprise Scale & Series A'
|
||||
: 'Enterprise Scale & Series A'}
|
||||
</p>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||
{quarters.map((quarter, index) => (
|
||||
<motion.div
|
||||
key={quarter.quarter}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: index * 0.1 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-4"
|
||||
>
|
||||
<div className={`bg-gradient-to-r ${quarter.accent} text-white text-sm font-bold px-3 py-1 rounded-lg inline-block mb-4`}>
|
||||
{quarter.quarter}
|
||||
</div>
|
||||
<ul className="space-y-3">
|
||||
{quarter.items.map((item, i) => (
|
||||
<li key={i} className="text-sm text-gray-300 flex items-start">
|
||||
<span className="text-blue-400 mr-2">•</span>
|
||||
<span>{item}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.5 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-6"
|
||||
>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-6">
|
||||
{metrics.map((metric, index) => {
|
||||
const Icon = metric.icon
|
||||
return (
|
||||
<div key={index} className="text-center">
|
||||
<Icon className="w-8 h-8 text-blue-400 mx-auto mb-2" />
|
||||
<p className="text-sm text-gray-400 mb-1">{metric.label}</p>
|
||||
<p className="text-2xl font-bold text-white">{metric.value}</p>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
130
pitch-deck/components/slides/AnnexSecuritySlide.tsx
Normal file
130
pitch-deck/components/slides/AnnexSecuritySlide.tsx
Normal file
@@ -0,0 +1,130 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Shield, Lock, ShieldCheck, Search, FileCode, Key, FileText } from 'lucide-react'
|
||||
import { Language } from '@/lib/types'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
|
||||
interface AnnexSecuritySlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
export default function AnnexSecuritySlide({ lang }: AnnexSecuritySlideProps) {
|
||||
const securityFeatures = [
|
||||
{
|
||||
icon: Shield,
|
||||
title: lang === 'de' ? 'BSI & Compliance' : 'BSI & Compliance',
|
||||
accentColor: 'from-blue-400 to-blue-600',
|
||||
items: [
|
||||
lang === 'de' ? 'BSI-TR-03161 zertifizierte Architektur' : 'BSI-TR-03161 certified architecture',
|
||||
lang === 'de' ? 'DSGVO Art. 32 TOM implementiert' : 'DSGVO Art. 32 TOM implemented',
|
||||
lang === 'de' ? 'Regelmäßige Penetrationstests' : 'Regular penetration testing',
|
||||
lang === 'de' ? 'Sicherheits-Audit-Trail' : 'Security audit trail'
|
||||
]
|
||||
},
|
||||
{
|
||||
icon: Lock,
|
||||
title: lang === 'de' ? 'Verschlüsselung & Vault' : 'Encryption & Vault',
|
||||
accentColor: 'from-purple-400 to-purple-600',
|
||||
items: [
|
||||
lang === 'de' ? 'E2E-Verschlüsselung für Daten in Transit (TLS 1.3)' : 'E2E encryption for all data in transit (TLS 1.3)',
|
||||
lang === 'de' ? 'AES-256 Verschlüsselung im Ruhezustand' : 'AES-256 encryption at rest',
|
||||
lang === 'de' ? 'HashiCorp Vault für Secret Management' : 'HashiCorp Vault for secret management',
|
||||
lang === 'de' ? 'Automatische Zertifikatsrotation' : 'Automatic certificate rotation'
|
||||
]
|
||||
},
|
||||
{
|
||||
icon: ShieldCheck,
|
||||
title: lang === 'de' ? 'Zero Trust' : 'Zero Trust',
|
||||
accentColor: 'from-green-400 to-green-600',
|
||||
items: [
|
||||
lang === 'de' ? 'Kein implizites Vertrauen, alles verifizieren' : 'No implicit trust, verify everything',
|
||||
lang === 'de' ? 'JWT-basierte Authentifizierung' : 'JWT-based authentication',
|
||||
lang === 'de' ? 'RBAC mit minimalen Rechten' : 'RBAC with least privilege',
|
||||
lang === 'de' ? 'Netzwerksegmentierung via Docker' : 'Network segmentation via Docker'
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
const securityTools = [
|
||||
{ name: 'Trivy', description: lang === 'de' ? 'Container Scanning' : 'Container Scanning', icon: Search },
|
||||
{ name: 'Semgrep', description: 'SAST', icon: FileCode },
|
||||
{ name: 'Gitleaks', description: lang === 'de' ? 'Secret Detection' : 'Secret Detection', icon: Key },
|
||||
{ name: 'SBOM', description: lang === 'de' ? 'Software Bill of Materials' : 'Software Bill of Materials', icon: FileText }
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<FadeInView>
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-5xl font-bold mb-4">
|
||||
<GradientText>
|
||||
{lang === 'de' ? 'Sicherheitsarchitektur' : 'Security Architecture'}
|
||||
</GradientText>
|
||||
</h2>
|
||||
<p className="text-xl text-white/60">
|
||||
{lang === 'de'
|
||||
? 'Enterprise-Grade Sicherheit auf eigener Hardware'
|
||||
: 'Enterprise-grade security on own hardware'}
|
||||
</p>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
{/* Security Features Grid */}
|
||||
<div className="grid md:grid-cols-3 gap-6 mb-8">
|
||||
{securityFeatures.map((feature, index) => (
|
||||
<motion.div
|
||||
key={feature.title}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: index * 0.1 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-4"
|
||||
>
|
||||
<div className={`w-12 h-12 rounded-lg bg-gradient-to-br ${feature.accentColor} flex items-center justify-center mb-4`}>
|
||||
<feature.icon className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold mb-4 text-white">{feature.title}</h3>
|
||||
<ul className="space-y-2">
|
||||
{feature.items.map((item, itemIndex) => (
|
||||
<li key={itemIndex} className="text-sm text-white/70 flex items-start">
|
||||
<span className="mr-2 text-white/40">•</span>
|
||||
<span>{item}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Security Tools Bar */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.4 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-6"
|
||||
>
|
||||
<h3 className="text-lg font-semibold mb-4 text-white/90">
|
||||
{lang === 'de' ? 'Sicherheitstools' : 'Security Tools'}
|
||||
</h3>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{securityTools.map((tool, index) => (
|
||||
<motion.div
|
||||
key={tool.name}
|
||||
initial={{ opacity: 0, scale: 0.9 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ delay: 0.5 + index * 0.05 }}
|
||||
className="bg-white/[0.06] border border-white/[0.08] rounded-lg px-4 py-2 flex items-center gap-2"
|
||||
>
|
||||
<tool.icon className="w-4 h-4 text-white/60" />
|
||||
<div>
|
||||
<span className="text-sm font-medium text-white">{tool.name}</span>
|
||||
<span className="text-xs text-white/50 ml-2">{tool.description}</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
181
pitch-deck/components/slides/AnnexUSPComparisonSlide.tsx
Normal file
181
pitch-deck/components/slides/AnnexUSPComparisonSlide.tsx
Normal file
@@ -0,0 +1,181 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Check, X, Minus } from 'lucide-react'
|
||||
import { Language } from '@/lib/types'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
|
||||
interface AnnexUSPComparisonSlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
const comparisonData = [
|
||||
{
|
||||
featureDE: 'Self-Hosted',
|
||||
featureEN: 'Self-Hosted',
|
||||
breakpilot: 'yes',
|
||||
proliance: 'no',
|
||||
dataguard: 'no',
|
||||
heydata: 'no'
|
||||
},
|
||||
{
|
||||
featureDE: 'Eigene KI',
|
||||
featureEN: 'Own AI',
|
||||
breakpilot: 'yes',
|
||||
proliance: 'no',
|
||||
dataguard: 'partial',
|
||||
heydata: 'no'
|
||||
},
|
||||
{
|
||||
featureDE: 'Autonomer Support',
|
||||
featureEN: 'Autonomous Support',
|
||||
breakpilot: 'yes',
|
||||
proliance: 'no',
|
||||
dataguard: 'no',
|
||||
heydata: 'no'
|
||||
},
|
||||
{
|
||||
featureDE: 'DSGVO',
|
||||
featureEN: 'GDPR',
|
||||
breakpilot: 'yes',
|
||||
proliance: 'yes',
|
||||
dataguard: 'yes',
|
||||
heydata: 'yes'
|
||||
},
|
||||
{
|
||||
featureDE: 'AI Act',
|
||||
featureEN: 'AI Act',
|
||||
breakpilot: 'yes',
|
||||
proliance: 'no',
|
||||
dataguard: 'partial',
|
||||
heydata: 'no'
|
||||
},
|
||||
{
|
||||
featureDE: 'NIS2',
|
||||
featureEN: 'NIS2',
|
||||
breakpilot: 'yes',
|
||||
proliance: 'no',
|
||||
dataguard: 'no',
|
||||
heydata: 'no'
|
||||
},
|
||||
{
|
||||
featureDE: 'Hardware inkl.',
|
||||
featureEN: 'Hardware incl.',
|
||||
breakpilot: 'yes',
|
||||
proliance: 'no',
|
||||
dataguard: 'no',
|
||||
heydata: 'no'
|
||||
},
|
||||
{
|
||||
featureDE: 'Preis/Monat',
|
||||
featureEN: 'Price/Month',
|
||||
breakpilot: 'ab EUR 149',
|
||||
proliance: 'ab EUR 299',
|
||||
dataguard: 'ab EUR 499',
|
||||
heydata: 'ab EUR 199'
|
||||
}
|
||||
]
|
||||
|
||||
const StatusIcon = ({ status }: { status: string }) => {
|
||||
if (status === 'yes') {
|
||||
return <Check className="w-5 h-5 text-green-500" />
|
||||
} else if (status === 'no') {
|
||||
return <X className="w-5 h-5 text-white/40" />
|
||||
} else if (status === 'partial') {
|
||||
return <Minus className="w-5 h-5 text-amber-500" />
|
||||
}
|
||||
return <span className="text-sm text-white/80">{status}</span>
|
||||
}
|
||||
|
||||
export default function AnnexUSPComparisonSlide({ lang }: AnnexUSPComparisonSlideProps) {
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<FadeInView>
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-4">
|
||||
<GradientText>
|
||||
{lang === 'de' ? 'Detailvergleich Wettbewerb' : 'Detailed Competitor Comparison'}
|
||||
</GradientText>
|
||||
</h2>
|
||||
<p className="text-xl text-white/60">
|
||||
{lang === 'de' ? 'BreakPilot vs. etablierte Anbieter' : 'BreakPilot vs. established providers'}
|
||||
</p>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl overflow-hidden"
|
||||
>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full">
|
||||
<thead>
|
||||
<tr className="border-b border-white/[0.06]">
|
||||
<th className="text-left p-4 text-white/60 font-medium"></th>
|
||||
<th className="text-center p-4 bg-indigo-500/10 border-x border-indigo-500/20">
|
||||
<div className="text-lg font-bold bg-gradient-to-r from-indigo-400 to-purple-400 bg-clip-text text-transparent">
|
||||
BreakPilot
|
||||
</div>
|
||||
</th>
|
||||
<th className="text-center p-4 text-white font-medium">Proliance</th>
|
||||
<th className="text-center p-4 text-white font-medium">DataGuard</th>
|
||||
<th className="text-center p-4 text-white font-medium">heyData</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{comparisonData.map((row, index) => (
|
||||
<motion.tr
|
||||
key={index}
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: index * 0.05, duration: 0.3 }}
|
||||
className="border-b border-white/[0.06] hover:bg-white/[0.02] transition-colors"
|
||||
>
|
||||
<td className="p-4 text-white/80 font-medium">
|
||||
{lang === 'de' ? row.featureDE : row.featureEN}
|
||||
</td>
|
||||
<td className="p-4 text-center bg-indigo-500/5 border-x border-indigo-500/10">
|
||||
<div className="flex justify-center">
|
||||
<StatusIcon status={row.breakpilot} />
|
||||
</div>
|
||||
</td>
|
||||
<td className="p-4 text-center">
|
||||
<div className="flex justify-center">
|
||||
<StatusIcon status={row.proliance} />
|
||||
</div>
|
||||
</td>
|
||||
<td className="p-4 text-center">
|
||||
<div className="flex justify-center">
|
||||
<StatusIcon status={row.dataguard} />
|
||||
</div>
|
||||
</td>
|
||||
<td className="p-4 text-center">
|
||||
<div className="flex justify-center">
|
||||
<StatusIcon status={row.heydata} />
|
||||
</div>
|
||||
</td>
|
||||
</motion.tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.6, duration: 0.5 }}
|
||||
className="mt-8 text-center"
|
||||
>
|
||||
<p className="text-sm text-white/50">
|
||||
{lang === 'de'
|
||||
? 'Stand: Februar 2026. Preise und Features der Wettbewerber koennen variieren.'
|
||||
: 'As of: February 2026. Competitor prices and features may vary.'}
|
||||
</p>
|
||||
</motion.div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
127
pitch-deck/components/slides/AnnexUSPMoatSlide.tsx
Normal file
127
pitch-deck/components/slides/AnnexUSPMoatSlide.tsx
Normal file
@@ -0,0 +1,127 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Lock, RefreshCw, Network, RotateCw, Clock } from 'lucide-react'
|
||||
import { Language } from '@/lib/types'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
|
||||
interface AnnexUSPMoatSlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
const moats = [
|
||||
{
|
||||
icon: Lock,
|
||||
gradient: 'from-blue-500 to-cyan-500',
|
||||
titleDE: 'Hardware Lock-In',
|
||||
titleEN: 'Hardware Lock-In',
|
||||
descDE: 'Physische Hardware beim Kunden. Wechsel bedeutet Hardware-Austausch und Datenmigration.',
|
||||
descEN: 'Physical hardware at customer site. Switching means hardware replacement and data migration.'
|
||||
},
|
||||
{
|
||||
icon: RefreshCw,
|
||||
gradient: 'from-purple-500 to-pink-500',
|
||||
titleDE: 'Switching Costs',
|
||||
titleEN: 'Switching Costs',
|
||||
descDE: 'Compliance-Dokumentation, trainierte KI-Modelle und Audit-Historie sind nicht portabel.',
|
||||
descEN: 'Compliance documentation, trained AI models and audit history are not portable.'
|
||||
},
|
||||
{
|
||||
icon: Network,
|
||||
gradient: 'from-green-500 to-emerald-500',
|
||||
titleDE: 'Network Effects',
|
||||
titleEN: 'Network Effects',
|
||||
descDE: 'Jeder Kunde verbessert die KI. Shared learnings ueber anonymisierte Compliance-Patterns.',
|
||||
descEN: 'Every customer improves the AI. Shared learnings via anonymized compliance patterns.'
|
||||
},
|
||||
{
|
||||
icon: RotateCw,
|
||||
gradient: 'from-amber-500 to-orange-500',
|
||||
titleDE: 'Data Flywheel',
|
||||
titleEN: 'Data Flywheel',
|
||||
descDE: 'Mehr Daten → bessere KI → bessere Compliance → mehr Kunden → mehr Daten.',
|
||||
descEN: 'More data → better AI → better compliance → more customers → more data.'
|
||||
},
|
||||
{
|
||||
icon: Clock,
|
||||
gradient: 'from-pink-500 to-rose-500',
|
||||
titleDE: 'Time Advantage',
|
||||
titleEN: 'Time Advantage',
|
||||
descDE: '18 Monate Vorsprung. Erster Self-Hosted Compliance-AI Anbieter im DACH-Raum.',
|
||||
descEN: '18 months head start. First self-hosted compliance AI provider in DACH region.'
|
||||
}
|
||||
]
|
||||
|
||||
export default function AnnexUSPMoatSlide({ lang }: AnnexUSPMoatSlideProps) {
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<FadeInView>
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-4">
|
||||
<GradientText>
|
||||
{lang === 'de' ? 'Verteidigbare Marktposition' : 'Defensible Market Position'}
|
||||
</GradientText>
|
||||
</h2>
|
||||
<p className="text-xl text-white/60">
|
||||
{lang === 'de'
|
||||
? 'Fuenf Verteidigungslinien gegen Wettbewerber'
|
||||
: 'Five lines of defense against competitors'}
|
||||
</p>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
<div className="space-y-6">
|
||||
{moats.map((moat, index) => {
|
||||
const Icon = moat.icon
|
||||
return (
|
||||
<motion.div
|
||||
key={index}
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: index * 0.1, duration: 0.5 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-6 flex items-center gap-6 hover:bg-white/[0.06] transition-colors"
|
||||
>
|
||||
<div className="flex-shrink-0">
|
||||
<div className={`w-16 h-16 rounded-full bg-gradient-to-r ${moat.gradient} flex items-center justify-center relative`}>
|
||||
<div className="absolute -top-2 -left-2 w-8 h-8 rounded-full bg-white/10 backdrop-blur-sm flex items-center justify-center border border-white/20">
|
||||
<span className="text-xs font-bold text-white">
|
||||
{String(index + 1).padStart(2, '0')}
|
||||
</span>
|
||||
</div>
|
||||
<Icon className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex-1">
|
||||
<h3 className="text-xl font-bold text-white mb-2">
|
||||
{lang === 'de' ? moat.titleDE : moat.titleEN}
|
||||
</h3>
|
||||
<p className="text-white/70 leading-relaxed">
|
||||
{lang === 'de' ? moat.descDE : moat.descEN}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={`w-1 h-16 rounded-full bg-gradient-to-b ${moat.gradient} flex-shrink-0`} />
|
||||
</motion.div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.8, duration: 0.5 }}
|
||||
className="mt-12 text-center"
|
||||
>
|
||||
<div className="bg-gradient-to-r from-indigo-500/10 to-purple-500/10 border border-indigo-500/20 rounded-xl p-6">
|
||||
<p className="text-white/80 text-lg font-medium">
|
||||
{lang === 'de'
|
||||
? 'Kombination aus physischen und digitalen Barriers macht Marktposition langfristig verteidigbar'
|
||||
: 'Combination of physical and digital barriers makes market position defensible long-term'}
|
||||
</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
129
pitch-deck/components/slides/AnnexUSPOverviewSlide.tsx
Normal file
129
pitch-deck/components/slides/AnnexUSPOverviewSlide.tsx
Normal file
@@ -0,0 +1,129 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Server, Brain, Shield, Layers, Bot } from 'lucide-react'
|
||||
import { Language } from '@/lib/types'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
|
||||
interface AnnexUSPOverviewSlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
const usps = [
|
||||
{
|
||||
icon: Server,
|
||||
gradient: 'from-blue-500 to-cyan-500',
|
||||
titleDE: 'Self-Hosted',
|
||||
titleEN: 'Self-Hosted',
|
||||
descDE: 'Volle Datensouveraenitaet. Kein Byte verlaesst das Unternehmen. Hardware steht im eigenen Serverraum.',
|
||||
descEN: 'Full data sovereignty. No byte leaves the company. Hardware sits in your own server room.'
|
||||
},
|
||||
{
|
||||
icon: Brain,
|
||||
gradient: 'from-purple-500 to-pink-500',
|
||||
titleDE: 'AI-First',
|
||||
titleEN: 'AI-First',
|
||||
descDE: 'Alles was durch KI loesbar ist, wird durch KI geloest. Kein klassischer Support, minimales Personal.',
|
||||
descEN: 'Everything solvable by AI is solved by AI. No traditional support, minimal personnel.'
|
||||
},
|
||||
{
|
||||
icon: Shield,
|
||||
gradient: 'from-green-500 to-emerald-500',
|
||||
titleDE: 'Hardware-Moat',
|
||||
titleEN: 'Hardware-Moat',
|
||||
descDE: 'Apple Hardware als physische Markteintrittsbarriere. Wechselkosten machen Lock-in positiv.',
|
||||
descEN: 'Apple hardware as physical market entry barrier. Switching costs create positive lock-in.'
|
||||
},
|
||||
{
|
||||
icon: Layers,
|
||||
gradient: 'from-amber-500 to-orange-500',
|
||||
titleDE: 'All-in-One',
|
||||
titleEN: 'All-in-One',
|
||||
descDE: 'DSGVO + AI Act + NIS2 in einer Loesung. Kein Tool-Dschungel, eine Plattform fuer alles.',
|
||||
descEN: 'GDPR + AI Act + NIS2 in one solution. No tool jungle, one platform for everything.'
|
||||
},
|
||||
{
|
||||
icon: Bot,
|
||||
gradient: 'from-pink-500 to-rose-500',
|
||||
titleDE: 'Autonomous Support',
|
||||
titleEN: 'Autonomous Support',
|
||||
descDE: '24/7 KI-Support beantwortet Fragen, aendert Dokumente, bereitet Audits vor. Ohne menschliches Eingreifen.',
|
||||
descEN: '24/7 AI support answers questions, modifies documents, prepares audits. Without human intervention.'
|
||||
}
|
||||
]
|
||||
|
||||
export default function AnnexUSPOverviewSlide({ lang }: AnnexUSPOverviewSlideProps) {
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<FadeInView>
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-4">
|
||||
<GradientText>
|
||||
{lang === 'de' ? 'Unsere 5 USPs' : 'Our 5 USPs'}
|
||||
</GradientText>
|
||||
</h2>
|
||||
<p className="text-xl text-white/60">
|
||||
{lang === 'de' ? 'Was uns einzigartig macht' : 'What makes us unique'}
|
||||
</p>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
|
||||
{usps.slice(0, 3).map((usp, index) => {
|
||||
const Icon = usp.icon
|
||||
return (
|
||||
<motion.div
|
||||
key={index}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: index * 0.1, duration: 0.5 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-4 relative overflow-hidden"
|
||||
>
|
||||
<div className={`absolute top-0 left-0 right-0 h-1 bg-gradient-to-r ${usp.gradient}`} />
|
||||
<div className="flex flex-col items-center text-center pt-2">
|
||||
<div className={`w-16 h-16 rounded-full bg-gradient-to-r ${usp.gradient} flex items-center justify-center mb-4`}>
|
||||
<Icon className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-white mb-3">
|
||||
{lang === 'de' ? usp.titleDE : usp.titleEN}
|
||||
</h3>
|
||||
<p className="text-sm text-white/70 leading-relaxed">
|
||||
{lang === 'de' ? usp.descDE : usp.descEN}
|
||||
</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 max-w-4xl mx-auto">
|
||||
{usps.slice(3, 5).map((usp, index) => {
|
||||
const Icon = usp.icon
|
||||
return (
|
||||
<motion.div
|
||||
key={index + 3}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: (index + 3) * 0.1, duration: 0.5 }}
|
||||
className="bg-white/[0.04] border border-white/[0.06] rounded-xl p-4 relative overflow-hidden"
|
||||
>
|
||||
<div className={`absolute top-0 left-0 right-0 h-1 bg-gradient-to-r ${usp.gradient}`} />
|
||||
<div className="flex flex-col items-center text-center pt-2">
|
||||
<div className={`w-16 h-16 rounded-full bg-gradient-to-r ${usp.gradient} flex items-center justify-center mb-4`}>
|
||||
<Icon className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-white mb-3">
|
||||
{lang === 'de' ? usp.titleDE : usp.titleEN}
|
||||
</h3>
|
||||
<p className="text-sm text-white/70 leading-relaxed">
|
||||
{lang === 'de' ? usp.descDE : usp.descEN}
|
||||
</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
68
pitch-deck/components/slides/AppendixSlide.tsx
Normal file
68
pitch-deck/components/slides/AppendixSlide.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
'use client';
|
||||
|
||||
import { motion } from 'framer-motion';
|
||||
import { Language } from '@/lib/types';
|
||||
import GradientText from '../ui/GradientText';
|
||||
import FadeInView from '../ui/FadeInView';
|
||||
|
||||
interface AppendixSlideProps {
|
||||
lang: Language;
|
||||
}
|
||||
|
||||
export default function AppendixSlide({ lang }: AppendixSlideProps) {
|
||||
const content = {
|
||||
de: {
|
||||
title: 'Appendix',
|
||||
subtitle: 'Deep Dive — Technologie, Compliance & Strategie',
|
||||
detailInfo: '14 Detailfolien für Investoren',
|
||||
},
|
||||
en: {
|
||||
title: 'Appendix',
|
||||
subtitle: 'Deep Dive — Technology, Compliance & Strategy',
|
||||
detailInfo: '14 detail slides for investors',
|
||||
},
|
||||
};
|
||||
|
||||
const t = content[lang];
|
||||
|
||||
return (
|
||||
<div className="h-full flex items-center justify-center px-16">
|
||||
<FadeInView className="text-center max-w-4xl">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.2 }}
|
||||
>
|
||||
<h1 className="text-7xl font-bold mb-8">
|
||||
<GradientText>{t.title}</GradientText>
|
||||
</h1>
|
||||
</motion.div>
|
||||
|
||||
<motion.p
|
||||
className="text-2xl text-white/80 mb-12"
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.4 }}
|
||||
>
|
||||
{t.subtitle}
|
||||
</motion.p>
|
||||
|
||||
<motion.div
|
||||
className="w-full h-px bg-gradient-to-r from-transparent via-white/20 to-transparent mb-8"
|
||||
initial={{ scaleX: 0, opacity: 0 }}
|
||||
animate={{ scaleX: 1, opacity: 1 }}
|
||||
transition={{ duration: 0.8, delay: 0.6 }}
|
||||
/>
|
||||
|
||||
<motion.p
|
||||
className="text-sm text-white/50"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.6, delay: 0.8 }}
|
||||
>
|
||||
{t.detailInfo}
|
||||
</motion.p>
|
||||
</FadeInView>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
99
pitch-deck/components/slides/BusinessModelSlide.tsx
Normal file
99
pitch-deck/components/slides/BusinessModelSlide.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language, PitchProduct } from '@/lib/types'
|
||||
import { t } from '@/lib/i18n'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import GlassCard from '../ui/GlassCard'
|
||||
import { DollarSign, Repeat, TrendingUp } from 'lucide-react'
|
||||
|
||||
interface BusinessModelSlideProps {
|
||||
lang: Language
|
||||
products: PitchProduct[]
|
||||
}
|
||||
|
||||
export default function BusinessModelSlide({ lang, products }: BusinessModelSlideProps) {
|
||||
const i = t(lang)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FadeInView className="text-center mb-12">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-3">
|
||||
<GradientText>{i.businessModel.title}</GradientText>
|
||||
</h2>
|
||||
<p className="text-lg text-white/50 max-w-2xl mx-auto">{i.businessModel.subtitle}</p>
|
||||
</FadeInView>
|
||||
|
||||
{/* Key Metrics */}
|
||||
<div className="grid md:grid-cols-3 gap-4 mb-8">
|
||||
<GlassCard delay={0.2} className="text-center">
|
||||
<Repeat className="w-6 h-6 text-indigo-400 mx-auto mb-2" />
|
||||
<p className="text-sm text-white/50 mb-1">{i.businessModel.recurringRevenue}</p>
|
||||
<p className="text-2xl font-bold text-white">100%</p>
|
||||
<p className="text-xs text-white/30">SaaS / Subscription</p>
|
||||
</GlassCard>
|
||||
<GlassCard delay={0.3} className="text-center">
|
||||
<DollarSign className="w-6 h-6 text-green-400 mx-auto mb-2" />
|
||||
<p className="text-sm text-white/50 mb-1">{i.businessModel.margin}</p>
|
||||
<p className="text-2xl font-bold text-white">>70%</p>
|
||||
<p className="text-xs text-white/30">{lang === 'de' ? 'nach Amortisation' : 'post amortization'}</p>
|
||||
</GlassCard>
|
||||
<GlassCard delay={0.4} className="text-center">
|
||||
<TrendingUp className="w-6 h-6 text-purple-400 mx-auto mb-2" />
|
||||
<p className="text-sm text-white/50 mb-1">{i.businessModel.amortization}</p>
|
||||
<p className="text-2xl font-bold text-white">24 {i.businessModel.months}</p>
|
||||
<p className="text-xs text-white/30">{lang === 'de' ? 'Hardware-Amortisation' : 'Hardware Amortization'}</p>
|
||||
</GlassCard>
|
||||
</div>
|
||||
|
||||
{/* Unit Economics per Product */}
|
||||
<FadeInView delay={0.5}>
|
||||
<h3 className="text-lg font-semibold mb-4 text-white/70">{i.businessModel.unitEconomics}</h3>
|
||||
<div className="grid md:grid-cols-3 gap-4">
|
||||
{products.map((p, idx) => {
|
||||
const amort = p.hardware_cost_eur > 0 ? Math.round(p.hardware_cost_eur / 24) : 0
|
||||
const monthlyMargin = p.monthly_price_eur - amort - (p.operating_cost_eur > 0 ? p.operating_cost_eur : 0)
|
||||
const marginPct = Math.round((monthlyMargin / p.monthly_price_eur) * 100)
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
key={p.id}
|
||||
initial={{ opacity: 0, rotateY: -15 }}
|
||||
animate={{ opacity: 1, rotateY: 0 }}
|
||||
transition={{ delay: 0.6 + idx * 0.15 }}
|
||||
className="bg-white/[0.05] border border-white/10 rounded-2xl p-5"
|
||||
>
|
||||
<h4 className="font-bold text-white mb-3">{p.name}</h4>
|
||||
<div className="space-y-2 text-sm">
|
||||
<div className="flex justify-between">
|
||||
<span className="text-white/50">{lang === 'de' ? 'Monatspreis' : 'Monthly Price'}</span>
|
||||
<span className="text-white font-medium">{p.monthly_price_eur} EUR</span>
|
||||
</div>
|
||||
{p.hardware_cost_eur > 0 && (
|
||||
<div className="flex justify-between">
|
||||
<span className="text-white/50">{i.businessModel.hardwareCost}</span>
|
||||
<span className="text-white/70">-{amort} EUR/Mo</span>
|
||||
</div>
|
||||
)}
|
||||
{p.operating_cost_eur > 0 && (
|
||||
<div className="flex justify-between">
|
||||
<span className="text-white/50">{i.businessModel.operatingCost}</span>
|
||||
<span className="text-white/70">-{p.operating_cost_eur.toLocaleString('de-DE')} EUR/Mo</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="border-t border-white/10 pt-2 flex justify-between">
|
||||
<span className="text-white/50">{i.businessModel.margin}</span>
|
||||
<span className={`font-bold ${marginPct > 0 ? 'text-green-400' : 'text-red-400'}`}>
|
||||
{marginPct > 0 ? '+' : ''}{monthlyMargin} EUR ({marginPct}%)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</FadeInView>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
107
pitch-deck/components/slides/CompetitionSlide.tsx
Normal file
107
pitch-deck/components/slides/CompetitionSlide.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
'use client'
|
||||
|
||||
import { Language, PitchFeature, PitchCompetitor } from '@/lib/types'
|
||||
import { t } from '@/lib/i18n'
|
||||
import { ShieldCheck, Code2, ScanLine, FileSearch, Package, Bug } from 'lucide-react'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import FeatureMatrix from '../ui/FeatureMatrix'
|
||||
import GlassCard from '../ui/GlassCard'
|
||||
import BrandName from '../ui/BrandName'
|
||||
|
||||
interface CompetitionSlideProps {
|
||||
lang: Language
|
||||
features: PitchFeature[]
|
||||
competitors: PitchCompetitor[]
|
||||
}
|
||||
|
||||
const securityFeatures = {
|
||||
de: [
|
||||
{ icon: ShieldCheck, title: 'DevSecOps Security Suite', desc: '6 integrierte Security-Tools fuer kontinuierliche Sicherheitsueberwachung' },
|
||||
{ icon: ScanLine, title: 'SAST & Secrets Detection', desc: 'Automatische Code-Analyse (Semgrep) + Secrets-Scanning (Gitleaks) in der CI/CD Pipeline' },
|
||||
{ icon: Bug, title: 'Container & Dependency Scanning', desc: 'Trivy + Grype scannen Container-Images und Abhaengigkeiten auf CVEs' },
|
||||
{ icon: Package, title: 'SBOM-Generator (NIS2-konform)', desc: 'CycloneDX/SPDX Software Bill of Materials fuer NIS2 und ISO 27001 Compliance' },
|
||||
{ icon: FileSearch, title: 'Software-Risikoanalyse', desc: 'Automatisierte Risikoklassifizierung fuer Embedded-Entwicklung und AI-Act-konforme Systeme' },
|
||||
{ icon: Code2, title: 'KI-Code-Assistent (1000b)', desc: 'Das Cloud-LLM unterstuetzt Entwickler bei Code-Reviews, Security-Fixes und Compliance-Dokumentation' },
|
||||
],
|
||||
en: [
|
||||
{ icon: ShieldCheck, title: 'DevSecOps Security Suite', desc: '6 integrated security tools for continuous security monitoring' },
|
||||
{ icon: ScanLine, title: 'SAST & Secrets Detection', desc: 'Automatic code analysis (Semgrep) + secrets scanning (Gitleaks) in CI/CD pipeline' },
|
||||
{ icon: Bug, title: 'Container & Dependency Scanning', desc: 'Trivy + Grype scan container images and dependencies for CVEs' },
|
||||
{ icon: Package, title: 'SBOM Generator (NIS2 compliant)', desc: 'CycloneDX/SPDX Software Bill of Materials for NIS2 and ISO 27001 compliance' },
|
||||
{ icon: FileSearch, title: 'Software Risk Analysis', desc: 'Automated risk classification for embedded development and AI Act compliant systems' },
|
||||
{ icon: Code2, title: 'AI Code Assistant (1000b)', desc: 'Cloud LLM assists developers with code reviews, security fixes and compliance documentation' },
|
||||
],
|
||||
}
|
||||
|
||||
export default function CompetitionSlide({ lang, features, competitors }: CompetitionSlideProps) {
|
||||
const i = t(lang)
|
||||
const coreFeatures = features.filter(f => f.category !== 'security')
|
||||
const secFeats = securityFeatures[lang]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FadeInView className="text-center mb-8">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-3">
|
||||
<GradientText>{i.competition.title}</GradientText>
|
||||
</h2>
|
||||
<p className="text-lg text-white/50 max-w-2xl mx-auto">{i.competition.subtitle}</p>
|
||||
</FadeInView>
|
||||
|
||||
{/* Feature Matrix (Core Compliance) */}
|
||||
<FadeInView delay={0.3}>
|
||||
<GlassCard className="mb-6 p-4 overflow-x-auto" hover={false}>
|
||||
<FeatureMatrix features={coreFeatures} lang={lang} />
|
||||
</GlassCard>
|
||||
</FadeInView>
|
||||
|
||||
{/* Security & Developer Features — nur bei ComplAI */}
|
||||
<FadeInView delay={0.5}>
|
||||
<div className="mb-6">
|
||||
<h3 className="text-sm font-semibold text-indigo-400 mb-3 flex items-center gap-2">
|
||||
<ShieldCheck className="w-4 h-4" />
|
||||
{lang === 'de' ? <>Integrierte Security & Developer Tools — nur bei <BrandName /></> : <>Integrated Security & Developer Tools — <BrandName /> only</>}
|
||||
</h3>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
|
||||
{secFeats.map((feat, idx) => {
|
||||
const Icon = feat.icon
|
||||
return (
|
||||
<FadeInView key={idx} delay={0.6 + idx * 0.08}>
|
||||
<div className="bg-indigo-500/5 border border-indigo-500/10 rounded-xl p-3">
|
||||
<div className="flex items-center gap-2 mb-1.5">
|
||||
<Icon className="w-4 h-4 text-indigo-400 shrink-0" />
|
||||
<span className="text-xs font-semibold text-white">{feat.title}</span>
|
||||
</div>
|
||||
<p className="text-[11px] text-white/40 leading-relaxed">{feat.desc}</p>
|
||||
</div>
|
||||
</FadeInView>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
{/* Competitor Summary */}
|
||||
<div className="grid md:grid-cols-3 gap-4">
|
||||
{competitors.map((c, idx) => (
|
||||
<FadeInView key={c.id} delay={0.9 + idx * 0.1}>
|
||||
<div className="bg-white/[0.04] border border-white/5 rounded-xl p-4">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<h4 className="font-medium text-white/70">{c.name}</h4>
|
||||
<span className="text-xs text-white/30">{c.customers_count.toLocaleString()} {lang === 'de' ? 'Kunden' : 'customers'}</span>
|
||||
</div>
|
||||
<p className="text-xs text-white/40 mb-2">{c.pricing_range}</p>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{(c.weaknesses || []).slice(0, 2).map((w, widx) => (
|
||||
<span key={widx} className="text-xs px-2 py-0.5 rounded-full bg-red-500/10 text-red-400">
|
||||
{w}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</FadeInView>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
93
pitch-deck/components/slides/CoverSlide.tsx
Normal file
93
pitch-deck/components/slides/CoverSlide.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language } from '@/lib/types'
|
||||
import { t } from '@/lib/i18n'
|
||||
import { ArrowRight } from 'lucide-react'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import BrandName from '../ui/BrandName'
|
||||
|
||||
interface CoverSlideProps {
|
||||
lang: Language
|
||||
onNext: () => void
|
||||
}
|
||||
|
||||
export default function CoverSlide({ lang, onNext }: CoverSlideProps) {
|
||||
const i = t(lang)
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center text-center min-h-[70vh]">
|
||||
{/* Logo / Brand */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.5 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.8, ease: [0.22, 1, 0.36, 1] }}
|
||||
className="mb-8"
|
||||
>
|
||||
<div className="w-20 h-20 mx-auto mb-6 rounded-2xl bg-gradient-to-br from-indigo-500 to-purple-600
|
||||
flex items-center justify-center shadow-lg shadow-indigo-500/30">
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none">
|
||||
<path d="M8 12L20 6L32 12V28L20 34L8 28V12Z" stroke="white" strokeWidth="2" fill="none" />
|
||||
<path d="M20 6V34" stroke="white" strokeWidth="1.5" opacity="0.5" />
|
||||
<path d="M8 12L32 28" stroke="white" strokeWidth="1.5" opacity="0.3" />
|
||||
<path d="M32 12L8 28" stroke="white" strokeWidth="1.5" opacity="0.3" />
|
||||
<circle cx="20" cy="20" r="4" fill="white" opacity="0.8" />
|
||||
</svg>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* Company Name */}
|
||||
<motion.h1
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.3 }}
|
||||
className="text-5xl md:text-7xl font-bold mb-4 tracking-tight"
|
||||
>
|
||||
BreakPilot{' '}
|
||||
<motion.span
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.5 }}
|
||||
>
|
||||
<BrandName className="text-5xl md:text-7xl font-bold" />
|
||||
</motion.span>
|
||||
</motion.h1>
|
||||
|
||||
{/* Tagline */}
|
||||
<motion.p
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.8, delay: 0.6 }}
|
||||
className="text-xl md:text-2xl text-white/60 mb-2 max-w-2xl"
|
||||
>
|
||||
{i.cover.tagline}
|
||||
</motion.p>
|
||||
|
||||
{/* Subtitle */}
|
||||
<motion.p
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.5, delay: 0.8 }}
|
||||
className="text-sm text-white/30 font-mono tracking-wider mb-12"
|
||||
>
|
||||
{i.cover.subtitle}
|
||||
</motion.p>
|
||||
|
||||
{/* CTA */}
|
||||
<motion.button
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 1.2 }}
|
||||
whileHover={{ scale: 1.05 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
onClick={onNext}
|
||||
className="group flex items-center gap-2 px-8 py-3 rounded-full
|
||||
bg-indigo-500 hover:bg-indigo-600 transition-colors text-white font-medium
|
||||
shadow-lg shadow-indigo-500/30"
|
||||
>
|
||||
{i.cover.cta}
|
||||
<ArrowRight className="w-4 h-4 group-hover:translate-x-1 transition-transform" />
|
||||
</motion.button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
313
pitch-deck/components/slides/FinancialsSlide.tsx
Normal file
313
pitch-deck/components/slides/FinancialsSlide.tsx
Normal file
@@ -0,0 +1,313 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { Language } from '@/lib/types'
|
||||
import { t } from '@/lib/i18n'
|
||||
import { useFinancialModel } from '@/lib/hooks/useFinancialModel'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import FinancialChart from '../ui/FinancialChart'
|
||||
import FinancialSliders from '../ui/FinancialSliders'
|
||||
import KPICard from '../ui/KPICard'
|
||||
import RunwayGauge from '../ui/RunwayGauge'
|
||||
import WaterfallChart from '../ui/WaterfallChart'
|
||||
import UnitEconomicsCards from '../ui/UnitEconomicsCards'
|
||||
import ScenarioSwitcher from '../ui/ScenarioSwitcher'
|
||||
import AnnualPLTable, { AccountingStandard } from '../ui/AnnualPLTable'
|
||||
import AnnualCashflowChart from '../ui/AnnualCashflowChart'
|
||||
|
||||
type FinTab = 'overview' | 'guv' | 'cashflow'
|
||||
|
||||
interface FinancialsSlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
export default function FinancialsSlide({ lang }: FinancialsSlideProps) {
|
||||
const i = t(lang)
|
||||
const fm = useFinancialModel()
|
||||
const [activeTab, setActiveTab] = useState<FinTab>('overview')
|
||||
const [accountingStandard, setAccountingStandard] = useState<AccountingStandard>('hgb')
|
||||
const de = lang === 'de'
|
||||
|
||||
const activeResults = fm.activeResults
|
||||
const summary = activeResults?.summary
|
||||
const lastResult = activeResults?.results[activeResults.results.length - 1]
|
||||
|
||||
// Build scenario color map
|
||||
const scenarioColors: Record<string, string> = {}
|
||||
fm.scenarios.forEach(s => { scenarioColors[s.id] = s.color })
|
||||
|
||||
// Build compare results (exclude active scenario)
|
||||
const compareResults = new Map(
|
||||
Array.from(fm.results.entries()).filter(([id]) => id !== fm.activeScenarioId)
|
||||
)
|
||||
|
||||
// Initial funding from assumptions
|
||||
const initialFunding = (fm.activeScenario?.assumptions.find(a => a.key === 'initial_funding')?.value as number) || 200000
|
||||
|
||||
const tabs: { id: FinTab; label: string }[] = [
|
||||
{ id: 'overview', label: de ? 'Uebersicht' : 'Overview' },
|
||||
{ id: 'guv', label: de ? 'GuV (Jahres)' : 'P&L (Annual)' },
|
||||
{ id: 'cashflow', label: de ? 'Cashflow & Finanzbedarf' : 'Cashflow & Funding' },
|
||||
]
|
||||
|
||||
if (fm.loading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center h-full">
|
||||
<div className="w-8 h-8 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<FadeInView className="text-center mb-3">
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-1">
|
||||
<GradientText>{i.financials.title}</GradientText>
|
||||
</h2>
|
||||
<p className="text-sm text-white/50 max-w-2xl mx-auto">{i.financials.subtitle}</p>
|
||||
</FadeInView>
|
||||
|
||||
{/* Hero KPI Cards */}
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-2 mb-3">
|
||||
<KPICard
|
||||
label={`ARR 2030`}
|
||||
value={summary ? Math.round(summary.final_arr / 1_000_000 * 10) / 10 : 0}
|
||||
suffix=" Mio."
|
||||
decimals={1}
|
||||
trend="up"
|
||||
color="#6366f1"
|
||||
delay={0.1}
|
||||
subLabel="EUR"
|
||||
/>
|
||||
<KPICard
|
||||
label={de ? 'Kunden 2030' : 'Customers 2030'}
|
||||
value={summary?.final_customers || 0}
|
||||
trend="up"
|
||||
color="#22c55e"
|
||||
delay={0.15}
|
||||
/>
|
||||
<KPICard
|
||||
label="Break-Even"
|
||||
value={summary?.break_even_month || 0}
|
||||
suffix={de ? ' Mo.' : ' mo.'}
|
||||
trend={summary?.break_even_month && summary.break_even_month <= 24 ? 'up' : 'down'}
|
||||
color="#eab308"
|
||||
delay={0.2}
|
||||
subLabel={summary?.break_even_month ? `~${Math.ceil((summary.break_even_month) / 12) + 2025}` : ''}
|
||||
/>
|
||||
<KPICard
|
||||
label="LTV/CAC"
|
||||
value={summary?.final_ltv_cac || 0}
|
||||
suffix="x"
|
||||
decimals={1}
|
||||
trend={(summary?.final_ltv_cac || 0) >= 3 ? 'up' : 'down'}
|
||||
color="#a855f7"
|
||||
delay={0.25}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Tab Navigation + Accounting Standard Toggle */}
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<div className="flex items-center gap-1">
|
||||
{tabs.map((tab) => (
|
||||
<button
|
||||
key={tab.id}
|
||||
onClick={() => setActiveTab(tab.id)}
|
||||
className={`px-3 py-1.5 rounded-lg text-xs transition-all
|
||||
${activeTab === tab.id
|
||||
? 'bg-indigo-500/20 text-indigo-300 border border-indigo-500/30'
|
||||
: 'bg-white/[0.04] text-white/40 border border-transparent hover:text-white/60 hover:bg-white/[0.06]'
|
||||
}`}
|
||||
>
|
||||
{tab.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* HGB / US GAAP Toggle — only visible on GuV and Cashflow tabs */}
|
||||
{(activeTab === 'guv' || activeTab === 'cashflow') && (
|
||||
<div className="flex items-center gap-1 bg-white/[0.04] rounded-lg p-0.5 border border-white/[0.06]">
|
||||
<button
|
||||
onClick={() => setAccountingStandard('hgb')}
|
||||
className={`px-2.5 py-1 rounded-md text-[10px] font-medium transition-all
|
||||
${accountingStandard === 'hgb'
|
||||
? 'bg-indigo-500/25 text-indigo-300 shadow-sm'
|
||||
: 'text-white/40 hover:text-white/60'
|
||||
}`}
|
||||
>
|
||||
HGB
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setAccountingStandard('usgaap')}
|
||||
className={`px-2.5 py-1 rounded-md text-[10px] font-medium transition-all
|
||||
${accountingStandard === 'usgaap'
|
||||
? 'bg-indigo-500/25 text-indigo-300 shadow-sm'
|
||||
: 'text-white/40 hover:text-white/60'
|
||||
}`}
|
||||
>
|
||||
US GAAP
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Main content: 3-column layout */}
|
||||
<div className="grid md:grid-cols-12 gap-3">
|
||||
{/* Left: Charts (8 columns) */}
|
||||
<div className="md:col-span-8 space-y-3">
|
||||
|
||||
{/* TAB: Overview — monatlicher Chart + Waterfall + Unit Economics */}
|
||||
{activeTab === 'overview' && (
|
||||
<>
|
||||
<FadeInView delay={0.1}>
|
||||
<div className="bg-white/[0.05] backdrop-blur-xl border border-white/10 rounded-2xl p-3">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<p className="text-xs text-white/40">
|
||||
{de ? 'Umsatz vs. Kosten (60 Monate)' : 'Revenue vs. Costs (60 months)'}
|
||||
</p>
|
||||
<div className="flex items-center gap-3 text-[9px]">
|
||||
<span className="flex items-center gap-1"><span className="w-2 h-0.5 bg-indigo-500 inline-block" /> {de ? 'Umsatz' : 'Revenue'}</span>
|
||||
<span className="flex items-center gap-1"><span className="w-2 h-0.5 bg-red-400 inline-block" style={{ borderBottom: '1px dashed' }} /> {de ? 'Kosten' : 'Costs'}</span>
|
||||
<span className="flex items-center gap-1"><span className="w-2 h-0.5 bg-emerald-500 inline-block" /> {de ? 'Kunden' : 'Customers'}</span>
|
||||
</div>
|
||||
</div>
|
||||
<FinancialChart
|
||||
activeResults={activeResults}
|
||||
compareResults={compareResults}
|
||||
compareMode={fm.compareMode}
|
||||
scenarioColors={scenarioColors}
|
||||
lang={lang}
|
||||
/>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-3">
|
||||
<FadeInView delay={0.2}>
|
||||
<div className="bg-white/[0.05] backdrop-blur-xl border border-white/10 rounded-2xl p-3">
|
||||
<p className="text-xs text-white/40 mb-2">
|
||||
{de ? 'Cash-Flow (Quartal)' : 'Cash Flow (Quarterly)'}
|
||||
</p>
|
||||
{activeResults && <WaterfallChart results={activeResults.results} lang={lang} />}
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
<FadeInView delay={0.25}>
|
||||
<div className="space-y-3">
|
||||
<div className="bg-white/[0.05] backdrop-blur-xl border border-white/10 rounded-2xl p-3 flex justify-center">
|
||||
<RunwayGauge
|
||||
months={lastResult?.runway_months || 0}
|
||||
size={120}
|
||||
label={de ? 'Runway (Monate)' : 'Runway (months)'}
|
||||
/>
|
||||
</div>
|
||||
{lastResult && (
|
||||
<UnitEconomicsCards
|
||||
cac={lastResult.cac_eur}
|
||||
ltv={lastResult.ltv_eur}
|
||||
ltvCacRatio={lastResult.ltv_cac_ratio}
|
||||
grossMargin={lastResult.gross_margin_pct}
|
||||
churnRate={fm.activeScenario?.assumptions.find(a => a.key === 'churn_rate_monthly')?.value as number || 3}
|
||||
lang={lang}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</FadeInView>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* TAB: GuV — Annual P&L Table */}
|
||||
{activeTab === 'guv' && activeResults && (
|
||||
<FadeInView delay={0.1}>
|
||||
<div className="bg-white/[0.05] backdrop-blur-xl border border-white/10 rounded-2xl p-4">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<p className="text-xs text-white/40">
|
||||
{accountingStandard === 'hgb'
|
||||
? (de ? 'Gewinn- und Verlustrechnung (HGB, 5 Jahre)' : 'Profit & Loss Statement (HGB, 5 Years)')
|
||||
: (de ? 'Gewinn- und Verlustrechnung (US GAAP, 5 Jahre)' : 'Profit & Loss Statement (US GAAP, 5 Years)')
|
||||
}
|
||||
</p>
|
||||
<p className="text-[9px] text-white/20">
|
||||
{de ? 'Alle Werte in EUR' : 'All values in EUR'}
|
||||
</p>
|
||||
</div>
|
||||
<AnnualPLTable results={activeResults.results} lang={lang} standard={accountingStandard} />
|
||||
</div>
|
||||
</FadeInView>
|
||||
)}
|
||||
|
||||
{/* TAB: Cashflow & Finanzbedarf */}
|
||||
{activeTab === 'cashflow' && activeResults && (
|
||||
<FadeInView delay={0.1}>
|
||||
<div className="bg-white/[0.05] backdrop-blur-xl border border-white/10 rounded-2xl p-4">
|
||||
<p className="text-xs text-white/40 mb-3">
|
||||
{accountingStandard === 'hgb'
|
||||
? (de ? 'Kapitalflussrechnung (HGB)' : 'Cash Flow Statement (HGB)')
|
||||
: (de ? 'Cash Flow Statement (US GAAP)' : 'Cash Flow Statement (US GAAP)')
|
||||
}
|
||||
</p>
|
||||
<AnnualCashflowChart
|
||||
results={activeResults.results}
|
||||
initialFunding={initialFunding}
|
||||
lang={lang}
|
||||
standard={accountingStandard}
|
||||
/>
|
||||
</div>
|
||||
</FadeInView>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Right: Controls (4 columns) */}
|
||||
<div className="md:col-span-4 space-y-3">
|
||||
{/* Scenario Switcher */}
|
||||
<FadeInView delay={0.15}>
|
||||
<div className="bg-white/[0.05] backdrop-blur-xl border border-white/10 rounded-2xl p-3">
|
||||
<ScenarioSwitcher
|
||||
scenarios={fm.scenarios}
|
||||
activeId={fm.activeScenarioId}
|
||||
compareMode={fm.compareMode}
|
||||
onSelect={(id) => {
|
||||
fm.setActiveScenarioId(id)
|
||||
}}
|
||||
onToggleCompare={() => {
|
||||
if (!fm.compareMode) {
|
||||
fm.computeAll()
|
||||
}
|
||||
fm.setCompareMode(!fm.compareMode)
|
||||
}}
|
||||
lang={lang}
|
||||
/>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
{/* Assumption Sliders */}
|
||||
<FadeInView delay={0.2}>
|
||||
<div className="bg-white/[0.05] backdrop-blur-xl border border-white/10 rounded-2xl p-3">
|
||||
<p className="text-[10px] text-white/40 uppercase tracking-wider mb-2">
|
||||
{i.financials.adjustAssumptions}
|
||||
</p>
|
||||
{fm.activeScenario && (
|
||||
<FinancialSliders
|
||||
assumptions={fm.activeScenario.assumptions}
|
||||
onAssumptionChange={(key, value) => {
|
||||
if (fm.activeScenarioId) {
|
||||
fm.updateAssumption(fm.activeScenarioId, key, value)
|
||||
}
|
||||
}}
|
||||
lang={lang}
|
||||
/>
|
||||
)}
|
||||
{fm.computing && (
|
||||
<div className="flex items-center gap-2 mt-2 text-[10px] text-indigo-400">
|
||||
<div className="w-3 h-3 border border-indigo-400 border-t-transparent rounded-full animate-spin" />
|
||||
{de ? 'Berechne...' : 'Computing...'}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</FadeInView>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
65
pitch-deck/components/slides/HowItWorksSlide.tsx
Normal file
65
pitch-deck/components/slides/HowItWorksSlide.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language } from '@/lib/types'
|
||||
import { t } from '@/lib/i18n'
|
||||
import { Plug, Settings, RefreshCw, CheckCircle2 } from 'lucide-react'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
|
||||
interface HowItWorksSlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
const stepIcons = [Plug, Settings, RefreshCw, CheckCircle2]
|
||||
const stepColors = ['text-blue-400', 'text-indigo-400', 'text-purple-400', 'text-green-400']
|
||||
|
||||
export default function HowItWorksSlide({ lang }: HowItWorksSlideProps) {
|
||||
const i = t(lang)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FadeInView className="text-center mb-12">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-3">
|
||||
<GradientText>{i.howItWorks.title}</GradientText>
|
||||
</h2>
|
||||
<p className="text-lg text-white/50 max-w-2xl mx-auto">{i.howItWorks.subtitle}</p>
|
||||
</FadeInView>
|
||||
|
||||
<div className="relative max-w-4xl mx-auto">
|
||||
{/* Connection Line */}
|
||||
<div className="absolute left-8 top-12 bottom-12 w-px bg-gradient-to-b from-blue-500 via-purple-500 to-green-500 hidden md:block" />
|
||||
|
||||
<div className="space-y-8">
|
||||
{i.howItWorks.steps.map((step, idx) => {
|
||||
const Icon = stepIcons[idx]
|
||||
return (
|
||||
<motion.div
|
||||
key={idx}
|
||||
initial={{ opacity: 0, x: -30 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.3 + idx * 0.2, duration: 0.5 }}
|
||||
className="flex items-start gap-6 relative"
|
||||
>
|
||||
<div className={`
|
||||
w-16 h-16 rounded-2xl bg-white/[0.06] border border-white/10
|
||||
flex items-center justify-center shrink-0 relative z-10
|
||||
${stepColors[idx]}
|
||||
`}>
|
||||
<Icon className="w-7 h-7" />
|
||||
</div>
|
||||
<div className="pt-2">
|
||||
<div className="flex items-center gap-3 mb-1">
|
||||
<span className="text-xs font-mono text-white/30">0{idx + 1}</span>
|
||||
<h3 className="text-xl font-bold text-white">{step.title}</h3>
|
||||
</div>
|
||||
<p className="text-sm text-white/50 leading-relaxed max-w-lg">{step.desc}</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
91
pitch-deck/components/slides/MarketSlide.tsx
Normal file
91
pitch-deck/components/slides/MarketSlide.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language, PitchMarket } from '@/lib/types'
|
||||
import { t, formatEur } from '@/lib/i18n'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import AnimatedCounter from '../ui/AnimatedCounter'
|
||||
|
||||
interface MarketSlideProps {
|
||||
lang: Language
|
||||
market: PitchMarket[]
|
||||
}
|
||||
|
||||
const sizes = [280, 200, 130]
|
||||
const colors = ['border-indigo-500/30 bg-indigo-500/5', 'border-purple-500/30 bg-purple-500/5', 'border-blue-500/30 bg-blue-500/5']
|
||||
const textColors = ['text-indigo-400', 'text-purple-400', 'text-blue-400']
|
||||
|
||||
export default function MarketSlide({ lang, market }: MarketSlideProps) {
|
||||
const i = t(lang)
|
||||
const labels = [i.market.tamLabel, i.market.samLabel, i.market.somLabel]
|
||||
const segments = [i.market.tam, i.market.sam, i.market.som]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FadeInView className="text-center mb-12">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-3">
|
||||
<GradientText>{i.market.title}</GradientText>
|
||||
</h2>
|
||||
<p className="text-lg text-white/50 max-w-2xl mx-auto">{i.market.subtitle}</p>
|
||||
</FadeInView>
|
||||
|
||||
<div className="flex flex-col md:flex-row items-center justify-center gap-12">
|
||||
{/* Circles */}
|
||||
<div className="relative flex items-center justify-center" style={{ width: 300, height: 300 }}>
|
||||
{market.map((m, idx) => (
|
||||
<motion.div
|
||||
key={m.id}
|
||||
initial={{ scale: 0, opacity: 0 }}
|
||||
animate={{ scale: 1, opacity: 1 }}
|
||||
transition={{ delay: 0.3 + idx * 0.2, type: 'spring', stiffness: 200 }}
|
||||
className={`absolute rounded-full border-2 ${colors[idx]} flex items-center justify-center`}
|
||||
style={{
|
||||
width: sizes[idx],
|
||||
height: sizes[idx],
|
||||
}}
|
||||
>
|
||||
{idx === market.length - 1 && (
|
||||
<div className="text-center">
|
||||
<span className={`text-xs font-mono ${textColors[idx]}`}>{segments[idx]}</span>
|
||||
</div>
|
||||
)}
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Labels */}
|
||||
<div className="space-y-6">
|
||||
{market.map((m, idx) => (
|
||||
<motion.div
|
||||
key={m.id}
|
||||
initial={{ opacity: 0, x: 20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.5 + idx * 0.15 }}
|
||||
className="flex items-center gap-4"
|
||||
>
|
||||
<div className={`w-3 h-3 rounded-full ${textColors[idx]} bg-current`} />
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className={`text-sm font-bold ${textColors[idx]}`}>{segments[idx]}</span>
|
||||
<span className="text-xs text-white/30">{labels[idx]}</span>
|
||||
</div>
|
||||
<div className="text-2xl font-bold text-white">
|
||||
<AnimatedCounter
|
||||
target={m.value_eur / 1_000_000_000}
|
||||
suffix={lang === 'de' ? ' Mrd. EUR' : 'B EUR'}
|
||||
decimals={1}
|
||||
duration={1500}
|
||||
/>
|
||||
</div>
|
||||
<div className="text-xs text-white/40">
|
||||
{i.market.growth}: {m.growth_rate_pct}% · {i.market.source}: {m.source}
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
54
pitch-deck/components/slides/ProblemSlide.tsx
Normal file
54
pitch-deck/components/slides/ProblemSlide.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language } from '@/lib/types'
|
||||
import { t } from '@/lib/i18n'
|
||||
import { AlertTriangle, Scale, Shield } from 'lucide-react'
|
||||
import GlassCard from '../ui/GlassCard'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
|
||||
interface ProblemSlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
const icons = [AlertTriangle, Scale, Shield]
|
||||
|
||||
export default function ProblemSlide({ lang }: ProblemSlideProps) {
|
||||
const i = t(lang)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FadeInView className="text-center mb-12">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-3">
|
||||
<GradientText>{i.problem.title}</GradientText>
|
||||
</h2>
|
||||
<p className="text-lg text-white/50 max-w-2xl mx-auto">{i.problem.subtitle}</p>
|
||||
</FadeInView>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-6 mb-12">
|
||||
{i.problem.cards.map((card, idx) => {
|
||||
const Icon = icons[idx]
|
||||
return (
|
||||
<GlassCard key={idx} delay={0.2 + idx * 0.15} className="text-center">
|
||||
<div className="w-12 h-12 mx-auto mb-4 rounded-xl bg-red-500/10 flex items-center justify-center">
|
||||
<Icon className="w-6 h-6 text-red-400" />
|
||||
</div>
|
||||
<h3 className="text-lg font-bold mb-2 text-white">{card.title}</h3>
|
||||
<p className="text-3xl font-bold text-red-400 mb-3">{card.stat}</p>
|
||||
<p className="text-sm text-white/50 leading-relaxed">{card.desc}</p>
|
||||
</GlassCard>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
<FadeInView delay={0.8} className="max-w-3xl mx-auto">
|
||||
<blockquote className="text-center">
|
||||
<p className="text-lg md:text-xl text-white/70 italic leading-relaxed">
|
||||
“{i.problem.quote}”
|
||||
</p>
|
||||
</blockquote>
|
||||
</FadeInView>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
33
pitch-deck/components/slides/ProductSlide.tsx
Normal file
33
pitch-deck/components/slides/ProductSlide.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
'use client'
|
||||
|
||||
import { Language, PitchProduct } from '@/lib/types'
|
||||
import { t } from '@/lib/i18n'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import PricingCard from '../ui/PricingCard'
|
||||
|
||||
interface ProductSlideProps {
|
||||
lang: Language
|
||||
products: PitchProduct[]
|
||||
}
|
||||
|
||||
export default function ProductSlide({ lang, products }: ProductSlideProps) {
|
||||
const i = t(lang)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FadeInView className="text-center mb-12">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-3">
|
||||
<GradientText>{i.product.title}</GradientText>
|
||||
</h2>
|
||||
<p className="text-lg text-white/50 max-w-2xl mx-auto">{i.product.subtitle}</p>
|
||||
</FadeInView>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
{products.map((product, idx) => (
|
||||
<PricingCard key={product.id} product={product} lang={lang} delay={0.2 + idx * 0.15} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
57
pitch-deck/components/slides/SolutionSlide.tsx
Normal file
57
pitch-deck/components/slides/SolutionSlide.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language } from '@/lib/types'
|
||||
import { t } from '@/lib/i18n'
|
||||
import { Server, ShieldCheck, Bot } from 'lucide-react'
|
||||
import GlassCard from '../ui/GlassCard'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import BrandName from '../ui/BrandName'
|
||||
|
||||
interface SolutionSlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
const icons = [Server, ShieldCheck, Bot]
|
||||
const colors = ['from-blue-500 to-cyan-500', 'from-indigo-500 to-purple-500', 'from-purple-500 to-pink-500']
|
||||
|
||||
export default function SolutionSlide({ lang }: SolutionSlideProps) {
|
||||
const i = t(lang)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FadeInView className="text-center mb-12">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-3">
|
||||
<GradientText>{i.solution.title}</GradientText>
|
||||
</h2>
|
||||
<p className="text-lg text-white/50 max-w-2xl mx-auto">
|
||||
<BrandName /> — {lang === 'de' ? 'Compliance auf Autopilot' : 'Compliance on Autopilot'}
|
||||
</p>
|
||||
</FadeInView>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
{i.solution.pillars.map((pillar, idx) => {
|
||||
const Icon = icons[idx]
|
||||
return (
|
||||
<motion.div
|
||||
key={idx}
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ delay: 0.3 + idx * 0.2, duration: 0.5 }}
|
||||
>
|
||||
<GlassCard className="text-center h-full" delay={0}>
|
||||
<div className={`w-16 h-16 mx-auto mb-5 rounded-2xl bg-gradient-to-br ${colors[idx]}
|
||||
flex items-center justify-center shadow-lg`}>
|
||||
<Icon className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-3 text-white">{pillar.title}</h3>
|
||||
<p className="text-sm text-white/50 leading-relaxed">{pillar.desc}</p>
|
||||
</GlassCard>
|
||||
</motion.div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
76
pitch-deck/components/slides/TeamSlide.tsx
Normal file
76
pitch-deck/components/slides/TeamSlide.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language, PitchTeamMember } from '@/lib/types'
|
||||
import { t } from '@/lib/i18n'
|
||||
import { User } from 'lucide-react'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
|
||||
interface TeamSlideProps {
|
||||
lang: Language
|
||||
team: PitchTeamMember[]
|
||||
}
|
||||
|
||||
export default function TeamSlide({ lang, team }: TeamSlideProps) {
|
||||
const i = t(lang)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FadeInView className="text-center mb-12">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-3">
|
||||
<GradientText>{i.team.title}</GradientText>
|
||||
</h2>
|
||||
<p className="text-lg text-white/50 max-w-2xl mx-auto">{i.team.subtitle}</p>
|
||||
</FadeInView>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-8 max-w-4xl mx-auto">
|
||||
{team.map((member, idx) => (
|
||||
<motion.div
|
||||
key={member.id}
|
||||
initial={{ opacity: 0, x: idx === 0 ? -40 : 40 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.3 + idx * 0.2, duration: 0.6 }}
|
||||
className="bg-white/[0.08] backdrop-blur-xl border border-white/10 rounded-3xl p-8"
|
||||
>
|
||||
<div className="flex items-start gap-5">
|
||||
{/* Avatar */}
|
||||
<div className="w-20 h-20 rounded-2xl bg-gradient-to-br from-indigo-500 to-purple-600
|
||||
flex items-center justify-center shrink-0 shadow-lg">
|
||||
<User className="w-10 h-10 text-white" />
|
||||
</div>
|
||||
|
||||
<div className="flex-1">
|
||||
<h3 className="text-xl font-bold text-white mb-1">{member.name}</h3>
|
||||
<p className="text-indigo-400 text-sm font-medium mb-3">
|
||||
{lang === 'de' ? member.role_de : member.role_en}
|
||||
</p>
|
||||
<p className="text-sm text-white/50 leading-relaxed mb-4">
|
||||
{lang === 'de' ? member.bio_de : member.bio_en}
|
||||
</p>
|
||||
|
||||
{/* Equity */}
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<span className="text-xs text-white/40">{i.team.equity}:</span>
|
||||
<span className="text-sm font-bold text-white">{member.equity_pct}%</span>
|
||||
</div>
|
||||
|
||||
{/* Expertise Tags */}
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{(member.expertise || []).map((skill, sidx) => (
|
||||
<span
|
||||
key={sidx}
|
||||
className="text-xs px-2.5 py-1 rounded-full bg-indigo-500/10 text-indigo-300 border border-indigo-500/20"
|
||||
>
|
||||
{skill}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
125
pitch-deck/components/slides/TechnologySlide.tsx
Normal file
125
pitch-deck/components/slides/TechnologySlide.tsx
Normal file
@@ -0,0 +1,125 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language } from '@/lib/types'
|
||||
import { t } from '@/lib/i18n'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import { Cpu, Brain, Server, Shield, Database } from 'lucide-react'
|
||||
|
||||
interface TechnologySlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
const phaseColors = [
|
||||
'from-blue-500/20 to-blue-600/10 border-blue-500/30',
|
||||
'from-indigo-500/20 to-indigo-600/10 border-indigo-500/30',
|
||||
'from-purple-500/20 to-purple-600/10 border-purple-500/30',
|
||||
'from-violet-500/20 to-violet-600/10 border-violet-500/30',
|
||||
'from-fuchsia-500/20 to-fuchsia-600/10 border-fuchsia-500/30',
|
||||
]
|
||||
|
||||
const phaseAccents = [
|
||||
'text-blue-400',
|
||||
'text-indigo-400',
|
||||
'text-purple-400',
|
||||
'text-violet-400',
|
||||
'text-fuchsia-400',
|
||||
]
|
||||
|
||||
const layerIcons = [Cpu, Brain, Server, Shield, Database]
|
||||
const layerColors = [
|
||||
'text-blue-400 bg-blue-500/10 border-blue-500/20',
|
||||
'text-purple-400 bg-purple-500/10 border-purple-500/20',
|
||||
'text-green-400 bg-green-500/10 border-green-500/20',
|
||||
'text-red-400 bg-red-500/10 border-red-500/20',
|
||||
'text-amber-400 bg-amber-500/10 border-amber-500/20',
|
||||
]
|
||||
|
||||
export default function TechnologySlide({ lang }: TechnologySlideProps) {
|
||||
const i = t(lang) as any
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<FadeInView className="text-center mb-6">
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-2">
|
||||
<GradientText>{i.technology.title}</GradientText>
|
||||
</h2>
|
||||
<p className="text-sm text-white/50 max-w-2xl mx-auto">{i.technology.subtitle}</p>
|
||||
</FadeInView>
|
||||
|
||||
{/* Timeline Section */}
|
||||
<FadeInView delay={0.1}>
|
||||
<div className="mb-6">
|
||||
<p className="text-[10px] text-white/30 uppercase tracking-wider mb-3">
|
||||
{i.technology.timelineTitle}
|
||||
</p>
|
||||
|
||||
{/* Timeline Line */}
|
||||
<div className="relative">
|
||||
<div className="absolute top-4 left-0 right-0 h-px bg-gradient-to-r from-blue-500/40 via-purple-500/40 to-fuchsia-500/40" />
|
||||
|
||||
<div className="grid grid-cols-5 gap-2">
|
||||
{i.technology.phases.map((phase: any, idx: number) => (
|
||||
<motion.div
|
||||
key={phase.year}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.2 + idx * 0.1, duration: 0.5 }}
|
||||
className="relative"
|
||||
>
|
||||
{/* Dot on timeline */}
|
||||
<div className="flex justify-center mb-2">
|
||||
<div className={`w-2.5 h-2.5 rounded-full ${phaseAccents[idx].replace('text-', 'bg-')} ring-2 ring-slate-950 relative z-10`} />
|
||||
</div>
|
||||
|
||||
{/* Phase Card */}
|
||||
<div className={`bg-gradient-to-b ${phaseColors[idx]} border rounded-xl p-2.5 backdrop-blur-sm`}>
|
||||
<p className={`text-xs font-bold ${phaseAccents[idx]} mb-0.5`}>{phase.year}</p>
|
||||
<p className="text-[10px] font-semibold text-white mb-1.5">{phase.phase}</p>
|
||||
<div className="space-y-0.5">
|
||||
{phase.techs.map((tech: string, i: number) => (
|
||||
<p key={i} className="text-[9px] text-white/40 leading-tight">
|
||||
{tech}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
{/* Tech Stack Layers */}
|
||||
<FadeInView delay={0.4}>
|
||||
<p className="text-[10px] text-white/30 uppercase tracking-wider mb-2">
|
||||
{i.technology.stackTitle}
|
||||
</p>
|
||||
<div className="space-y-1.5">
|
||||
{i.technology.layers.map((layer: any, idx: number) => {
|
||||
const Icon = layerIcons[idx]
|
||||
return (
|
||||
<motion.div
|
||||
key={layer.name}
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.5 + idx * 0.08, duration: 0.4 }}
|
||||
className={`flex items-center gap-3 bg-white/[0.04] backdrop-blur-sm border border-white/[0.06] rounded-xl px-3 py-2`}
|
||||
>
|
||||
<div className={`w-8 h-8 rounded-lg border flex items-center justify-center shrink-0 ${layerColors[idx]}`}>
|
||||
<Icon className="w-4 h-4" />
|
||||
</div>
|
||||
<div className="flex items-center gap-3 flex-1 min-w-0">
|
||||
<p className="text-[11px] font-semibold text-white/80 w-24 shrink-0">{layer.name}</p>
|
||||
<p className="text-[10px] text-white/40 truncate">{layer.techs}</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</FadeInView>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
212
pitch-deck/components/slides/TheAskSlide.tsx
Normal file
212
pitch-deck/components/slides/TheAskSlide.tsx
Normal file
@@ -0,0 +1,212 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language, PitchFunding } from '@/lib/types'
|
||||
import { t } from '@/lib/i18n'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import AnimatedCounter from '../ui/AnimatedCounter'
|
||||
import GlassCard from '../ui/GlassCard'
|
||||
import { Target, Calendar, FileText, Building2, Users, Landmark, TrendingUp } from 'lucide-react'
|
||||
import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip } from 'recharts'
|
||||
|
||||
interface TheAskSlideProps {
|
||||
lang: Language
|
||||
funding: PitchFunding
|
||||
}
|
||||
|
||||
const COLORS = ['#6366f1', '#a78bfa', '#60a5fa', '#34d399', '#fbbf24', '#f87171']
|
||||
|
||||
const FUNDING_TIMELINE = [
|
||||
{
|
||||
month: 'Aug 2026',
|
||||
amount: 25000,
|
||||
icon: Building2,
|
||||
color: '#6366f1',
|
||||
label_de: 'Stammkapital',
|
||||
label_en: 'Share Capital',
|
||||
desc_de: 'GmbH-Gruendung',
|
||||
desc_en: 'GmbH Founding',
|
||||
},
|
||||
{
|
||||
month: 'Sep 2026',
|
||||
amount: 25000,
|
||||
icon: Users,
|
||||
color: '#a78bfa',
|
||||
label_de: 'Angel-Runde',
|
||||
label_en: 'Angel Round',
|
||||
desc_de: '5% Anteile',
|
||||
desc_en: '5% Equity',
|
||||
},
|
||||
{
|
||||
month: 'Okt 2026',
|
||||
amount: 200000,
|
||||
icon: Landmark,
|
||||
color: '#60a5fa',
|
||||
label_de: 'Wandeldarlehen',
|
||||
label_en: 'Convertible Note',
|
||||
desc_de: '40k Investor + 160k L-Bank',
|
||||
desc_en: '40k Investor + 160k L-Bank',
|
||||
},
|
||||
{
|
||||
month: 'Jul 2027',
|
||||
amount: 1000000,
|
||||
icon: TrendingUp,
|
||||
color: '#34d399',
|
||||
label_de: 'Series A',
|
||||
label_en: 'Series A',
|
||||
desc_de: 'Skalierungskapital',
|
||||
desc_en: 'Growth Capital',
|
||||
},
|
||||
]
|
||||
|
||||
export default function TheAskSlide({ lang, funding }: TheAskSlideProps) {
|
||||
const i = t(lang)
|
||||
const useOfFunds = funding?.use_of_funds || []
|
||||
|
||||
const pieData = useOfFunds.map((item) => ({
|
||||
name: lang === 'de' ? item.label_de : item.label_en,
|
||||
value: item.percentage,
|
||||
}))
|
||||
|
||||
const totalFunding = 1250000
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FadeInView className="text-center mb-8">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-3">
|
||||
<GradientText>{i.theAsk.title}</GradientText>
|
||||
</h2>
|
||||
<p className="text-lg text-white/50 max-w-2xl mx-auto">{i.theAsk.subtitle}</p>
|
||||
</FadeInView>
|
||||
|
||||
{/* Main Number */}
|
||||
<FadeInView delay={0.2} className="text-center mb-8">
|
||||
<motion.div
|
||||
initial={{ scale: 0.5, opacity: 0 }}
|
||||
animate={{ scale: 1, opacity: 1 }}
|
||||
transition={{ delay: 0.4, type: 'spring', stiffness: 200 }}
|
||||
>
|
||||
<p className="text-5xl md:text-7xl font-bold text-white mb-1">
|
||||
<AnimatedCounter target={1.25} suffix="M" duration={2000} decimals={2} />
|
||||
<span className="text-2xl md:text-3xl text-white/50 ml-2">EUR</span>
|
||||
</p>
|
||||
<p className="text-sm text-white/40">
|
||||
{lang === 'de' ? 'Gestaffelte Finanzierung 2026-2027' : 'Staged Funding 2026-2027'}
|
||||
</p>
|
||||
</motion.div>
|
||||
</FadeInView>
|
||||
|
||||
{/* Funding Timeline */}
|
||||
<FadeInView delay={0.4} className="mb-8">
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
||||
{FUNDING_TIMELINE.map((event, idx) => {
|
||||
const Icon = event.icon
|
||||
return (
|
||||
<motion.div
|
||||
key={idx}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.5 + idx * 0.15 }}
|
||||
>
|
||||
<GlassCard delay={0} className="p-4 text-center h-full">
|
||||
<Icon className="w-5 h-5 mx-auto mb-2" style={{ color: event.color }} />
|
||||
<p className="text-xs text-white/40 mb-1">{event.month}</p>
|
||||
<p className="text-lg font-bold text-white mb-0.5">
|
||||
{event.amount >= 1000000
|
||||
? `${(event.amount / 1000000).toFixed(0)}M`
|
||||
: `${(event.amount / 1000).toFixed(0)}k`}
|
||||
</p>
|
||||
<p className="text-xs font-medium text-white/70">
|
||||
{lang === 'de' ? event.label_de : event.label_en}
|
||||
</p>
|
||||
<p className="text-[10px] text-white/30 mt-0.5">
|
||||
{lang === 'de' ? event.desc_de : event.desc_en}
|
||||
</p>
|
||||
</GlassCard>
|
||||
</motion.div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
{/* Details Row */}
|
||||
<div className="grid md:grid-cols-3 gap-3 mb-6">
|
||||
<GlassCard delay={0.8} className="text-center p-4">
|
||||
<FileText className="w-5 h-5 text-indigo-400 mx-auto mb-2" />
|
||||
<p className="text-xs text-white/40 mb-1">{i.theAsk.instrument}</p>
|
||||
<p className="text-sm font-bold text-white">{funding?.instrument || 'Stammkapital + Wandeldarlehen + Equity'}</p>
|
||||
</GlassCard>
|
||||
<GlassCard delay={0.9} className="text-center p-4">
|
||||
<Calendar className="w-5 h-5 text-purple-400 mx-auto mb-2" />
|
||||
<p className="text-xs text-white/40 mb-1">{i.theAsk.targetDate}</p>
|
||||
<p className="text-sm font-bold text-white">
|
||||
{lang === 'de' ? 'Aug 2026 — Jul 2027' : 'Aug 2026 — Jul 2027'}
|
||||
</p>
|
||||
</GlassCard>
|
||||
<GlassCard delay={1.0} className="text-center p-4">
|
||||
<Target className="w-5 h-5 text-blue-400 mx-auto mb-2" />
|
||||
<p className="text-xs text-white/40 mb-1">{lang === 'de' ? 'Runway' : 'Runway'}</p>
|
||||
<p className="text-sm font-bold text-white">36+ {lang === 'de' ? 'Monate' : 'Months'}</p>
|
||||
</GlassCard>
|
||||
</div>
|
||||
|
||||
{/* Use of Funds */}
|
||||
<FadeInView delay={1.1}>
|
||||
<GlassCard hover={false} className="p-5">
|
||||
<h3 className="text-base font-semibold text-white mb-3 text-center">
|
||||
{i.theAsk.useOfFunds} (1,25 Mio. EUR)
|
||||
</h3>
|
||||
<div className="flex flex-col md:flex-row items-center gap-6">
|
||||
{/* Pie Chart */}
|
||||
<div className="w-40 h-40">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<PieChart>
|
||||
<Pie
|
||||
data={pieData}
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
innerRadius={45}
|
||||
outerRadius={70}
|
||||
dataKey="value"
|
||||
stroke="none"
|
||||
>
|
||||
{pieData.map((_, idx) => (
|
||||
<Cell key={idx} fill={COLORS[idx % COLORS.length]} />
|
||||
))}
|
||||
</Pie>
|
||||
<Tooltip
|
||||
contentStyle={{
|
||||
background: 'rgba(10, 10, 26, 0.9)',
|
||||
border: '1px solid rgba(255,255,255,0.1)',
|
||||
borderRadius: 8,
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
}}
|
||||
formatter={(value: number) => `${value}%`}
|
||||
/>
|
||||
</PieChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
|
||||
{/* Legend */}
|
||||
<div className="flex-1 space-y-2">
|
||||
{useOfFunds.map((item, idx) => (
|
||||
<div key={idx} className="flex items-center gap-3">
|
||||
<div className="w-2.5 h-2.5 rounded-full flex-shrink-0" style={{ backgroundColor: COLORS[idx] }} />
|
||||
<span className="flex-1 text-sm text-white/70">
|
||||
{lang === 'de' ? item.label_de : item.label_en}
|
||||
</span>
|
||||
<span className="text-sm font-bold text-white">{item.percentage}%</span>
|
||||
<span className="text-xs text-white/30">
|
||||
{((totalFunding * item.percentage) / 100).toLocaleString('de-DE')} EUR
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</GlassCard>
|
||||
</FadeInView>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
58
pitch-deck/components/slides/TractionSlide.tsx
Normal file
58
pitch-deck/components/slides/TractionSlide.tsx
Normal file
@@ -0,0 +1,58 @@
|
||||
'use client'
|
||||
|
||||
import { Language, PitchMilestone, PitchMetric } from '@/lib/types'
|
||||
import { t } from '@/lib/i18n'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import GlassCard from '../ui/GlassCard'
|
||||
import Timeline from '../ui/Timeline'
|
||||
import LiveIndicator from '../ui/LiveIndicator'
|
||||
|
||||
interface TractionSlideProps {
|
||||
lang: Language
|
||||
milestones: PitchMilestone[]
|
||||
metrics: PitchMetric[]
|
||||
}
|
||||
|
||||
export default function TractionSlide({ lang, milestones, metrics }: TractionSlideProps) {
|
||||
const i = t(lang)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FadeInView className="text-center mb-10">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-3">
|
||||
<GradientText>{i.traction.title}</GradientText>
|
||||
</h2>
|
||||
<p className="text-lg text-white/50 max-w-2xl mx-auto">{i.traction.subtitle}</p>
|
||||
</FadeInView>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
{/* KPI Cards */}
|
||||
<div>
|
||||
<div className="grid grid-cols-2 gap-3 mb-6">
|
||||
{metrics.slice(0, 6).map((m, idx) => (
|
||||
<GlassCard key={m.id} delay={0.2 + idx * 0.08} className="p-4">
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<span className="text-xs text-white/40">
|
||||
{lang === 'de' ? m.label_de : m.label_en}
|
||||
</span>
|
||||
{m.is_live && <LiveIndicator />}
|
||||
</div>
|
||||
<p className="text-2xl font-bold text-white">
|
||||
{m.value}{m.unit ? ` ${m.unit}` : ''}
|
||||
</p>
|
||||
</GlassCard>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Timeline */}
|
||||
<FadeInView delay={0.4}>
|
||||
<div className="bg-white/[0.03] rounded-2xl p-5 border border-white/5 max-h-[400px] overflow-y-auto">
|
||||
<Timeline milestones={milestones} lang={lang} />
|
||||
</div>
|
||||
</FadeInView>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user