ultra-do

byAkram Salah

do it

Landing
Landing

Comments (0)

No comments yet. Be the first!

System Requirements

Page 1 of 17

System Requirements Document

1. Introduction

This System Requirements Document defines ultra-do, the project codename for Vanguard & Stone, a cinematic, scroll-driven marketing website for a premium architectural developer. The site presents the "River District" development as one continuous, scroll-driven experience where a raw construction site transforms into a glowing living city, rendered in real time by a persistent Three.js world behind fixed HTML overlays.

The document captures the required capabilities, architecture, data, visual language, interaction model, motion direction, and technical stack as specified by the source material. The product scope is a single-page, scroll-narrative marketing experience — not an application with accounts, dashboards, or administrative surfaces. The explicit user directive is to build the described experience but with improved 3D, better transformations, better movement, and better scroll.

Page 2 of 17

2. System Overview

Vanguard & Stone is a single-page experience built on a 600vh scroll track. As the visitor scrolls, a fixed, full-viewport Three.js canvas (rendered behind all content) grows a procedural city from a raw construction site into a completed glowing living city. Fixed-position HTML overlays — one per narrative section — mount and unmount at discrete scroll boundaries, presenting copy, controls, data cards, forms, and a floor-plan modal.

Core structural ideas:

  • One continuous scroll drives everything: camera movement, city construction growth, sky/time-of-day, section transitions.
  • A single animation loop in a dedicated scroll engine owns all per-frame work and fans out to imperative 3D subscribers. React components re-render only on discrete section boundaries — never per frame.
  • Fixed HTML overlays sit above the canvas, each mounted only within its own section range, with pointer-events enabled only on interactive children.
  • A persistent UI store (custom, via useSyncExternalStore) holds discrete state: current section, time preference, blueprint mode, exploded view, active project/pin/floor, saved homes, modal, hover tooltip, quality tier, and scene-ready flag.

Sections and global progress ranges:

SectionRangeNav Label
hero0.00–0.10Overview
build0.10–0.46The Rise
residences0.46–0.62Residences
district0.62–0.76District
record0.76–0.88Record
contact0.88–1.00Inquire

Build-phase sub-ranges inside build: DATUM 0.10–0.18 · RISE 0.18–0.27 · FAÇADE 0.27–0.36 · REALM 0.36–0.42 · LIFE 0.42–0.46.

Page 3 of 17

3. Functional Requirements

Page 4 of 17

3.1 Scroll Architecture & Engine

  • As a visitor, I want a single continuous 600vh scroll track so that scrolling drives the entire narrative from construction site to living city.
  • As a visitor, I want smooth scrolling (Lenis, duration 1.15) so that movement through the narrative feels fluid and cinematic.
  • As a motion-sensitive visitor, I want reduced-motion users to have Lenis and heavy motion disabled so that the experience respects my prefers-reduced-motion setting.
  • As a system, I want a single scrollEngine that owns the only requestAnimationFrame loop so that all per-frame work is centralized.
  • As a system, I want the scroll engine to drive Lenis so that smooth scroll is integrated with the frame loop.
  • As a system, I want the scroll engine to compute global progress (0..1) so that all scroll-driven behavior shares one source of truth.
  • As a system, I want the scroll engine to compute the current section so that overlays and camera behavior switch at correct boundaries.
  • As a system, I want the scroll engine to fan out to imperative subscribers via onFrame(progress, dt, time) so that the 3D world updates every frame without React involvement.
  • As a system, I want onSectionChange notifications so that discrete UI state updates only at section boundaries.
  • As a system, I want React components to never re-render per frame and to change state only at discrete section boundaries, so that performance stays high.
  • As a system, I want a custom store implemented with useSyncExternalStore (no external state library) so that UI state is shared predictably.
  • As a system, I want the store to hold section so that the active overlay and camera behavior can be derived.
  • As a system, I want the store to hold timePreference ('auto' | 'day' | 'golden' | 'night') so that time-of-day can be controlled by the user or the scroll story.
  • As a system, I want the store to hold blueprint (boolean) so that blueprint X-ray mode can be toggled.
  • As a system, I want the store to hold exploded (boolean) so that the exploded tower view can be toggled.
  • As a system, I want the store to hold activeProjectId so that the active residence tower is tracked.
  • As a system, I want the store to hold activePinId so that the active district pin is tracked.
  • As a system, I want the store to hold selectedFloor (number | null) so that the selected floor is tracked.
  • As a system, I want the store to hold savedHomes: string[] so that saved homes are available across overlays.
  • As a system, I want savedHomes persisted to localStorage under key vs-saved-homes-v1, with entries formatted as projectId:floorNumber, so that saves persist between visits.
  • As a system, I want the store to hold modalFloor: {projectId, floorNumber} | null so that the floor-plan modal can be opened/closed.
  • As a system, I want the store to hold hoverTip: {x, y, label, sub} | null so that 3D hover tooltips can be displayed.
  • As a system, I want the store to hold quality: 'high' | 'medium' | 'low' so that render quality tier is tracked.
  • As a system, I want the store to hold sceneReady so that the scene-ready state is available to the UI.
  • As a system, I want a section map with the six named sections and their progress ranges so that scroll behavior is deterministic.
  • As a system, I want build-phase sub-ranges (DATUM, RISE, FAÇADE, REALM, LIFE) within the build section so that construction phases map to scroll positions.
  • As a system, I want each overlay to mount only in its own section (e.g., section === 'hero' && <HeroOverlay />) so that overlays appear in the correct narrative window.
  • As a system, I want overlays to be fixed inset-0 z-20 with pointer-events-none on the root and pointer-events-auto on interactive children so that overlays don't block canvas interaction.
  • As a developer, I want a path alias @ → repo root in vite.config.ts so that imports are consistent.
  • As a system, I want the anonymous visitor to reach the Landing hero before navigating the scroll narrative, and the Preloader to complete before the hero becomes active, so that the accepted arrival journey is executable.
Page 5 of 17

3.2 3D Engine

  • As a user, I want a SceneEngine built on WebGLRenderer and an EffectComposer (RenderPass → UnrealBloomPass → ShaderPass → OutputPass from three/addons) so that the world renders with bloom and post-processing.
  • As a user, I want a fixed full-viewport canvas behind everything so that the 3D world is persistent across the whole scroll narrative.
  • As a user, I want FPS-based auto quality degradation between high/medium/low (via onQualityChange) so that the experience stays smooth on weaker devices.
  • As a system, I want WebGL to be available for the persistent 3D world, with quality degradation under load, so that the experience degrades gracefully when the capability is constrained.
  • As a user, I want raycast picking to detect hovered floor slabs and produce a hoverTip so that I know what I'm hovering.
  • As a user, I want raycast picking to detect clicks on floor slabs so that I can select a floor and open its floor plan.
  • As a user, I want raycast picking on district pins for hover and click so that I can inspect neighborhood amenities.
  • As a user, I want drag-to-orbit (dragAz/dragPol) so that I can rotate the view.
  • As a user, I want mouse parallax (parX/parY) so that the scene feels alive and responsive to my cursor.
  • As a system, I want a cityBuilder that generates a procedural city from seeded lots (x, z, w, d, h, minH, stagger, bucket, variant) so that the district is reproducible and varied.
  • As a system, I want city geometries merged with mergeGeometries for performance so that large building counts render efficiently.
  • As a system, I want canvas-generated facade textures so that building surfaces have detailed, procedural detail.
  • As a user, I want cityBuilder.update(buildT, dt, time) to grow the construction as I scroll through the build section so that the city literally builds itself.
  • As a user, I want setDusk(dusk) to lerp city lighting so that the district changes with time of day.
  • As a user, I want setConstructionFxVisible so that construction effects appear during the build narrative.
  • As a system, I want glowMaterials exposed for bloom so that glowing elements participate in post-processing.
  • As a system, I want focus (the construction point for the camera) exposed so that the camera can target the active construction area.
  • As a user, I want the three hero towers rendered as stacks of floor slabs matching the residences data so that the visual model and data stay consistent.
  • As a user, I want setExplode(0..1) for an exploded axonometric view so that I can see a tower's structure separated.
  • As a user, I want setGrowth(0..1) so that towers grow along the scroll narrative.
  • As a user, I want setHighlightFloor(floorNumber | null) so that the selected floor is highlighted in 3D.
  • As a system, I want pick(raycaster) → { projectId, floorNumber, listed, label, price, point } so that hovering/clicking a tower yields structured unit data.
  • As a user, I want setDusk on hero towers so that towers respond to time of day.
  • As a system, I want tower anchors (Spire [0,-16], Skybridge [-34,2]) and midY exposed so that the camera can orbit/frame each tower.
  • As a user, I want a skyRig gradient sky dome shader that transitions day → golden hour → night (with stars) so that the sky matches the story.
  • As a user, I want sun/moon tracking in the sky rig so that the light source matches the time of day.
  • As a user, I want fog and light palettes in the sky rig so that atmosphere matches the sky state.
  • As a user, I want an animated canal water shader so that the river/water reads as alive.
  • As a system, I want dusk 0..1 to blend sky palettes driven by timePreference so that sky transitions are continuous.
  • As a user, I want a cameraDirector with section-aware analytic camera goals (position/lookAt/fov) and heavy exponential damping so that camera movement is smooth and cinematic.
  • As a user, I want the hero section camera to be a wide overview so that the district is introduced.
  • As a user, I want the build section camera to perform a crane-like move toward the construction focus so that the rise feels like a construction move.
  • As a user, I want the residences section camera to orbit around the active tower anchor so that I can inspect towers.
  • As a user, I want the district section camera to be an elevated overview of pins so that I can read amenities in context.
  • As a user, I want the record and contact sections to use composed frames so that closing sections feel composed and settled.
  • As a system, I want a textures module generating 2D-canvas facade/window patterns via makeFacade, scaleBoxUVs, and reseed so that facades are procedurally varied.
  • As a system, I want makeCloudTexture and makeGlowSprite so that clouds and glow sprites are available to the scene.
Page 6 of 17

3.3 Data

  • As a user, I want BUILD_PHASES data (01 DATUM Foundations +0m · 02 RISE Superstructure +85m · 03 FAÇADE Glass & bronze +140m · 04 REALM Parks & canal +165m · 05 LIFE First residents 2027) so that the build narrative has precise phases.
  • As a user, I want RESIDENCE_PROJECTS with three projects — The Spire (36 storeys · river glass tower, highrise, 165 m, 36 floors, from €890K, 8 left, Q3 2027, "Full-height solar glass, corner loggias, skyline forever."), Skybridge One (Twin towers · pool in the sky, 110 m, 28 floors, from €740K, 6 left, Q1 2027, "Two slender towers joined at level 20 by a glass sky club."), and River Terraces (Stepped villas · private pools, from €1.45M, 3 left, Q4 2026) — so that all residences are presented accurately.
  • As a user, I want The Spire floors presented (Floor 34 Sky Penthouse, Penthouse, 295 m², 4 bed, 4.5 bath, Panoramic, €4.85M, features: Private lift foyer / 65 m² sky terrace / Plunge pool; rooms: Grand Salon 75.5 m² Silver Travertine, Primary Suite 33.5 Oak & Linen, Kitchen 21.8 Calacatta & Bronze, Sky Terrace 39.5 Ash Decking · Floor 22 Corner River Home, 3-bed, 178 m², SE waterfront, €2.15M · Floor 8 Parkside Loft, 1-bed loft, 72 m², Park & canal, €890K) so that unit detail is complete.
  • As a user, I want Skybridge One Floor 20 Skybridge Residence presented (3-bed, 198 m², €2.49M) so that its flagship unit is shown.
  • As a system, I want each floor modeled with fields floorNumber, name, type, areaSqm, bedrooms, bathrooms, orientation, price, priceEUR, status, features[], rooms[] so that unit data is structured.
  • As a system, I want rooms defined as { id, name, areaSqm, finish, at: [x,z], size: [w,d] } so that they are SVG-ready floor-plan geometry (at/size → rects).
  • As a user, I want NEIGHBORHOOD_PINS data with four pins — Express Metro (transit, 3 min, [-40,-15.5]) · Central River Park (nature, 2 min, [-8,-34]) · Marina Promenade (water, 1 min, [16,25]) · Avenue Roastery (culinary, 2 min, [22,-13]) — so that amenities are accurate and placed.
  • As a user, I want RECORD_STATS data — EST. 2004 / 22 / Years · DELIVERED / 1240+ / Homes · MASTERPLAN / 485k m² / Built realm · PROTOCOL / 99.4% / On time — so that the record section shows real credibility figures.

3.4 Chrome Components (Always Mounted)

  • As a user, I want a Preloader — full-screen with wordmark "The River District" and a large mono progress counter stepping 0–100 through thresholds, then onComplete — so that the experience loads deliberately.
  • As a user, I want a CustomCursor that follows the mouse so that the site feels bespoke and cinematic.
  • As a user, I want a Header (fixed top-0 left-0 right-0 z-40 flex items-center justify-between gap-3 px-4 md:px-6 py-3 bg-white/75 backdrop-blur-md border-b border-stone-900/8) so that global controls are always available.
  • As a user, I want the header wordmark button Vanguard<span>&</span>Stone (text-base md:text-lg font-serif font-semibold tracking-tight, hover → #E65100) plus a hidden lg:inline text-[9px] font-mono uppercase tracking-[0.2em] text-stone-400 "River District" label, so that brand identity is persistent.
  • As a user, I want center section pills (hidden md:flex, container p-0.5 rounded-full bg-stone-900/5) for Overview / The Rise / Residences / District / Record / Inquire, with active state bg-stone-900 text-white shadow-sm and inactive text-stone-500 hover:text-stone-900, so that I can navigate sections.
  • As a user, I want a time-of-day segmented control (Lucide Sparkles auto / Sun day / Sunset golden / Moon night; active bg-[#E65100] text-white) so that I can control the sky.
  • As a user, I want a blueprint toggle (DraftingCompass, active bg-[#0b3aa8] text-white, tooltip "Blueprint X-Ray (B)") so that I can switch to blueprint X-ray view.
  • As a user, I want a saved-homes heart (Heart) button with a count so that I can open/review saved homes.
  • As a user, I want an audio toggle (Volume2/VolumeX) so that I can enable/disable the ambient soundscape.
  • As a user, I want an ElevationGauge — vertical elevation readout tracking camera height — so that the vertical narrative is legible.
  • As a user, I want a StatusBar bottom strip (mono) showing 51.9225° N · 4.4792° E, the current section, and scroll progress so that I have orientation.
  • As a user, I want Audio (utils/audio.ts) as an opt-in ambient soundscape whose soundscape.updateScroll(p) is fed from the frame loop (no React state) so that sound responds to scroll without causing re-renders.
Page 7 of 17

3.5 Section Overlays

Hero Overlay

  • As a user, I want a hero kicker with a pulsing dot (w-1.5 h-1.5 rounded-full bg-[#E65100] animate-pulse) plus "River District" (text-[10px] font-mono tracking-[0.25em] uppercase) so that the district is introduced.
  • As a user, I want the H1 (Fraunces) "Live above / the river<span>.</span>" (text-5xl sm:text-7xl md:text-8xl font-serif text-stone-900 leading-[0.95] tracking-tight mb-6) so that the brand statement lands.
  • As a user, I want the hero sub-line 3 towers · 165 m · 2027 so that key facts are immediate.
  • As a user, I want a primary button "Explore residences" that scrolls to residences (group flex items-center gap-2.5 px-6 py-3.5 bg-[#E65100] hover:bg-[#D84300] text-white text-xs font-bold uppercase tracking-widest transition-all shadow-lg shadow-orange-900/20 + Lucide ArrowRight with group-hover:translate-x-1) so that I can jump to residences.
  • As a user, I want a secondary button "Watch it rise" that scrolls to build (px-6 py-3.5 bg-white/85 hover:bg-white backdrop-blur-sm border border-stone-900/10 text-stone-800 text-xs font-bold uppercase tracking-widest) so that I can watch construction.
  • As a user, I want a bottom-right scroll hint (hidden sm:flex, absolute bottom-6 right-6 md:right-12) with a MousePointer2 icon and text-[10px] font-mono uppercase tracking-widest text-stone-500 "Scroll — the city builds itself" so that I know to scroll.
  • As a user, I want a bottom progress hairline (absolute bottom-0 left-0 right-0 h-[2px] with bg-gradient-to-r from-[#E65100] to-transparent opacity-60) so that hero progress is visible.

Build Overlay

  • As a user, I want a build kicker showing the phase code (text-[10px] font-mono font-bold tracking-[0.3em] text-[#E65100] uppercase, e.g. "02 / RISE") so that the current phase is labeled.
  • As a user, I want a phase title (Fraunces, text-4xl md:text-6xl font-serif text-stone-900 leading-none tracking-tight) plus elevation (text-lg md:text-2xl font-mono text-stone-400 tabular-nums, e.g. +85m) so that phase and height are shown.
  • As a user, I want a phase progress bar (mt-5 h-[3px] w-64 max-w-full bg-stone-900/10 overflow-hidden with inner h-full w-full bg-[#E65100] origin-left scaled by phase progress) so that phase completion is visible.

Residences Overlay

  • As a user, I want project tabs top-left (container pointer-events-auto flex items-center gap-1 p-1 bg-white/85 backdrop-blur-md border border-stone-900/10 shadow-lg; tab px-3 md:px-4 py-2 text-[11px] font-bold uppercase tracking-wider, active bg-[#E65100] text-white shadow-sm, inactive text-stone-600 hover:text-stone-900 hover:bg-stone-100) so that I can switch between the three projects.
  • As a user, I want an exploded toggle top-right (Layers icon + "Exploded"/"Assembled", active bg-stone-900 text-white border-stone-900, inactive bg-white/85 backdrop-blur-md text-stone-700 border-stone-900/10, text-[10px] font-mono uppercase tracking-widest) so that I can switch tower views.
  • As a user, I want a bottom unit card (pointer-events-auto w-full max-w-sm bg-white/88 backdrop-blur-md border border-stone-900/10 shadow-2xl) with a header row (tagline text-[9px] font-mono uppercase tracking-[0.25em] text-[#E65100] font-bold, serif name, right-aligned from {price} + availability in text-emerald-700 font-bold) so that project pricing is clear.
  • As a user, I want floor rows (floor number, name, beds, price) with a heart save button so that I can browse and save units.
  • As a user, I want selecting a floor to highlight it in 3D and open the modal so that selection is reflected both visually and in detail.

District Overlay

  • As a user, I want an active pin card (flex items-center gap-3 px-4 py-2 bg-white/85 backdrop-blur-md border border-stone-900/10 shadow-xl) with MapPin w-3.5 h-3.5 text-[#E65100], name (text-xs font-semibold text-stone-900), and walk time (text-[10px] font-mono text-emerald-700 font-bold) so that I see pin details.
  • As a user, I want a filter chips row (flex flex-wrap justify-center items-center gap-1.5 p-1.5 bg-white/85 backdrop-blur-md border border-stone-900/10 shadow-xl max-w-[94vw], chips text-[11px] font-bold uppercase tracking-wider) so that I can filter amenities.

Record Overlay

  • As a user, I want a record kicker (text-[10px] font-mono font-bold tracking-[0.3em] text-[#E65100] uppercase) and a serif headline (text-4xl md:text-6xl ... leading-[0.95] mb-7 drop-shadow-sm) so that the credibility section is introduced.
  • As a user, I want a stats grid (pointer-events-auto grid grid-cols-2 md:grid-cols-4 gap-2.5 md:gap-3) with cards (bg-white/80 backdrop-blur-md border border-stone-900/10 shadow-xl px-4 py-4 md:px-6 md:py-5), kicker (text-[9px] font-mono font-bold tracking-[0.25em] text-[#E65100] uppercase), value (text-3xl md:text-5xl font-mono font-bold text-stone-900 tabular-nums leading-tight), and label (text-[11px] font-medium text-stone-500) so that the four record stats read clearly.

Contact Overlay

  • As a user, I want a contact grid (pointer-events-auto grid grid-cols-1 lg:grid-cols-12 gap-4 w-full max-w-4xl) with a form card (lg:col-span-7 bg-white/88 backdrop-blur-md border border-stone-900/10 shadow-2xl p-6 md:p-8) so that the inquiry form is presented cleanly.
  • As a user, I want the form card kicker "Private inquiry" (text-[10px] font-mono font-bold tracking-[0.3em] text-[#E65100] uppercase mb-1) and H2 "The keys are waiting<span>.</span>" (text-3xl md:text-4xl font-serif text-stone-900 tracking-tight mb-5) so that the closing message lands.
  • As a user, I want form fields Full name / Email (w-full px-4 py-3 text-sm bg-white/70 border border-stone-900/15 focus:border-[#E65100] focus:outline-none transition-colors) so that I can submit an inquiry.
  • As a user, I want a submit button "Request private gallery" (w-full flex items-center justify-center gap-2 py-3.5 bg-[#E65100] hover:bg-[#D84300] text-white text-xs font-bold uppercase tracking-[0.2em] transition-all shadow-lg shadow-orange-900/20, with ArrowRight nudge; label "Sending…" while submitting) so that I can request contact.
  • As a user, I want a success state (w-11 h-11 rounded-full bg-emerald-100 + Check w-5 h-5 text-emerald-700, "Received — an advisor replies within 24h.", and a "Send another" link) so that I know my inquiry was received.
  • As a user, I want a right column with a saved-homes summary (from savedHomes) and an address block "14 Quai de Saint-Jude" with MapPin so that my saved units and the address are visible.
  • As a system, I want the inquiry submission to deliver to the external Sales Advisor so that the stated reply outcome ("an advisor replies within 24h.") is fulfilled.

Floor Plan Modal

  • As a user, I want a FloorPlanModal that draws an SVG floor plan from floor.rooms (at/size → rects) so that I can see the unit layout.
  • As a user, I want hovering a room to update the footer to {room.name} — {room.finish} (otherwise "Hover rooms for finishes") so that I can inspect finishes.
  • As a user, I want the modal footer stats {areaSqm} m² · {bedrooms} bed · {bathrooms} bath so that unit specs are summarized.
Page 8 of 17

3.6 Interactions

  • As a keyboard user, I want ArrowDown/ArrowRight to advance to the next section and ArrowUp/ArrowLeft to go to the previous section in order (hero, build, residences, district, record, contact) so that I can navigate without a mouse.
  • As a keyboard user, I want B to toggle blueprint X-ray so that I can switch views from the keyboard.
  • As a keyboard user, I want keyboard shortcuts ignored while I'm typing in inputs so that typing isn't interrupted.
  • As a user, I want drag-to-orbit on the 3D scene so that I can rotate the view.
  • As a user, I want mouse parallax so that the scene responds to my cursor.
  • As a user, I want hovering a floor slab to show a tooltip (hoverTip) so that I know what I'm hovering.
  • As a user, I want clicking a slab to select the floor and open FloorPlanModal so that I can inspect the unit.
  • As a user, I want clicking a district pin to set activePinId so that I can inspect that amenity.
  • As a user, I want the time-of-day control to switch the sky rig (with "auto" following the scroll story) so that I can set atmosphere.
  • As a user, I want the blueprint toggle to switch materials to a blueprint X-ray style (#0b3aa8) so that I can view structures as blueprints.
  • As a user, I want saved homes (heart buttons) to persist to localStorage and surface in the contact overlay so that my saves carry through the experience and across visits.
  • As a user, I want the exploded toggle to drive setExplode on the active tower so that I can separate/reassemble a tower.
  • As a system, I want quality to auto-step high → medium → low under frame-time pressure so that performance is maintained.
  • As a user, I want custom range sliders (.vs-range in index.css) with a 3px track rgba(28,25,23,0.12) and a square orange thumb #e65100 with white border and orange glow that rotates 45° and scales on hover (mortgage/payment calculator styling) so that sliders feel on-brand.
  • As a user, I want a film-grain architectural overlay (body::after, fixed, low opacity, pointer-events-none) so that the site has a subtle cinematic texture.

3.7 Motion Direction

  • As a user, I want scroll-driven camera moves and city construction growth so that the signature effect — "the city builds itself as you scroll" — is delivered.
  • As a user, I want the exploded/assembled tower transition, floor highlight, dusk/night sky crossfade, and water shimmer so that key transitions feel alive.
  • As a user, I want UI color/background transitions on pills, tabs, and buttons; an arrow nudge on button hover; a pulsing hero kicker dot; and a preloader counter so that UI motion is polished but restrained.
  • As a user, I want no floating badges, no stat-strip marquees, and no gratuitous animation so that motion stays intentional.
Page 9 of 17

3.8 Responsiveness

  • As a mobile user, I want overlay padding to adapt (p-4 md:p-8 / p-6 md:p-12) so that content fits small screens.
  • As a mobile user, I want hero type to scale (text-5xl sm:text-7xl md:text-8xl) so that the hero headline is legible.
  • As a mobile user, I want record stats to use grid-cols-2 md:grid-cols-4 so that stats stack appropriately.
  • As a mobile user, I want contact layout to use grid-cols-1 lg:grid-cols-12 so that the form is usable on small screens.
  • As a mobile user, I want header pills hidden md:flex and the hero scroll hint hidden sm:flex so that small screens aren't cluttered.
  • As a mobile user, I want tabs to wrap (flex-wrap, max-w-[94vw] on district chips) so that controls remain accessible.

3.9 Faithful Reproduction

  • As a stakeholder, I want the same brand reproduced — "Vanguard & Stone" and "River District" — so that the site matches the intended identity exactly.
  • As a stakeholder, I want the same copy reproduced exactly ("Live above the river.", "Scroll — the city builds itself", "The keys are waiting.", "Received — an advisor replies within 24h.") so that the approved messaging is preserved.
  • As a stakeholder, I want the same palette reproduced (#E65100, stone neutrals, #0b3aa8, white/85–90 glass) so that the visual identity is consistent.
  • As a stakeholder, I want the same fonts reproduced (Fraunces / Plus Jakarta Sans / JetBrains Mono) so that typographic character is preserved.
  • As a stakeholder, I want the same section map reproduced (hero / build / residences / district / record / contact with their progress ranges) so that the narrative structure is preserved.
  • As a stakeholder, I want the same 600vh scroll architecture reproduced so that the single continuous scroll-driver behavior is preserved.
  • As a stakeholder, I want the same scroll-driven Three.js construction-growth technique reproduced so that the signature "city builds itself" mechanism is preserved.

3.10 User-Directed Enhancement

  • As a user, I want the 3D scene to be improved/better so that the world looks and feels higher quality than the base specification.
  • As a user, I want better transformations so that tower and city transitions (explode/assemble, growth, phase changes) feel more refined.
  • As a user, I want better movements so that camera and scene motion feel more cinematic and fluid.
  • As a user, I want better scroll so that the scroll-driven experience feels smoother and more responsive.
Page 10 of 17

4. User Personas

  • Prospective Resident (Private Client) — A high-net-worth individual exploring the River District. Their accepted workflow: scroll through the Overview and The Rise to experience the city building itself; browse Residences to switch projects, orbit towers, toggle exploded views, hover/select floors to open the floor-plan modal, and save homes; explore District to inspect neighborhood pins and filter amenities; review Record for credibility stats; and submit a private inquiry via the contact form, where saved homes and the address are shown and a success confirmation appears. This is the single active product persona — every active workflow in the source (explore scroll narrative, browse residences, inspect floor plans, save homes, filter district pins, submit inquiry, control time/blueprint/audio) belongs to this person.
  • Motion-Sensitive Visitor — A visitor with prefers-reduced-motion: reduce who loads the site and needs Lenis and heavy motion disabled while content and overlays remain reachable. Their successful outcome is that the narrative sections, controls, and inquiry flow stay usable without heavy motion.

System Actors (not product personas):

  • 3D Scene Engine — renders the persistent world, owns raycasting, camera direction, and post-processing.
  • Scroll Engine — owns the single rAF loop and fans out frame/section events.
  • UI Store — holds discrete state and persists saved homes to localStorage.

External Recipients:

  • Sales Advisor — receives inquiries submitted via the contact form ("Received — an advisor replies within 24h.").
Page 11 of 17

5. Core User Flows

Flow 1 — Arrival & Narrative Scroll (Prospective Resident)

  1. Visitor loads the site; Preloader shows the "The River District" wordmark and a mono counter stepping 0–100.
  2. On onComplete, the Hero Overlay appears over the persistent 3D world with the pulsing "River District" kicker, the "Live above the river." headline, the 3 towers · 165 m · 2027 sub-line, and the scroll hint.
  3. Visitor scrolls; Lenis smooth scroll drives global progress. As progress enters the build section, the camera performs a crane-like move and the city construction grows through DATUM → RISE → FAÇADE → REALM → LIFE, with the build overlay showing phase code, phase title, elevation, and phase progress bar.
  4. Visitor pauses, drags to orbit, and moves the mouse to apply parallax.

Flow 2 — Exploring Residences (Prospective Resident)

  1. Visitor selects "Residences" (nav pill, hero button, or keyboard), and the camera orbits the active tower anchor.
  2. Visitor switches project tabs (The Spire / Skybridge One / River Terraces); the unit card updates with tagline, name, from {price}, and availability.
  3. Visitor toggles Exploded/Assembled (setExplode) to see the axonometric separation.
  4. Visitor hovers a floor slab → hoverTip tooltip appears; clicks a slab → floor is selected, highlighted in 3D, and FloorPlanModal opens.
  5. In the modal, the SVG plan renders from rooms; hovering a room updates the footer to {room.name} — {room.finish}; footer stats show area, bed, bath.
  6. Visitor clicks the heart on a floor row to save it (persisted to localStorage under vs-saved-homes-v1 as projectId:floorNumber).

Flow 3 — Exploring the District (Prospective Resident)

  1. Visitor scrolls into the district section; the camera gives an elevated overview of pins.
  2. Visitor hovers/clicks a district pin (Express Metro, Central River Park, Marina Promenade, Avenue Roastery); activePinId is set and the active pin card shows name, MapPin, and walk time.
  3. Visitor uses filter chips to narrow amenity categories.

Flow 4 — Setting Atmosphere & View (Prospective Resident)

  1. Visitor uses the header time-of-day segmented control (auto/day/golden/night); timePreference updates and the sky rig crossfades palettes (with fog/light and water shimmer) via the dusk blend.
  2. Visitor toggles Blueprint X-Ray via the DraftingCompass button or the B key; materials switch to #0b3aa8 blueprint style.
  3. Visitor toggles the audio control to enable the ambient soundscape; soundscape.updateScroll(p) is fed from the frame loop.

Flow 5 — Record & Inquiry (Prospective Resident → External Recipient)

  1. Visitor scrolls to Record; the camera composes a settled frame and the four RECORD_STATS cards (Years, Homes, Built realm, On time) appear.
  2. Visitor scrolls to Contact; the camera composes a final frame and the inquiry grid appears.
  3. Visitor completes Full name / Email and clicks "Request private gallery"; the button shows "Sending…".
  4. On success, the emerald success state ("Received — an advisor replies within 24h.") and "Send another" link appear.
  5. The right column shows the saved-homes summary (from savedHomes) and the address block "14 Quai de Saint-Jude" with MapPin. The inquiry is delivered to a Sales Advisor as an external recipient.

Flow 6 — Reduced Motion (Motion-Sensitive Visitor)

  1. Visitor with prefers-reduced-motion: reduce loads the site; Lenis and heavy motion are disabled while content and overlays remain reachable.
Page 12 of 17

6. Visuals, Colors, and Theme

Brand & Typography (exact): Single Google Fonts link loading Fraunces, JetBrains Mono, and Plus Jakarta Sans. Tailwind v4 @theme in src/index.css:

  • --font-serif: 'Fraunces', Georgia, serif
  • --font-sans: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif
  • --font-mono: 'JetBrains Mono', monospace

Body: bg-[#f4f2ec] antialiased overflow-x-hidden. App root: bg-[#eef1f2] text-stone-900 selection:bg-[#E65100] selection:text-white.

Palette (exact):

  • Accent orange #E65100 (hover #D84300, shadow shadow-orange-900/20)
  • Ink stone-900; muted stone-400 / 500 / 600; hairlines border-stone-900/8 and /10; chips bg-stone-900/5
  • Blueprint blue #0b3aa8
  • Success emerald-700 on emerald-100
  • Glass panels bg-white/85 or bg-white/88 + backdrop-blur-md + border border-stone-900/10 + shadow-lg / shadow-xl / shadow-2xl
  • Page bg #eef1f2 (app) over #f4f2ec (body)

Sky Palettes (shader): day zen #6fa8d8 / mid #bfd9ec / hor #f2ede2; golden zen #5b7fb4 / mid #e8a878 / hor #ffd9a0; night zen #04060e / mid #0a1428 / hor #1c2c46; fog day #dce7ee.

Theme Character: Warm-neutral stone canvas, glass panels over a living 3D world, a single hot orange accent for action and emphasis, blueprint blue reserved for X-ray mode, emerald for success/availability. Editorial serif display type against mono labels and sans body text. A subtle fixed architectural film-grain overlay (body::after) adds cinematic texture.

Page 13 of 17

7. Signature Design Concept

The signature concept is "the city builds itself as you scroll." A single 600vh scroll track transforms a raw construction site into a glowing living city, with a persistent Three.js world behind fixed HTML overlays. The 3D scene is the hero — the HTML is a restrained glass-and-stone editorial layer floating above it. Scroll is the primary input; the camera is a director operating through six composed sections (Overview → The Rise → Residences → District → Record → Inquire), and the construction narrative advances through five explicit phases (DATUM → RISE → FAÇADE → REALM → LIFE) with matching elevation readouts. Motion is intentional and limited, with no floating badges, marquees, or gratuitous animation.

8. Interaction Model & Motion Direction

Interaction Model:

  • Scroll (Lenis, duration 1.15) is the primary driver of narrative, camera, and construction growth.
  • 3D interaction: drag to orbit, mouse parallax, hover slabs for tooltips, click slabs to select + open the floor plan, click district pins to activate.
  • Keyboard: ArrowDown/ArrowRight next section, ArrowUp/ArrowLeft previous section, B toggles blueprint X-ray (ignored while typing in inputs).
  • Controls: time-of-day segmented control, blueprint toggle, saved-homes heart with count, audio toggle, exploded toggle, project tabs, district filter chips.
  • Persistence: saved homes persist to localStorage (vs-saved-homes-v1) and surface in the contact overlay.

Motion Direction (only intentional motion):

  1. Scroll-driven camera moves and city construction growth — the signature effect.
  2. Exploded/assembled tower transition, floor highlight, dusk/night sky crossfade, water shimmer.
  3. UI color/background transitions on pills, tabs, and buttons; arrow nudge on button hover; pulsing hero kicker dot; preloader counter.
  4. No floating badges, no stat-strip marquees, no gratuitous animation.
  • prefers-reduced-motion disables Lenis and heavy motion.
Page 14 of 17

9. Non-Functional Requirements

  • Performance: A single requestAnimationFrame loop owned by scrollEngine; React components never re-render per frame (state changes only at discrete section boundaries); city geometries merged via mergeGeometries; FPS-based auto quality degradation (high → medium → low).
  • Rendering: WebGL rendering through EffectComposer with RenderPass → UnrealBloomPass → ShaderPass → OutputPass; bloom driven by exposed glowMaterials.
  • Accessibility: prefers-reduced-motion: reduce disables Lenis and heavy motion; full keyboard section navigation and B blueprint toggle; keyboard shortcuts ignored during input entry.
  • Responsiveness: Overlay padding p-4 md:p-8 / p-6 md:p-12; hero type text-5xl sm:text-7xl md:text-8xl; record stats grid-cols-2 md:grid-cols-4; contact grid-cols-1 lg:grid-cols-12; header pills hidden md:flex; hero scroll hint hidden sm:flex; tabs wrap (flex-wrap, max-w-[94vw] district chips).
  • Persistence: Saved homes stored in localStorage under vs-saved-homes-v1 as projectId:floorNumber entries.
  • Visual fidelity: Exact fonts (Fraunces / Plus Jakarta Sans / JetBrains Mono), exact palette (#E65100, stone neutrals, #0b3aa8, white/85–88 glass), and exact copy strings preserved.
  • Motion restraint: Only the enumerated intentional motions are permitted; no gratuitous animation.
  • State management: Custom store via useSyncExternalStore; no external state library.
Page 15 of 17

10. Tech Stack

  • Framework: React 19 + TypeScript
  • Build tool: Vite (path alias @ → repo root in vite.config.ts)
  • Styling: Tailwind CSS v4 (via @tailwindcss/vite, @import "tailwindcss" + @theme in CSS — no tailwind.config)
  • 3D: three.js (including three/addons: EffectComposer, RenderPass, UnrealBloomPass, ShaderPass, OutputPass, mergeGeometries)
  • Icons: Lucide React
  • Smooth scroll: Lenis (duration 1.15)
  • Animation: GSAP / motion
  • Fonts: Fraunces, Plus Jakarta Sans, JetBrains Mono (single Google Fonts link)
  • State: custom store via useSyncExternalStore + localStorage (vs-saved-homes-v1)
  • Constraint: No other UI libraries.

File tree to produce:

index.html                     (fonts, title, body classes)
src/main.tsx · src/App.tsx · src/index.css
src/lib/scrollEngine.ts        (Lenis + single rAF loop + section map)
src/state/store.ts             (useSyncExternalStore UI store)
src/data/residences.ts         (phases, projects+floors+rooms, pins, stats)
src/types/index.ts
src/utils/audio.ts
src/three/SceneEngine.ts · cameraDirector.ts · cityBuilder.ts · heroTowers.ts · skyRig.ts · textures.ts
src/components/Preloader.tsx · Header.tsx · ElevationGauge.tsx · StatusBar.tsx · CustomCursor.tsx
src/components/HeroOverlay.tsx · BuildOverlay.tsx · ResidencesOverlay.tsx · DistrictOverlay.tsx · RecordOverlay.tsx · ContactOverlay.tsx · FloorPlanModal.tsx · ThreeScene.tsx
Page 16 of 17

11. Assumptions and Constraints

  • Single-page scroll narrative: The product is one continuous 600vh scroll experience — not a multi-page site or application.
  • Exact brand reproduction: Brand name ("Vanguard & Stone", River District), section names, and copy ("Live above the river.", "Scroll — the city builds itself", "The keys are waiting.", "Received — an advisor replies within 24h.") must be preserved exactly.
  • Exact fonts and palette: Fraunces / Plus Jakarta Sans / JetBrains Mono and the specified hex palette must be used as given.
  • Tailwind v4 without config file: No tailwind.config; theme defined via @theme in CSS.
  • No other UI libraries: Only React 19, TypeScript, Vite, Tailwind CSS v4, three.js, Lucide React, Lenis, and GSAP/motion.
  • Fixed section map: Global progress ranges and build-phase sub-ranges are fixed as specified.
  • Single rAF loop: Only scrollEngine may own a requestAnimationFrame loop; React must not re-render per frame.
  • LocalStorage schema: Saved homes use key vs-saved-homes-v1 with projectId:floorNumber entries.
  • WebGL dependency: The experience requires WebGL; quality auto-degrades under load.
  • Reduced motion: Lenis and heavy motion must disable under prefers-reduced-motion: reduce.
  • Enhancement directive: The build should improve 3D quality, transformations, movements, and scroll relative to the base specification, without violating the constraints above.
  • Document hygiene: No header metadata, author, date, or placeholder fields belong in this SRD.
  • Project codename: The project is named ultra-do; the user-facing brand remains "Vanguard & Stone" / "River District" and must not be renamed.
Page 17 of 17

12. Glossary

  • 600vh Scroll Track: The single continuous scroll spacer (h-[600vh]) that drives the entire narrative.
  • scrollEngine: The module owning the only requestAnimationFrame loop, driving Lenis, computing global progress, and fanning out frame/section events.
  • Section Map: The fixed mapping of global progress ranges to the six narrative sections (hero, build, residences, district, record, contact).
  • Build Phases: The five construction phases within the build section — DATUM, RISE, FAÇADE, REALM, LIFE.
  • Lenis: The smooth-scroll library (duration 1.15).
  • SceneEngine: The WebGL renderer + post-processing composer module and raycast picking system.
  • EffectComposer: The three.js post-processing chain (RenderPass → UnrealBloomPass → ShaderPass → OutputPass).
  • cityBuilder: The procedural city generator that grows buildings as the user scrolls.
  • heroTowers: The three hero towers rendered as stacks of floor slabs matching the residences data.
  • skyRig: The gradient sky dome shader with sun/moon tracking, fog/light palettes, and canal water shader.
  • cameraDirector: The section-aware analytic camera system with heavy exponential damping.
  • textures: The 2D-canvas texture generators for facades, clouds, and glow sprites.
  • Blueprint X-Ray: A materials mode rendering structures in blueprint blue #0b3aa8, toggled by control or B key.
  • Exploded View: An axonometric view separating a tower's floor slabs, driven by setExplode(0..1).
  • hoverTip: The tooltip state produced when hovering a floor slab in 3D.
  • Saved Homes: Units bookmarked by the user via heart buttons, persisted to localStorage.
  • Quality Tiers: The high / medium / low render quality levels chosen automatically under frame-time pressure.
  • dusk: A 0..1 shader value blending sky/light palettes between day, golden hour, and night.
  • Time Preference: The user or auto setting ('auto' | 'day' | 'golden' | 'night') controlling the sky rig.
  • Floor Plan Modal: The SVG floor-plan viewer drawn from a unit's rooms geometry.
  • RECORD_STATS: The four credibility figures (Years, Homes, Built realm, On time).
  • NEIGHBORHOOD_PINS: The four district amenity pins with categories and walk times.
  • Preloader: The full-screen loading screen with wordmark and mono progress counter.
  • Faithful Reproduction: The requirement to preserve the same brand, copy, palette, fonts, section map, 600vh scroll architecture, and scroll-driven Three.js construction-growth technique.
Landing design preview
Landing: Load site with reduced motion
Landing: View Overview with motion off
Landing: Scroll narrative with Lenis off
Landing: Browse Residences without heavy motion
Landing: Inspect neighborhood pins
Landing: Review Record stats
Landing: Set atmosphere controls
Landing: Open inquiry form
Landing: Submit private inquiry
Landing: View static success confirmation
Landing design preview
Landing: Load site with reduced motion
Landing: View Overview with motion off
Landing: Scroll narrative with Lenis off
Landing: Browse Residences without heavy motion
Landing: Inspect neighborhood pins
Landing: Review Record stats
Landing: Set atmosphere controls
Landing: Open inquiry form
Landing: Submit private inquiry
Landing: View static success confirmation