Corniche 2400 Back to the site
← Back to the hotel

Design guide · drawn entirely in code

How a mountain gets built out of paths and particles.

01Concept & art direction

A hotel above the weather, drawn without a single photograph

Corniche 2400 is a fictional ski hotel on a ridge at 2,400 metres — above the valley fog, not below the summit. The whole site is organised by altitude: the hero is the summit, the rooms sit at 2,400 m, the journey climbs from the valley at 1,447 m, and a live altitude rail on the left descends as you scroll. Every visual is code — layered SVG for the panorama, canvas for the snow — because a hand-drawn mountain says "boutique" where a stock photo says "template".

02Palette & type

Glacier light, pine shadow, one stripe of sun

Glacier white#F4F8FB
Ice#DCE8F1
Ice shadow#9FBBD0
High sky#6E93AD
Slate ink#1B3042
Dark pine#1E2F2A
Sun gold#D9A84E

Sleep above the weather.

Archivo · variable width 62–125

Display and UI. Stretched to width 116–122 for headlines it reads like Swiss resort signage — crisp, modernist, cold-air clear. One family, many voices, via the wdth axis.

The valley makes its own weather.

Vollkorn · 400 / 500

The chalet voice. Warm, sturdy old-style serif for stories, room descriptions and anything spoken by the hotel rather than the mountain.

2 400 m · 16:40

Sometype Mono · 400–600

The instrument voice. Altitudes, timetables, prices, labels — anything you would find engraved on a lift station sign.

03Techniques

The signature: a panorama with true depth

The hero is one inline SVG with seven stacked groups — sun, two mountain ranges, a cloud sea behind the hotel ridge, the ridge and hotel, a second cloud sea in front of the ridge, and the foreground where you stand. Each group carries a data-depth factor; on scroll, one rAF-throttled handler translates each layer down by scrollY × depth, so far layers lag and the mountain separates into planes. Putting one cloud layer in front of the ridge is what sells "above the clouds".

<!-- back clouds → ridge+hotel → front clouds: the sandwich is the trick -->
<g class="layer" data-depth="0.42"> …back cloud sea… </g>
<g class="layer" data-depth="0.30"> …ridge, hotel, cable car… </g>
<g class="layer" data-depth="0.24"> …front cloud sea… </g>

// one scroll handler, throttled with requestAnimationFrame
layer.style.transform =
  "translate3d(0," + (scrollY * depth).toFixed(1) + "px,0)";

Snow is a plain 2D-canvas particle system — ~140 flakes with individual fall speed and a sine-wave sway — that only draws while the hero is on screen. Clouds drift on infinite alternating CSS keyframes. The cable-car cabin rides its own SVG path via getPointAtLength with a smoothstepped ping-pong, an 18-second round trip. All of it checks prefers-reduced-motion first: with motion reduced, the clouds hold still, the snow never starts, and the cabin parks a third of the way down the cable.

// the cabin commutes along the cable path
var t = pingPong(now / 18000);       // 0→1→0
t = t * t * (3 - 2 * t);             // smoothstep easing
var pt = cable.getPointAtLength(t * cable.getTotalLength());
cabin.setAttribute("transform", "translate(" + pt.x + " " + (pt.y + 6) + ")");

The room cards are lift tickets: a dashed perforation, two punched holes cut with pseudo-elements the exact colour of the section behind them, and a stub that slides 5 px along the perforation on hover — as if about to tear.

04Iteration

Three passes over the mountain

  1. Pass 1

    Correctness and composition: the first screenshots showed the hotel oversized, dead-centre, and colliding with the headline on desktop and mobile. Redrew the ridge with a lower plateau, rescaled the hotel to two-thirds size and moved it right of the text column, and resized the cable car to match — the hero finally read as headline, mountain, booking bar, each owning its own band.

  2. Pass 2

    Elevation: gave the ridge its namesake — a drifted snow cornice along the whole top edge with a wind-lip overhanging the drop; darkened the far range so its summits stopped dissolving into the sky; carved two first-tracks ski lines into the foreground slope; and made the stat band count up to its readings like instruments settling.

  3. Pass 3

    Taste: removed the embossed shadow from the ticket punch holes so they read as clean die-cuts, re-verified the reduced-motion path end to end — clouds hold, snow never starts, cabin parks — and confirmed both pages ship with zero console errors and no horizontal overflow at 1440 and 390 px.

05Do this yourself

The recipe, if you and Claude want a mountain of your own

  1. Pick one true fact about your subject and make it the thesis. Here: the fog stops at 2,380 m and the hotel is at 2,400. Everything else follows.
  2. Ask Claude for a palette pulled from the subject's physics — snow, ice shadow, low sun, pine — not from a trend. Name each colour and give it a job.
  3. Choose three type voices: one for the brand (a variable-width sans buys you range), one for stories, one for data. Ban them from doing each other's jobs.
  4. Build the signature element first, alone in a blank page: a layered inline SVG scene, back-to-front, with a data-depth on each group. Get the overlap right (something must pass in front of your subject) before styling anything else.
  5. Wire scroll parallax with a single rAF-throttled handler, and add one ambient system (snow, drift, a moving cabin) that only runs while it is on screen.
  6. Let the structure encode the content: this page is sorted by altitude, so labels, rail and journey all speak in metres. Find your subject's axis and sort by it.
  7. Screenshot at 1440 and 390, critique hard, and iterate three times: correctness, elevation, taste. On the last pass remove one accessory.
  8. Test prefers-reduced-motion and keyboard focus last — the calm version of the page should still feel finished, not switched off.