diff --git a/public/discord-logo.png b/public/discord-logo.png new file mode 100644 index 0000000..6dac7a4 Binary files /dev/null and b/public/discord-logo.png differ diff --git a/public/signal-logo.png b/public/signal-logo.png new file mode 100644 index 0000000..f545e20 Binary files /dev/null and b/public/signal-logo.png differ diff --git a/src/App.css b/src/App.css index 110d560..d2bab7e 100644 --- a/src/App.css +++ b/src/App.css @@ -131,3 +131,121 @@ body { color: rgba(255, 255, 255, 0.7); font-size: 1rem; } + +.animated-paragraph { + font-size: 1.15rem; + color: #e0e0e0; + margin: 24px 0 32px 0; + text-align: center; + max-width: 600px; + margin-left: auto; + margin-right: auto; + letter-spacing: 0.01em; + line-height: 1.6; +} + +.animated-paragraph .cursor { + display: inline-block; + width: 0.5em; + height: 1.2em; + background-color: #e0e0e0; + margin-left: 2px; + animation: blink 1s step-end infinite; + vertical-align: middle; +} + +.modal-backdrop { + position: fixed; + top: 0; left: 0; right: 0; bottom: 0; + background: rgba(0,0,0,0.7); + z-index: 1000; + display: flex; + align-items: center; + justify-content: center; +} + +.modal-content { + background: rgba(35, 39, 47, 0.85); + border-radius: 16px; + padding: 32px 24px 24px 24px; + box-shadow: 0 8px 32px rgba(0,0,0,0.45); + position: relative; + min-width: 340px; + max-width: 380px; + width: 100%; + max-height: 90vh; + display: flex; + flex-direction: column; + align-items: center; + border: 1.5px solid rgba(255,255,255,0.12); + backdrop-filter: blur(16px); + -webkit-backdrop-filter: blur(16px); +} + +.modal-image { + max-width: 320px; + width: 100%; + height: auto; + border-radius: 12px; + margin-bottom: 16px; + background: #fff; +} + +.modal-caption { + color: #e0e0e0; + font-size: 1.1rem; + margin-top: 8px; + text-align: center; +} + +.modal-close { + position: absolute; + top: 12px; + right: 16px; + background: none; + border: none; + font-size: 2rem; + color: #aaa; + cursor: pointer; + transition: color 0.2s; +} + +.modal-close:hover { + color: #EA4335; +} + +.discord-tag-row { + display: flex; + align-items: center; + gap: 1rem; + justify-content: center; + margin-top: 8px; +} + +.discord-tag { + font-size: 1.3rem; + font-family: 'Courier New', monospace; + color: #e0e0e0; + background: #23272f; + padding: 6px 16px; + border-radius: 8px; + border: 1px solid #5865F2; + letter-spacing: 0.03em; +} + +.copy-btn { + background: #5865F2; + color: #fff; + border: none; + border-radius: 6px; + padding: 6px 16px; + font-size: 1rem; + cursor: pointer; + transition: background 0.2s, color 0.2s; + font-family: inherit; +} + +.copy-btn:hover, .copy-btn:focus { + background: #4752c4; + color: #fff; +} diff --git a/src/App.tsx b/src/App.tsx index 6365c2b..fe65d06 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,7 @@ import './App.css' import { useState, useEffect } from 'react' -function TypeWriter({ text }: { text: string }) { +function TypeWriter({ text, onComplete }: { text: string, onComplete: () => void }) { const [displayText, setDisplayText] = useState('') const [currentIndex, setCurrentIndex] = useState(0) @@ -10,10 +10,12 @@ function TypeWriter({ text }: { text: string }) { const timeout = setTimeout(() => { setDisplayText(prev => prev + text[currentIndex]) setCurrentIndex(prev => prev + 1) - }, 100) + }, 200) return () => clearTimeout(timeout) + } else { + onComplete() } - }, [currentIndex, text]) + }, [currentIndex, text, onComplete]) return (
+ {displayText} + {isTyping && } +
+ ) +} + +function SocialCard({ title, icon, description, href, onClick }: { title: string, icon: string, description: string, - href: string + href: string, + onClick?: () => void }) { return ( - + { if (onClick) { e.preventDefault(); onClick(); } }}>
+
+