diff --git a/app/page.tsx b/app/page.tsx
index 3788d8c..a2d6d85 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -15,7 +15,15 @@ import OperationTimeline from '../src/components/landing/OperationTimeline';
import Footer from '../src/components/shared/Footer';
import FloatingContactButton from '@/src/components/landing/FloatingContactForm';
import LandingChampionshipWorks from '../src/components/landing/HowItWorks';
+import RegistrationEndingPopup from '../src/components/landing/RegistrationEndingPopup';
export default function LandingPage() {
+ const [showRegPopup, setShowRegPopup] = useState(false);
+
+ useEffect(() => {
+ const timer = setTimeout(() => setShowRegPopup(true), 3000);
+ return () => clearTimeout(timer);
+ }, []);
+
return (
{/* Blurred Satellite Background */}
@@ -72,6 +80,12 @@ export default function LandingPage() {
{/* Floating Contact Button */}
+
+ {/* Registration Ending Popup */}
+ setShowRegPopup(false)}
+ />
);
}
\ No newline at end of file
diff --git a/src/components/landing/Header.tsx b/src/components/landing/Header.tsx
index 02f6740..98f2946 100644
--- a/src/components/landing/Header.tsx
+++ b/src/components/landing/Header.tsx
@@ -319,8 +319,8 @@ const LandingHeader = () => {
{/* Content Box with Border */}
-
-
+
+
{
-
+
void;
+}
+
+const RegistrationEndingPopup: React.FC = ({ isOpen, onClose }) => {
+ const overlayRef = useRef(null);
+ const modalRef = useRef(null);
+ const progressBarRef = useRef(null);
+ const [mounted, setMounted] = useState(false);
+
+ useEffect(() => {
+ setMounted(true);
+ }, []);
+
+ useEffect(() => {
+ if (isOpen && mounted) {
+ const tl = gsap.timeline();
+
+ tl.to(overlayRef.current, {
+ opacity: 1,
+ duration: 0.4,
+ ease: 'power2.out',
+ });
+
+ tl.fromTo(modalRef.current,
+ { scaleY: 0, scaleX: 0.05, opacity: 0 },
+ { scaleY: 1, opacity: 1, duration: 0.3, ease: 'power2.inOut' }
+ )
+ .to(modalRef.current, {
+ scaleX: 1,
+ duration: 0.3,
+ ease: 'back.out(1.2)'
+ });
+
+ if (progressBarRef.current) {
+ gsap.fromTo(progressBarRef.current,
+ { width: '100%' },
+ { width: '0%', duration: 25, ease: 'none', delay: 0.6 }
+ );
+ }
+
+ const timer = setTimeout(() => {
+ handleClose();
+ }, 25600);
+
+ return () => {
+ clearTimeout(timer);
+ tl.kill();
+ };
+ }
+ }, [isOpen, mounted]);
+
+ const handleClose = () => {
+ const tl = gsap.timeline({ onComplete: onClose });
+ tl.to(modalRef.current, { scale: 0.85, opacity: 0, y: 30, duration: 0.3, ease: 'power2.in' })
+ .to(overlayRef.current, { opacity: 0, duration: 0.3 }, '<');
+ };
+
+ if (!isOpen || !mounted) return null;
+
+ return createPortal(
+
+
+
+
+
+
+ {/* Timer bar */}
+
+
+ {/* Close button */}
+
+
+ {/* Content */}
+
+
+ Registration Ends Soon!
+
+
+
+ Last chance to secure your spot and compete in the CTF.
+
+
+
+ π
+ Qualifiers: 20thβ21st June
+
+
+
+ Sign Up Now π
+
+
+
+ {/* Corner brackets */}
+
+
+
+
+
+
+
+
,
+ document.body
+ );
+};
+
+export default RegistrationEndingPopup;
diff --git a/src/components/shared/GlitchText.tsx b/src/components/shared/GlitchText.tsx
index 4ba8c98..154a57f 100644
--- a/src/components/shared/GlitchText.tsx
+++ b/src/components/shared/GlitchText.tsx
@@ -62,28 +62,22 @@ const GlitchText = ({ text, className = "", delay = 0, strikethrough = false, tr
}, [started, text, triggerOnView]);
return (
-
+
- {/* Invisible spacer to reserve layout space */}
-
- {text}
-
-
- {/* Overlay for the actual effect */}
-
- {!typingComplete ? (
-
- {displayText}
- |
-
- ) : (
-
- {text}
-
- )}
-
+ {!typingComplete ? (
+
+ {displayText}
+ |
+
+ ) : (
+
+ {text}
+
+ )}
{/* Strikethrough Lines */}
{strikethrough && (