# Handoff: Healify Launch Film (cinematic brand video suite)

## Overview
A ~70-second cinematic launch-trailer video for Healify ("Your superhuman era starts now"), built as a self-contained animated HTML/React component driven by a single shared timeline engine. It exists in 6 exported cuts (aspect ratio × length combinations) for paid social, organic social, and the App Store. The film mixes: (1) real AI-generated cinematic b-roll footage, (2) hand-animated HTML/CSS scenes (brand reveal, "Meet Anna", device trio, animated counter), and (3) a live embedded product mockup (the actual Healify chat prototype, running in an iframe) for the "real plan" beat — so viewers see the literal in-app experience, not a fake screenshot.

## About the Design Files
The files in this bundle are **design references built in HTML/React (via Babel-in-browser, no build step)** — working prototypes showing the intended visual composition, motion timing, and audio sync, not production code to ship as-is. The task is to **recreate this experience in the target codebase's real environment** (e.g. native video export via After Effects/Remotion, or a native app's onboarding video player) using its established rendering pipeline. If no such pipeline exists, the least-effort faithful path is often to literally screen-record this HTML film at 1920×1080 (or the relevant aspect) and ship it as an MP4 — see "Recommended production path" below.

## Fidelity
**High-fidelity.** Every scene, timing mark, color, font, and the full narration script are final. Treat pixel positions, hex colors, timing numbers (all in seconds against a single running clock), and copy as production-accurate. The one placeholder-quality element is the AI-voiced narration track (see Assets/Known limitations) — the STRUCTURE and TIMING are final, but the actual voice performance should be replaced with a professional VO read or a higher-tier TTS pass before public launch.

## How the film is built (architecture)
- **Timeline engine**: `animations.jsx` — a reusable `<Stage width height duration>` component providing: auto-scale-to-fit, a scrubber with play/pause/seek, keyboard nav, and `useTime()` — a hook returning the current playhead in seconds. Everything in the film reads `const t = useTime()` and computes its own opacity/position/scale as a pure function of `t`. There is no scene-by-scene state machine — it's closer to a single expression evaluated every frame (a "MoGraph" style declarative animation, similar to Remotion/After Effects expressions).
- **Main film component**: `healify-film.jsx` exports `window.HealifyFilm`, a single React component parameterized by `props.aspect` (`'16:9' | '9:16' | '4:5'`) and `props.cut` (`undefined` = full ~70s film, `'30'` = 30s cut, `'15'` = 15s teaser). Each `.dc.html` entry file just mounts `<HealifyFilm aspect="..." cut="..." />` inside the Stage.
- **Timeline structure** (full cut, `SEGS` array + hardcoded beat markers, all in seconds):
  1. 0.0–5.6 "Your body has been talking..." (dawn footage)
  2. 5.6–10.2 "It's all there. The years you could win back." (hero-by-window footage)
  3. 10.2–15.0 "But raw data can't save you." (overwhelm footage)
  4. 15.0–21.6 "So it slips by. Missed birthdays..." (cake/missed-moments footage)
  5. 21.6–26.8 "A decade of healthy life isn't a statistic. It's you." (warm portrait footage)
  6. ~28.5–30.6 Brand reveal: heart-mark blooms, "Healify" wordmark
  7. ~30.5–34.8 "Meet Anna" — Anna's avatar + coach intro copy
  8. ~37.4–44.0 "A real plan, in plain words" — **live embedded product mockup** (real chat prototype in an iframe, not a screenshot)
  9. ~43.6–47.6 "iPhone. iPad. Web." — device trio (laptop + iPad + phone), real UI screenshots inside custom-drawn device bezels
  10. ~47.4–51.6 Animated health-score counter climbing 47→72
  11. ~51.6–58.2 "Years back. Birthdays back. Life back." (graduation + payoff footage)
  12. ~58.0–65+ Finale lockup: Healify mark, tagline, "Start free today" CTA, trust badges, handle/hashtag
- **Audio**: Web Audio API (not `<audio>` tags — the CDN serving the generated voice files mislabels content-type, which breaks `<audio>` playback; Web Audio's `fetch` + `decodeAudioData` bypasses this reliably). One `FilmAudio` component decodes all VO lines, a music bed, and SFX once on mount into an `AudioContext`, then fires each line via a `{url, at}` cue table matched 1:1 to the on-screen captions. A "Play with sound" gate overlay (`SoundGate`) is required by all browsers' autoplay policy — it also waits for every audio buffer to finish decoding before enabling the click, so playback starts in perfect sync with no post-click lag.
- **Device bezels**: `Phone`, `IPad`, `Laptop` are hand-drawn CSS components (dark rounded rect + notch/camera cutout), not images — see Design Tokens for exact radii/bezel widths.
- **Cinematic footage**: 9 AI-generated video clips (5.04s each, 1284×1284, stored as MP4) are prefetched as blobs (not streamed) to avoid the dev-server's lack of byte-range support, then played via `<video>` at a computed seek position so they always line up with the timeline regardless of scrub/loop.

## Screens / Cuts in this bundle
| File | Aspect | Length | Use case |
|---|---|---|---|
| `Healify Launch Film.dc.html` | 16:9 | ~70s | Full-length hero film — YouTube, site hero, sales decks |
| `Healify Launch Film 9x16.dc.html` | 9:16 | ~70s | Full-length, Reels/TikTok/Stories full watch |
| `Healify Launch Film 4x5.dc.html` | 4:5 | ~70s | Instagram feed |
| `Healify Launch Film 30s (9x16).dc.html` | 9:16 | 30s | Shorter paid social cut |
| `Healify Teaser 15s (16x9).dc.html` | 16:9 | 15s | Pre-roll / bumper |
| `Healify Teaser 15s (9x16).dc.html` | 9:16 | 15s | Stories/Reels teaser |
| `Healify Video Gallery.dc.html` | — | — | Internal review page — embeds all 6 cuts on one scrollable page for approval, not a deliverable itself |

All 6 cuts share one underlying component (`healify-film.jsx`) — there is no per-cut fork to maintain; aspect/length are just props.

## Interactions & Behavior
- **Playback gate**: On load, a full-bleed "Play with sound" button overlay blocks the view (`SoundGate`). Any click or keypress anywhere dismisses it and starts playback from t=0. This is required because browsers block audio-with-sound autoplay; there is no way to remove this gate and keep audio.
- **No other interactivity** — the film plays linearly to its end and stops (no loop, no replay button in the shipped cuts; the Stage's own scrubber/play controls are development/QA chrome only, hidden or irrelevant in a real export).
- **Live product embed**: during the "real plan" beat, an `<iframe>` loads the actual `webapp/Healify Web.html` chat prototype pre-seeded (via `localStorage`) to the Anna chat screen, scaled down to fit inside the phone bezel. This means that beat is always pixel-perfect-current with the real product — but it also means the film's export/screen-recording MUST wait for that iframe to finish loading before capturing that segment.

## State Management
Minimal — the entire film is a pure function of one number (`t`, seconds elapsed). The only actual React state lives in:
- `FilmAudio`: decoded `AudioBuffer`s, an `AudioContext`, and a "fired" set (which cues have already played) to avoid re-triggering on every render.
- `SoundGate`: `show` (has the user dismissed the overlay) and `ready` (has all audio finished decoding).
- `CineLayer` (video clips): a "seeded" ref per clip to know whether it's been given its initial seek yet, to avoid re-seeking every frame (which caused visible flicker/twitch in an earlier iteration — see Known limitations).

## Design Tokens

**Colors**
- Primary/CTA orange: `#FF6942` (exposed as `ORANGE`, overridable via `accent` prop)
- Gold/secondary: gradient stop `#FDB36B`
- Ink/near-black: `#03040D` (`INK`)
- Dark backdrop gradient: `linear-gradient(135deg, #03040D 0%, #0D0B12 52%, #1A1018 100%)`
- Light backdrop gradient: `radial-gradient(120% 80% at 50% -10%, #FFF1EA 0%, <appBg> 46%, #EAEEF1 100%)`
- Body copy on dark: `#EDEFF3` → `#CFD2DA` (headline → secondary, in descending emphasis)

**Typography**
- Display/headline font: `FONT_D` — used for all large titles, kickers, numerals
- Body font: `FONT_B` — used for supporting lines, kickers (uppercase, letter-spaced)
- Caption sizing: headline "big" sizes range 44–104px depending on beat emphasis (climax lines like "Life back." run largest)

**Device bezel radii**
- Phone: 44px screen corner radius, 9px bezel width (see Known limitations — was 13px, thinned per feedback), 56px outer case radius
- iPad: 22px screen corner radius, 22px bezel width, 42px outer case radius
- Laptop: 12px bezel width

**Motion**
- Standard fade/appear: `prog(t, start, end, easing)` → 0→1 opacity+translateY ramp, typically 0.6–1.2s
- Standard easing: `easeOutCubic` for entrances, `easeInOutCubic`/`easeInOutSine` for holds/focus-pulls
- Caption entrance: fade + 4–8px translateY, no bounce/spring (matches brand motion guidelines: calm, not gamified)

## Assets
- `assets/cine/*.mp4` + matching `.png` posters — 9 AI-generated cinematic clips (dawn, window, overwhelm, cake, portrait, walk, graduation, payoff, superhuman-ridge), 5.04s @ 1284×1284 each. Landscape originals; `CINE_TALL` holds separately-generated 9:16 vertical reframes of the same 8 clips for the tall aspect cuts.
- `assets/anna-hd.png` — Anna's avatar, a 512×512 face-centered crop of the design system's higher-res reference portrait (the original in-app asset was too low-res and read as blurry at the display size used in this film).
- `assets/screens/*.png` — real captured screenshots of the Healify web/mobile prototype, composited into the Laptop/iPad/Phone device bezels for the "everywhere" beat.
- `assets/app-icon.png` — the Healify heart mark, used in the brand-reveal and finale beats.
- **Audio** (all hosted on a CDN, embedded as absolute URLs in `healify-film.jsx`'s `AUDIO` object): 12 narration lines (voice: "Roman", a Higgsfield seed_audio preset — see Known limitations), 1 music bed, heartbeat + shimmer SFX. Also 3 bespoke short lines for the 30s cut and 3 for the 15s teaser.

## Known limitations / suggested follow-up polish
These are flagged honestly so the receiving team can prioritize — none block using the film today, but a "final mile" pass should address them:

1. **Narration voice is a placeholder-quality AI TTS read** ("Roman" preset via Higgsfield seed_audio). It reads clearly and is properly timed/synced, but is not a professional VO performance. **Recommended**: re-record with a professional voice actor or a premium TTS tier (e.g. ElevenLabs with a licensed voice), matching the exact script and per-line timing already established in `AUDIO.vo` + the `vo:` cue table in `FilmAudio`'s spec (each cue is `{url, at}` in seconds — swap URLs, keep `at` unless the new read's duration requires nudging the next cue later).
2. **Per-line VO timing was manually fitted** to each caption's on-screen window by trimming the script text to a length that reads naturally in the available seconds (rather than time-stretching audio, which was tried and rejected — pitch-shifting a `BufferSource`'s `playbackRate` audibly distorts the voice, the "helium" effect). If the replacement VO read runs long on any line, either trim that line's copy further or push the next cue's `at` later (and confirm it doesn't collide with the following cue).
3. **Cinematic footage is AI-generated** (all 9 clips + the 8 vertical reframes). It reads as premium/plausible but should be reviewed for any subtle generation artifacts before paid media spend, and ideally replaced with real licensed/shot footage for a final production pass if budget allows.
4. **The "real plan" beat depends on a live iframe** of the actual product prototype. This is a feature (always current) but also a fragility: any screen-recording/export pipeline must allow that iframe time to fully load before capturing, or that beat will show a blank/loading phone screen.
5. **No loop/replay affordance** is built into the shipped film — confirm the target placement (site hero vs. paid social vs. App Store preview) doesn't need one; each platform has different expectations here.
6. **Device bezel weight**: bezel width was reduced from 13px→9px per live feedback during this project; if the target brand system has an official device-mockup spec, prefer that over these hand-tuned values.
7. **Editor-only chrome**: the visible scrubber/playback bar and its reserved 44px of vertical space (from the shared `Stage` engine) are development affordances only — they are not intended to appear in any exported/shipped video and should not be captured when recording/exporting.

## Files
- `Healify Launch Film.dc.html`, `Healify Launch Film 9x16.dc.html`, `Healify Launch Film 4x5.dc.html`, `Healify Launch Film 30s (9x16).dc.html`, `Healify Teaser 15s (16x9).dc.html`, `Healify Teaser 15s (9x16).dc.html` — the 6 shippable cuts (entry points, mount `HealifyFilm`)
- `healify-film.jsx` — the entire film: all scenes, timing, captions, audio sync, device bezels, cinematic layer
- `animations.jsx` — shared timeline/Stage engine (auto-scale, scrubber, `useTime()`, easing helpers)
- `assets/` — cinematic footage, avatar, screenshots, app icon
- `webapp/` — the live Healify product prototype embedded during the "real plan" beat

## Recommended production path
For most teams, the fastest path to a shippable MP4 is: open each `.dc.html` cut full-screen at its native resolution (1920×1080 for 16:9, 1080×1920 for 9:16, 1080×1350 for 4:5), let the live product iframe fully load, dismiss the "Play with sound" gate, and screen-record the full playthrough (or use the project's built-in video export tooling, if available, pointed at each cut). Re-encode/trim any capture-tool chrome (cursor, browser frame) before delivery.
