MOTION PALETTE
← すべてのデモ

VHS Rewind

ScrollCanvas / GSAP / ScrollTrigger / CSS / WebP

フルスクリーンで開く ↗

枠の中でスクロール・クリックして動きを試せます。端末指定は実寸表示です。幅が足りない場合は横にスクロールできます。

再現プロンプト

架空のレンタルビデオ店サイト。走査線とトラッキングノイズが常に画面を覆い、セクションの切り替わりはノイズ帯が走る「巻き戻し」演出で表現され、左上のOSDがスクロール位置をタイムコードとして表示する。 配色・構成・動きの数値をまとめた指示書です。 お使いのAIに貼り、素材やお店の情報を伝えて実装してください。仕上がりは利用するAIと素材によって変わります。

Build a single self-contained HTML file (inline CSS/JS; GSAP + ScrollTrigger from a CDN is the only allowed dependency, no external network images or video — the only image assets are the 12 local WebP files described in Imagery, and every element must degrade gracefully to its gradient fallback if they are missing) for "REWIND ROOM VIDEO CLUB", a fictional rental store and late-night broadcast archive. The whole page is presented as if watched through a worn VHS deck: persistent scanlines and a drifting tracking-noise band sit over every section, a top-left on-screen display (OSD) reads scroll position as a deck timecode, section boundaries are crossed through "rewind" transitions, and the page boots with a color-bars-then-static power-on sequence. There is NO scroll-velocity-driven RGB channel split anywhere (that belongs to a different page in this series) — any chromatic fringing is a single static text-shadow detail on the hero title only, never an interactive/dynamic mechanic. The page scrolls normally with the window.

## Art direction
- Background: near-black #0B0B10 for hero/arrivals/archive; a warmer dark purple #15121C for membership, now-showing, and the footer.
- Text: main #F2EFFA, muted #A79FC0, accent (OSD label, borders, CTA) #C77DFF.
- Typography: system sans, weight 700-800 for headings; ui-monospace for eyebrows, OSD text, timecodes, and EPG channel numbers, letter-spacing 0.22-0.26em on eyebrows.
- Tape case colors (linear-gradient 160deg, light to deep — used as the fallback layer under each box-art image, and as each tape's identity color): NEON HIGHWAY #C4432E/#6E2013, STATIC BLOOM #12312B/#050F0C, THE LAST FRIDAY #A9792C/#5A3E14, MIDNIGHT CIRCUIT #6B3FA0/#3A1F5C, STRAY SIGNAL #2C4E8A/#132649, STRANGE WEATHER #2E6B3E/#153A20.

## Imagery (12 local WebP assets, art only — every word on the page stays DOM text)
Twelve AI-painted images live next to the file: six box-art fronts (boxart-neon-highway / boxart-static-bloom / boxart-last-friday / boxart-midnight-circuit / boxart-stray-signal / boxart-strange-weather, ~768x512, object-fit-cover onto the 270x190-ish case face) and six shelf-spine textures (spine-action / spine-horror / spine-scifi / spine-drama / spine-comedy / spine-cult, ~148x420, covering the 74x210 spine). All twelve are 1980s hand-painted-airbrush rental-box art with halftone print grain and sun-faded CMYK color, and contain NO text, letters, logos, or numbers of any kind — titles, genres, years, prices, and tape counts are ALL rendered as live DOM text layered above the art. Every generation prompt shares the suffix "1980s VHS rental box cover art, hand-painted airbrush illustration, coarse halftone print grain, slightly sun-faded CMYK colors, direct-to-video B-movie aesthetic, no text, no letters, no logo", with these subjects, each keyed to its tape's case color: NEON HIGHWAY — a muscle car speeding down a night highway, trailing taillights, distant explosion glow (rust red); STATIC BLOOM — eerie white flowers blooming out of a static-filled CRT TV in a dark greenhouse (deep green); THE LAST FRIDAY — a rainy diner window at dusk, amber lamplight, empty counter stools (amber); MIDNIGHT CIRCUIT — a motorcycle on a wet purple-neon ring road chased by headlights (violet); STRAY SIGNAL — a giant radio dish in a desert sending one stray beam into a starry sky (steel blue); STRANGE WEATHER — a downpour and tiny tornado over exactly one suburban lawn while the neighbors stay sunny (green). The six spines are the same six colors as worn cardboard spine textures (shelf scuffs, faded blank labels, dark left/right edges). Box-art composition rule: main subject centered-right, calm upper-left corner (the genre label sits there), darker lower third (year/price sit there); readability is then guaranteed by a DOM scrim layer, not by the image.

## Persistent CRT/tape overlay (hero -> footer, present on every section)
1. Scanlines: a full-viewport absolutely-positioned layer, pointer-events none, background a repeating-linear-gradient to bottom of rgba(0,0,0,0.09) 1px lines every 3px, blended with mix-blend-mode: multiply.
2. Tracking-noise band: a 34px-tall absolutely-positioned strip, opacity 0.18, mix-blend-mode: screen, containing a small canvas whose pixels are regenerated on a STEPPED interval (every 90ms, not every animation frame — draw random 0-255 grayscale noise into a 96x96 ImageData buffer via requestAnimationFrame but only rewrite pixels when elapsed >= 90ms) scaled up with image-rendering: pixelated. The whole band drifts vertically via a CSS keyframe (translateY 0 to "100vh + 34px") over 9s, using animation-timing-function: steps(24) for an authentically juddery (not smooth) drift, looping infinitely.
3. Chroma fringe: apply only to the hero H1, a static text-shadow of -1.5px 0 rgba(255,40,80,0.45) and 1.5px 0 rgba(60,220,255,0.4) — fixed, never animated or cursor-linked.

## Persistent OSD (signature: play/pause/rewind language)
Fixed top-left (16px/18px from the edges), monospace, pointer-events none: a small red REC-style dot (8px circle, box-shadow glow) blinking via steps(1) keyframes at 1.1s (hard cut, not a fade) between opacity 1 and 0.15; a bordered "SP" speed tag; a label span defaulting to "▶ PLAY"; and a live timecode span. Drive the timecode with one ScrollTrigger pinned to the whole document (start "top top", end "bottom bottom", scrub: true, no easing) whose onUpdate computes seconds = progress * 3138.133 and formats it as HH:MM:SS:FF (24-hour zero-padded, frame = floor(fractional_seconds * 30) clamped to 29) — a live instrument that reads scroll position directly, never an animated count-up tally. The label swaps to "⏸ PAUSE" on pointerenter of any tape card (back to "▶ PLAY" on pointerleave — the required mouse reactivity) and to "◀◀ REW ×2" while any rewind divider (see below) is scrolled through its own trigger range (start "top 65%", end "bottom 35%", toggled via onEnter/onEnterBack/onLeave/onLeaveBack), reverting to "▶ PLAY" once past it.

## Power-on sequence (Easter egg, one spot only, hero on mount)
On mount (skip entirely under prefers-reduced-motion, showing the hero content immediately instead): show a full-hero color-bars layer (7 equal vertical stripes: #F2EFFA, #E8D200, #00C2FF, #1FBF5C, #D200C2, #FF2B2B, #2B52FF, plus a centered "CH 03 — PLEASE STAND BY" tag on a translucent black chip) at opacity 1 while the hero's real content sits at opacity 0. After a 0.35s hold, fade the bars out over 0.08s, cut a full-bleed static canvas to opacity 1 (same stepped-noise technique as the tracking band, 128x128 buffer, 55ms interval), hold it for 0.4s, fade it out over 0.15s, and cross-fade the hero content in over 0.5s with ease power1.out (overlapping the static fade-out by 0.1s). Stop the noise loop once the timeline completes.

## Section 1: Hero
Eyebrow "REWIND ROOM VIDEO CLUB · EST. 1987". H1 (clamp 2rem-3.3rem, weight 800, max-width 18ch, with the chroma fringe above): "Every tape gets a second life." Sub-copy (max 44ch, muted): "Six thousand titles on the shelf, one deck behind the counter, and a rewind bin that never sits empty for long. Scroll to browse the archive." A scroll cue "▼ INSERT TAPE" blinking via steps(2) at 2.4s (hard cut between opacity 1 and 0.3, not a smooth pulse).

## Section 2: New Arrivals
Eyebrow "NEW ARRIVALS // THIS WEEK", H2 "Fresh off the truck, still in the case." A 3-column grid (2 columns under 760px) of 6 VHS tape cases (190px tall, border-radius 6px, 1px rgba(199,125,255,0.25) border, inset shadow). Each case is layered bottom-to-top: (1) the tape's case-color gradient (fallback), (2) its box-art image as an absolutely-positioned cover layer, slightly desaturated (filter saturate(0.85) contrast(0.97) brightness(0.96)) so the art sits behind the CRT overlay like faded print, (3) a scrim layer — linear-gradient to top rgba(4,3,8,0.8) -> transparent at 62% plus a 125deg top-left corner gradient rgba(4,3,8,0.5) -> transparent at 38% — so the DOM text stays readable, (4) the DOM text itself (genre, title, year/rating, price; position relative, z-index 2, text-shadow 0 1px 4px rgba(0,0,0,0.75)), then the RENTED ribbon (z-index 3) and the preview overlay (z-index 4) above everything: NEON HIGHWAY (Action, 1988, $2.99/3 nights), STATIC BLOOM (Horror, 1991, $3.49), THE LAST FRIDAY (Drama, 1985, $1.99), MIDNIGHT CIRCUIT (Thriller, 1993, $2.49, wears a diagonal red "RENTED" ribbon), STRAY SIGNAL (Sci-Fi, 1990, $2.99), STRANGE WEATHER (Comedy, 1987, $1.49). Hover lifts a case translateY(-10px) rotate(4deg) over 0.3s cubic-bezier(0.22,1,0.36,1). NEON HIGHWAY only is a preview Easter egg: on hover, an overlay fades in (opacity via steps(2) over 0.15s) showing the same 7-stripe color-bars pattern, then after a further 0.18s delay a stepped-noise static canvas (48x48 buffer, 55ms interval) fades in over its own 0.2s steps(2) keyframe and a small "PREVIEW UNAVAILABLE" tag — the tape's preview is just permanent snow.

## Rewind dividers (signature: section transitions "rewind", 4 instances)
Placed between Arrivals/Archive, Archive/Membership, Membership/Now-Showing, and Now-Showing/Footer. Each is its own full-width block, min-height 46cqh, background #06050A, containing: (a) a full-bleed frame-flicker strip — a single element with a 6-color horizontal linear-gradient (#3A2B52, #7C3AED, #C77DFF, #2B3A52, #0F766E, #5B2140, each an equal 16.66% slice) at background-size 600% 100%, animated via background-position-x 0% -> 100% with animation-timing-function steps(5) over 0.5s infinite, opacity 0.45, mix-blend-mode screen — mimicking a deck scrubbing rapidly through frames; (b) 5 stacked noise-canvas bands, each 14px tall, using the same stepped-noise technique (64x64 buffer, 70ms interval) scaled with image-rendering: pixelated, each animated via translateY(-14px) to translateY(320px) with steps(8) over 1.2s infinite, staggered with a negative animation-delay of i * (1.2s / 5) so the 5 bands never line up; (c) a centered "◀◀ REW ×2" label chip (monospace, bold, translucent black background, accent border).

## Section 3: The Archive
Eyebrow "THE ARCHIVE // BROWSE BY GENRE", H2 "Six aisles. No two shelves alike." A wrapped row of 6 shelf spines (74x210px, vertical rounded bars, 1px accent-tinted border; background-color #100D18 with a #1C1626->#100D18 gradient as the no-image fallback). Each spine's background-image stacks a readability scrim over its genre spine texture, cover-sized and centered: linear-gradient(180deg, rgba(8,6,14,0.72) 0%, rgba(8,6,14,0.16) 26%, rgba(8,6,14,0.16) 66%, rgba(8,6,14,0.78) 100%), then url(spine-<genre>.webp) — dark at the top and bottom where the vertical DOM labels sit, open in the middle where the art shows. Labels use writing-mode: vertical-rl with text-shadow 0 1px 4px rgba(0,0,0,0.85): HORROR (142 tapes), SCI-FI (98), ACTION (176), DRAMA (64), COMEDY (120), CULT (53) — the counts are static labels, never an animated count-up. Hover pulls a spine forward: translateY(-26px) rotate(-6deg) scale(1.04) over 0.3s cubic-bezier(0.22,1,0.36,1), the second required mouse interaction.

## Section 4: Membership
Eyebrow "MEMBERSHIP // NO. 004821", H2 "One card. No monthly fee. Just don't lose it." A laminated membership card (max 340px, border-radius 12px, gradient #2A2140 to #17121F, accent border) showing the brand name, "MEMBER SINCE 1987", "VALUED RENTER" in accent-colored monospace, and a barcode of 30 vertical white bars with deterministic pseudo-random widths (1-3px, seeded so it's stable across renders). Below it, three rental rules in a left-accent-bordered list: "3-NIGHT RENTAL — Standard tapes return in 3 nights. New releases, 2.", "BE KIND — Rewind fully before you drop it in the return slot.", "LATE FEE — $1.00 per night after the due date, no exceptions."

## Section 5: Now Showing
Warm background #15121C. Eyebrow "NOW SHOWING // LATE-NIGHT BROADCAST", H2 "Some tapes only play after midnight." An EPG-style list (max 560px, bordered, rounded) of 4 rows — CH 04 NEON HIGHWAY 11:00 PM TV-14, CH 07 STATIC BLOOM 12:30 AM TV-MA, CH 09 THE LAST FRIDAY 2:00 AM PG, CH 12 MIDNIGHT CIRCUIT 3:45 AM TV-14 — with a moving "on air" highlight bar (height 25% of the list, accent-tinted background, 3px accent left border) whose vertical position is scrubbed by ScrollTrigger (trigger the list itself, start "top 70%", end "bottom 40%", scrub 0.5): translateY = progress * (rows-1) * (100/rows) percent, so the highlight glides down through the schedule as you scroll past it, like a channel-guide selection cursor.

## Footer
Same warm background, continuous from Now Showing. H2 "Membership never expires. Neither does the static." Copy: "Stop by the counter, or hold a tape at the register until close." A pill-free rectangular CTA "Become A Member →" (1px solid #C77DFF border, transparent fill; hover fills #C77DFF, text turns #16081F, translateY(-2px), 0.3s ease, focus ring 2px accent offset 3px). Closing monospace log line: "TAPE COUNTER · 00:52:18:04 · STOP ▪" (matching the OSD timecode's end value exactly).

## Scroll animations (entrance language for every heading/eyebrow/paragraph/card)
No generic fade-up anywhere. Every tagged element starts at opacity 0, x: -6px, filter: brightness(0.4), then plays a 5-step "tracking settle" burst on scroll-enter (ScrollTrigger start "top 78%", toggleActions "play none none reverse", staggered 0.08s per element): step 1 opacity to 1 over 0.06s; step 2 x to +6px, brightness to 1.6, over 0.07s; step 3 x to -3px, brightness to 0.7, over 0.07s; step 4 x to +1.8px, brightness to 1.2, over 0.07s; step 5 x to 0, brightness to 1, over 0.13s with ease power2.out (total 0.4s) — reading as a deck correcting its tracking as the section rolls in. All five steps use ease "none" except the final settle. On leave-back, reverse to the initial hidden state over 0.2s ease power1.in.

## Performance & accessibility
Noise canvases are tiny (48-128px square) and only repaint on their stepped interval, never every animation frame, keeping CPU cost negligible even with several mounted at once (persistent band + up to 4 rewind dividers x 5 bands + one preview canvas). No layout-thrashing properties are animated; everything is transform/opacity/filter/background-position, or a canvas write inside a throttled rAF. Respect prefers-reduced-motion: reduce by skipping the power-on sequence entirely (show hero content immediately), stopping the tracking band and rewind-divider animations, and setting entrance targets straight to their visible state with no burst. All decorative canvases/spans are aria-hidden; the CTA and any focusable control keep a visible focus ring; body-text contrast meets AA against both background tones. Target 60fps on a mid-range laptop.

## Action flow and content

Implement the following local planning experience for the primary CTA, in the visual language of the page. Use a real button opening a labelled modal dialog. Choosing a pricing card must preselect that exact plan. A navigation link may move to another section; a planning CTA must lead to its review flow.

Use this content for the dialog, including the option details and notes:

{
  "slug": "vhs-rewind",
  "brand": "REWIND ROOM VIDEO CLUB",
  "accent": "#765733",
  "title": "Find your place in the video club",
  "intro": "Compare the shelf pass with the screening circle. Pick the kind of film night you want and keep the membership details.",
  "facts": [
    [
      "Collection",
      "Cult cinema, independent releases and broadcast ephemera"
    ],
    [
      "Borrowing",
      "Seven-day loans; return at the counter"
    ],
    [
      "Care",
      "Rewind before returning and report any playback faults"
    ]
  ],
  "groups": [
    {
      "label": "Membership",
      "options": [
        {
          "title": "Shelf pass · $12 / month",
          "detail": "Two films on loan at a time and access to staff recommendations."
        },
        {
          "title": "Screening circle · $20 / month",
          "detail": "Shelf-pass benefits plus one monthly club screening."
        }
      ]
    }
  ],
  "notes": [
    "Illustrative membership plans. Account creation, availability and billing are outside this sample. Saving a plan does not create a membership."
  ]
}

- Explain before input that this is a fictional brand sample: choices can be reviewed and saved, with no external submission, booking, payment or registration. Use each brand's language. Do not launch a mail client or present an installer for a fictional product.
- Give every option group a legend, inputs explicit labels and errors linked descriptions. Validate options against the allowed values, requested dates as actual dates from today onward, and free text as 10–2,000 trimmed characters. Blank spaces alone must fail. Tracking accepts the sample reference TG-2048 only.
- Focus the first invalid field and preserve every entered value. On success, show the selected option WITH its full detail, requested date or brief, relevant facts and notes. An edit action returns to the preserved form. Do not claim a real reservation, purchase or account has succeeded.
- Save the complete review as UTF-8 text. A browser download request is not proof of a file being written. On download failure, retain the full text in a labelled, selectable textarea and offer retry. Do not show a false success state.
- Constrain modal content to the viewport with internal scrolling. Support keyboard and touch, trap focus while open, close on Escape and restore focus to the exact initiating control. Keep these operations available with motion disabled.
- If a separate project-contact CTA is present, let it collect a project brief and review it locally; a product selection CTA must retain the product choice. Verify both flows independently.