feat(web): restore tall hero + carousel slide + viewport-fixed scroll cue
All checks were successful
Deploy to Production / deploy (push) Successful in 1m0s
All checks were successful
Deploy to Production / deploy (push) Successful in 1m0s
Three coordinated tweaks to the landing-page above-the-fold: 1. **Hero padding restored to py-14/sm:py-20/md:py-28** (was py-12/14/16). Compressing it for the scroll-cue position fight made the hero feel cramped and gave the ParticleHero background less room to breathe. With the cue moved out (see #3), there's no reason to shrink the hero. 2. **Step rotator switches to carousel-style horizontal slide.** The AnimatePresence transition was a fade+y-shift cross-fade — clean but sequential. Now the leaving card slides left out (x:-220) while the entering card slides right in (x:220→0), both coexisting in the same 3D-space and inheriting the same mouse-tilt. The container gets `min-h-[240px]` so the absolutely-positioned cards have layout to anchor to (claude_desktop_config.json is the tallest at 7 lines). Reduced-motion still gets the opacity-only cross-fade — sliding content sideways is exactly the kind of motion that preference is meant to suppress. 3. **`<ScrollCue>` extracted into its own client component**, fixed- positioned at viewport bottom (bottom-5) with a frosted pill style. Fades to opacity:0 once `window.scrollY > 80`, so it doesn't shadow the rest of the page. Lives next to `<section>` in page.tsx rather than inside the hero — that way it anchors to the loadscreen's natural bottom edge whether the hero is short or tall. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -109,23 +109,38 @@ export function HeroStepRotator() {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center gap-5">
|
||||
{/* Container is relative + has a min-height so the absolutely-
|
||||
positioned cards inside (during the slide) overlap cleanly
|
||||
without collapsing the layout. min-h is sized for the tallest
|
||||
card (claude_desktop_config.json at 7 lines). */}
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="relative w-full max-w-md"
|
||||
className="relative w-full max-w-md min-h-[240px]"
|
||||
style={{ perspective: 1200 }}
|
||||
onMouseEnter={onEnter}
|
||||
onMouseLeave={onLeave}
|
||||
onMouseMove={onMove}
|
||||
>
|
||||
<AnimatePresence mode="wait" initial={false}>
|
||||
<AnimatePresence initial={false}>
|
||||
<motion.div
|
||||
key={step}
|
||||
initial={reduced ? { opacity: 0 } : { opacity: 0, scale: 0.96, y: 12 }}
|
||||
animate={reduced ? { opacity: 1 } : { opacity: 1, scale: 1, y: 0 }}
|
||||
exit={reduced ? { opacity: 0 } : { opacity: 0, scale: 0.97, y: -8 }}
|
||||
transition={{ duration: reduced ? 0.15 : 0.5, ease: [0.16, 1, 0.3, 1] }}
|
||||
style={{ rotateX, rotateY, transformStyle: 'preserve-3d' }}
|
||||
className="relative overflow-hidden rounded-lg border border-[--color-border-strong] bg-[--color-bg-elevated] shadow-2xl shadow-black/50"
|
||||
// Carousel: current card slides left-out, next slides right-in.
|
||||
// Both cards coexist briefly in the same 3D-space and inherit
|
||||
// the same tilt — reads as a single tile that's swapping its
|
||||
// contents, not two discrete tiles. Reduced-motion collapses
|
||||
// the slide to a plain opacity cross-fade.
|
||||
initial={reduced ? { opacity: 0 } : { x: 220, opacity: 0 }}
|
||||
animate={reduced ? { opacity: 1 } : { x: 0, opacity: 1 }}
|
||||
exit={reduced ? { opacity: 0 } : { x: -220, opacity: 0 }}
|
||||
transition={{ duration: reduced ? 0.15 : 0.55, ease: [0.16, 1, 0.3, 1] }}
|
||||
style={{
|
||||
rotateX,
|
||||
rotateY,
|
||||
position: 'absolute',
|
||||
inset: 0,
|
||||
transformStyle: 'preserve-3d',
|
||||
}}
|
||||
className="overflow-hidden rounded-lg border border-[--color-border-strong] bg-[--color-bg-elevated] shadow-2xl shadow-black/50"
|
||||
>
|
||||
{/* Cursor-following glow — sits behind the content, additive. */}
|
||||
<motion.div
|
||||
|
||||
Reference in New Issue
Block a user