Build notes · Bergbahn-Gesellschaft Kleinbahn

One rope, two cars, and the arithmetic of a mountain.

Kleinbahn is a fictional 1907 funicular above the invented town of Sankt Alben. The page has one job: hand you the brass winch lever and let you feel the counterweight — one car can only climb because the other is falling — then reward a patient stop at each halt with a page of the mountain's guestbook.

Concept

A funicular is the most honest machine on any mountain: two cars are lashed to opposite ends of a single steel rope laid over a wheel at the summit, so the winch never lifts anything — it only settles arguments, covering friction and saying when to stop. The site is a cutaway alpine slope at dusk (layered SVG: sky, peaks, viaduct, tunnel, avalanche gallery, pines that thin toward the snowline) with a driver's console below. Drag the lever or nudge it with the arrow keys; dwell at Wolfgrat, Galerie or Bergstation to unlock a guestbook entry. Every pixel is procedural — no images, no libraries, one file.

Palette

The sky gradient behind the slope — alpine dusk, night arriving from the summit down:

Alpine dusk
#2B3A55
The base of everything — cold high-altitude blue at the hour the last car comes home. The page is built of it.
Car red
#B3342B
The one warm object on the mountain. Reserved almost entirely for the two cars, so the eye tracks them the way a driver would.
Pine
#2E4A3B
The forest below the track, darkening into the ravine. Two shades let the procedural pines read as depth, not a wall.
Brass
#C09A57
The instrument metal — lever, gauges, station lamps, links. Aged, not gold; it argues for 1907.
Guestbook paper
#EFE7D8
The only bright field on the page, used solely for unlocked entries so a page opening genuinely lifts out of the dusk.

Type

One car falls,
the other climbs

Jost — a geometric sans in the lineage of the 1920s, close to the moment electricity replaced the water ballast. It carries every display line, label, gauge and number at light weights, wide tracking used as engraving.

The rope decides, madam

Source Serif 4 — body copy and the guestbook voices. Its italic does the emotional work: the visitors' entries, the weather line, the single-word emphases a founder's ledger would underline.

Techniques

The signature: the lever and its counterweight. The whole ride is one number. A single state variable holds Car I's position along the track, t from 0 (valley) to 1 (summit); Car II is drawn at exactly 1 − t, so the two cars are always each other's complement across the summit wheel — "one falls so the other climbs" is not a slogan, it's the assignment. The lever sets a target rope velocity (lever × VMAX) which a winch constant eases toward, and a soft brake bleeds speed off in the last 6% of travel so the cars settle into their stations rather than slamming. On release, the lever itself eases back to the nearest notch with a slight overshoot (cubic-bezier(.6,-.12,.3,1.18)) — the counterweight feel — and glows brass while held.

Sampling an invisible track. Both cars, the halt flags, the passing-loop rails and the extra pines are all positioned by sampling one hidden SVG path with getPointAtLength, then rotating each car to the local tangent. A Begegnung bump nudges the two cars onto separate rails as they pass at the halfway point, exactly as a real single-track funicular does. A small elastic term lets the cars breathe against the rope under acceleration; the summit flywheel spins in proportion to rope speed; the cable's visible length is driven by a dash offset between the lower car and the wheel.

Unlocking the guestbook. Hold a car still at a halt (lamp lit) for half a second and its page unfolds with a 3D rotateX, printed on the paper stock. Balance both cars at the precise midpoint — the Begegnung — and a second-read entry appears that isn't in the count. Weather (drizzle → mist → sleet → dry summit snow) and a falling-snow particle field track the driven car's altitude.

No libraries. No three.js, no GSAP, no canvas even — the entire scene is inline SVG animated by a single requestAnimationFrame loop that pauses on document.hidden, with a clamped delta so returning to the tab never jumps the cars.

Iteration log

  1. Pass 1 — Craft

    Headless checks at 375 px caught the page scrolling 78 px sideways: the header's four-item nav (The line · Guestbook · Guide · Index) was 258 px wide and refused to fit beside the wordmark. Let the top bar and the nav wrap, with a tighter row gap, so the links drop cleanly onto a second line instead of blowing out the viewport. Re-read the type scale and spacing rhythm across the console — left as-is; it was already on grid.

  2. Pass 2 — Depth

    Spent the boldness on the signature. The lever previously snapped to its notch instantly; it now eases home with a counterweight overshoot on both drag-release and arrow-key steps, and picks up a brass drop-shadow while grabbed or keyboard-focused — you can feel the mass leave your hand. Added one second-read detail the console doesn't announce: every 17–43 seconds a faint shooting star crosses the dusk sky, drawn as a self-erasing SVG line and fully guarded against reduced motion and hidden tabs. (The existing 1-in-6 ibex and the hidden Begegnung entry stay.)

  3. Pass 3 — Hardening

    Applied the Chanel rule — took one thing off. Two drifting mist bands were one too many; removing the second lets the single band read as weather rather than decoration, and quiets the motion. Re-verified the 375 px layout (nav wraps, facts go two-up, halt notes drop to their own line), the reduced-motion path (lever transition off, snow settles to a static frame, no shooting star, twinkle and mist stilled), focus rings on the lever and every link, and that the rAF loop bails the instant the tab hides. DPR handling isn't needed — the scene is pure SVG that scales to its container with no raster buffer.