레이아웃
바깥 래퍼에 (섹션 수 + 1) 100vh 높이를 주어 문서 스크롤 거리를 확보하고, 안쪽은 h-screen과 sticky top-0으로 뷰포트에 고정된 한 장면처럼 보이게 했습니다. 각 섹션은 같은 위치에 absolute로 겹쳐 두고, activeIndex에 맞는 레이어만 불투명도 전환으로 노출합니다. 문서의 scrollY와 래퍼의 문서 기준 topbottom을 비교해, 구간 밖이면 첫/마지막 섹션을 유지하고 구간 안에서는 뷰포트 높이 단위로 인덱스를 나눕니다. 마지막 섹션은 한 칸 더 길게 잡아 스크롤 끝에서도 장면이 유지되도록 했습니다. 스크롤 핸들러는 requestAnimationFrame으로 한 프레임에 한 번만 계산하도록 묶었습니다.
하이드레이션
react-responsive의 useMediaQuery는 서버와 클라이언트 첫 결과가 어긋날 수 있어, mounted 이후에만 데스크톱 전용 높이와 스크롤 리스너를 켜서 React 하이드레이션 경고를 피했습니다.
모바일좁은 화면
이 프로젝트는 Tailwind max-width 변형을 쓰므로, hidden lg:flex 등으로 좁은 뷰에서는 세로 스택만 보이게 분기했습니다. 스크롤 연동 페이드는 넓은 화면 전용입니다.