Skip to content

Slide 01 / 07

Click the deck, then use the arrow keys like a real presentation.

Readout

Family
Signature
Theme
Dark
Type
Barlow + Barlow Condensed
Accent
#e0409a
Corners
6px
Moves on
Keys, swipe
Studio
Ready

03 of 30, Signature

Vertigo.

A wireframe soundstage whose walls swing from telephoto-flat to wide-angle-cavernous around a content plate that never moves a pixel.

Look
As designed

How it moves

The dolly zoom, used as navigation: the lens changes on every slide while the camera, the far wall and the title stay nailed to the frame. Cinematic but sober, good for a studio or product story that wants one still subject and a room that keeps re-reading itself.

This is the specification the Studio sends to the model, written for Vertigo's own look. Change the look in the Studio and every value follows.

Palette

  • Background#0b0e12
  • Text#e8ecf1
  • Muted#78828e
  • Accent#e0409a
  • Surfacergba(232,236,241,.05)
  • Hairlinergba(232,236,241,.11)

Type: Barlow + Barlow Condensed. Corners: 6px.

Layout

  • One room, drawn once, never cut. A fixed .room with perspective: calc(var(--p) * 1px) and perspective-origin 50% 50% holds exactly five text-free divs and no text ever enters it: ceiling, floor, left wall and right wall are each 1400px deep and hinged at a viewport edge (rotateX(±90deg) / rotateY(±90deg) with the origin on that edge), and an opaque back plate sits at translateZ(calc(var(--p) * var(--k) * -1px)). Every plane carries the same 44px ruled grid in rgba(232,236,241,.11), 72px on the back plate, and nothing else. The back plate is last in the DOM, so it hides the tails of the other four and the five faces tile the frame as one clean one-point perspective.
  • The far plane's depth is authored as a FRACTION of the focal length (--k: .6) and its projected scale is DERIVED, never authored: --proj: calc(1 / (1 + var(--k))). So the far plane lands at .625 of the viewport for every value of --p, 800×450px at 1280×720, pinned to the pixel, and changing --k in a copy of this deck cannot slide the painted far plane off the geometric one. A 1px #e0409a hairline along its bottom edge is the only lit element in the room.
  • Content is a flat sibling outside the 3D context and physically cannot move. .stage is fixed at left 9.2vw / top 13vh, 72vw × 70vh, grid-template-columns: minmax(0,1fr), with every slide in cell 1/1 at align-self:start, so the title lands on the same pixel on all seven slides. A 1px rgba(232,236,241,.11) rule at left 7vw runs the full 70vh beside it. Each slide authors its own width as --plate (46 to 66 vw); that varying proportion is the only thing pacing the deck. Inactive slides are visibility:hidden (delayed 0s linear .3s so the leave still fades), because the engine marks them aria-hidden and their buttons must leave the tab order too.
  • Type. a slug at .74rem / 600 / .2em uppercase condensed in #78828e between two 2.2rem hairlines, then the title at clamp(2.2rem,5vw,6rem) / 800 / -.035em / line-height .95, then the lede. The title gets a second life painted on the far wall: the same words at 15vw inside a fixed .backplate that is transform: scale(var(--proj)) (.625) with overflow hidden, right-aligned, drawn as hairline outline only, color: transparent; -webkit-text-stroke: 1.6px color-mix(in oklab, #e8ecf1 22%, #0b0e12), so it reads as drafting lettering on a cyclorama.
  • Objects scale with the plate, because the plate is authored in vw: .rings and .stats are repeat(3, minmax(0,1fr)) grids that span the plate at any width and the ring diameter is clamp(7rem,13vw,16rem). Without that the exhibit caps out in rem and 1920 reads as a 1280 layout enlarged.

Signature motion

  • On every change the lens changes and the camera does not. perspective travels between authored focal lengths (2200, 1700, 1500, 1250, 820, 560, 320, monotonic, so the barrel's rail and its numbers tell the same story) over 1150ms cubic-bezier(.65,0,.25,1), and the back plate's translateZ travels on the same duration and easing, so z = -k·p holds at every instant of the interpolation, not only at the ends. The four side planes never change their transform at all; their grid pitch is fixed in world px, so the ribs crowd and unpack toward the vanishing point and disappear behind the back plate, about 30 visible ribs per wall at 2200, 7 at 560, while the corner rays, the room's silhouette and the far plane do not move a pixel.
  • Content follows the move. .slide leaves at opacity .3s ease and arrives at opacity .85s ease + transform translateY(22px)→none .85s cubic-bezier(.22,1,.36,1), both delayed .4s. body carries data-reveal-delay="900" data-animate-delay="900" so objects stagger at 900 + j·90ms, after the room has landed. Objects that carry prose, .card, .compare > div, .carousel-item, .timeline .step, .frame, .code, are opaque flats standing in the room (background color-mix(in oklab, #0b0e12 95%, #e8ecf1), 1px rgba(232,236,241,.11), radius 6), so they occlude the grid and the painted title behind them and no paragraph is ever read off the wall. Captions, ledes and numerals do sit directly on the wall: behind them there is only the 11% grid and the ghost's 1.6px outline, so keep them short and never put a paragraph there.
  • The close is the only slide that changes --k (.6 → .3), so the invariant finally breaks: the far plane swells .625 → .769 (800×450 → 985×554) and the room rushes the audience, the side walls fall to opacity .2 and the ceiling to .12 while the floor goes to 1, the plate rule turns #e0409a, the title jumps to clamp(2.8rem,7.6vw,8rem), and the readout stops being a number and reads OPEN. Key those five rules to html:has(.slide.close[data-state="active"]), never to a slide index, a nine-slide deck must still close on its last slide.
  • prefers-reduced-motion kills the travel, not the room: only the transitions are removed, so each slide still takes its own authored lens instantly and the barrel's readout keeps describing what is on screen instead of becoming decoration.

HUD, the lens barrel, fixed right 3vw, vertically centred, clamp(158px,13vw,220px) wide. Head: the live focal length in condensed tabular numerals at clamp(2rem,3.6vh,2.9rem) with a .64rem / .22em uppercase caption, cross-faded on a 320ms hinge. Beside the list, a 1px × (--n × --row) rgba(232,236,241,.11) rail whose accent fill is transform: scaleY(var(--progress)) from the top and whose 3×9px accent index mark rides it by translateY(calc(var(--progress) * (var(--rows-h) - 9px))), both 1150ms on the room's easing, so mark and fill advance in lockstep with the swing. Then one real <button data-goto> row per slide (grid-auto-rows, never repeat(7,…), and --rows-h: calc(var(--n) * var(--row)), the engine publishes --n, so a nine-slide deck still fits the barrel), each a 26px × 2px tick, the slide title at .8rem and that slide's focal length in tabular condensed at weight 400: the contents page and the camera's settings are the same object. Future = #78828e with the tick at scaleX(.66) scaleY(.5); done = color-mix(in oklab, #78828e 55%, #e8ecf1) with a 60% accent tick; active = #e8ecf1 with a full accent tick at scale 1. Under it, 01 / 07 in condensed tabular.

Navigation. → ← ↓ ↑ Space PageUp/PageDown Home End and 1–9, touch swipe, and clicking any barrel row jumps to that slide. No wheel, the gesture is 1150ms and must not be chained.