I'll read the current project setup to align my implementation with what's already there.
Before building, here's my plan and reasoning. Let me kick off the artwork image generation in parallel while I set everything up.
Let me quickly verify the generated artwork looks right.
Both images are perfectly on-brand. Now let me design the system. Here's my approach before writing code:
Visual concept — "Contemporary Museum Editorial × Forensic Archive." A warm paper canvas (#F5F3EE) for editorial sections, a near-black gallery void (#101312) for the hero and forensic sections, forest green (#23453B) used sparingly as the only saturated accent. Instrument Serif for large editorial headlines, Manrope for UI/body, IBM Plex Mono for IDs and metadata — exactly the "passport / lab report" feeling.
Flow — Nav → dark gallery hero → cinematic fingerprint reveal (scroll-scrubbed image→texture crossfade with a constellation of surface landmarks) → editorial problem statement → 3-step "How It Works" with a drawing connector line → split Passport mockup → dark Surface Explorer with interactive landmarks (hover + tap) → growing provenance timeline → deep-green final CTA → minimal footer.
Animation strategy — No heavy libs/WebGL. A tiny useInView (IntersectionObserver) + a throttled scroll-progress hook drive transform/opacity only. A global Reduced Motion toggle (seeded from prefers-reduced-motion) snaps everything to final state. Mobile gets lighter, single-focus layouts and tap interactions.
Let me set up the theme, fonts, and config first.
Now the theme tokens and fonts in globals.css:
Now append helper animations and base styles to globals.css:
Now the layout with fonts and metadata:
Now the motion provider/context and the in-view hook:
A scroll-progress hook for the cinematic reveal:
Now the static data files:
Now a reusable Reveal wrapper, then all sections. Starting with shared pieces and the Navbar:
Now the Hero section:
Now the centerpiece — the cinematic Fingerprint Reveal:
Now the Problem Statement and How It Works sections:
Now the Passport preview:
Now the interactive Surface Explorer:
I need to define the fadeIn keyframe. Let me add it to globals.css:
Now the Provenance timeline, Final CTA, and Footer:
Now compose everything in the page:
Let me check for compile errors and then verify in the browser.
Server is running cleanly. Let me verify the page renders properly in the browser.
The hero is exactly the editorial gallery look intended. Let me check the fingerprint reveal mid-scroll and a couple light sections.
The Surface Explorer is great. The fingerprint reveal isn't pinning correctly — overflow-x-hidden on <main> turns it into a scroll container, which breaks position: sticky. I'll switch to overflow-x-clip (prevents horizontal overflow without creating a scroll container).
The reveal now pins and crossfades to the texture correctly. Let me confirm the end-state copy appears and check the editorial light sections plus mobile.
Excellent — the reveal end-state shows the constellation and copy, and all editorial sections render beautifully. Let me verify the final CTA, footer, and mobile layout.
Mobile surface explorer and footer look great. But the mobile hero looks off — the headline copy isn't visible above the painting. Let me inspect the DOM order.
That explains it — scroll-behavior: smooth meant the programmatic scrollTo(0,0) was still animating when the screenshot was taken. Let me jump instantly and re-capture the mobile hero.
The mobile hero is correct — the earlier blank capture was just a mid-smooth-scroll artifact. Everything verifies cleanly across desktop and mobile, with the cinematic reveal pinning and crossfading as intended.
The landing page is fully built, static-export ready (output: 'export'), and verified in the browser on desktop + mobile.
Folder structure
app/ layout.tsx (fonts + metadata), page.tsx, globals.css (palette tokens)
components/ navbar, hero-section, fingerprint-reveal, problem-section,
how-it-works, passport-preview, surface-explorer-preview,
provenance-timeline, final-cta, footer, reveal, motion-provider
lib/ use-in-view, use-scroll-progress (animation hooks)
data/ artwork.ts, provenance.ts, surfaceLandmarks.ts
public/images/ silent-harbor-main.png, -detail.png, -texture.pngDependencies — none added. I used only what ships with the template (Next.js, React, Tailwind, lucide-react). Animation is native CSS + IntersectionObserver + an rAF‑throttled scroll hook, which keeps mobile fast and avoids a motion library entirely.
Run it — npm install then npm run dev; npm run build produces a static out/ you can drop on Vercel.
Assets to swap for a real painting — replace the three files in public/images/ (paths centralized in data/artwork.ts): silent-harbor-main (hero/passport), silent-harbor-texture (reveal + surface explorer macro), and silent-harbor-detail (spare crop). Edit data/surfaceLandmarks.ts to reposition the x/y landmark percentages over your own surface, and data/provenance.ts for the timeline. If an image is missing, each next/image falls back to /placeholder.svg so layouts never break.
Key design decisions — a warm paper canvas for editorial sections vs. a near-black gallery void for the hero/reveal/surface sections, with forest green (#23453B) as the only saturated accent; Instrument Serif for headlines, Manrope for UI, IBM Plex Mono for IDs/metadata to evoke a passport + lab report; the scroll-scrubbed fingerprint reveal (image→texture crossfade with a landmark constellation) carries the core message; and a global Motion toggle in the nav (seeded from prefers-reduced-motion) snaps all animation to its final state for accessibility. There's a skip link, ARIA-labeled interactive landmarks that work on tap, and no horizontal overflow.
Let me look at both components to understand the current implementation.
Let me check the artwork data for the image paths I can reuse in the provenance section.
Both issues are clear. For How It Works, the single full-width SVG line runs behind all three circles and trails off-screen past step 03, which reads as broken. I'll replace it with a clean per-step connector tick that starts at each number and extends within its own column. For Provenance, I'll fill the empty right half with a sticky visual panel — the artwork plus a live "passport status" card — turning dead space into narrative reinforcement.
cn is no longer used in this file. Let me remove the now-unused import.
Now the Provenance section — add a sticky visual panel on the right to fill the whitespace:
Let me verify both sections in the browser.
Both fixes are working. The How It Works connectors are now clean, intentional ticks (number → measured line), and the Provenance section fills the right half with the verified artwork and a passport card. Let me confirm the passport card below the image renders correctly.
Both issues are fixed and verified.
How It Works — the broken full-width line that ran behind the circles and trailed off past step 03 is replaced with a per-step "measured tick": each number now has its own connector line that draws in from left to right within its own column, reading as intentional 01 ——— markers.
Provenance — the empty right half now holds a sticky panel with the verified artwork (with an "Identity Verified" badge) and a passport summary card (ID, title/artist, registration, latest rescan, landmark count, and live status). It fills the whitespace meaningfully and reinforces the product narrative, and it stacks below the timeline on mobile.