The page is RTL, so the oversized flex track's natural (untransformed) box wasn't left-aligned with its container the way the 0%->-50% keyframe math assumed. Halfway through the loop, translateX(-50%) was scrolling past all the actual image content into empty space beyond the track, showing a fully blank marquee for part of every cycle.
Force direction:ltr on .achv-marquee so the track lays out and scrolls the same predictable way regardless of page direction. Verified: track's left edge now matches the container's left edge at rest, and the duplicate set's first image lands exactly where the original one started, so the loop is seamless.
Add explicit width/height attributes to every marquee image so the browser reserves the correct aspect-ratio box immediately from HTML parse time, instead of waiting for each image's bytes to arrive. Previously (CSS height:260px;width:auto only) any image not yet fully downloaded rendered at ~0 width, making the animated track look like one image followed by a large empty gap until everything finished loading.
Remove loading="lazy" from marquee images — since the carousel moves images via CSS transform (not real scroll), the browser's lazy-load viewport check never fired for the off-screen duplicate set, leaving a blank gap right before the loop seam.
- Add live Google Maps rating badge (4.8, 395 reviews) above testimonials
- Convert 12 testimonial cards from a stacked grid into a single-card auto-advancing slider with nav arrows and dots
- Convert achievements gallery from a static grid into a continuous horizontal marquee with edge fade and hover-to-pause