feat: Tag/Nacht-Modus fuer gesamtes Pitch Deck

- CSS-Variablen-basiertes Theming (globals.css)
- .theme-light Klasse auf html-Element schaltet alles um
- Toggle-Button oben rechts (Sonne/Mond Icon)
- Light Mode: helle Hintergruende, dunkle Texte, gedaempfte Glass-Effekte
- Alle text-white/* Klassen werden per CSS Override umgemapped
- Partikel-Background auf 8% Opacity im Light Mode
- Kein text-shadow-glow im Light Mode

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-27 08:08:16 +01:00
parent 16de384831
commit fa8010cf91
2 changed files with 142 additions and 9 deletions

View File

@@ -4,18 +4,117 @@
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap');
/* === Dark Mode (default) === */
:root {
--bg-primary: #0a0a1a;
--bg-secondary: #111128;
--bg-card: rgba(255, 255, 255, 0.08);
--bg-card-hover: rgba(255, 255, 255, 0.12);
--border-subtle: rgba(255, 255, 255, 0.1);
--text-primary: #ffffff;
--text-secondary: rgba(255, 255, 255, 0.6);
--text-muted: rgba(255, 255, 255, 0.4);
--text-faint: rgba(255, 255, 255, 0.15);
--accent-indigo: #6366f1;
--accent-purple: #a78bfa;
--accent-blue: #60a5fa;
--glass-bg: rgba(255, 255, 255, 0.08);
--glass-border: rgba(255, 255, 255, 0.1);
--glass-hover: rgba(255, 255, 255, 0.12);
--gradient-from: #0f172a;
--gradient-via: #0a0a1a;
--gradient-to: #0f172a;
--scrollbar-thumb: rgba(255, 255, 255, 0.2);
--scrollbar-hover: rgba(255, 255, 255, 0.3);
--selection-bg: rgba(99, 102, 241, 0.3);
--selection-color: white;
--red-text: #f87171;
--green-text: #34d399;
--table-row-hover: rgba(255, 255, 255, 0.02);
--table-sum-bg: rgba(255, 255, 255, 0.03);
--sticky-bg: rgba(15, 15, 30, 0.9);
}
/* === Light Mode === */
.theme-light {
--bg-primary: #f8f9fc;
--bg-secondary: #eef0f5;
--bg-card: rgba(0, 0, 0, 0.04);
--bg-card-hover: rgba(0, 0, 0, 0.07);
--border-subtle: rgba(0, 0, 0, 0.1);
--text-primary: #1a1a2e;
--text-secondary: rgba(26, 26, 46, 0.7);
--text-muted: rgba(26, 26, 46, 0.5);
--text-faint: rgba(26, 26, 46, 0.15);
--accent-indigo: #4f46e5;
--accent-purple: #7c3aed;
--accent-blue: #3b82f6;
--glass-bg: rgba(255, 255, 255, 0.7);
--glass-border: rgba(0, 0, 0, 0.08);
--glass-hover: rgba(255, 255, 255, 0.85);
--gradient-from: #eef0f5;
--gradient-via: #f8f9fc;
--gradient-to: #eef0f5;
--scrollbar-thumb: rgba(0, 0, 0, 0.15);
--scrollbar-hover: rgba(0, 0, 0, 0.25);
--selection-bg: rgba(79, 70, 229, 0.2);
--selection-color: #1a1a2e;
--red-text: #dc2626;
--green-text: #059669;
--table-row-hover: rgba(0, 0, 0, 0.02);
--table-sum-bg: rgba(0, 0, 0, 0.03);
--sticky-bg: rgba(248, 249, 252, 0.95);
}
/* === Light mode overrides for Tailwind white/ opacity classes === */
.theme-light .text-white { color: var(--text-primary); }
.theme-light .text-white\/80 { color: rgba(26, 26, 46, 0.85); }
.theme-light .text-white\/70 { color: rgba(26, 26, 46, 0.75); }
.theme-light .text-white\/60 { color: rgba(26, 26, 46, 0.65); }
.theme-light .text-white\/50 { color: rgba(26, 26, 46, 0.55); }
.theme-light .text-white\/40 { color: rgba(26, 26, 46, 0.45); }
.theme-light .text-white\/30 { color: rgba(26, 26, 46, 0.35); }
.theme-light .text-white\/20 { color: rgba(26, 26, 46, 0.25); }
.theme-light .text-white\/15 { color: rgba(26, 26, 46, 0.18); }
.theme-light .bg-white\/\[0\.08\],
.theme-light .bg-white\/\[0\.06\],
.theme-light .bg-white\/\[0\.05\],
.theme-light .bg-white\/\[0\.04\],
.theme-light .bg-white\/\[0\.03\] { background-color: var(--glass-bg); }
.theme-light .border-white\/10,
.theme-light .border-white\/\[0\.03\] { border-color: var(--glass-border); }
.theme-light .bg-slate-900\/90,
.theme-light .bg-slate-900\/80 { background-color: var(--sticky-bg); }
.theme-light .bg-gradient-to-br { background: linear-gradient(135deg, var(--gradient-from), var(--gradient-via), var(--gradient-to)); }
.theme-light .hover\:bg-white\/\[0\.02\]:hover,
.theme-light .hover\:bg-white\/\[0\.04\]:hover { background-color: var(--table-row-hover); }
/* Glass cards in light mode */
.theme-light .backdrop-blur-xl { backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); }
/* Indigo/purple tints in light mode — slightly more opaque */
.theme-light .bg-indigo-500\/20 { background-color: rgba(79, 70, 229, 0.1); }
.theme-light .bg-indigo-500\/15 { background-color: rgba(79, 70, 229, 0.08); }
.theme-light .bg-indigo-500\/10 { background-color: rgba(79, 70, 229, 0.06); }
.theme-light .bg-emerald-500\/20 { background-color: rgba(5, 150, 105, 0.1); }
.theme-light .bg-emerald-500\/10 { background-color: rgba(5, 150, 105, 0.06); }
.theme-light .bg-purple-500\/20 { background-color: rgba(124, 58, 237, 0.1); }
.theme-light .bg-blue-500\/15 { background-color: rgba(59, 130, 246, 0.08); }
.theme-light .border-indigo-500\/30 { border-color: rgba(79, 70, 229, 0.2); }
.theme-light .border-emerald-500\/30 { border-color: rgba(5, 150, 105, 0.2); }
.theme-light .text-red-400,
.theme-light .text-red-400\/70 { color: var(--red-text); }
/* Hide particle background in light mode */
.theme-light canvas { opacity: 0.08 !important; }
* {
margin: 0;
padding: 0;
@@ -31,8 +130,8 @@ html, body {
}
::selection {
background: rgba(99, 102, 241, 0.3);
color: white;
background: var(--selection-bg);
color: var(--selection-color);
}
::-webkit-scrollbar {
@@ -44,28 +143,28 @@ html, body {
}
::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.2);
background: var(--scrollbar-thumb);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.3);
background: var(--scrollbar-hover);
}
@layer utilities {
.glass {
background: var(--bg-card);
background: var(--glass-bg);
backdrop-filter: blur(24px);
-webkit-backdrop-filter: blur(24px);
border: 1px solid var(--border-subtle);
border: 1px solid var(--glass-border);
}
.glass-hover:hover {
background: var(--bg-card-hover);
background: var(--glass-hover);
}
.gradient-text {
background: linear-gradient(135deg, #6366f1, #a78bfa, #60a5fa);
background: linear-gradient(135deg, var(--accent-indigo), var(--accent-purple), var(--accent-blue));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
@@ -75,3 +174,7 @@ html, body {
text-shadow: 0 0 40px rgba(99, 102, 241, 0.3);
}
}
.theme-light .text-shadow-glow {
text-shadow: none;
}

View File

@@ -52,6 +52,19 @@ export default function PitchDeck({ lang, onToggleLanguage }: PitchDeckProps) {
const { data, loading, error } = usePitchData()
const nav = useSlideNavigation()
const [fabOpen, setFabOpen] = useState(false)
const [theme, setTheme] = useState<'dark' | 'light'>('dark')
const toggleTheme = useCallback(() => {
setTheme(prev => {
const next = prev === 'dark' ? 'light' : 'dark'
if (next === 'light') {
document.documentElement.classList.add('theme-light')
} else {
document.documentElement.classList.remove('theme-light')
}
return next
})
}, [])
const presenter = usePresenterMode({
goToSlide: nav.goToSlide,
@@ -172,10 +185,27 @@ export default function PitchDeck({ lang, onToggleLanguage }: PitchDeckProps) {
}
return (
<div className="h-screen relative overflow-hidden bg-gradient-to-br from-slate-950 via-[#0a0a1a] to-slate-950">
<div className={`h-screen relative overflow-hidden bg-gradient-to-br ${theme === 'light' ? 'from-[#eef0f5] via-[#f8f9fc] to-[#eef0f5]' : 'from-slate-950 via-[#0a0a1a] to-slate-950'}`}>
<ParticleBackground />
<ProgressBar current={nav.currentIndex} total={nav.totalSlides} />
{/* Theme Toggle */}
<button
onClick={toggleTheme}
className="fixed top-4 right-4 z-50 p-2 rounded-full bg-white/[0.08] border border-white/10 hover:bg-white/[0.15] transition-colors backdrop-blur-xl"
title={theme === 'dark' ? 'Tag-Modus' : 'Nacht-Modus'}
>
{theme === 'dark' ? (
<svg className="w-4 h-4 text-amber-300" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<circle cx="12" cy="12" r="5" /><path d="M12 1v2m0 18v2M4.22 4.22l1.42 1.42m12.72 12.72l1.42 1.42M1 12h2m18 0h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" />
</svg>
) : (
<svg className="w-4 h-4 text-indigo-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z" />
</svg>
)}
</button>
<SlideContainer slideKey={nav.currentSlide} direction={nav.direction}>
{renderSlide()}
</SlideContainer>