Composes
scrolling-index-dual-rail(the layout + scroll mechanic)active-row-darken(the focus shift as rows cross center)inner-video-playback(looping video clips inside media thumbnails)persistent-corner-chrome(brand tag bottom-left)
Renderer
hyperframe-gsap by default. Remotion can do it but HTML+GSAP+real video gives more realistic scroll velocity and inner-video playback.
Layout
canvas: viewport-style (often 16:9 or square)
viewport_container: position: centered, with bleed top/bottom border_radius: 40 border: 1px outline (ink color)
text_rail: position: left 40% of viewport align: right # right-aligned to vertical gutter at 38% canvas_w font_family: editorial serif italic (e.g. Cormorant Garamond) font_size: 56 line_height: 96
media_rail: position: right 50% of viewport thumbnail_size: 320 × 400 # 4:5 thumbnail_radius: 16 thumbnail_gap: 24 visible_count: 3
fade_masks: top_pct: 0.08 bottom_pct: 0.08
## Choreography
```yaml
scroll_velocity_px_per_sec: 60
direction: bottom-to-top
easing: linear
loop: optional
per_row_focus:
focal_y: canvas_h / 2
distance_for_50_opacity_px: 96
distance_for_full_dim_px: 240
min_opacity: 0.18
active_font_weight: 600 # bumps from 400 base when focal
inner_video_playback:
per_thumbnail_mp4: required
mute: true
loop: true
Style pack compatibility
supported: [SP-D]
preferred_in: [SP-D]
incompatible: [SP-A, SP-B, SP-C, SP-E, SP-F, SP-G]
This is exclusively SP-D's archetype — editorial-magazine pack.
Pack-specific overrides
SP-D (editorial-magazine)
- Off-white bg, ink text.
- Cormorant Garamond Italic for list titles.
- Corner brand tag bottom-left ("SESSIONS").
- Soft fade-mask at top + bottom of viewport.
Duration
duration_seconds: [10.0, 30.0+]
notes: this archetype is usually the ENTIRE spot, not one scene of many.
Driven by list_length × per_row_seconds_to_cross_focal (~1.5s per row).
Quality Checks
- Scroll velocity constant.
- Active-row darkens as it approaches focal y; restores as it leaves.
- Inner thumbnails are REAL playing video, not static images.
- Fade masks render — content fades cleanly at viewport edges.
- Brand corner-chrome renders at frame 0 and last frame.
Failure Modes
- Scroll feels janky. Velocity isn't truly linear. Use direct
transform: translateYwithuseCurrentFrame(). - Active row doesn't dim adjacent rows. Focus mechanic broken. Verify opacity ramp on per-row distance from focal_y.
- Thumbnails are static images. Pack source mp4s for each thumbnail and verify
<video autoplay loop muted>in the HTML. - Viewport border doesn't render. CSS outline got stripped — use explicit
borderon the viewport container.