"use client"; import { useCallback, useEffect, useState, type CSSProperties } from "react"; import { MoreSection, PROFILE } from "@/data/content"; import { useFullBleed, usePrefersReducedMotion } from "@/hooks/useAnimations"; import "@/styles/more-section.css"; function useThresholdTint(ref: React.RefObject) { useEffect(() => { const el = ref.current; if (!el) return; const root = document.documentElement; const publish = () => { const rect = el.getBoundingClientRect(); // The rule sits at the element's vertical centre. const y = rect.top + window.scrollY + rect.height / 2; root.style.setProperty("--threshold-y", `${Math.round(y)}px`); }; publish(); const observer = new ResizeObserver(publish); observer.observe(root); observer.observe(el); return () => { observer.disconnect(); root.style.removeProperty("--threshold-y"); }; }, [ref]); } /** Per-section stagger once the threshold opens. */ const STAGGER_MS = 90; export default function ProfileMore() { const [open, setOpen] = useState(false); const [armed, setArmed] = useState(false); const reducedMotion = usePrefersReducedMotion(); const { ref: bleedRef, style: bleedStyle } = useFullBleed(); useThresholdTint(bleedRef); const start = PROFILE.moreSectionsStart ?? 0; const above = PROFILE.moreSections.slice(0, start); const below = PROFILE.moreSections.slice(start); const cross = useCallback((e: any) => { if(e.pointerType=='touch'){ return; } setArmed(true); setOpen(true); }, []); const toggle = useCallback(() => { setArmed(true); setOpen((prev) => !prev); }, []); if (below.length === 0) { return ( <> {above.map((item, i) => (
))} ); } return (
{above.map((item, i) => (
))} {/* The threshold. The rule sits at this box's vertical centre, and the rule and glow bleed to the viewport edges via the measured offset. Entering the band at all is what counts as crossing it. */}
{/* Everything below the line, revealed in one motion. */}
{below.map((item, i) => (
))}
); } function Section({ item, revealed = false, style, }: { item: MoreSection; revealed?: boolean; style?: CSSProperties; }) { return (
{item.title && (

{item.title}

)}

{item.text}

); }