diff --git a/docker/frontend/src/Landing.tsx b/docker/frontend/src/Landing.tsx index 05a8a0c..4c3a37b 100644 --- a/docker/frontend/src/Landing.tsx +++ b/docker/frontend/src/Landing.tsx @@ -317,6 +317,27 @@ export function Landing() { [photos], ); + // The marquee loops by translating half the track, so one half has to be at + // least as wide as the window: a reel too short for the screen runs out of + // frames before the loop restarts, and the band on the right goes blank until + // the next pass arrives. Lay out one pass, then repeat the reel until a half + // covers the window — and again on resize, which changes what "covers" means. + const track = useRef(null); + const [reelCopies, setReelCopies] = useState(1); + useEffect(() => { + const el = track.current; + const fan = el?.querySelector('.lp-frame'); + if (!el || !fan || !reel.length) return; + const pitch = fan.getBoundingClientRect().width + (parseFloat(getComputedStyle(fan).marginRight) || 0); + if (pitch <= 0) return; + const view = () => el.parentElement?.clientWidth || window.innerWidth; + const fit = () => setReelCopies(Math.max(1, Math.ceil(view() / (reel.length * pitch)))); + fit(); + window.addEventListener('resize', fit); + return () => window.removeEventListener('resize', fit); + }, [reel]); + const loop = useMemo(() => Array.from({ length: reelCopies }, () => reel).flat(), [reel, reelCopies]); + // The three live sections, each cycling the stills the curator tagged for its // slot. Every set is drawn from a random start once per page load, so the // preview does not change under the visitor's eyes on every render; a slot @@ -643,8 +664,8 @@ export function Landing() {

{c({ en: 'Every still here is picked and placed by the studio — this reel is curated, not crowd-sourced.', vi: 'Mọi khung ảnh ở đây đều do studio chọn và đặt — dải phim này được tuyển chọn, không phải ai cũng tự thêm được.' })}

-
- {[...reel, ...reel].map((look, i) => { +
+ {[...loop, ...loop].map((look, i) => { const score = ratings[look.rateKey] ?? { avg: 0, n: 0, mine: 0 }; return (