diff --git a/app/[locale]/page.tsx b/app/[locale]/page.tsx index 72e2f9d..d71ecd3 100644 --- a/app/[locale]/page.tsx +++ b/app/[locale]/page.tsx @@ -2,7 +2,7 @@ import { Link } from '@/src/i18n/navigation' import Image from 'next/image' import { getAllPosts } from '@/lib/markdown' import { formatDate } from '@/lib/utils' -import { ThemeToggle } from '@/components/theme-toggle' +import { HeroHeader } from '@/components/layout/hero-header' import { setRequestLocale, getTranslations } from 'next-intl/server' type Props = { @@ -29,29 +29,11 @@ export default async function HomePage({ params }: Props) {
diff --git a/app/globals.css b/app/globals.css index 7d82f03..3340151 100644 --- a/app/globals.css +++ b/app/globals.css @@ -449,3 +449,83 @@ margin-bottom: 3rem; } } + +/* === MOBILE RESPONSIVE UTILITIES === */ +@media (max-width: 767px) { + .show-mobile-only { + display: block; + } + .hide-mobile { + display: none !important; + } +} + +@media (min-width: 768px) { + .show-mobile-only { + display: none !important; + } + .hide-mobile { + display: block; + } +} + +/* === BUTTON GLITCH EFFECT === */ +@layer utilities { + .glitch-btn-cyber { + --glitch-shimmy: 5; + --glitch-clip-1: polygon(0 2%, 100% 2%, 100% 95%, 95% 95%, 95% 90%, 85% 90%, 85% 95%, 8% 95%, 0 70%); + --glitch-clip-2: polygon(0 78%, 100% 78%, 100% 100%, 95% 100%, 95% 90%, 85% 90%, 85% 100%, 8% 100%, 0 78%); + --glitch-clip-3: polygon(0 44%, 100% 44%, 100% 54%, 95% 54%, 95% 54%, 85% 54%, 85% 54%, 8% 54%, 0 54%); + --glitch-clip-4: polygon(0 0, 100% 0, 100% 0, 95% 0, 95% 0, 85% 0, 85% 0, 8% 0, 0 0); + --glitch-clip-5: polygon(0 40%, 100% 40%, 100% 85%, 95% 85%, 95% 85%, 85% 85%, 85% 85%, 8% 85%, 0 70%); + --glitch-clip-6: polygon(0 63%, 100% 63%, 100% 80%, 95% 80%, 95% 80%, 85% 80%, 85% 80%, 8% 80%, 0 70%); + } + + .glitch-overlay { + position: absolute; + inset: 0; + display: none; + align-items: center; + justify-content: center; + pointer-events: none; + color: var(--neon-cyan); + z-index: 10; + } + + .glitch-btn-cyber:is(:hover, :focus-visible) .glitch-overlay { + display: flex; + animation: glitch-btn-animate 2s infinite; + } + + @keyframes glitch-btn-animate { + 0% { clip-path: var(--glitch-clip-1); } + 2%, 8% { clip-path: var(--glitch-clip-2); transform: translate(calc(var(--glitch-shimmy) * -1%), 0); } + 6% { clip-path: var(--glitch-clip-2); transform: translate(calc(var(--glitch-shimmy) * 1%), 0); } + 9% { clip-path: var(--glitch-clip-2); transform: translate(0, 0); } + 10% { clip-path: var(--glitch-clip-3); transform: translate(calc(var(--glitch-shimmy) * 1%), 0); } + 13% { clip-path: var(--glitch-clip-3); transform: translate(0, 0); } + 14%, 21% { clip-path: var(--glitch-clip-4); transform: translate(calc(var(--glitch-shimmy) * 1%), 0); } + 25%, 30% { clip-path: var(--glitch-clip-5); transform: translate(calc(var(--glitch-shimmy) * -1%), 0); } + 35%, 45% { clip-path: var(--glitch-clip-6); transform: translate(calc(var(--glitch-shimmy) * -1%), 0); } + 40% { clip-path: var(--glitch-clip-6); transform: translate(calc(var(--glitch-shimmy) * 1%), 0); } + 50% { clip-path: var(--glitch-clip-6); transform: translate(0, 0); } + 55% { clip-path: var(--glitch-clip-3); transform: translate(calc(var(--glitch-shimmy) * 1%), 0); } + 60% { clip-path: var(--glitch-clip-3); transform: translate(0, 0); } + 61%, 100% { clip-path: var(--glitch-clip-4); } + } + + .glitch-btn-subtle { + --glitch-shimmy: 2; + } + + .glitch-overlay-pink { color: var(--neon-pink); } + .glitch-overlay-purple { color: var(--neon-purple); } + .glitch-overlay-magenta { color: var(--neon-magenta); } + + @media (prefers-reduced-motion: reduce) { + .glitch-btn-cyber:is(:hover, :focus-visible) .glitch-overlay { + animation: none; + display: none; + } + } +} diff --git a/components/blog/navbar.tsx b/components/blog/navbar.tsx index d226c3d..476a7c0 100644 --- a/components/blog/navbar.tsx +++ b/components/blog/navbar.tsx @@ -5,11 +5,13 @@ import { useTranslations } from 'next-intl' import { Link } from '@/i18n/navigation' import { ThemeToggle } from '@/components/theme-toggle' import LanguageSwitcher from '@/components/layout/LanguageSwitcher' +import { GlitchButton } from '@/components/effects/glitch-button' export function Navbar() { const t = useTranslations('Navigation') const [isVisible, setIsVisible] = useState(true) const [lastScrollY, setLastScrollY] = useState(0) + const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false) useEffect(() => { const handleScroll = () => { @@ -19,6 +21,7 @@ export function Navbar() { setIsVisible(true) } else if (currentScrollY > lastScrollY) { setIsVisible(false) + setIsMobileMenuOpen(false) } else { setIsVisible(true) } @@ -44,11 +47,12 @@ export function Navbar() { > < {t('home')} - + // {t('blog')} ARCHIVE