pitch-deck: light mode support + MilestonesSlide redesign
All checks were successful
Build pitch-deck / build-push-deploy (push) Successful in 1m12s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 32s
CI / test-python-voice (push) Successful in 28s
CI / test-bqas (push) Successful in 32s
All checks were successful
Build pitch-deck / build-push-deploy (push) Successful in 1m12s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 32s
CI / test-python-voice (push) Successful in 28s
CI / test-bqas (push) Successful in 32s
- ArchitectureSlide: full light mode via useIsLight() hook, all inline styles adapt - USPSlide: full light mode via useIsLight() hook, all inline styles adapt - MilestonesSlide: new component — horizontal timeline with past/HEUTE/future, THEMES object (dark + light), clickable milestone nodes and stat cards with detail modal, bilingual (de/en), scaling via ResizeObserver - PitchDeck: register new 'milestones' slide case Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -21,12 +21,29 @@ const CSS_KF = `
|
||||
0%,100% { box-shadow: 0 0 38px rgba(167,139,250,.55), 0 0 80px rgba(167,139,250,.2), inset 0 3px 0 rgba(255,255,255,.35), inset 0 -6px 12px rgba(0,0,0,.35); }
|
||||
50% { box-shadow: 0 0 58px rgba(167,139,250,.85), 0 0 110px rgba(167,139,250,.35), inset 0 3px 0 rgba(255,255,255,.4), inset 0 -6px 12px rgba(0,0,0,.35); }
|
||||
}
|
||||
@keyframes uspPulseLight {
|
||||
0%,100% { box-shadow: 0 0 28px rgba(167,139,250,.4), 0 0 56px rgba(167,139,250,.15), inset 0 3px 0 rgba(255,255,255,.5), inset 0 -6px 12px rgba(0,0,0,.2); }
|
||||
50% { box-shadow: 0 0 44px rgba(167,139,250,.65), 0 0 80px rgba(167,139,250,.25), inset 0 3px 0 rgba(255,255,255,.55), inset 0 -6px 12px rgba(0,0,0,.2); }
|
||||
}
|
||||
@keyframes uspHeading {
|
||||
0%,100% { text-shadow: 0 0 22px rgba(167,139,250,.3); }
|
||||
50% { text-shadow: 0 0 36px rgba(167,139,250,.55); }
|
||||
}
|
||||
`
|
||||
|
||||
// ── Light mode hook ───────────────────────────────────────────────────────────
|
||||
function useIsLight() {
|
||||
const [isLight, setIsLight] = useState(false)
|
||||
useEffect(() => {
|
||||
const check = () => setIsLight(document.documentElement.classList.contains('theme-light'))
|
||||
check()
|
||||
const obs = new MutationObserver(check)
|
||||
obs.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] })
|
||||
return () => obs.disconnect()
|
||||
}, [])
|
||||
return isLight
|
||||
}
|
||||
|
||||
// ── Ticker ────────────────────────────────────────────────────────────────────
|
||||
function useTicker(fn: () => void, min = 180, max = 420, skip = 0.1) {
|
||||
const ref = useRef(fn)
|
||||
@@ -42,32 +59,34 @@ function useTicker(fn: () => void, min = 180, max = 420, skip = 0.1) {
|
||||
}, [min, max, skip])
|
||||
}
|
||||
|
||||
function TickerShell({ tint, children }: { tint: string; children: React.ReactNode }) {
|
||||
function TickerShell({ tint, isLight, children }: { tint: string; isLight: boolean; children: React.ReactNode }) {
|
||||
return (
|
||||
<div style={{
|
||||
...MONO, marginTop: 10, padding: '5px 9px',
|
||||
background: 'rgba(0,0,0,.38)', border: `1px solid ${tint}55`,
|
||||
borderRadius: 6, fontSize: 10.5, color: 'rgba(236,233,247,.88)',
|
||||
background: isLight ? '#f1f5f9' : 'rgba(0,0,0,.38)',
|
||||
border: `1px solid ${tint}55`,
|
||||
borderRadius: 6, fontSize: 10.5,
|
||||
color: isLight ? '#475569' : 'rgba(236,233,247,.88)',
|
||||
display: 'flex', alignItems: 'center', gap: 7,
|
||||
whiteSpace: 'nowrap', overflow: 'hidden', height: 22,
|
||||
}}>{children}</div>
|
||||
)
|
||||
}
|
||||
|
||||
function TickTrace({ tint }: { tint: string }) {
|
||||
function TickTrace({ tint, isLight }: { tint: string; isLight: boolean }) {
|
||||
const [n, setN] = useState(12748)
|
||||
useTicker(() => setN(v => v + 1 + Math.floor(Math.random() * 3)), 250, 500)
|
||||
return (
|
||||
<TickerShell tint={tint}>
|
||||
<span style={{ color: '#4ade80' }}>●</span>
|
||||
<TickerShell tint={tint} isLight={isLight}>
|
||||
<span style={{ color: isLight ? '#16a34a' : '#4ade80' }}>●</span>
|
||||
<span style={{ color: tint, opacity: .85 }}>trace</span>
|
||||
<span style={{ color: '#f5f3fc', fontWeight: 600 }}>{n.toLocaleString()}</span>
|
||||
<span style={{ color: 'rgba(236,233,247,.45)' }}>evidence-chain</span>
|
||||
<span style={{ color: isLight ? '#1a1a2e' : '#f5f3fc', fontWeight: 600 }}>{n.toLocaleString()}</span>
|
||||
<span style={{ color: isLight ? '#94a3b8' : 'rgba(236,233,247,.45)' }}>evidence-chain</span>
|
||||
</TickerShell>
|
||||
)
|
||||
}
|
||||
|
||||
function TickEngine({ tint }: { tint: string }) {
|
||||
function TickEngine({ tint, isLight }: { tint: string; isLight: boolean }) {
|
||||
const [v, setV] = useState(428)
|
||||
const [rate, setRate] = useState(99.4)
|
||||
useTicker(() => {
|
||||
@@ -75,40 +94,40 @@ function TickEngine({ tint }: { tint: string }) {
|
||||
setRate(r => Math.max(97, Math.min(99.9, r + (Math.random() - 0.5) * 0.3)))
|
||||
}, 220, 420)
|
||||
return (
|
||||
<TickerShell tint={tint}>
|
||||
<span style={{ color: '#4ade80' }}>●</span>
|
||||
<TickerShell tint={tint} isLight={isLight}>
|
||||
<span style={{ color: isLight ? '#16a34a' : '#4ade80' }}>●</span>
|
||||
<span style={{ color: tint, opacity: .85 }}>validate</span>
|
||||
<span style={{ color: '#f5f3fc', fontWeight: 600 }}>{v.toLocaleString()}</span>
|
||||
<span style={{ color: '#4ade80' }}>{rate.toFixed(1)}%</span>
|
||||
<span style={{ color: isLight ? '#1a1a2e' : '#f5f3fc', fontWeight: 600 }}>{v.toLocaleString()}</span>
|
||||
<span style={{ color: isLight ? '#16a34a' : '#4ade80' }}>{rate.toFixed(1)}%</span>
|
||||
</TickerShell>
|
||||
)
|
||||
}
|
||||
|
||||
function TickOptimizer({ tint }: { tint: string }) {
|
||||
function TickOptimizer({ tint, isLight }: { tint: string; isLight: boolean }) {
|
||||
const ops = ['ROI: 2.418 € / dev', 'gap → policy §4.2', 'dedup 128 tickets', 'sweet-spot: 22 KLOC', 'tradeoff: speed↔risk']
|
||||
const [i, setI] = useState(0)
|
||||
useTicker(() => setI(x => (x + 1) % ops.length), 900, 1600, 0.05)
|
||||
return (
|
||||
<TickerShell tint={tint}>
|
||||
<TickerShell tint={tint} isLight={isLight}>
|
||||
<span style={{ color: '#fbbf24' }}>✦</span>
|
||||
<span style={{ color: tint, opacity: .85 }}>optimize</span>
|
||||
<span style={{ color: '#f5f3fc', overflow: 'hidden', textOverflow: 'ellipsis', flex: 1 }}>{ops[i]}</span>
|
||||
<span style={{ color: isLight ? '#1a1a2e' : '#f5f3fc', overflow: 'hidden', textOverflow: 'ellipsis', flex: 1 }}>{ops[i]}</span>
|
||||
</TickerShell>
|
||||
)
|
||||
}
|
||||
|
||||
function TickStack({ tint }: { tint: string }) {
|
||||
function TickStack({ tint, isLight }: { tint: string; isLight: boolean }) {
|
||||
const regs = ['DSGVO', 'NIS-2', 'DORA', 'EU AI Act', 'ISO 27001', 'BSI C5']
|
||||
const [i, setI] = useState(0)
|
||||
const [c, setC] = useState(1208)
|
||||
useTicker(() => { setI(x => (x + 1) % regs.length); setC(v => v + Math.floor(Math.random() * 3)) }, 800, 1400, 0.05)
|
||||
return (
|
||||
<TickerShell tint={tint}>
|
||||
<span style={{ color: '#4ade80' }}>●</span>
|
||||
<TickerShell tint={tint} isLight={isLight}>
|
||||
<span style={{ color: isLight ? '#16a34a' : '#4ade80' }}>●</span>
|
||||
<span style={{ color: tint, opacity: .85 }}>check</span>
|
||||
<span style={{ color: '#f5f3fc', fontWeight: 600 }}>{regs[i]}</span>
|
||||
<span style={{ color: 'rgba(236,233,247,.4)' }}>·</span>
|
||||
<span style={{ color: '#f5f3fc' }}>{c.toLocaleString()}</span>
|
||||
<span style={{ color: isLight ? '#1a1a2e' : '#f5f3fc', fontWeight: 600 }}>{regs[i]}</span>
|
||||
<span style={{ color: isLight ? '#94a3b8' : 'rgba(236,233,247,.4)' }}>·</span>
|
||||
<span style={{ color: isLight ? '#1a1a2e' : '#f5f3fc' }}>{c.toLocaleString()}</span>
|
||||
</TickerShell>
|
||||
)
|
||||
}
|
||||
@@ -233,10 +252,10 @@ function getDetails(de: boolean): Record<string, DetailItem> {
|
||||
}
|
||||
|
||||
// ── Pillar row ────────────────────────────────────────────────────────────────
|
||||
function PillarRow({ side, title, body, tint, onClick, active }: {
|
||||
function PillarRow({ side, title, body, tint, onClick, active, isLight }: {
|
||||
side: 'left' | 'right'
|
||||
title: string; body: string; tint: string
|
||||
onClick: () => void; active: boolean
|
||||
onClick: () => void; active: boolean; isLight: boolean
|
||||
}) {
|
||||
const [hover, setHover] = useState(false)
|
||||
const lit = hover || active
|
||||
@@ -266,13 +285,15 @@ function PillarRow({ side, title, body, tint, onClick, active }: {
|
||||
background: lit ? `${tint}3a` : `${tint}22`,
|
||||
border: `1px solid ${lit ? tint : tint + '66'}`,
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
color: lit ? '#fff' : tint, fontSize: 13, fontWeight: 700, marginTop: 2,
|
||||
color: lit ? (isLight ? tint : '#fff') : tint, fontSize: 13, fontWeight: 700, marginTop: 2,
|
||||
boxShadow: lit ? `0 0 14px ${tint}88, inset 0 1px 0 ${tint}80` : `inset 0 1px 0 ${tint}50`,
|
||||
transition: 'all .25s',
|
||||
}}>◆</div>
|
||||
<div style={{ flex: 1, minWidth: 0 }}>
|
||||
<div style={{
|
||||
fontSize: 13, fontWeight: 700, color: '#f7f5fc', letterSpacing: -0.15, marginBottom: 3,
|
||||
fontSize: 13, fontWeight: 700,
|
||||
color: isLight ? '#1a1a2e' : '#f7f5fc',
|
||||
letterSpacing: -0.15, marginBottom: 3,
|
||||
display: 'flex', alignItems: 'center', gap: 6,
|
||||
justifyContent: isLeft ? 'flex-end' : 'flex-start',
|
||||
}}>
|
||||
@@ -283,15 +304,21 @@ function PillarRow({ side, title, body, tint, onClick, active }: {
|
||||
transition: 'all .25s',
|
||||
}}>{isLeft ? '‹' : '›'}</span>
|
||||
</div>
|
||||
<div style={{ fontSize: 11, lineHeight: 1.55, color: `rgba(236,233,247,${lit ? .82 : .62})`, transition: 'color .25s' }}>{body}</div>
|
||||
<div style={{
|
||||
fontSize: 11, lineHeight: 1.55,
|
||||
color: isLight
|
||||
? `rgba(71,85,105,${lit ? 1 : .78})`
|
||||
: `rgba(236,233,247,${lit ? .82 : .62})`,
|
||||
transition: 'color .25s',
|
||||
}}>{body}</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// ── Column header ─────────────────────────────────────────────────────────────
|
||||
function ColHeader({ side, label, color, icon, sub }: {
|
||||
side: 'left' | 'right'; label: string; color: string; icon: string; sub: string
|
||||
function ColHeader({ side, label, color, icon, sub, isLight }: {
|
||||
side: 'left' | 'right'; label: string; color: string; icon: string; sub: string; isLight: boolean
|
||||
}) {
|
||||
const isLeft = side === 'left'
|
||||
return (
|
||||
@@ -305,11 +332,11 @@ function ColHeader({ side, label, color, icon, sub }: {
|
||||
background: `linear-gradient(135deg, ${color}55, ${color}20)`,
|
||||
border: `1px solid ${color}88`,
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
color: '#fff', fontSize: 15, fontWeight: 700,
|
||||
color: isLight ? color : '#fff', fontSize: 15, fontWeight: 700,
|
||||
boxShadow: `0 0 18px ${color}55, inset 0 1px 0 ${color}aa`,
|
||||
}}>{icon}</div>
|
||||
<div>
|
||||
<div style={{ fontSize: 18, fontWeight: 700, color: '#f7f5fc', letterSpacing: -0.3, lineHeight: 1 }}>{label}</div>
|
||||
<div style={{ fontSize: 18, fontWeight: 700, color: isLight ? '#1a1a2e' : '#f7f5fc', letterSpacing: -0.3, lineHeight: 1 }}>{label}</div>
|
||||
<div style={{ ...MONO, fontSize: 9.5, letterSpacing: 2, color, opacity: .75, marginTop: 3, textTransform: 'uppercase' as const }}>{sub}</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -317,7 +344,7 @@ function ColHeader({ side, label, color, icon, sub }: {
|
||||
}
|
||||
|
||||
// ── Central hub ───────────────────────────────────────────────────────────────
|
||||
function CentralHub({ caption }: { caption: string }) {
|
||||
function CentralHub({ caption, isLight }: { caption: string; isLight: boolean }) {
|
||||
return (
|
||||
<div style={{ position: 'relative', width: 260, height: 320, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||||
<div style={{
|
||||
@@ -325,11 +352,14 @@ function CentralHub({ caption }: { caption: string }) {
|
||||
background: 'radial-gradient(circle at 32% 28%, #f0e9ff 0%, #c4aaff 26%, #7b5cd6 58%, #2a1560 100%)',
|
||||
border: '1.5px solid rgba(216,202,255,.7)',
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
boxShadow: '0 0 50px rgba(167,139,250,.65), 0 0 100px rgba(167,139,250,.25), inset 0 3px 0 rgba(255,255,255,.35), inset 0 -8px 14px rgba(0,0,0,.35)',
|
||||
animation: 'uspPulse 2.6s ease-in-out infinite', zIndex: 3,
|
||||
boxShadow: isLight
|
||||
? '0 0 30px rgba(167,139,250,.4), 0 0 60px rgba(167,139,250,.15), inset 0 3px 0 rgba(255,255,255,.5), inset 0 -8px 14px rgba(0,0,0,.2)'
|
||||
: '0 0 50px rgba(167,139,250,.65), 0 0 100px rgba(167,139,250,.25), inset 0 3px 0 rgba(255,255,255,.35), inset 0 -8px 14px rgba(0,0,0,.35)',
|
||||
animation: isLight ? 'uspPulseLight 2.6s ease-in-out infinite' : 'uspPulse 2.6s ease-in-out infinite',
|
||||
zIndex: 3,
|
||||
}}>
|
||||
<div style={{ position: 'absolute', inset: -14, borderRadius: '50%', border: '1px dashed rgba(216,202,255,.42)', animation: 'uspSpin 14s linear infinite' }} />
|
||||
<div style={{ position: 'absolute', inset: -30, borderRadius: '50%', border: '1px dashed rgba(216,202,255,.2)', animation: 'uspSpin 22s linear infinite reverse' }} />
|
||||
<div style={{ position: 'absolute', inset: -14, borderRadius: '50%', border: `1px dashed ${isLight ? 'rgba(167,139,250,.5)' : 'rgba(216,202,255,.42)'}`, animation: 'uspSpin 14s linear infinite' }} />
|
||||
<div style={{ position: 'absolute', inset: -30, borderRadius: '50%', border: `1px dashed ${isLight ? 'rgba(167,139,250,.3)' : 'rgba(216,202,255,.2)'}`, animation: 'uspSpin 22s linear infinite reverse' }} />
|
||||
<svg width="54" height="26" viewBox="0 0 54 26" fill="none" stroke="#fff" strokeWidth="2.8" strokeLinecap="round" strokeLinejoin="round"
|
||||
style={{ filter: 'drop-shadow(0 1px 3px rgba(0,0,0,.5))' }}>
|
||||
<path d="M 10 13 C 10 5, 22 5, 27 13 C 32 21, 44 21, 44 13 C 44 5, 32 5, 27 13 C 22 21, 10 21, 10 13 Z" />
|
||||
@@ -337,7 +367,8 @@ function CentralHub({ caption }: { caption: string }) {
|
||||
</div>
|
||||
<div style={{
|
||||
position: 'absolute', left: 0, right: 0, bottom: 24, textAlign: 'center',
|
||||
...MONO, fontSize: 9.5, letterSpacing: 2.5, color: 'rgba(216,202,255,.75)',
|
||||
...MONO, fontSize: 9.5, letterSpacing: 2.5,
|
||||
color: isLight ? 'rgba(109,77,194,.75)' : 'rgba(216,202,255,.75)',
|
||||
textTransform: 'uppercase' as const, fontWeight: 600,
|
||||
}}>{caption}</div>
|
||||
</div>
|
||||
@@ -345,7 +376,7 @@ function CentralHub({ caption }: { caption: string }) {
|
||||
}
|
||||
|
||||
// ── Bridge SVG connectors ─────────────────────────────────────────────────────
|
||||
function BridgeConnectors() {
|
||||
function BridgeConnectors({ isLight }: { isLight: boolean }) {
|
||||
const rfpY = 130
|
||||
const sub2Y = 250
|
||||
const hubCx = 500
|
||||
@@ -356,12 +387,12 @@ function BridgeConnectors() {
|
||||
<defs>
|
||||
<linearGradient id="uspFromL" x1="0" x2="1">
|
||||
<stop offset="0" stopColor="#a78bfa" stopOpacity="0" />
|
||||
<stop offset=".3" stopColor="#a78bfa" stopOpacity=".85" />
|
||||
<stop offset="1" stopColor="#c084fc" stopOpacity=".3" />
|
||||
<stop offset=".3" stopColor="#a78bfa" stopOpacity={isLight ? '.6' : '.85'} />
|
||||
<stop offset="1" stopColor="#c084fc" stopOpacity={isLight ? '.2' : '.3'} />
|
||||
</linearGradient>
|
||||
<linearGradient id="uspToR" x1="0" x2="1">
|
||||
<stop offset="0" stopColor="#c084fc" stopOpacity=".3" />
|
||||
<stop offset=".7" stopColor="#fbbf24" stopOpacity=".85" />
|
||||
<stop offset="0" stopColor="#c084fc" stopOpacity={isLight ? '.2' : '.3'} />
|
||||
<stop offset=".7" stopColor="#fbbf24" stopOpacity={isLight ? '.6' : '.85'} />
|
||||
<stop offset="1" stopColor="#fbbf24" stopOpacity="0" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
@@ -381,9 +412,9 @@ function BridgeConnectors() {
|
||||
|
||||
{([rfpY, sub2Y] as number[]).map(y => (
|
||||
<g key={y}>
|
||||
<circle cx={hubCx - hubR} cy={y} r="4" fill="#1a0f34" stroke="#a78bfa" strokeWidth="1.2" />
|
||||
<circle cx={hubCx - hubR} cy={y} r="4" fill={isLight ? '#eef2ff' : '#1a0f34'} stroke="#a78bfa" strokeWidth="1.2" />
|
||||
<circle cx={hubCx - hubR} cy={y} r="1.5" fill="#a78bfa" />
|
||||
<circle cx={hubCx + hubR} cy={y} r="4" fill="#1a0f34" stroke="#fbbf24" strokeWidth="1.2" />
|
||||
<circle cx={hubCx + hubR} cy={y} r="4" fill={isLight ? '#eef2ff' : '#1a0f34'} stroke="#fbbf24" strokeWidth="1.2" />
|
||||
<circle cx={hubCx + hubR} cy={y} r="1.5" fill="#fbbf24" />
|
||||
</g>
|
||||
))}
|
||||
@@ -401,10 +432,10 @@ function BridgeConnectors() {
|
||||
}
|
||||
|
||||
// ── Under-the-hood feature card ───────────────────────────────────────────────
|
||||
function FeatureCard({ icon, title, body, tint, Ticker, onClick, active }: {
|
||||
function FeatureCard({ icon, title, body, tint, Ticker, onClick, active, isLight }: {
|
||||
icon: string; title: string; body: string; tint: string
|
||||
Ticker: React.ComponentType<{ tint: string }>
|
||||
onClick: () => void; active: boolean
|
||||
Ticker: React.ComponentType<{ tint: string; isLight: boolean }>
|
||||
onClick: () => void; active: boolean; isLight: boolean
|
||||
}) {
|
||||
const [hover, setHover] = useState(false)
|
||||
const lit = hover || active
|
||||
@@ -415,12 +446,18 @@ function FeatureCard({ icon, title, body, tint, Ticker, onClick, active }: {
|
||||
onMouseLeave={() => setHover(false)}
|
||||
style={{
|
||||
position: 'relative', padding: '13px 15px',
|
||||
background: `linear-gradient(180deg, ${tint}${lit ? '2a' : '1a'} 0%, ${tint}07 55%, rgba(14,8,28,.85) 100%)`,
|
||||
border: `1px solid ${lit ? tint : tint + '4a'}`,
|
||||
background: isLight
|
||||
? lit
|
||||
? `linear-gradient(180deg, ${tint}18 0%, ${tint}08 55%, rgba(248,250,252,.95) 100%)`
|
||||
: 'linear-gradient(180deg, #ffffff, #f8fafc)'
|
||||
: `linear-gradient(180deg, ${tint}${lit ? '2a' : '1a'} 0%, ${tint}07 55%, rgba(14,8,28,.85) 100%)`,
|
||||
border: `1px solid ${lit ? tint : isLight ? 'rgba(0,0,0,.1)' : tint + '4a'}`,
|
||||
borderRadius: 12,
|
||||
boxShadow: lit
|
||||
? `0 18px 40px ${tint}33, 0 0 0 1px ${tint}66, inset 0 1px 0 ${tint}60`
|
||||
: `0 10px 24px rgba(0,0,0,.4), inset 0 1px 0 ${tint}35`,
|
||||
: isLight
|
||||
? '0 2px 8px rgba(0,0,0,.08), inset 0 1px 0 rgba(255,255,255,.8)'
|
||||
: `0 10px 24px rgba(0,0,0,.4), inset 0 1px 0 ${tint}35`,
|
||||
minWidth: 0, cursor: 'pointer',
|
||||
transform: lit ? 'translateY(-3px)' : 'translateY(0)',
|
||||
transition: 'transform .25s, box-shadow .25s, background .25s, border-color .25s',
|
||||
@@ -432,21 +469,27 @@ function FeatureCard({ icon, title, body, tint, Ticker, onClick, active }: {
|
||||
background: lit ? `${tint}44` : `${tint}22`,
|
||||
border: `1px solid ${lit ? tint : tint + '66'}`,
|
||||
display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
|
||||
color: lit ? '#fff' : tint, fontSize: 12,
|
||||
color: lit ? (isLight ? tint : '#fff') : tint, fontSize: 12,
|
||||
boxShadow: lit ? `0 0 12px ${tint}88` : 'none',
|
||||
transition: 'all .25s',
|
||||
}}>{icon}</span>
|
||||
<span style={{ fontSize: 12.5, fontWeight: 700, color: '#f7f5fc', letterSpacing: -0.15, flex: 1 }}>{title}</span>
|
||||
<span style={{ fontSize: 12.5, fontWeight: 700, color: isLight ? '#1a1a2e' : '#f7f5fc', letterSpacing: -0.15, flex: 1 }}>{title}</span>
|
||||
<span style={{ fontSize: 10, color: tint, opacity: lit ? 1 : 0.5, transform: `translateX(${lit ? 0 : -3}px)`, transition: 'all .25s' }}>↗</span>
|
||||
</div>
|
||||
<div style={{ fontSize: 11, lineHeight: 1.45, color: `rgba(236,233,247,${lit ? .82 : .65})`, transition: 'color .25s' }}>{body}</div>
|
||||
<Ticker tint={tint} />
|
||||
<div style={{
|
||||
fontSize: 11, lineHeight: 1.45,
|
||||
color: isLight
|
||||
? `rgba(71,85,105,${lit ? 1 : .78})`
|
||||
: `rgba(236,233,247,${lit ? .82 : .65})`,
|
||||
transition: 'color .25s',
|
||||
}}>{body}</div>
|
||||
<Ticker tint={tint} isLight={isLight} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// ── Detail modal ──────────────────────────────────────────────────────────────
|
||||
function DetailModal({ item, onClose }: { item: DetailItem | null; onClose: () => void }) {
|
||||
function DetailModal({ item, onClose, isLight }: { item: DetailItem | null; onClose: () => void; isLight: boolean }) {
|
||||
useEffect(() => {
|
||||
if (!item) return
|
||||
const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose() }
|
||||
@@ -465,7 +508,8 @@ function DetailModal({ item, onClose }: { item: DetailItem | null; onClose: () =
|
||||
onClick={onClose}
|
||||
style={{
|
||||
position: 'absolute', inset: 0, zIndex: 50,
|
||||
background: 'rgba(5,2,16,.72)', backdropFilter: 'blur(6px)',
|
||||
background: isLight ? 'rgba(240,244,255,.72)' : 'rgba(5,2,16,.72)',
|
||||
backdropFilter: 'blur(6px)',
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
@@ -477,11 +521,16 @@ function DetailModal({ item, onClose }: { item: DetailItem | null; onClose: () =
|
||||
onClick={e => e.stopPropagation()}
|
||||
style={{
|
||||
width: 560, maxWidth: '88%',
|
||||
background: `linear-gradient(180deg, ${item.tint}18 0%, rgba(20,10,40,.96) 50%, rgba(14,8,28,.98) 100%)`,
|
||||
border: `1px solid ${item.tint}66`,
|
||||
background: isLight
|
||||
? `linear-gradient(180deg, ${item.tint}10 0%, rgba(255,255,255,.98) 50%, rgba(248,250,252,.99) 100%)`
|
||||
: `linear-gradient(180deg, ${item.tint}18 0%, rgba(20,10,40,.96) 50%, rgba(14,8,28,.98) 100%)`,
|
||||
border: `1px solid ${item.tint}${isLight ? '44' : '66'}`,
|
||||
borderRadius: 16,
|
||||
boxShadow: `0 30px 80px rgba(0,0,0,.6), 0 0 60px ${item.tint}33, inset 0 1px 0 ${item.tint}55`,
|
||||
padding: '22px 26px', color: '#ece9f7',
|
||||
boxShadow: isLight
|
||||
? `0 20px 60px rgba(0,0,0,.12), 0 0 40px ${item.tint}18, inset 0 1px 0 rgba(255,255,255,.9)`
|
||||
: `0 30px 80px rgba(0,0,0,.6), 0 0 60px ${item.tint}33, inset 0 1px 0 ${item.tint}55`,
|
||||
padding: '22px 26px',
|
||||
color: isLight ? '#1a1a2e' : '#ece9f7',
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 14 }}>
|
||||
@@ -490,25 +539,25 @@ function DetailModal({ item, onClose }: { item: DetailItem | null; onClose: () =
|
||||
background: `linear-gradient(135deg, ${item.tint}66, ${item.tint}22)`,
|
||||
border: `1px solid ${item.tint}`,
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
color: '#fff', fontSize: 16, fontWeight: 700,
|
||||
color: isLight ? item.tint : '#fff', fontSize: 16, fontWeight: 700,
|
||||
boxShadow: `0 0 18px ${item.tint}66`,
|
||||
}}>{item.icon}</div>
|
||||
<div style={{ flex: 1 }}>
|
||||
<div style={{ ...MONO, fontSize: 9.5, letterSpacing: 2.5, color: item.tint, textTransform: 'uppercase' as const, fontWeight: 600, marginBottom: 2 }}>
|
||||
{item.kicker}
|
||||
</div>
|
||||
<div style={{ fontSize: 19, fontWeight: 700, color: '#f7f5fc', letterSpacing: -0.3 }}>{item.title}</div>
|
||||
<div style={{ fontSize: 19, fontWeight: 700, color: isLight ? '#1a1a2e' : '#f7f5fc', letterSpacing: -0.3 }}>{item.title}</div>
|
||||
</div>
|
||||
<button onClick={onClose} style={{
|
||||
background: 'transparent', border: `1px solid ${item.tint}55`,
|
||||
borderRadius: 8, cursor: 'pointer', width: 30, height: 30,
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
color: 'rgba(236,233,247,.6)',
|
||||
color: isLight ? '#64748b' : 'rgba(236,233,247,.6)',
|
||||
}}>
|
||||
<X style={{ width: 14, height: 14 }} />
|
||||
</button>
|
||||
</div>
|
||||
<div style={{ fontSize: 13, lineHeight: 1.6, color: 'rgba(236,233,247,.82)', marginBottom: 16 }}>
|
||||
<div style={{ fontSize: 13, lineHeight: 1.6, color: isLight ? '#475569' : 'rgba(236,233,247,.82)', marginBottom: 16 }}>
|
||||
{item.body}
|
||||
</div>
|
||||
{item.bullets && (
|
||||
@@ -517,10 +566,11 @@ function DetailModal({ item, onClose }: { item: DetailItem | null; onClose: () =
|
||||
<div key={i} style={{
|
||||
display: 'flex', alignItems: 'flex-start', gap: 10,
|
||||
padding: '8px 12px', borderRadius: 8,
|
||||
background: 'rgba(0,0,0,.3)', border: `1px solid ${item.tint}33`,
|
||||
background: isLight ? 'rgba(0,0,0,.04)' : 'rgba(0,0,0,.3)',
|
||||
border: `1px solid ${item.tint}${isLight ? '22' : '33'}`,
|
||||
}}>
|
||||
<span style={{ color: item.tint, fontSize: 12, marginTop: 1 }}>▸</span>
|
||||
<span style={{ fontSize: 12, lineHeight: 1.5, color: 'rgba(236,233,247,.78)' }}>{b}</span>
|
||||
<span style={{ fontSize: 12, lineHeight: 1.5, color: isLight ? '#475569' : 'rgba(236,233,247,.78)' }}>{b}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -528,13 +578,14 @@ function DetailModal({ item, onClose }: { item: DetailItem | null; onClose: () =
|
||||
{item.stat && (
|
||||
<div style={{
|
||||
...MONO, padding: '10px 14px', borderRadius: 8,
|
||||
background: 'rgba(0,0,0,.45)', border: `1px solid ${item.tint}55`,
|
||||
fontSize: 12, color: 'rgba(236,233,247,.9)',
|
||||
background: isLight ? 'rgba(0,0,0,.04)' : 'rgba(0,0,0,.45)',
|
||||
border: `1px solid ${item.tint}${isLight ? '33' : '55'}`,
|
||||
fontSize: 12, color: isLight ? '#475569' : 'rgba(236,233,247,.9)',
|
||||
display: 'flex', alignItems: 'center', gap: 10,
|
||||
}}>
|
||||
<span style={{ color: '#4ade80' }}>●</span>
|
||||
<span style={{ color: isLight ? '#16a34a' : '#4ade80' }}>●</span>
|
||||
<span style={{ color: item.tint }}>{item.stat.k}</span>
|
||||
<span style={{ color: '#f5f3fc', fontWeight: 600 }}>{item.stat.v}</span>
|
||||
<span style={{ color: isLight ? '#1a1a2e' : '#f5f3fc', fontWeight: 600 }}>{item.stat.v}</span>
|
||||
</div>
|
||||
)}
|
||||
</motion.div>
|
||||
@@ -545,12 +596,13 @@ function DetailModal({ item, onClose }: { item: DetailItem | null; onClose: () =
|
||||
}
|
||||
|
||||
// ── Star field ────────────────────────────────────────────────────────────────
|
||||
function StarField() {
|
||||
function StarField({ isLight }: { isLight: boolean }) {
|
||||
const stars = useMemo(() => {
|
||||
let s = 41
|
||||
const r = () => { s = (s * 9301 + 49297) % 233280; return s / 233280 }
|
||||
return Array.from({ length: 90 }, () => ({ x: r() * 100, y: r() * 100, size: r() * 1.4 + 0.3, op: r() * 0.5 + 0.15 }))
|
||||
}, [])
|
||||
if (isLight) return null
|
||||
return (
|
||||
<div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
|
||||
{stars.map((st, i) => (
|
||||
@@ -568,6 +620,7 @@ function StarField() {
|
||||
// ── Main slide ────────────────────────────────────────────────────────────────
|
||||
export default function USPSlide({ lang }: USPSlideProps) {
|
||||
const de = lang === 'de'
|
||||
const isLight = useIsLight()
|
||||
const details = getDetails(de)
|
||||
const [detail, setDetail] = useState<DetailItem | null>(null)
|
||||
const open = (k: string) => setDetail(details[k])
|
||||
@@ -587,38 +640,45 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
||||
{/* ── MAIN CANVAS ───────────────────────────────────────────────── */}
|
||||
<div style={{
|
||||
position: 'relative', overflow: 'hidden', borderRadius: 16,
|
||||
background: 'radial-gradient(ellipse at 50% 30%, #1a0f34 0%, #0e0720 55%, #050210 100%)',
|
||||
color: '#ece9f7', fontFamily: '"Inter", system-ui, sans-serif',
|
||||
background: isLight
|
||||
? 'linear-gradient(160deg, #f0f4ff 0%, #eff6ff 50%, #f5f0ff 100%)'
|
||||
: 'radial-gradient(ellipse at 50% 30%, #1a0f34 0%, #0e0720 55%, #050210 100%)',
|
||||
color: isLight ? '#1a1a2e' : '#ece9f7',
|
||||
fontFamily: '"Inter", system-ui, sans-serif',
|
||||
WebkitFontSmoothing: 'antialiased',
|
||||
}}>
|
||||
{/* Ambient glow */}
|
||||
<div style={{
|
||||
position: 'absolute', top: -120, left: '50%', transform: 'translateX(-50%)',
|
||||
width: 800, height: 500, borderRadius: '50%',
|
||||
background: 'radial-gradient(ellipse, rgba(167,139,250,.2), transparent 65%)',
|
||||
filter: 'blur(50px)', pointerEvents: 'none',
|
||||
}} />
|
||||
<StarField />
|
||||
{/* Ambient glow — dark only */}
|
||||
{!isLight && (
|
||||
<div style={{
|
||||
position: 'absolute', top: -120, left: '50%', transform: 'translateX(-50%)',
|
||||
width: 800, height: 500, borderRadius: '50%',
|
||||
background: 'radial-gradient(ellipse, rgba(167,139,250,.2), transparent 65%)',
|
||||
filter: 'blur(50px)', pointerEvents: 'none',
|
||||
}} />
|
||||
)}
|
||||
<StarField isLight={isLight} />
|
||||
|
||||
{/* Interaction hint */}
|
||||
<div style={{
|
||||
position: 'absolute', top: 20, right: 28, zIndex: 5,
|
||||
...MONO, fontSize: 9.5, letterSpacing: 2, color: 'rgba(167,139,250,.55)',
|
||||
...MONO, fontSize: 9.5, letterSpacing: 2,
|
||||
color: isLight ? 'rgba(109,77,194,.6)' : 'rgba(167,139,250,.55)',
|
||||
textTransform: 'uppercase', fontWeight: 600,
|
||||
display: 'flex', alignItems: 'center', gap: 6,
|
||||
}}>
|
||||
<span style={{ display: 'inline-block', width: 6, height: 6, borderRadius: '50%', background: '#4ade80', boxShadow: '0 0 8px #4ade80' }} />
|
||||
<span style={{ display: 'inline-block', width: 6, height: 6, borderRadius: '50%', background: isLight ? '#16a34a' : '#4ade80', boxShadow: `0 0 8px ${isLight ? '#16a34a' : '#4ade80'}` }} />
|
||||
{de ? 'Element anklicken' : 'Click any element'}
|
||||
</div>
|
||||
|
||||
{/* Heading */}
|
||||
<div style={{ position: 'relative', padding: '30px 48px 0', textAlign: 'center', zIndex: 2 }}>
|
||||
<div style={{ ...MONO, fontSize: 10, letterSpacing: 4, color: 'rgba(167,139,250,.7)', textTransform: 'uppercase', fontWeight: 600, marginBottom: 6 }}>
|
||||
<div style={{ ...MONO, fontSize: 10, letterSpacing: 4, color: isLight ? 'rgba(109,77,194,.7)' : 'rgba(167,139,250,.7)', textTransform: 'uppercase', fontWeight: 600, marginBottom: 6 }}>
|
||||
{de ? 'Alleinstellungsmerkmal' : 'Unique Selling Proposition'}
|
||||
</div>
|
||||
<h1 style={{
|
||||
fontSize: 34, fontWeight: 700, letterSpacing: -0.8, margin: 0, lineHeight: 1.2,
|
||||
color: '#f7f5fc', animation: 'uspHeading 4s ease-in-out infinite',
|
||||
color: isLight ? '#1a1a2e' : '#f7f5fc',
|
||||
animation: isLight ? undefined : 'uspHeading 4s ease-in-out infinite',
|
||||
}}>
|
||||
{de ? 'Die erste Plattform, die ' : 'The first platform bridging '}
|
||||
<span style={{ background: 'linear-gradient(90deg, #c4aaff, #a78bfa)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', backgroundClip: 'text' }}>
|
||||
@@ -634,7 +694,7 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
||||
|
||||
{/* Bridge */}
|
||||
<div style={{ position: 'relative', margin: '14px 48px 0', height: 340 }}>
|
||||
<BridgeConnectors />
|
||||
<BridgeConnectors isLight={isLight} />
|
||||
<div style={{
|
||||
position: 'relative', zIndex: 2,
|
||||
display: 'grid', gridTemplateColumns: '1fr 260px 1fr', gap: 0,
|
||||
@@ -643,11 +703,11 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
||||
{/* LEFT — Compliance */}
|
||||
<div style={{ display: 'flex', flexDirection: 'column', paddingRight: 20 }}>
|
||||
<div style={{ height: 40, marginBottom: 36 }}>
|
||||
<ColHeader side="left" label="Compliance" color="#a78bfa" icon="⎈" sub="policy · audit · proof" />
|
||||
<ColHeader side="left" label="Compliance" color="#a78bfa" icon="⎈" sub="policy · audit · proof" isLight={isLight} />
|
||||
</div>
|
||||
<div style={{ height: 110, display: 'flex', alignItems: 'center' }}>
|
||||
<div style={{ width: '100%' }}>
|
||||
<PillarRow side="left" tint="#a78bfa"
|
||||
<PillarRow side="left" tint="#a78bfa" isLight={isLight}
|
||||
title={de ? 'RFQ-Prüfung' : 'RFQ Verification'}
|
||||
body={de
|
||||
? 'Kunden-Anforderungsdokumente automatisch gegen aktuellen Code validiert. Abweichungen erkannt, Änderungen vorgeschlagen.'
|
||||
@@ -659,7 +719,7 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
||||
</div>
|
||||
<div style={{ height: 110, display: 'flex', alignItems: 'center' }}>
|
||||
<div style={{ width: '100%' }}>
|
||||
<PillarRow side="left" tint="#c084fc"
|
||||
<PillarRow side="left" tint="#c084fc" isLight={isLight}
|
||||
title={de ? 'Prozess-Compliance' : 'Process Compliance'}
|
||||
body={de
|
||||
? 'Vom Audit-Finding bis zur Code-Änderung vollständig automatisiert. Rollen, Fristen, Eskalation — End-to-End verwaltet.'
|
||||
@@ -679,18 +739,18 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
||||
onMouseEnter={e => { (e.currentTarget as HTMLDivElement).style.transform = 'scale(1.05)'; (e.currentTarget as HTMLDivElement).style.filter = 'brightness(1.15)' }}
|
||||
onMouseLeave={e => { (e.currentTarget as HTMLDivElement).style.transform = 'scale(1)'; (e.currentTarget as HTMLDivElement).style.filter = 'brightness(1)' }}
|
||||
>
|
||||
<CentralHub caption={de ? 'Immer in Sync' : 'Always in sync'} />
|
||||
<CentralHub caption={de ? 'Immer in Sync' : 'Always in sync'} isLight={isLight} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* RIGHT — Code */}
|
||||
<div style={{ display: 'flex', flexDirection: 'column', paddingLeft: 20 }}>
|
||||
<div style={{ height: 40, marginBottom: 36 }}>
|
||||
<ColHeader side="right" label="Code" color="#fbbf24" icon="⟨/⟩" sub="sast · dast · sbom" />
|
||||
<ColHeader side="right" label="Code" color="#fbbf24" icon="⟨/⟩" sub="sast · dast · sbom" isLight={isLight} />
|
||||
</div>
|
||||
<div style={{ height: 110, display: 'flex', alignItems: 'center' }}>
|
||||
<div style={{ width: '100%' }}>
|
||||
<PillarRow side="right" tint="#fbbf24"
|
||||
<PillarRow side="right" tint="#fbbf24" isLight={isLight}
|
||||
title={de ? 'Bidirektional' : 'Bidirectional Sync'}
|
||||
body={de
|
||||
? 'Compliance-Änderungen fliessen in Code; Code-Änderungen aktualisieren Docs. Beide Seiten immer synchron — kein Informationsverlust.'
|
||||
@@ -702,7 +762,7 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
||||
</div>
|
||||
<div style={{ height: 110, display: 'flex', alignItems: 'center' }}>
|
||||
<div style={{ width: '100%' }}>
|
||||
<PillarRow side="right" tint="#f59e0b"
|
||||
<PillarRow side="right" tint="#f59e0b" isLight={isLight}
|
||||
title={de ? 'Kontinuierlich' : 'Continuous, Not Yearly'}
|
||||
body={de
|
||||
? 'Klassische Audits einmal jährlich — wir prüfen bei jedem Commit. Findings werden sofort zu Tickets mit konkreten Fixes.'
|
||||
@@ -719,16 +779,17 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
||||
{/* Under the Hood */}
|
||||
<div style={{ position: 'relative', zIndex: 2, padding: '0 48px 16px' }}>
|
||||
<div style={{
|
||||
...MONO, fontSize: 9.5, letterSpacing: 3.5, color: 'rgba(167,139,250,.7)',
|
||||
...MONO, fontSize: 9.5, letterSpacing: 3.5,
|
||||
color: isLight ? 'rgba(109,77,194,.7)' : 'rgba(167,139,250,.7)',
|
||||
textTransform: 'uppercase', fontWeight: 600, textAlign: 'center', marginBottom: 12,
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 14,
|
||||
}}>
|
||||
<span style={{ width: 80, height: 1, background: 'linear-gradient(90deg, transparent, rgba(167,139,250,.5))' }} />
|
||||
<span style={{ width: 80, height: 1, background: isLight ? 'linear-gradient(90deg, transparent, rgba(109,77,194,.4))' : 'linear-gradient(90deg, transparent, rgba(167,139,250,.5))' }} />
|
||||
{de ? 'Unter der Haube' : 'Under the Hood'}
|
||||
<span style={{ width: 80, height: 1, background: 'linear-gradient(270deg, transparent, rgba(167,139,250,.5))' }} />
|
||||
<span style={{ width: 80, height: 1, background: isLight ? 'linear-gradient(270deg, transparent, rgba(109,77,194,.4))' : 'linear-gradient(270deg, transparent, rgba(167,139,250,.5))' }} />
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12 }}>
|
||||
<FeatureCard tint="#a78bfa" icon="⇄"
|
||||
<FeatureCard tint="#a78bfa" icon="⇄" isLight={isLight}
|
||||
title={de ? 'End-to-End Rückverfolgbarkeit' : 'End-to-End Traceability'}
|
||||
body={de
|
||||
? 'Regulatorische Anforderungen deterministisch mit Code und System verknüpft — inklusive revisionssicherem Evidence-Layer.'
|
||||
@@ -737,7 +798,7 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
||||
active={detail?.title === details.trace.title}
|
||||
Ticker={TickTrace}
|
||||
/>
|
||||
<FeatureCard tint="#c084fc" icon="◉"
|
||||
<FeatureCard tint="#c084fc" icon="◉" isLight={isLight}
|
||||
title={de ? 'Continuous Compliance Engine' : 'Continuous Compliance Engine'}
|
||||
body={de
|
||||
? 'Automatische Audit-Validierung bei jeder Änderung — Code, Infrastruktur, Prozesse.'
|
||||
@@ -746,7 +807,7 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
||||
active={detail?.title === details.engine.title}
|
||||
Ticker={TickEngine}
|
||||
/>
|
||||
<FeatureCard tint="#fbbf24" icon="✦"
|
||||
<FeatureCard tint="#fbbf24" icon="✦" isLight={isLight}
|
||||
title={de ? 'Compliance Optimizer' : 'Compliance Optimizer'}
|
||||
body={de
|
||||
? 'Maximale Compliance pro €. Findet den Sweet Spot zwischen Geschwindigkeit und Risiko.'
|
||||
@@ -755,7 +816,7 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
||||
active={detail?.title === details.opt.title}
|
||||
Ticker={TickOptimizer}
|
||||
/>
|
||||
<FeatureCard tint="#f59e0b" icon="◎"
|
||||
<FeatureCard tint="#f59e0b" icon="◎" isLight={isLight}
|
||||
title={de ? 'EU-Trust & Governance' : 'EU Trust & Governance'}
|
||||
body={de
|
||||
? 'DSGVO, NIS-2, DORA, EU AI Act — eine Plattform, EU-souverän.'
|
||||
@@ -771,10 +832,12 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
||||
<div style={{
|
||||
position: 'relative', zIndex: 2, margin: '0 48px 24px',
|
||||
padding: '11px 20px', borderRadius: 10,
|
||||
background: 'linear-gradient(90deg, rgba(251,191,36,.08), rgba(167,139,250,.1), rgba(139,92,246,.08))',
|
||||
border: '1px solid rgba(167,139,250,.22)',
|
||||
background: isLight
|
||||
? 'linear-gradient(90deg, rgba(251,191,36,.08), rgba(167,139,250,.08), rgba(139,92,246,.06))'
|
||||
: 'linear-gradient(90deg, rgba(251,191,36,.08), rgba(167,139,250,.1), rgba(139,92,246,.08))',
|
||||
border: `1px solid ${isLight ? 'rgba(167,139,250,.2)' : 'rgba(167,139,250,.22)'}`,
|
||||
textAlign: 'center', fontStyle: 'italic',
|
||||
fontSize: 12.5, color: 'rgba(236,233,247,.82)',
|
||||
fontSize: 12.5, color: isLight ? '#475569' : 'rgba(236,233,247,.82)',
|
||||
}}>
|
||||
<span style={{ color: '#fbbf24', marginRight: 8, fontSize: 16, verticalAlign: -2 }}>"</span>
|
||||
{de
|
||||
@@ -783,7 +846,7 @@ export default function USPSlide({ lang }: USPSlideProps) {
|
||||
<span style={{ color: '#fbbf24', marginLeft: 8, fontSize: 16, verticalAlign: -2 }}>"</span>
|
||||
</div>
|
||||
|
||||
<DetailModal item={detail} onClose={close} />
|
||||
<DetailModal item={detail} onClose={close} isLight={isLight} />
|
||||
</div>
|
||||
</FadeInView>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user