"use client"; import { useRef, useLayoutEffect, useEffect, useState, useCallback } from "react"; import gsap from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; if (typeof window !== "undefined") { gsap.registerPlugin(ScrollTrigger); } export default function AboutSection() { const sectionRef = useRef(null); const clippedContentRef = useRef(null); const headerWrapperRef = useRef(null); const heroLine1Ref = useRef(null); const heroLine2Ref = useRef(null); const storyBlock1Ref = useRef(null); const storyBlock2Ref = useRef(null); const stripsWrapperRef = useRef(null); const [mounted, setMounted] = useState(false); const [isMobile, setIsMobile] = useState(false); // --- Hover reveal circle --- const revealAreaRef = useRef(null); const revealRef = useRef(null); const circlePos = useRef({ x: -300, y: -300 }); const currentPos = useRef({ x: -300, y: -300 }); const isHovering = useRef(false); const circleSize = 300; const handleMouseMove = useCallback((e: React.MouseEvent) => { const rect = revealAreaRef.current?.getBoundingClientRect(); if (!rect) return; circlePos.current = { x: e.clientX - rect.left, y: e.clientY - rect.top, }; isHovering.current = true; }, []); const handleMouseLeave = useCallback(() => { isHovering.current = false; }, []); // Smooth animation loop for the reveal circle useEffect(() => { let animId: number; const animate = () => { const reveal = revealRef.current; if (!reveal) { animId = requestAnimationFrame(animate); return; } currentPos.current.x += (circlePos.current.x - currentPos.current.x) * 0.12; currentPos.current.y += (circlePos.current.y - currentPos.current.y) * 0.12; const x = currentPos.current.x; const y = currentPos.current.y; const r = isHovering.current ? circleSize / 2 : 0; reveal.style.clipPath = `circle(${r}px at ${x}px ${y}px)`; animId = requestAnimationFrame(animate); }; animId = requestAnimationFrame(animate); return () => cancelAnimationFrame(animId); }, []); useEffect(() => { setMounted(true); const checkMobile = () => setIsMobile(window.innerWidth < 768); checkMobile(); window.addEventListener('resize', checkMobile); return () => window.removeEventListener('resize', checkMobile); }, []); useLayoutEffect(() => { if (!mounted) return; const isMobile = window.innerWidth < 768; const insetX = isMobile ? "6%" : "14%"; const radius = isMobile ? "16px" : "28px"; const ctx = gsap.context(() => { gsap.fromTo( clippedContentRef.current, { clipPath: `inset(0 ${insetX} 0 ${insetX} round ${radius})`, }, { clipPath: "inset(0 0% 0 0% round 0px)", ease: "power2.inOut", scrollTrigger: { trigger: sectionRef.current, start: "top 85%", end: "top 5%", scrub: 0.6, }, } ); gsap.to(".about-header-marquee", { xPercent: -50, repeat: -1, duration: 20, ease: "linear", }); gsap.to(".about-strip-1-marquee", { xPercent: -50, repeat: -1, duration: 25, ease: "linear", }); gsap.fromTo(".about-strip-2-marquee", { xPercent: -50 }, { xPercent: 0, repeat: -1, duration: 25, ease: "linear", } ); gsap.set(headerWrapperRef.current, { opacity: 0, y: 30 }); gsap.set(heroLine1Ref.current, { opacity: 0, y: 100, filter: "blur(10px)" }); gsap.set(heroLine2Ref.current, { opacity: 0, y: 100, filter: "blur(10px)" }); gsap.set(storyBlock1Ref.current, { opacity: 0, x: -100, filter: "blur(8px)" }); gsap.set(storyBlock2Ref.current, { opacity: 0, x: 100, filter: "blur(8px)" }); gsap.set(stripsWrapperRef.current, { opacity: 0, y: 60 }); gsap.to(headerWrapperRef.current, { opacity: 1, y: 0, ease: "power2.out", scrollTrigger: { trigger: sectionRef.current, start: "top 90%", end: "top 50%", scrub: 0.3, }, }); const tl = gsap.timeline({ scrollTrigger: { trigger: sectionRef.current, start: "top top", end: isMobile ? "+=900" : "+=1500", scrub: 1, pin: true, anticipatePin: 1, pinSpacing: true, }, }); tl.to(heroLine1Ref.current, { opacity: 1, y: 0, filter: "blur(0px)", duration: 0.25, ease: "power3.out" }, 0); tl.to(heroLine2Ref.current, { opacity: 1, y: 0, filter: "blur(0px)", duration: 0.25, ease: "power3.out" }, 0.15); tl.to(storyBlock1Ref.current, { opacity: 1, x: 0, filter: "blur(0px)", duration: 0.25, ease: "power3.out" }, 0.35); tl.to(storyBlock2Ref.current, { opacity: 1, x: 0, filter: "blur(0px)", duration: 0.25, ease: "power3.out" }, 0.50); tl.to(stripsWrapperRef.current, { opacity: 1, y: 0, duration: 0.25, ease: "power3.out" }, 0.70); }, sectionRef); return () => ctx.revert(); }, [mounted]); const marqueeText = "DATA SCIENTIST ✦ PYTHON BACKEND DEVELOPER ✦ AI ENTHUSIAST ✦ PROBLEM SOLVER ✦ "; const strip1Text = "★ Driven by Curiosity, Powered by Data ★ Machine Learning Solutions ★ Predictive Analytics ★ AI-Driven Insights ★ "; const strip2Text = "★ Data Quality ★ Model Accuracy ★ Scalable Pipelines ★ Statistical Analysis ★ Deep Learning ★ Python Engineering ★ "; return (
{/* Clipped content — clip-path creates the expanding box effect */}
{/* Subtle top edge glow inside the clipped box */}
{/* Content */}
{/* Large Header Marquee Banner */}
{marqueeText.repeat(6)}
{/* Hero + Story area — this is where the reveal mask lives */}
{/* Normal layer (white text on dark bg) */}

I extract insights that

drive real decisions

My Journey

Started as a curious teenager exploring datasets, I've evolved into a data scientist who obsesses over every feature and every decimal of model accuracy.

My Approach

I believe the best data solutions are the ones that speak for themselves—clear insights, actionable results, and decisions backed by evidence.

{/* Reveal layer (black text on white bg) — different alternate text */}

I build models that

transform raw data

The Spark

What started as late-night experiments turned into a lifelong obsession with uncovering patterns, building models, and letting data tell its story.

The Philosophy

Great analysis is invisible—it removes noise, reveals clarity, and makes complex data feel wonderfully simple.

{/* Diagonal Crossing Strips */}
{strip1Text.repeat(15)}
{strip2Text.repeat(15)}
); }