# ALBA: a coffee roaster site that opens on a sunrise film, with a light meter, a word-by-word light reveal and a working brew guide

## Motion implementation and acceptance

Implement the interactions specified in the brief. The catalogue recording is a visual reference and the poster is a loading, error or reduced-motion fallback. Implement the moving scene separately from both.
- Catalogue recording (reference only): https://media.scrollhaus.ai/previews-hd/alba.587bf185.mp4
- Poster (still fallback only): https://media.scrollhaus.ai/thumbs/alba.3784851f7626.webp
- Scene source · hero film: dark room to morning light, 1920x1080 H.264, 7.9 s, no audio (play at 1.5x): https://media.scrollhaus.ai/sites/alba/v1/hero.mp4

Additional source assets. For each grouped list, prepend its base URL to each filename or path exactly as written.
- Base URL https://media.scrollhaus.ai/sites/alba/ → v1/start.webp · v1/end.webp · v1/bag-hero.webp · v1/guji.webp · v1/cherries.webp · v1/station.webp · v1/pour.webp · v1/bag-guji.webp · v1/bag-huila.webp · v1/bag-dusk.webp

For scroll-scrubbed video, use a muted inline video, wait for loaded metadata, and map section progress in both directions to the video timeline. Seek when the target changes and coalesce seeks while one is pending. For a frame sequence, draw the indexed frame to canvas as scroll progress changes. For scripted, CSS or 3D motion, recreate the triggers and transforms in the brief. Use normal playback for clips described as loops.

Test at two different scroll positions and then scroll back. Confirm the video time and visible frame change, or confirm the specified canvas, CSS or 3D state changes. If a required source fails, report its URL and the missing motion before calling the build complete.

Build a calm, warm, editorial one-page site for a fictional coffee roaster in React + TypeScript + Vite + Tailwind CSS. Use no animation library: use CSS transitions with cubic-bezier(.22,.61,.36,1), IntersectionObserver and small rAF loops. It must be responsive at 1000px and 760px down to 375px, with no sideways scroll. Nothing bounces.

Components:
- Hero (Film, Shade, Nav, Copy, LightMeter, ScrollCue)
- Statement
- Harvest (Facts, AltitudeLine)
- DryingPanorama
- Roasts (BagCard ×3)
- BrewGuide (MethodTabs, DoseSlider, Recipe, PourTimer)
- Subscription
- Footer (SunriseMark, Newsletter)

Every word stays real HTML text. Do not output a giant HTML file, an iframe, or a screenshot pretending to be the website.

## Tokens
- **Colours:**
  - background #121012
  - text #F6F1E9
  - ink #2C211B
  - accent brown #6A4632
  - paper #EFE8DD and #E6DCCD
  - brew-section night #1a1512, with a gold accent #d9b48f
- **Fonts:**
  - headlines: Crimson Pro 300, with italic `<em>` in brown
  - body: Crimson Pro 300 at 18–22px
  - labels and buttons: Poppins 500, 10–12px, uppercase, tracked .16–.3em
- **Buttons:** solid #F6F1E9 with ink text, padding 15px 30px, Poppins 500 11px, letter spacing .22em, square corners. Text links get a 1px underline at 50% opacity, offset 6px.

## Media (media.scrollhaus.ai/sites/alba/v1/)
- **Film:** `hero.mp4`, 1920×1080, 7.9s, H.264, no audio. A room goes from dark to morning light.
- **Posters:** `start.webp` (first frame) and `end.webp` (last frame).
- **Photos (WebP, 2K):**
  - `bag-hero` (cream ALBA bag on a walnut sideboard)
  - `guji` (misty coffee forest at dawn)
  - `cherries` (hands with red cherries)
  - `station` (raised drying beds, 16:9)
  - `pour` (pour-over in window light)
  - `bag-guji` (cream), `bag-huila` (terracotta), `bag-dusk` (charcoal), each 1:1

## Hero (100svh)
- **Film:** in a 16:9 stage, width max(100vw, 177.78svh), centred, object-fit cover. It is muted, playsinline and does not loop, with start.webp as the poster. Play it once at playbackRate and defaultPlaybackRate 1.5.
- **End poster:** end.webp sits above the film at opacity 0.
- **Copy:** at 72% of the film, add `.lit`.
  - The shade fades in over 1.6s: linear-gradient(90deg, rgba(26,19,14,.46), rgba(26,19,14,.2) 36%, transparent 58%).
  - The eyebrow, H1, paragraph and actions each fade over 1.3s from 12px down, with delays of .05, .25, .5 and .75s.
- **Copy content:**
  - eyebrow "New harvest · Ethiopia Guji"
  - H1 "Coffee for / *the first light.*" at clamp(44px, 6.2vw, 96px), line height .98
  - paragraph "Washed, light roasted and rested for ten days. Notes / of bergamot, white peach and black tea."
  - "Shop the roast" button and a "Brew guide" link, 28px apart
- **Copy position:** left clamp(20px, 6vw, 96px), top clamp(110px, 18vh, 190px).
- **Nav:** padding 28px clamp(20px, 4.5vw, 64px). On the left, a half-sun SVG (30×16) and the wordmark "ALBA" (24px, letter spacing .24em). On the right: Shop, Subscriptions, Origins, Brew guides.
- **Light meter (bottom right):**
  - film progress k maps local time to 05:41 + 37k minutes
  - light = 1240·k^1.8 lux, shown in tabular numerals
  - a small sun dot climbs an arc
- **End state:** when the film ends, set localStorage 'alba-first-light' = 1 (in try/catch). Returning visitors, prefers-reduced-motion, blocked autoplay, or a film still paused after 9s all show end.webp with the copy already lit.
- **Mobile (<760px):** only Shop stays in the nav, the copy moves to top 96px, and the paragraph is hidden.

## Sections
1. **Statement:** a background gradient from #121012 to paper. The paragraph is about 40 words at clamp(30px, 4.3vw, 68px). It is split into word spans that go from 14% ink to full ink as scroll progress crosses them; "light", "slowly" and "window" turn brown italic.
2. **Harvest:**
   - A 4:5 forest photo with a caption, beside "Grown in the cloud *forest of Guji.*"
   - A lead paragraph and a facts list: Shakiso, Guji · 1,950–2,200 m · heirloom 74110/74112 · washed, 36 h ferment, 14 days raised beds · Nov 2025 – Jan 2026.
   - An SVG altitude ridge that draws itself with a stroke-dashoffset over 2.6s, then fills and pins "OUR LOT · 2,100 M".
   - A cherries photo with a picker quote.
   - Photos zoom from 1.08 to 1 over 2.4s when revealed.
3. **Drying panorama:** 86vh, the image at 124% height with ±8% scroll parallax. The caption is "Fourteen slow days on raised beds…", with counters 14 / 36 / 10 that count up.
4. **Roasts:** three cards.
   - Each has a bag photo, a name and process, and a price in euros.
   - Three tasting bars scale in from 0 to their value.
   - Each has a tag and an "Add to bag" link that confirms with "Added ✓".
   - A soft-light radial highlight follows the cursor across each photo ("light on the bag").
5. **Brew guide (dark):**
   - **Method tabs:** Pour-over (1:16.7, med-fine, 94°, 3:00), Chemex (1:16, medium-coarse, 95°, 4:00), AeroPress (1:14, fine, 88°, 2:00).
   - **Dose slider:** 12–36 g, which updates water, ratio, grind and temperature.
   - **Pour steps:** each step lists its time and target grams.
   - **Timer:** "Start the brew" runs a circular SVG timer. It highlights the current step, strikes through the finished ones, and ends on "ENJOY".
6. **Subscription:** "At your door *before sunrise.*" with a three-way frequency picker (€17/€18/€19 a bag). It works out the next real roast day (Tuesday/Friday) and the delivery day two days later.
7. **Footer:** a half sun that rises behind a horizon line as the footer scrolls in, a 19vw wordmark "ALBA", a newsletter field and links.
