🪄
Source of truth: ResVR Interior UI
— This system governs the 3D visualizer, interior customizer, and any product-side UI.
Do not apply these tokens to the marketing site.
Color Palette
Brand Accent — Dark Mode
Base Surfaces — Dark Mode
Text Colors — Dark Mode
white/70
rgba(255,255,255,0.7)
white/50
rgba(255,255,255,0.5)
white/30
rgba(255,255,255,0.3)
On dark backgrounds: text-white (primary) · text-slate-300 / white/70 (secondary) · text-slate-400 / white/50 (tertiary) · text-slate-500 / white/30 (disabled)
Brand Accent — Light Mode
teal-500/10
rgba(20,184,166,0.10)
Accent bg
teal-500/15
rgba(20,184,166,0.15)
Semantic — Option Tiers
Colors
Tier Badge
Values
Standard — Included
text: #34d399 · bg: rgba(52,211,153,0.10) · border: rgba(52,211,153,0.25)
Level 1 — Up to $1.5k
text: #60a5fa · bg: rgba(96,165,250,0.10) · border: rgba(96,165,250,0.25)
Level 2 — Up to $3k
text: #fbbf24 · bg: rgba(251,191,36,0.10) · border: rgba(251,191,36,0.25)
Level 3 — Up to $5k
text: #c084fc · bg: rgba(192,132,252,0.10) · border: rgba(192,132,252,0.25)
Level 4 — $5k+
text: #fb7185 · bg: rgba(251,113,133,0.10) · border: rgba(251,113,133,0.25)
Semantic — Status & Actions
Colors
Label
Usage
✓ Complete / Success
text: #34d399 · bg: rgba(52,211,153,0.15) · completed items, success states
Exit / Danger
text: #f87171 · bg: rgba(239,68,68,0.15) · exit button, clear all, destructive actions
Finalize / Primary CTA
gradient: linear-gradient(90deg, #06b6d4, #22d3ee) · primary CTAs, Finalize Selections button
Secondary / Ghost
bg: rgba(255,255,255,0.1) or bg-slate-800 · text: rgba(255,255,255,0.7) · END TOUR, secondary actions
Glass & Alpha Overlays
Semi-transparent color tokens used throughout the glass UI — panel backgrounds, borders, hover states, and active highlights. All values are applied over a dark surface; shown below on slate-900 so you can see them.
white/10
rgba(255,255,255,0.10)
Default border
white/7
rgba(255,255,255,0.07)
Subtle divider
white/5
rgba(255,255,255,0.05)
Section bg
white/8
rgba(255,255,255,0.08)
Hover state
white/15
rgba(255,255,255,0.15)
Active tab bg
white/40
rgba(255,255,255,0.40)
Light border
cyan-400/20
rgba(34,211,238,0.20)
Active icon bg
cyan-400/15
rgba(34,211,238,0.15)
Display toggle bg
slate-900/70
rgba(15,23,42,0.70)
Glass panel
slate-900/90
rgba(15,23,42,0.90)
Elevated panel
slate-900/95
rgba(15,23,42,0.95)
Modal / popover
slate-900/80
rgba(15,23,42,0.80)
Toolbar bg
Glow / Shadow Colors
Selected option
rgba(6,182,212,0.5)
Mic button glow
rgba(34,211,238,0.4)
Slider thumb
rgba(34,211,238,0.6)
Position dot
rgba(34,211,238,0.5)
AI avatar border
rgba(34,211,238,0.3)
Typography
Font: Inter · Weights: 300 / 400 / 500 / 600 / 700 / 800 · fonts.google.com/specimen/Inter
Inter is the only font used throughout the entire product UI — mode rail, sidebar, panels, tooltips, overlays, bottom bar, AI transcript, all badges. No other typefaces.
Role Size Weight Notes Sample
section-header
18px 300 + 700
light + bold cyan pop
Customize Interior
body
14px 500
menu items, labels
Countertop Selection
label-sm
12px 500–600
secondary labels
Kitchen · 3/5 complete
micro
10–11px 700
uppercase, tracking-wider
Guided Tour
nano
9px 700
badges, option names
Standard
Glass Morphism System
The defining visual pattern of all product UI. Every surface uses backdrop-blur-xl with semi-transparent slate backgrounds.
Floating / 70%
bg-slate-900/70
Nav rail, sidebar, bottom bar
Panel / 90%
bg-slate-900/90
Options gallery, overlays
Modal / 95%
bg-slate-900/95
Popovers, confirm dialogs
Light Mode / 70%
bg-white/70
All panels, light theme
Border: border border-white/10 (dark) · border border-white/40 (light) · Shadow: shadow-2xl
▶ Component → Glass Tier Mapping — 13 components
Yes — every panel in the app uses one of these 4 tiers. No exceptions.
Component
Tier
BG class
Hex (approx)
Left Mode Rail Floating / 70% bg-slate-900/70 rgba(15,23,42,0.70)
Floating Toolbar Floating / 80% bg-slate-900/80 rgba(15,23,42,0.80)
Sidebar Panel Panel / 90% bg-slate-900/90 rgba(15,23,42,0.90)
Bottom Status Bar Floating / 70% bg-slate-900/70 rgba(15,23,42,0.70)
Options Gallery Panel / 95% bg-slate-900/95 rgba(15,23,42,0.95)
Settings/Controls Panel Modal / 92% bg-slate-900/92 rgba(15,23,42,0.92)
Rooms/Teleport Panel Panel / 90% bg-slate-900/90 rgba(15,23,42,0.90)
Your Selections Panel Modal / 95% bg-slate-900/95 rgba(15,23,42,0.95)
AI Transcript Bubble Panel / 90% bg-slate-900/90 rgba(15,23,42,0.90)
AI Avatar Card Panel / 90% + cyan glow border bg-slate-900/90 border-cyan-400 + box-shadow 0 0 20px rgba(34,211,238,0.3)
Tooltip Solid (no blur) bg-slate-800 #1e293b (solid)
Navigation Minimap Panel / 95% bg-slate-900/95 rgba(15,23,42,0.95)
Processing / Submit Overlay Full-screen dim + Modal 95% bg-slate-900/80 (overlay) + bg-slate-900/95 (panel) backdrop-blur-sm on overlay
Light Mode (all panels) Light / 70-95% bg-white/70 → bg-white/95 rgba(255,255,255,0.70-0.95) + border-white/40
Navigation Chrome
Floating Toolbar
Top-right vertical pill · z-50
Container: 44px wide ·
Position: top: 24px right: 24px ·
Button: p-2 (8px) ·
Icons: 20 × 20px ·
Gap: 4px ·
Divider: 1px white/10 horizontal rule
Default: slate-400 icon · Hover: white + bg-white/10
Active: bg-cyan-500/20 · text-cyan-400 · Rounded-2xl · p-2 · backdrop-blur-xl
Left Mode Rail
Fixed left · 100px wide · z-50
Container: 100px wide full height ·
Padding: py-8 (32px) top/bottom ·
Design mode icons: 24 × 24px wrapper p-3 (12px) rounded-xl ·
Nav mode icons: 20 × 20px wrapper p-2.5 (10px) rounded-lg ·
Active bar: 3px wide cyan-500 left edge ·
Labels: 9–10px uppercase bold tracking-wider mt-6
Active: left-edge 3px bar (cyan-500) + icon bg-cyan-500/20
Label: 9px bold uppercase tracking-wider · Animated active indicator via Framer Motion layoutId
Design Mode Selector — Left Vertical Rail
Fixed left rail (100px wide, full height) containing two sections: Design Modes (Exterior / Interior) at top and Navigation Modes (Walk / Tour / Step-by-Step) at bottom, with a Theme Toggle at the very bottom. Source: components/Interior/DesignModeSelector.tsx
fixed left-0 top-0 bottom-0 w-[100px] z-50 · backdrop-blur-xl · bg-slate-900/70 border-r border-white/10 · flex flex-col items-center py-8
100px wide ·
Design modes: icon 24 × 24px · icon bg 48 × 48px (p-3) · rounded-xl (12px) ·
Nav modes: icon 20 × 20px · icon bg 40 × 40px (p-2.5) · rounded-lg (8px) ·
Active left bar: 3 × full-height px · label margin-top: 6px
▶ Button anatomy & class reference
Design Mode Button (Exterior / Interior)
Active left-edge bar: absolute left-0 top-0 bottom-0 w-1 bg-cyan-500 — layoutId="activeDesignModeBorder" (Framer shared layout)
Active icon bg: bg-cyan-500/20 text-cyan-400 stroke-[2.5px]
Inactive icon: text-slate-400 group-hover:text-white group-hover:bg-white/5
Navigation Mode Button (Walk / Tour / Step-by-Step)
Smaller than design modes: p-2.5 rounded-lg w-5 h-5
Active: bg-white/10 text-white stroke-[2.5px]
Inactive: text-slate-500 group-hover:text-white group-hover:bg-white/5
No left-edge bar for nav modes — only design modes use the indicator
Theme Toggle
Icon: sun (dark mode → switch to light) / moon (light → dark)
Position: bottom of rail, pb-6
▶ States
State Visual Classes / Styles
Design mode: Active Cyan left bar + cyan icon bg + cyan text, stroke 2.5 w-1 bg-cyan-500 (bar) · bg-cyan-500/20 text-cyan-400 · stroke-[2.5px]
Design mode: Hover Icon bg appears white/5, text brightens to white group-hover:text-white group-hover:bg-white/5
Design mode: Inactive Slate-400 icon, slate-500 text, no bg, stroke 2 text-slate-400 label:text-slate-500 stroke-2
Nav mode: Active bg-white/10 icon bg, white icon + text, stroke 2.5 — NO left bar bg-white/10 text-white stroke-[2.5px]
Nav mode: Hover Same as active bg (white/10), text white group-hover:text-white group-hover:bg-white/5
Nav mode: Inactive Slate-500 icon + slate-600 label, invisible bg text-slate-500 label:text-slate-600
Active indicator animation Slides between design mode buttons (layoutId shared) motion.div layoutId="activeDesignModeBorder" spring
Theme toggle hover bg-white/10 bg, icon turns white hover:text-white hover:bg-white/10
Bottom Status Bar
Full-width · h-50px · absolute bottom-0 · see detailed spec below ↓
The Cascade
62%
Customized
Standard Bottom Bar (Default / Walk Mode)
Default bottom bar rendered when NOT in guided tour mode. 50px height. Left: builder logo + model name + customization %. Right: segmented Navigation / Rooms control. 2px cyan progress bar runs along top edge tracking customization percentage. Source: components/Interior/InteriorBottomBar.tsx
absolute bottom-0 right-0 left-[computedLeft] z-20 · h-[50px] · backdrop-blur-xl · bg-slate-900/70 border-t border-white/10
Bar height: 50px ·
Progress bar: 2px top edge, cyan-500 + glow ·
Left offset: 100px (sidebar closed) → 360px (sidebar open, 400ms ease) ·
Logo area: padding-left 16px · Nav/Rooms btns: p-2 · Icons: 14 × 14px
Landmark Homes
The Bellevue
65%
Customized
▶ Implementation notes
Left offset: computedLeft = sidebarOpen ? 260 : 0 — slides right when sidebar is open
Progress bar: h-[2px] bg-cyan-500 shadow-[0_0_10px_rgba(6,182,212,0.5)] width:{customizationPercent}%
Navigation btn active: bg-white/10 text-white chevron-down · inactive: transparent text-white/50 chevron-up hover:bg-white/5
Rooms btn: same pattern — layout-grid icon always visible
▶ States
State Visual Classes / Styles
Sidebar closed Bar spans full width from left-0 left: 0 (100px rail is fixed above)
Sidebar open Bar shifts right to avoid sidebar overlap left: 260 · transition-all 400ms ease
Navigation: open bg-white/10 bg, white text, chevron-down showNavigation → bg-white/10 text-white + chevron-down
Navigation: closed Transparent bg, muted text, chevron-up transparent text-white/50 hover:text-white hover:bg-white/5 + chevron-up
Rooms: open bg-white/10 bg, white text showRoomsPanel → bg-white/10 text-white
Progress 0% Bar width 0, just the track bg visible width: 0%
Progress 100% Full width cyan bar with glow width: 100% bg-cyan-500 shadow-[0_0_10px_rgba(6,182,212,0.5)]
Tour Mode — Guided Tour Bottom Bar
Replaces the standard bottom bar when isGuidedTourActive=true. Taller (60px vs 50px), cyan progress bar along top edge, live-dot indicator, room navigation. A separate "MENU" pill button appears top-left when sidebar is collapsed. Source: components/Interior/InteriorBottomBar.tsx
absolute bottom-0 right-0 left-[100px] z-20 · h-[60px] · backdrop-blur-xl · bg-slate-900/90 border-t border-cyan-500/20
Bar height: 60px ·
Progress bar: 3px ·
Left offset: fixed 100px (always, ignores sidebar) ·
Prev/Next btns: p-2 (8px) · skip icons 16 × 16px ·
Live dot: 6px ·
See diff notes below for class-level comparisons vs standard bar
Menu Pill (sidebar collapsed in tour)
Menu
Border color: border-cyan-500/20 vs standard border-white/10
Height: h-[60px] vs h-[50px]
Progress bar: h-[3px] bg-gradient-to-r from-cyan-500 to-cyan-400 shadow-[0_0_12px_rgba(6,182,212,0.6)] vs standard h-[2px] bg-cyan-500
Live dot: relative flex span animate-ping + inner solid dot — Tailwind ping animation
▶ States
State Visual Classes / Styles
Playing Live dot pulsing, progress bar advances per room animate-ping · progress width updates via tourProgress %
First room Prev (skip-back) button dimmed/disabled disabled opacity-30 cursor-not-allowed
Last room Next (skip-forward) dimmed, End Tour more prominent disabled opacity-30 cursor-not-allowed
Prev/Next hover bg-white/10 tint on hover hover:bg-white/10 text-white
End Tour hover bg-white/10 tint, text goes full white hover:bg-white/10 hover:text-white border-white/15
MENU button hover bg-white/10, text fully white hover:bg-white/10 hover:text-white
Rooms / Teleport Panel
Triggered from the ROOMS button in the bottom bar. Lists rooms with contextual Lucide icons (cyan) and white room name text.
rounded-2xl · backdrop-blur-xl · scrollable room list
Panel: 260px wide · border-radius 16px (rounded-2xl) ·
Header: h-10 (40px) px-5 ·
Room row: ~44px tall px-5 py-2.5 gap-3.5 ·
Room icon: 16 × 16px cyan-400 ·
Room label: 14px font-medium
Teleport
Kitchen
Basement
Primary Bedroom
Ensuite
Laundry
Bedroom 2
Bedroom 3
Room icons used: chef-hat
arrow-down-to-line
bed-double
bath
shirt
bed
Navigation Minimap
Triggered from NAVIGATION button in the bottom bar. Shows a floor plan with a position dot (cyan-400) and view cone (teal). Rounded-2xl glass panel.
Panel: ~260 × 260px · border-radius 16px (rounded-2xl) ·
Position dot: 12px diameter (w-3 h-3) cyan-400 ·
View cone: ~24px base SVG teal ·
N compass: top: 8px right: 8px · font-size 10px
Floor plan image rendered here
N
Position dot: bg-cyan-400 · w-3 h-3 · rounded-full
View cone: teal cone SVG · rotates with camera direction
N compass: top-right corner
Container: rounded-2xl backdrop-blur-xl
Settings & Controls
Settings & Controls Panel
w-80 · rounded-2xl · backdrop-blur-xl · fixed top-6 right-24 · z-40 · shown: Settings tab / Controls tab collapsed / Controls tab with How to Navigate expanded
Panel: 320px wide (w-80) ·
Position: top: 24px right: 96px ·
Border-radius: 16px (rounded-2xl) ·
Tab icons: 12 × 12px · Close icon: 14 × 14px ·
Content padding: 16px · Section gaps: 20px
Time of Day
Morning
Day
Evening
How to Navigate
Right Click
Collapse menus / Free navigation
How to Navigate — Keyboard Guide
Exists in two forms: Inline (collapsible section at the bottom of the Controls panel) and Standalone Modal (triggered by the keyboard icon — 4th button — in the floating toolbar). Same 5 cards, same SVGs, larger presentation in the modal.
SVG diagrams have dark/light color variants (cyan-400 dark / teal-600 light). MOVE card cycles WASD ↔ arrow keys every 2.5s.
5 cards · 2-col grid + 1 full-width row · rounded-xl · bg-white/5 dark
Right Click
Collapse menus / Free navigation
Rotate freely when activated
Standalone Modal — Triggered via Keyboard Icon (Toolbar)
Centered modal · rounded-xl · bg-slate-900/95 · backdrop-blur-xl · max-w-xl · triggered by keyboard icon (4th button in floating toolbar)
Right Click
Collapse menus / Free navigation
Rotate freely when activated
Mode Panels
Interior Sidebar — Tree Menu
Left-side navigation panel (260px wide) with collapsible category headers, subcategories, and leaf items. Tracks completion state per item. Search with alias support. Source: components/Interior/InteriorSidebar.tsx
w-[260px] · absolute top-0 left-[100px] bottom-0 z-40 · backdrop-blur-xl · bg-slate-900/70 border-r border-white/10
Panel: 260px wide ·
Offset: left: 100px (after mode rail) ·
Search input: h-9 (36px) px-3 ·
Category header: h-10 (40px) px-3 ·
Leaf item: h-8 (32px) px-3 ·
Collapse toggle pill: 20px wide · position: left-[360px] (open) / left-[100px] (closed)
Customize Interior
Customize finishes & fixtures
M
Main Options
(2/32)
Kitchen
2/5
Range Oven
Countertop
Refrigerator
Dishwasher
Microwave
Flooring
0/8
▶ Item anatomy & class reference
Category Header
Letter badge (first char) · category name · (completed/total) · chevron
Completed: bg-cyan-500/20 border-cyan-500/35 text-cyan-400
Default: bg-white/5 border-white/10 text-white/40
Leaf Item
Bullet dot → cyan when active, white/30 default
Completed: bg-emerald-500/20 check icon text-emerald-400
Selected: bg-cyan-500/15 text-white font-medium
AI-enhanced: sparkles icon text-white/20 (DEMO_ITEMS set)
Collapse Toggle
Pill tab on right edge of sidebar: chevron-left (open) / chevron-right + "MENU" (closed)
Animates with sidebar: left: isCollapsed ? 100 : 360
Step-by-Step Mode Panel
Anchored to the bottom of the InteriorSidebar when isStepByStep=true. Shows progress indicator, step navigation, and a camera views carousel. Source: InteriorSidebar.tsx → AnimatePresence bottom panel.
flex-shrink-0 · flex flex-col · p-5 · border-t · backdrop-blur-xl · bg-slate-900/95 · z-10 · anchored bottom of sidebar
Width: 260px (inherits sidebar) ·
Padding: 20px all sides (p-5) ·
Progress bar: h-1.5 (6px) rounded-full ·
Prev/Next arrows: 44 × 44px (w-11 h-11) ·
Camera thumb: 64 × 48px rounded-lg ·
Camera count tabs: 28px min-w
Camera thumbnail
Active
Kitchen Overview
▶ Props & implementation notes
Props
stepIndex / totalSteps → progress %
currentStepItem.name → center label
currentStepCategory → uppercase muted label
cameraViews[] → thumbnail carousel
cameraViewCount 2|3|4 → tab toggle
Camera Tab States
Default: text-white/40
Active: bg-cyan-500 text-black
Camera Thumbnail
Active view: border-cyan-500 + "ACTIVE" badge + cyan dot
Inactive: border-white/10 opacity-60
No cameras: fallback to "Switch View" button w/ RefreshCw
▶ States
State Visual Classes / Styles
Progress bar Animates width to (stepIndex+1)/totalSteps × 100% h-1.5 bg-cyan-500 motion animate width
Prev arrow (first step) Hidden (empty spacer div renders) w-[44px] invisible placeholder
Arrow hover Border brightens, bg tint hover:bg-white/5 border-white/10
Camera thumb: selected carousel pos White-tinted border (even if not active stream) border-white/50 opacity-100
Camera thumb: active stream Cyan border glow + cyan dot top-right border-cyan-400 shadow-[0_0_8px_rgba(6,182,212,0.25)]
Intro animation Slides up from bottom on isStepByStep=true initial y:100 → animate y:0 via AnimatePresence
AI Mode — Assistant Overlay
Full-screen pointer-events overlay that activates when AI mode is selected. Contains: avatar type selector pill (top-left), avatar card + mic controls (bottom-right), and transcript bubble (bottom-center). Three avatar variants: Human (photo), Orb (radial bar visualizer), Orb Alt (layered SVG soundwave). Source: components/Interior/AssistantOverlay.tsx
fixed inset-0 z-[55] pointer-events-none · children use pointer-events-auto
Avatar Type Selector (top-left, absolute top-20 left-28)
Human
Orb
Orb Alt
Human Avatar (speaking state — cyan glow)
Orb Avatar
56 radial SVG bars around a cyan gradient circle with ResVR logo. Bar heights randomise at 100ms (speaking) / 150ms (listening) / 400ms (idle).
Orb Alt Avatar
3-layer SVG soundwave SVGs (black/dark-teal/light-teal) composited over a white→cyan gradient circle + ResVR logo. Each layer rotates/scales at different speeds per voice state.
Transcript Bubble (bottom-center, absolute)
Speaking state (AI responding)
Welcome! You're currently in the kitchen. I can see you have the standard countertop selected. Would you like me to show you the premium quartz options?
Listening state (user speaking)
Idle state (waiting for input)
RESVR AI
Say something to get started...
Mode Rail: AI Active State
Icon bg: bg-cyan-500/20 rounded-lg + sparkles icon cyan
Label: text-cyan-400
Live indicator: small green dot above icon — w-1.5 h-1.5 bg-emerald-400 absolute top-0.5 right-0.5 animate-pulse
▶ States
State Visual Classes / Styles
Idle Mic button muted slate bg, transcript shows "Say something..." bg-slate-700 text-slate-400 (isMuted or voiceState idle)
Listening Mic button cyan glow, pulse ring, transcript shows "You" + pulsing dot bg-cyan-500 shadow-[0_0_15px_rgba(34,211,238,0.5)] · ping scale animation
Speaking (AI) Audio bars animate in transcript header, typewriter text reveal, cursor blink bars: h animate [3,10,3] stagger 0.1s · cursor opacity [1,0,1]
Muted Mic icon switches to mic-off, button turns slate isMuted → bg-slate-700 text-slate-400 · mic-off icon
Avatar: Human (speaking) Cyan gradient glow halo + border-cyan-400/60 -inset-1.5 rounded-2xl bg-gradient-to-br from-cyan-400/40 blur-sm
Avatar: Orb (speaking) Bars update at 100ms, center circle scale [1, 1.03, 1] setInterval 100ms · scale motion animate
Avatar: Orb Alt (speaking) All 3 SVG layers rotate/scale fast ([0,6,-5,3,0]), duration 1.2s rotate [0,6,-5,3,0] scale [1,1.06,0.95,1.04,1] repeat Infinity
Avatar type switch AnimatePresence mode="wait", scale 0.8→1, y 30→0 initial scale:0.8 y:30 → animate scale:1 y:0 duration 0.4s spring
End button hover bg-white/10, text goes white hover:bg-white/10 hover:text-white border-white/15
Selection & Options
Options Gallery
Horizontal scrollable strip anchored at the bottom of the 3D viewport (above the bottom bar). Shows upgrade options as thumbnail cards with tier badges, tier filter dropdown, search, and expand-to-grid mode. Source: components/Interior/OptionsGallery.tsx
max-w-5xl · rounded-2xl · backdrop-blur-xl · bg-slate-900/95 · border-white/10 · bottom-[60px] above bar
Container: max-w-5xl (1024px) centered ·
Position: bottom: 60px (above tour bar) ·
Padding: p-3 (12px) ·
Cards: 140px wide 160px tall flex-shrink-0 ·
Card image area: ~110px tall · card label: 12px · card price: 11px ·
Row height (single): max-h-[190px] · expanded grid: max-h-[460px]
Range Oven
All Levels
6 of 6
Standard
Level 1
Level 2
Level 3
Level 4
Options Gallery — Tier Filter Dropdown
Opens when user clicks "All Levels". Glass popover with checkbox rows per tier + item count. Selecting a specific tier deselects "All Levels" and filters the card strip. Built with Framer Motion AnimatePresence slide-down (opacity + y:−8→0, 150ms easeOut).
bg-slate-900/98 · rounded-xl · border-white/12 · shadow-2xl · z-50 · w-[220px] · AnimatePresence y(-8)→0 opacity 0→1 150ms easeOut
Options Gallery — Search Active
Search field filters cards in real time. Count label updates ("2 of 6"). Searches option name + aliases (e.g. "stainless" matches "SS Gas"). No-results state shows empty message with search term.
Search input: border-cyan-500/60 bg-white/8 · count label updates · cards re-render filtered list
Range Oven
All Levels
2 of 6
Options Gallery — Expanded Grid View
Clicking the expand icon (maximize-2) switches the card row from horizontal scroll (flex-nowrap, maxH 190px) to a wrapped grid (flex-wrap, maxH 460px, overflow-y auto). Minimize button (minimize-2) restores single-row mode.
isExpanded=true · flex-wrap · overflow-y-auto maxH-[460px] · maximize-2→minimize-2 icon swap · framer layout animation
Range Oven
All Levels
6 of 6
Options Gallery — Card Tooltip
Info button (ⓘ) in top-left corner of card, revealed on hover. Click or hover shows a glass tooltip above the card with option name, description, tier badge, and price. Always-dark glass pill — same treatment as toolbar tooltips.
Tooltip: bg-slate-800 border-white/10 rounded-xl shadow-xl px-3 py-2.5 · absolute above card · opacity-0 group-hover:opacity-100 scale-0.95→1 duration-150ms
SS Gas Range
Level 1
Stainless steel 30" freestanding with 5 burners and convection oven.
Upgrade cost
+$1,500
+$1,500
tooltip visible
+$1,500
default (hover to reveal)
▶ States
State Visual Classes / Styles
Default / Single Row Horizontal scroll, maxHeight 190px, no wrap flex-nowrap overflow-hidden maxH-[190px]
Expanded Grid Wraps to multi-row, maxHeight 460px, scrolls vertically flex-wrap overflow-y-auto maxH-[460px]
Card Selected Cyan border, glow, cyan overlay + check border-cyan-500 shadow-[0_0_15px_rgba(6,182,212,0.4)]
Card Hover Border brightens, image scales 110% group-hover:border-white/30 group-hover:scale-110
Info Tooltip Info button (i) top-left, tooltip above, arrow pointer opacity-0 group-hover:opacity-100 → absolute tooltip
Minimized Tab Chevron-up tab at bottom edge, click to restore rounded-t-xl border-b-0 animate on isMinimized
Color Selection Widget — ColorSwatchPopover
Floating pill that appears above the OptionsGallery when the selected option has color variants. Horizontal pill (Bar mode) — the default and only active mode. Source: components/Interior/ColorSwatchPopover.tsx
rounded-full · backdrop-blur-xl · bg-slate-800/90 · border-white/10 · mb-3 (above gallery)
French Door 36" Color
Stainless
▶ States
State Visual Classes / Styles
Unselected swatch Normal size, no ring w-8 h-8 rounded-full
Selected swatch Scale 1.1, cyan ring, check icon scale-110 · -inset-[3px] border-2 border-cyan-400
Light color border Thin border so white/cream swatches are visible border border-white/20 (dark)
Hover Scale 1.1 on hover hover:scale-110 transition-all duration-200
Color name label Shows hovered name, falls back to selected name AnimatePresence mode="wait" · opacity fade
Selections Cart Widget
Floating badge in the bottom-right corner. Expands into a full selections panel. Handles the full checkout flow: review → processing → submitted. Source: components/Interior/SelectionsWidget.tsx
fixed bottom-[80px] right-6 z-[90] · rounded-2xl · backdrop-blur-xl
Badge position: bottom: 80px right: 24px (gallery closed) / bottom: 360px (gallery open) ·
Badge: ~200px wide 44px tall · padding px-4 py-2.5 ·
Count dot: 20px diameter (w-5 h-5) ·
Icon: 16 × 16px
Toast (3s after adding)
Added to selections
Range Oven – Level 1 Gas
+$1,500
Selections Panel — Review State
fixed top-8 bottom-8 right-6 w-full max-w-md z-[100] · rounded-2xl · backdrop-blur-xl · flex flex-col
Panel: 448px wide (max-w-md) ·
Position: top: 32px bottom: 32px right: 24px ·
Header padding: 20px (p-5) ·
Item rows: ~72px tall · thumbnail: 56 × 56px rounded-lg ·
Footer (total + CTA): p-4 (16px)
Your Selections
2 upgrades selected
IMG
Main Options
Range Oven
Level 1 Stainless Gas
IMG
Main Options
Countertop
Quartz – Level 2
Total Upgrade Value
$3,000
Clear All
Finalize Selections
Selections Panel — Processing & Submitted States
Same panel shell · finalizeStep: 'processing' | 'success' · transitions via state machine
Processing (~2.5s)
Processing Your Selections
Generating selection summary...
Sending to Landmark Homes...
Preparing email confirmation...
Submitted (success)
Selections Submitted!
Your selections have been sent to Landmark Homes
Total Upgrades
2 items
Total Value
$3,000
Confirmation sent to demo@example.com
What happens next?
A design consultant will review your selections
Receive a detailed quote within 24–48 hours
Schedule a call to finalize your dream home
Continue Exploring
Start New Selection
▶ States
State Visual Classes / Styles
Empty (hidden) Widget hidden if 0 items and no toast returns null
Collapsed badge Cyan icon bg + count dot + price + chevron-up border-cyan-500/30 hover:border-cyan-500/50
Gallery open offset Badge lifts above gallery strip isGalleryOpen ? bottom-[360px] : bottom-[80px]
Panel open Backdrop + slide-in panel from right scale 0.95→1 spring · bg-black/40 backdrop
Processing Spinning border ring + 3 step items fade in border-4 border-t-transparent border-cyan-500 animate-spin
Success Spring-in check circle + summary card + what's next bg-emerald-500/20 · check-circle-2 · text-emerald-400
Selection swap arrow-left-right icon, closes panel, reopens gallery text-white/40 hover:text-cyan-400
Utility
Buttons
Primary Action
Secondary
Exit Model
Tooltip
Context-sensitive label used on toolbar buttons, icon-only controls, and option cards. 300ms show delay, 150ms Framer motion easeOut fade + scale. Four directional positions. Dark glass pill — consistent across both themes (always dark).
bg-slate-800 · text-xs font-medium · rounded · px-2.5 py-1.5 · border-white/10 · shadow-xl · scale 0.95→1 easeOut 150ms
Container: bg-slate-800 border border-white/10 rounded px-2.5 py-1.5 shadow-xl
Text: text-xs font-medium text-white
Animation: initial scale:0.95 opacity:0 → animate scale:1 opacity:1 · duration:0.15s easeOut · delay:300ms
Arrow: CSS border trick (transparent left+right, solid top/bottom in #1e293b to match bg)
▶ States
State Visual Classes / Styles
Hidden Invisible, no layout space opacity:0 scale:0.95 pointer-events-none
Appearing Fades + scales in after 300ms hover delay transition: opacity 150ms easeOut, scale 150ms easeOut
Visible Full opacity, scale 1, slate-800 bg, white text opacity:1 scale:1 bg-slate-800 border-white/10
Dismissing Immediate fade on mouse-leave (no delay on hide) exit opacity:0 duration:0.1s
⬛ Comprehensive States Reference
All interactive elements across the product UI, their states, triggers, and exact token classes. Use this as the source of truth when implementing new components or reviewing QA.
Buttons
Component State Trigger Visual / Classes
Primary CTA(Finalize, Continue) Default — bg-gradient-to-r from-cyan-600 to-cyan-400 text-white rounded-xl font-bold
Hover mouse-enter brightness-110 scale-[1.01] shadow-[0_0_20px_rgba(34,211,238,0.4)]
Active (pressed) mousedown scale-[0.98] brightness-95
Disabled 0 items / loading opacity-40 cursor-not-allowed pointer-events-none
Ghost Button(End Tour, controls) Default — border border-white/15 text-white/70 bg-transparent rounded-full
Hover mouse-enter bg-white/10 text-white
Disabled boundary reached (tour first/last) opacity-30 cursor-not-allowed
Icon Button(toolbar, controls) Default — p-2 rounded-lg text-slate-400 bg-transparent
Hover mouse-enter bg-white/10 text-white
Active (on) toggle on bg-cyan-500/20 text-cyan-400
Danger Button(Clear All) Default — text-red-400 bg-transparent border-none
Hover mouse-enter text-red-300 bg-red-500/10
Inputs & Form Controls
Component State Trigger Visual / Classes
Search Input(sidebar, gallery) Default — bg-white/5 border-white/10 text-white placeholder-slate-500 rounded-lg
Focused click / tab focus:outline-none focus:border-cyan-500/50
Has value typing X clear button appears (absolute right-2.5 text-slate-400)
Toggle Switch(settings panel) Off default bg-slate-700 w-8 h-4 rounded-full · thumb left-0.5
On click bg-cyan-500 · thumb right-0.5 · transition-all 200ms
Range Slider(settings, controls) Default — h-1.5 bg-slate-700 rounded · fill: bg-gradient-to-r from-cyan-600 to-cyan-400
Thumb always visible w-3.5 h-3.5 bg-cyan-400 rounded-full shadow-[0_0_8px_rgba(34,211,238,0.6)]
Cards & Selection Items
Component State Trigger Visual / Classes
Options Gallery Card Default — border-white/10 rounded-xl overflow-hidden flex-shrink-0
Hover mouse-enter border-white/30 · inner image scale-110
Selected click border-2 border-cyan-500 shadow-[0_0_15px_rgba(6,182,212,0.4)] + check overlay
AI Recommended AI flag in data sparkles badge absolute top-1.5 right-1.5 text-cyan-400 animate-pulse
Sidebar Leaf Item Default — text-slate-300 dot bg-white/20 hover:bg-slate-800/50 rounded-lg
Active / Selected click bg-cyan-500/15 text-white font-medium dot: bg-cyan-400
Completed selection saved check icon bg-emerald-500/20 text-emerald-400 text-white/90
Category Header Default (no completions) — badge: bg-white/5 border-white/10 text-white/40
Has completions item selected badge: bg-cyan-500/20 border-cyan-500/35 text-cyan-400
Expanded / Collapsed click chevron-down vs chevron-right · children AnimatePresence height:0→auto
Color Swatch Unselected — w-8 h-8 rounded-full (light colors: border border-white/20)
Selected click scale-110 -inset-[3px] border-2 border-cyan-400 + check icon
Overlays, Panels & Modals
Component State Trigger Visual / Classes
Selections Panel Closed — hidden (isOpen=false)
Opening badge click scale 0.95→1 · opacity 0→1 spring · backdrop bg-black/40 fade in
Processing Finalize click finalizeStep:'processing' → spinner + 3 steps · then 'success'
AI Overlay Inactive AI mode not selected isActive=false → returns null
Activating AI mode selected AnimatePresence opacity 0→1 · elements stagger in with delays
Listening mic active, user speaking voiceState:'listening' · mic glow ring pulse · "You" in transcript
AI Speaking AI responding voiceState:'speaking' · typewriter reveal · bars animate · avatar halo
Settings Panel Settings tab Settings tab click tab bg-white/10 text-white · settings icon visible
Controls tab Controls tab click tab bg-white/10 text-white · gamepad-2 icon visible
Tour Bar Active (playing) Tour nav mode selected isGuidedTourActive=true · h-60px · animate-ping dot · cyan border-t
Ended End Tour click reverts to standard bar isGuidedTourActive=false h-50px
Icon Library
Library: lucide-react · 1,400+ icons · Consistent thin stroke style
· lucide.dev
import { Search, ChevronDown, Check, X, LayoutGrid } from 'lucide-react'
Toolbar (top-right vertical pill)
rotate-ccwReset View
settingsSettings
gamepad-2Controls
keyboardNavigate
sparklesAI Assistant
log-outExit Model
alert-circleConfirm
Mode Rail (left)
building-2Exterior
armchairInterior
sparklesAI Mode
footprintsWalk
playTour
list-checksStep-by-step
sunLight Theme
moonDark Theme
homeHome Mode
starAmenities
map-pinSurroundings
gridLots
Navigation & UI Controls
chevron-right
chevron-left
chevron-down
chevron-up
arrow-left
arrow-right
skip-backPrev Room
skip-forwardNext Room
menu
navigationCompass
layout-gridRooms
squareStop Tour
Options Gallery & Selection
checkSelected
search
xClear / Close
infoOption info
maximize-2Expand gallery
minimize-2Collapse
refresh-cwSwitch View
cameraCamera Views
React Usage
Default stroke-width: 2 ·
Active/emphasis: 2.5
Standard: w-5 h-5 (20px) ·
Compact: w-4 h-4 (16px) ·
Micro: w-3 h-3 (12px)
PNG Export — 3D Engine
Export size: 128 × 128 px (power of 2)
Color: white on black · engine applies tinting at runtime
Stroke: stroke-width 2 (matches design spec, robust for mipmap compression)
Naming: T_UI_NameOfTexture.png (e.g. T_UI_RotateCcw, T_UI_Sparkles)
Engine generates: 64 · 32 · 16 automatically · 46 icons total
Motion & Animation
Library: Framer Motion. Primary easing feels snappy with a soft settle.
Token Value Used for
ease-snap [0.22, 1, 0.36, 1]Panels, sidebars, all layout transitions
duration-micro 150msPopovers, dropdowns, tooltips
duration-fast 200msFades, icon states, hover bg
duration-standard 300msProgress bars, state changes
duration-panel 400msSidebar slide, bottom bar offset
popover-in { opacity:0, y:-4, scale:0.97 } → visibleDropdowns, info cards
panel-in { opacity:0, y:30 } → visibleOptions gallery mount
marquee 2.5s ease-in-out infiniteLong option names on hover
Layout System
┌──────────────────────────────────────────────────────────────┐
│ [Mode Rail 100px] [Sidebar 260px] [3D Viewport] │
│ fixed left-0 absolute [Top Toolbar] │
│ top-0 bottom-0 left-[100px] absolute top-6 │
│ z-50 bottom-0 z-40 right-6 z-50 │
│ w-260px │
│ │
│ [Options Gallery] absolute left-[260px] right-0 │
│ bottom-[60px] z-30 (above bottom bar) │
├──────────────────────────────────────────────────────────────┤
│ [Status Bar] absolute bottom-0 right-0 h-50px z-20 │
│ left offset = sidebar open ? 360px : 100px │
└──────────────────────────────────────────────────────────────┘
Border Radius
rounded-2xl
Panels, gallery
rounded-xl
Cards, buttons
rounded-full
Pills, tags, dots