Layered Depth
Create a React + Vite + TypeScript + Tailwind CSS landing page for an architecture studio called "Qelora". The page has exactly two sections: a Hero and a Section 2. The entire site uses inline styles (no Tailwind utility classes in JSX -- Tailwind is only used for base reset). Use only react, react-dom, and lucide-react as dependencies (icons are all inline SVGs here, lucide is not actually used in this page).
FONTS
Load these three custom fonts in index.html <head>:
<link href="https://db.onlinewebfonts.com/c/076f8c5b3b67616658dd1e4e9bac62ec?family=Zimula+Trial+Med" rel="stylesheet">
<link href="https://db.onlinewebfonts.com/c/08d8ca53f66ab5b48659912fa0136b78?family=Zimula+Trial+Bd" rel="stylesheet">
Also import in index.css:
@import url('https://db.onlinewebfonts.com/c/46024824a3dd3309c3a7f46f4f1283ba?family=Zimula+Trial+Reg');
Font usage:
- Body / default:
'Zimula Trial Med', sans-serif - Bold / logo / hero text:
'Zimula Trial Bd', sans-serif - The
Regimport is available but Med is the primary weight used everywhere
GLOBAL CSS (index.css)
@import url('https://db.onlinewebfonts.com/c/46024824a3dd3309c3a7f46f4f1283ba?family=Zimula+Trial+Reg');
@tailwind base;
@tailwind components;
@tailwind utilities;
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
scroll-behavior: smooth;
}
body {
font-family: 'Zimula Trial Med', sans-serif;
background: #0e0c0a;
overflow-x: hidden;
}
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: #0e0c0a; }
::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.15); border-radius: 3px; }
COLOR PALETTE
- Dark background:
#0e0c0a - Primary text:
#241f21,#282425,#2a2420 - White:
#fff - Dark accent:
#100e0c - Warm transparent overlays:
rgba(235, 230, 218, 0.12),rgba(242, 238, 230, 0.38) - Frosted glass backgrounds:
rgba(248,245,240,0.72),rgba(248,245,240,0.88),rgba(248,245,240,0.92),rgba(248,245,240,0.96)
ASSET URLs (Cloudinary, not CloudFront)
Videos:
- Background video (Hero):
https://res.cloudinary.com/dy5er7kv5/video/upload/q_auto/f_auto/v1779808200/bg-video_xsmysw.mp4 - Bird enter animation:
https://res.cloudinary.com/dy5er7kv5/video/upload/q_auto/v1779808206/bird-entrada_e72qt7.webm - Bird idle 1:
https://res.cloudinary.com/dy5er7kv5/video/upload/q_auto/v1779808282/bird-idle_fzjami.webm - Bird idle 2:
https://res.cloudinary.com/dy5er7kv5/video/upload/q_auto/v1779808284/bird-idle2_rajmgo.webm - Bird leave animation:
https://res.cloudinary.com/dy5er7kv5/video/upload/q_auto/v1779808286/bird-saida_ifroz1.webm - Background video (Section 2):
https://res.cloudinary.com/dy5er7kv5/video/upload/q_auto/f_auto/v1779835701/bg-2-video_sgbpqt.mp4
Images:
- Q logo (unused but declared):
https://res.cloudinary.com/dy5er7kv5/image/upload/q_auto/f_auto/v1779808187/q-logo_isvugc.png - Center sculpture/slab:
https://res.cloudinary.com/dy5er7kv5/image/upload/q_auto/f_auto/v1779854565/slab_v1_kb4vqk.png - CTA card photo (Pexels):
https://images.pexels.com/photos/3184465/pexels-photo-3184465.jpeg?auto=compress&cs=tinysrgb&w=400
APP STRUCTURE
src/
main.tsx -> StrictMode, renders
App.tsx -> then , no routing
Hero.tsx -> Hero section component
Section2.tsx -> Second section component
index.css -> Global styles
SECTION 1: HERO (Hero.tsx)
Container: position: relative, width: 100%, minHeight: 100vh, overflow: visible, fontFamily: 'Zimula Trial Med', sans-serif.
Responsive breakpoint: isMobile = window.innerWidth < 768, checked on mount and resize.
Layer 1 -- Background Video (z-index: 0)
- `` with
autoPlay muted loop playsInline position: absolute,inset: 0,width: 100%,height: 100vh,objectFit: cover- Source:
BG_VIDEOURL
Layer 2 -- Warm Overlay (z-index: 1)
- A div covering the hero with
background: rgba(235, 230, 218, 0.12),height: 100vh,pointerEvents: none
Layer 3 -- Bird Animation System (z-index: 8)
- Container:
position: absolute,top: 0,left: 0,width: 100%,height: 100vh,pointerEvents: none,aria-hidden - Contains 4 `` elements (enter, idle1, idle2, leave), each toggled visible/hidden via
displayproperty - Desktop: Each video is
position: absolute,inset: 0,width: 100%,height: 100%,objectFit: cover - Mobile: Each video is
position: absolute,top: 50%,left: 0,transform: translateY(-50%),width: 100%,height: auto(full width, auto height, vertically centered) - State machine: Type
'enter' | 'idle1' | 'idle2' | 'leave' | 'hidden'- On page load: play
entervideo - When
enterends: transition toidle1 - When
idle1ends: transition toidle2 - When
idle2ends: transition back toidle1(infinite loop) - On scroll down (past 10px threshold): pause all idle/enter videos, reset their
currentTimeto 0, playleavevideo - On scroll back to top (below 10px): pause leave video, reset, play
entervideo again
- On page load: play
- Uses both React state and refs (
birdStateRef) to avoid stale closures in scroll handlers - All videos are preloaded with
.load()on mount - The
playVideohelper setscurrentTime = 0, checksreadyState >= 2, then plays (or waits forcanplayevent)
Layer 4 -- Center Brand Text "Qelora" (z-index: 5)
- Absolutely positioned container filling
100vh,display: flex,alignItems: center,justifyContent: center,pointerEvents: none - Text:
"Qelora"in'Zimula Trial Bd', sans-serif - Font size: mobile
26vw, desktop22vw letterSpacing: -0.05em,color: #241f21,lineHeight: 1marginBottom: mobile8vh, desktop12vh
Layer 5 -- Sculpture Image (z-index: 5)
- `` with
position: absolute,top: 50%,left: 50% transform: translateX(-50%) translateY(${-heroScroll 0.3}px)-- parallax that moves UP as user scrolls down- Width: mobile
220vw, desktop160vw;height: auto pointerEvents: none,willChange: transform
Layer 6 -- Fixed Navbar (z-index: 100)
position: fixed,top: 0, full width- Padding: mobile
16px 20px, desktop20px 36px - Left: Brand name "Qelora" with registered trademark superscript. Font:
'Zimula Trial Bd', size: mobile20px, desktop24px,letterSpacing: -0.03em,color: #241f21. The(R)sup hasfontSize: 0.4em,verticalAlign: super - Right (desktop):
NavPillscomponent -- a row of pill buttons for['Projects', 'Studio', 'Responsibility', 'Archive']plus anENlanguage selector- Each pill:
background: rgba(248,245,240,0.92),borderRadius: 12px,padding: 13px 22px 8px,height: 40px,fontSize: 13px,textTransform: uppercase,letterSpacing: 0.07em,color: #241f21 - Active pill has
fontWeight: 700and a 3px round dot atbottom: 3px, centered - Non-active:
fontWeight: 500 - Language pill: separate rounded capsule (
borderRadius: 100px),padding: 8px 14px,background: rgba(248,245,240,0.88),backdropFilter: blur(12px),boxShadow: 0 2px 20px rgba(0,0,0,0.1), contains "EN" text and a chevron-down SVG
- Each pill:
- Right (mobile): Hamburger button,
42x42px,borderRadius: 100px, same frosted glass style. Shows X icon when open, 3-line hamburger when closed
Layer 7 -- Mobile Dropdown Menu (z-index: 99)
position: fixed,top: 70px,left: 16px,right: 16pxbackground: rgba(248,245,240,0.96),backdropFilter: blur(16px),borderRadius: 18px,padding: 8px,boxShadow: 0 8px 40px rgba(0,0,0,0.14)- Each menu item: full-width button,
padding: 14px 20px,fontSize: 13px, uppercase,letterSpacing: 0.07em,borderBottom: 1px solid rgba(40,36,37,0.08) - Bottom: EN language selector row
Layer 8 -- Bottom Panels (z-index: 20)
bottomis calculated as:bottomOffset + heroScroll 0.5wherebottomOffsetis 24px on mobile, 36px on desktop. This creates a parallax push-down effect as user scrolls.
Desktop layout (side-by-side):
-
Bottom-left panel:
position: absolute,left: 36px,borderRadius: 18px,padding: 22px 28px,maxWidth: 270px- Headline:
"Designing places\nbeyond\nwhat's expected"--fontSize: clamp(17px, 2vw, 24px),lineHeight: 1.28,color: #282425,letterSpacing: -0.01em - Below: 1px border-top divider (
rgba(40,36,37,0.2)), then "EXPLORE OUR APPROACH" link with down-arrow SVG.fontSize: 11px, uppercase,letterSpacing: 0.1em
- Headline:
-
Bottom-right panel:
position: absolute,right: 36px,borderRadius: 18px,width: clamp(210px, 21vw, 290px),height: 180px,overflow: hidden- Background: Pexels photo covering the entire card
- Dark gradient overlay:
linear-gradient(to bottom, rgba(16,14,12,0.55) 0%, transparent 60%) - Top text:
"Every lasting space begins\nwith a quiet dialogue."--color: #fff,fontSize: 13px,lineHeight: 1.35 - Bottom: inline flex with a white circle (envelope SVG icon, 36x36px,
borderRadius: 12px) and a white "START A PROJECT" button (fontSize: 11px, uppercase,letterSpacing: 0.07em,fontWeight: 700,borderRadius: 12px,height: 36px)
Mobile layout (stacked):
- Single flex column container,
left: 20px,right: 20px,gap: 12px - Top card: Tagline panel with
background: rgba(248,245,240,0.72),backdropFilter: blur(8px),borderRadius: 16px,padding: 18px 20px. Same text as desktop but single line: "Designing places beyond what's expected",fontSize: 17px. Same divider + "Explore our approach" link below. - Bottom card: CTA card,
borderRadius: 16px,height: 120px. Same structure as desktop right panel but adapted for mobile (textfontSize: 12px, same button row).
SECTION 2 (Section2.tsx)
Container: position: relative, width: 100%, minHeight: 100vh, display: flex, flexDirection: column, alignItems: center, justifyContent: center, overflow: hidden, fontFamily: 'Zimula Trial Med', sans-serif
Layer 1 -- Background Video (z-index: 0)
- `` with
autoPlay muted loop playsInline,position: absolute,inset: 0,width: 100%,height: 100%,objectFit: cover - Source:
BG_VIDEO_2URL
Layer 2 -- Warm Overlay (z-index: 1)
background: rgba(242, 238, 230, 0.38),position: absolute,inset: 0,pointerEvents: none
Layer 3 -- Center Headline (z-index: 2)
- Absolutely positioned,
inset: 0, flex centered,pointerEvents: none,textAlign: center,padding: 0 24px - Text:
"What stands the\ntest of time is all\nthat guides the\nwork."usingtags fontSize: clamp(32px, 5.5vw, 80px),lineHeight: 1.18,color: #2a2420,maxWidth: 780px,letterSpacing: -0.025em,fontWeight: 400
Layer 4 -- Bottom Element (z-index: 2)
position: absolute,bottom: clamp(24px, 4vh, 48px), full width, flex column centered,padding: 0 24px- Vertical line:
width: 1px,height: 56px,background: rgba(42,36,32,0.25) - Below (margin-top: 22px): flex column centered,
gap: 14px- Map pin SVG: 24x28px outline pin icon,
stroke: #2a2420,strokeWidth: 1.4 - Subtext:
"Civic bodies and private clients trust us to shape resilient communities and purposeful places."--fontSize: clamp(11px, 1.4vw, 13px),color: #2a2420,letterSpacing: 0.04em,lineHeight: 1.6,maxWidth: 340px,opacity: 0.75
- Map pin SVG: 24x28px outline pin icon,
KEY BEHAVIORS SUMMARY
- Bird animation state machine: enter -> idle1 <-> idle2 loop; scroll triggers leave; scroll back triggers re-enter
- Parallax effects: Sculpture image moves up with
translateY(-scrollY 0.3). Bottom panels push down withbottom = offset + scrollY 0.5 - Responsive at 768px breakpoint: Nav collapses to hamburger, panels stack vertically, bird videos switch from cover-fill to width-100%/height-auto/vertically-centered, sculpture grows from 160vw to 220vw, brand text grows from 22vw to 26vw
- All styling is inline -- no CSS classes in JSX, no Tailwind utility classes on elements
- No third-party animation libraries -- all animations are native video playback + scroll-driven inline style changes via React state