Case 01 / 05 Luxury real estate Brand site · 18 pages
Luxora Estates
A private-residence house with a full design system and a motion engine written from scratch. Eighteen pages, no framework, no build step and no dependencies at all.
- Role
- Direction, design, build
- Pages
- 18
- Dependencies
- None
- Stack
- HTML · CSS · Vanilla JS
01 — Overview
A brand, not a template
Luxora Estates is a demonstration brand: the residences, prices and advisors are invented, and the site says so in its own README. What is not invented is the build. It is a complete house — home, a filterable collection, six residence pages, four curated collections, six markets, an editorial journal with four articles, a practice page, a contact flow and a 404.
The brief I set was to see how far a luxury experience could go with nothing installed. No React, no GSAP, no bundler. Every page is a file you can open, and every effect on it is code I wrote.
02 — Design direction
Charcoal, ivory, one gesture of gold
Fraunces for the display voice — an editorial serif with real optical sizing — paired with Inter for navigation, metadata and forms. Type sizes are fluid across a single modular scale, so nothing is hard-coded per breakpoint and nothing needs a media query to look right.
Deep charcoal #111111
The ground for dark sections and the ink on ivory.
Warm ivory #F5F2EA
The light phase. Sections alternate deliberately, so the page breathes.
Stone #B8B1A4
Secondary type on dark, and the only grey the system allows.
Champagne #B79A62
Accent only, and rationed to one gesture per view. That restraint is where the luxury comes from.
03 — Key features
Every control does something
Deep-linkable collection
The property filters write to the URL, so ?type=villa&price=25-40 is a shareable view of the collection rather than a state that dies on refresh.
Residence pages with a room study
Each of the six residences carries its own gallery, an interactive room study and a private-viewing modal.
A lightbox that behaves
Keyboard and swipe, focus trapped and returned, and no library underneath it.
A pinned signature sequence
The Signature Collection holds one sticky frame while panels scroll past, wiping between residences in the direction of travel.
A horizontal markets strip
Six destinations that drag on desktop, swipe on touch, and stay reachable from the keyboard with visible rail progress.
04 — Motion
One loop, no dependencies
The motion layer is a single file. One requestAnimationFrame loop drives every scroll-linked effect, and everything animates on transform, opacity or clip-path — nothing that forces layout.
Hero, released on decode
The staged entrance waits for the hero image to decode rather than for a timer, then hands over to a scroll transformation: media scales and drifts, content lifts, the scrim deepens.
Type measured into lines
Headlines are measured into their real visual lines and revealed through masks, then re-measured on resize — because a fluid heading rewraps and a stale split shows.
A contextual cursor
A ring that adopts a label — View, Drag, Explore, Read, Open — over each kind of region. Pointer-fine devices only.
A real reduced-motion path
Everything resolves to its finished state under prefers-reduced-motion, which also removes the custom cursor and the grain. Not a disabled site — the same site, still.
05 — Visual showcase
06 — Responsive
Verified, not assumed
Eighteen pages walked at 390, 768 and 1440: no horizontal overflow, no broken links or images, no console errors, one h1 per page and alt text on every image. Filters, deep links, the lightbox, form validation, both modals, the mobile drawer, the destinations strip, the room study and the reduced-motion path were each operated rather than eyeballed.
Full-bleed heroes use art-directed portrait, tablet and landscape crops rather than one image squeezed into every shape. Below the fold everything is lazy; hero frames are not, because a clipped element reads as hidden and would never start loading.