# PLENUM — Go inside the form

## 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://video.gumlet.io/6a7e9e0f2621db881577453e/6ad197502c6388d890ef7320/main.mp4
- Poster (still fallback only): https://media.scrollhaus.ai/thumbs/plenum.98f56bee6423.webp

Additional source assets. For each grouped list, prepend its base URL to each filename or path exactly as written.
- https://cdn.spline.design/@splinetool/runtime@2.0.85/build/runtime.js
- Base URL https://scrollhaus.ai/sites/plenum/ → assets/work-2.webp · assets/work-3.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.

Create a responsive React + TypeScript + Vite + Tailwind CSS website. Use small components for navigation, hero, interactive stage, content sections and footer. Put media URLs in src/lib/assets.ts and animations in cleaned-up hooks. Do not output a giant HTML file, an iframe, or a screenshot pretending to be the website.

## Design direction
A pale studio page built around one live Spline form: two soft graphite lobes made of stacked translucent fins. The cursor turns and tilts it and drags an iridescent colour sheen across it. Scroll dives the camera inside the form through three captioned layers until the page turns dark, then pulls back out at the footer. Petrona serif headings, Familjen Grotesk body, Red Hat Mono labels.

Palette and type: --paper: #edf2fd; --ink: #12141c; --muted: #5b6176; --accent: #3d5afe; inside: --ink #eef1fb, --accent #9db0ff; --serif: "Petrona", Georgia, serif; --sans: "Familjen Grotesk", system-ui, sans-serif; --mono: "Red Hat Mono", ui-monospace, monospace.
Font stylesheet: https://fonts.googleapis.com/css2?family=Familjen+Grotesk:wght@400;500;600&family=Petrona:ital,wght@0,300;0,400;1,300;1,400&family=Red+Hat+Mono:wght@400;500&display=swap

## Layout and copy
"Go inside the form." → dive captions "Surface" / "Structure" / "Core" → "Three disciplines, one way in." (Objects, Spaces, Forms + 40+ / 12 / 2014) → "Forms we've let out." (three work images) → "Step inside."
Preserve that section order, real text and distinctive composition. Use the asset map below for the full specification. Do not add unrelated sections or generic filler.

## Motion and interaction
Load assets/scene.splinecode with @splinetool/runtime 2.0.85 and own the camera every frame: position, rotation and lens zoom (the scene's scroll state zooms 1→6, so reset zoom to 1). Depth = scroll through a 300vh runway, smoothed 1−e^(−4.2dt), cubic in-out; camera z 1200−800e, y 150e, side offset −230(1−e) on wide screens; pointer sways x ±95 and y ±60, reduced with depth. Form rotation y = t·.11 + px·.5 (idle spin), x = .785 + py·.2 + e·.25. Scene background lerps #edf2fd→#0c0d12 with depth; html.is-inside flips text light past depth .62. Footer blends the camera to a large right framing (−330, 40, 1050). A mix-blend-mode:color radial sheen follows the pointer.
Use the npm package @splinetool/runtime@2.0.85 in one React component with a canvas ref; run one requestAnimationFrame loop, keep scroll progress outside React state, and dispose the Application on unmount. Match the demonstrated interaction, not just its opening still.

## Exact media
Asset and content map (JSON, not HTML): https://scrollhaus.ai/build-assets/plenum.json
Visual demo: https://video.gumlet.io/6a7e9e0f2621db881577453e/6ad197502c6388d890ef7320/main.mp4
Thumbnail / loading poster: https://media.scrollhaus.ai/thumbs/plenum.98f56bee6423.webp
- 3D scene: https://scrollhaus.ai/sites/plenum/assets/scene.splinecode
- Poster until the scene is ready: https://scrollhaus.ai/sites/plenum/assets/poster.webp
- Work images: https://scrollhaus.ai/sites/plenum/assets/work-1.webp, work-2.webp, work-3.webp (1200×1500)
Read the JSON map before implementing; its referenceNotes contain the full design and motion details. Follow this React/TypeScript instruction when historical notes mention a different stack or standalone HTML. Use the exact URLs. Do not replace the scene with a video or the images with stock pictures.

## Responsive behavior and finish
At 1440×900 keep the form right of the headline. At 390×844 keep the form above the title, stack sections, and avoid horizontal overflow. Honor reduced motion, keep keyboard access, and pause hidden-tab rendering.

Run the production build. Check desktop and phone layouts, the cursor turning the form, the dive into the dark interior and back out at the footer, navigation and CTAs. Compare against the reference; report any unverified differences rather than claiming a guaranteed match.
