LSD Framework
Aurora
Engine v0 · keyframe layer model

Motion as data, not deadlines

Aurora composes pages from named layers — each one a binding from a CSS property to a series of keyframed values. This page proves the engine: an authored Sequence emits to working CSS, applied live below.

01 · time driver

Hero entrance — three layers, one sequence

Three layers fire from a single sequence: the title fades up, the subtitle fades after a delay, the dot scales with a longer easing. Each layer becomes a @keyframes rule plus an animation shorthand on its selector. Hit Replay to re-trigger.

Layers are vocabulary

Delay, stagger, easing — all data

View emitted CSS
/* renders on mount */
View authored sequence (JSON)
/* renders on mount */
02 · scroll driver

Scrub pin — two layers driven by progress

Same sequence shape, but the layers' driver is "scroll". The emitter replaces the @keyframes path with a calc() chain reading --lsd-progress — written by lsd-scroll-trigger's scrub mechanism. Scroll the page; the title translates up and changes hue.

Brand reads,
motion follows

scroll through the frame
View emitted CSS
/* renders on mount */
View authored sequence (JSON)
/* renders on mount */
03 · scoped runtime

Per-instance playheads — six cards, six progress vars

The lsd-aurora.js runtime registers a controller per matched element, each writing its own --lsd-progress as the card scrolls through the viewport. Two authoring modes for variance:

Mode A — Authored personalities (what's shown here): six small sequences, each scoped to one :nth-child(n). Different easings + amplitudes per card — snap / glide / overshoot / gentle / linear / soft. Use when ≤ ~12 items need hand-crafted variety.

Mode B — Repeater + parametric variance (scales to N): one Sequence, scope .card, with per-instance overrides via :nth-child ranges (predictable) or random-seed CSS vars (organic). Use for archive grids, CMS content, anywhere N is unbounded. The curve shape stays shared; the amplitudes vary per instance through CSS, not new sequences.

card 01Independent playhead
card 02One scope selector
card 03One sequence definition
card 04N controllers · runtime-driven
card 05--lsd-progress per host
card 06CSS reads from each card
View emitted CSS
/* renders on mount */
View authored sequence (JSON)
/* renders on mount */
04 · event driver

Triggered playhead — events fire as it crosses

Sequence with scope.driver: "event" stays paused until called. Click Play — runtime advances the playhead over its duration; the bar fills via --lsd-progress; named events fire at 50% and 100% and log below. Behaviours panel will subscribe to these events to chain actions when Aurora ↔ Behaviours wiring lands.

View emitted CSS
/* renders on mount */
View authored sequence (JSON)
/* renders on mount */
05 · easings

Per-segment easing — four curves, one scroll

Four sequences, each on its own row. Same start/end values, same scroll-driver, different easing on the starting keyframe. The emitter expands each easing into a polynomial in calc() — no pow() needed, Safari 15.4+ safe.

Scroll pacing: data-lsd-scrub-pre="0.18" + data-lsd-scrub-post="0.18" hold the start/end stationary for the first/last 18% of the scroll range so the animation reads even on a slam-scroll. data-lsd-scrub-min="1600" caps the velocity — --lsd-progress takes at least 1.6s to traverse 0→1 no matter how fast you scroll. prefers-reduced-motion disables the lock.

linear
ease-in (t³)
ease-out (1 − (1−t)³)
ease-in-out (smoothstep)
View emitted CSS
/* renders on mount */
06 · composed sequences

Aurora driving real page regions

Six small Nebulae, each scoped to its own .aurora-scene-frame. Every frame carries .lsd-scroll.lsd-scrub so the runtime writes --lsd-progress on it; the scene's sequence reads that progress to choreograph its own elements. Same architecture as §03 — different scopes, different layouts, one sequence per scene. Each Nebula takes about 1.5 screens to play through.

Try scrolling — every frame below is its own playhead

6.1 · hero-takeover

Title letter-staggers in, the sub-line settles, then the CTA pulses three times as the playhead crosses 0.7. An ambient mesh drifts behind the headline the whole time.

LSD   Takeover

Aurora composes the entrance, the rest, and the call to action — one Nebula, one playhead.

6.2 · card-deck-shuffle

Four stacked Constellations fan out as you scroll — each rotates and translates on its own curve. The top card draws an accent ring at the end.

01 Stats
02 Charts
03 Bento
04 Cards

6.3 · nav-collapse

Full nav with brand-dot pulse, links, and CTA collapses to a sticky minimal bar. A gradient hairline grows at the bottom edge and the body content lines drift behind at different speeds — the nav adapts to scroll state.

Aurora
Page content scrolls behind the collapsing Nebula. The bar tightens, links dim, the CTA shrinks — every variable lives on the playhead.

6.4 · feature-cascade

Five pillars cascade-fade in sequence. A gradient rail on the left draws top-to-bottom as the dots pop on each reveal.

  • TokensSurface-aware design substrate.
  • MotionCSS-first, Aurora-orchestrated.
  • ContainersStyle-query aware regions.
  • SurfacesGenerated, edited, applied.
  • BehavioursTrigger → Action → Target.

6.5 · logo-cloud-orbit

Six satellites orbit a Pulsar core on a dashed ring; an inner ring counter-rotates. The core grows and glows with progress; each satellite picks up an accent halo at apoapsis.

A B C D E F

6.6 · product-spec-reveal

The Galaxy device stays pinned — notch, side buttons, pulsing screen-glow — while spec callouts slide in from alternating sides, each with a dashed leader line connecting back to the body.

OLED2400 × 1080 · 120 Hz
Titanium6.4 mm · 187 g
Aurora SoC3 nm · 8-core
Battery4 800 mAh · 26 h