+ Repo proof: examples/tailwind-host/. Showcase proves the Velora cinematic UI;
+ examples prove the host-agnostic path.
+
+
+
Layers
+
+ Velora uses @layer velora.*. Keep host utilities outside or after those layers so
+ Tailwind wins on appearance while vl-* attributes still drive animation.
+
+
diff --git a/apps/docs/src/pages/index.astro b/apps/docs/src/pages/index.astro
index 5059dd9..661a47a 100644
--- a/apps/docs/src/pages/index.astro
+++ b/apps/docs/src/pages/index.astro
@@ -2,12 +2,16 @@
import Base from "../layouts/Base.astro";
---
-
+Documentation
Getting Started
- A motion-native design system. Declarative HTML attributes. Zero JavaScript for animation. Modern CSS only.
+ A declarative motion language for HTML. Attributes describe intent; CSS executes it.
+ Works with Tailwind, Relume, or any UI. Showcase is the optional Velora look
+ (Skins — named models via data-editorial-theme).
+ The public Showcase is six pages; the previous demos live in
+ archive/showcase-2026-08/.
Installation
@@ -16,133 +20,53 @@ import Base from "../layouts/Base.astro";
# or
npm install @velora/css
-
- All Velora motion is prefers-reduced-motion aware. Users who have requested reduced motion
- see instant transitions with no animation.
+ Style with your own classes. Motion does not require .vl-card or brand tokens.
+ See Hosts (Tailwind) and Scenes.
-
/* Built into every Velora effect */
-@media (prefers-reduced-motion: reduce) {
- [vl-effect],
- [vl-scene],
- [vl-page-transition] {
- animation: none !important;
- transition-duration: 0ms !important;
- }
-}
Motion language — not a utility framework requirement
+
Zero JS for animation — scroll timelines, view transitions, CSS only
+
Showcase — cinematic reference UI / design system skin
+
diff --git a/apps/docs/src/pages/motion-conditions.astro b/apps/docs/src/pages/motion-conditions.astro
new file mode 100644
index 0000000..2173c80
--- /dev/null
+++ b/apps/docs/src/pages/motion-conditions.astro
@@ -0,0 +1,149 @@
+---
+import Base from "../layouts/Base.astro";
+---
+
+
+ Motion
+
+
Conditional Motion Engine
+
+ A single declarative attribute — vl-motion — selects a motion mode for an
+ element and its subtree. It does not name a preset; instead it re-scales the shared engine tokens
+ that every preset already reads, so one attribute adapts timing, travel, depth, blur and easing
+ across the whole subtree. Zero JavaScript.
+
+
+
The Modes
+
+ Add vl-motion to any element. Descendant vl-effect / vl-enter
+ reveals inherit the mode automatically.
+
+ Modes work by assigning central --vl-* knobs (declared in 01-tokens.css).
+ Presets consume these instead of hardcoding per-selector values, which keeps adaptation in one place.
+
+
+
+
Token
Role
Neutral default
+
+
+
--vl-motion-mode
Active mode (queried by if(style()))
standard
+
--vl-motion-speed-scale
Duration multiplier
1
+
--vl-motion-intensity
Travel-distance multiplier
1
+
--vl-motion-depth
Parallax / z-depth multiplier
1
+
--vl-motion-blur
Additive entrance blur
0px
+
--vl-motion-preference
Reflects reduced-motion intent
auto
+
--vl-motion-mode-ease
Easing selected by the mode
--vl-ease-cinematic
+
+
+
+ Because the defaults are neutral (scale 1, offset 0), motion behaves exactly
+ as before when no vl-motion mode is present. Explicit per-element modifiers such as
+ vl-speed and vl-depth still win over the mode.
+
+
+
Progressive Enhancement with CSS if()
+
+ The engine is CSS-first progressive enhancement. There are two layers:
+
+
+
+ Baseline (works everywhere): plain [vl-motion="…"] attribute
+ selectors assign the engine knobs. No if() required.
+
+
+ Enhancement (@supports + if()): a single
+ [vl-motion] rule re-derives the same knobs using CSS if() with
+ media(), style() and supports(), folding in live
+ conditions — prefers-reduced-motion, pointer: coarse, and
+ scroll-timeline availability.
+
+ If a browser does not support CSS if(), the entire @supports block is
+ ignored and the baseline [vl-motion="…"] values remain in effect. Modes still work —
+ they simply do not receive the extra live pointer/support-aware refinements. Nothing breaks, and no
+ JavaScript fallback is introduced.
+
+
+
Accessibility
+
+ Reduced motion is always respected:
+
+
+
+ Under @media (prefers-reduced-motion: reduce) the engine knobs collapse
+ (travel, depth and blur go to zero), and — as with every Velora effect — animations are disabled
+ globally in 03-motion.css.
+
+
+ vl-motion="still" lets an author opt any subtree into a motionless resting state
+ regardless of the OS setting.
+
+
+
+
Browser Support
+
+ The vl-motion modes themselves work in all modern browsers. The if()-based
+ refinement requires a browser with CSS if() support; everywhere else the baseline modes
+ are used. See the live comparison on the
+ Zero-JS Motion showcase page.
+
+
diff --git a/apps/docs/src/pages/scenes.astro b/apps/docs/src/pages/scenes.astro
index 1ac1d7f..7f1bfca 100644
--- a/apps/docs/src/pages/scenes.astro
+++ b/apps/docs/src/pages/scenes.astro
@@ -2,253 +2,57 @@
import Base from "../layouts/Base.astro";
---
-
+Orchestration
Scenes
- Scenes coordinate the motion of an element and all its descendants as a single
- choreographed unit. This is the difference between a primitive effect and a scene.
+ A scene is a shared clock for children — not a look. Layout and chrome come from the host UI
+ (or optional Velora theme recipes).
-
Primitive vs Scene
-
- A primitive effect animates one element:
-
-
<div vl-effect="fade-up" vl-timeline="view">
- Just this element fades up
-</div>
-
- A scene preset coordinates the element and its children with distinct timings
- per child slot:
-
-
<section
- vl-scene="hero"
- vl-effect="scene-hero-reveal"
- vl-timeline="view">
- <h1>1st child — fades up (slowest)</h1>
- <img src="hero.jpg" alt="" /> <!-- 2nd child — scales in after 120ms -->
- <p>3rd child — blurs in after 240ms</p>
- <a href="#" class="vl-cta">4th+ children — staggered fade</a>
-</section>
-
-
The vl-scene Attribute
-
- Add vl-scene to a container to mark it as a scene host. This applies CSS containment
- (contain: layout style) so the scene is self-contained.
-
- The value is a semantic label — it doesn't change behavior today but documents intent and allows
- future CSS hooks via [vl-scene="hero"] selectors.
-
-
-
Scene Presets
-
- Scene presets are set via vl-effect on the scene host. They define child-specific
- animation sequences:
-
- Each child gets a flow-in animation tied to view(block) scroll timeline,
- with cascading animation ranges (1st enters earliest, later children enter progressively later).
- Requires vl-timeline="view".
-
-
-
-
scene-story-pin
-
- Container becomes sticky (position: sticky; min-height: 100vh). Children use
- fade-up tied to the block scroll timeline.
-
-
-
-
scene-layer-stack
-
- Container gets perspective: 1200px. Children use 3d-entry with
- increasing translation depth per child (1rem → 4rem).
-
-
-
-
-
-
Hero Reveal — Full Example
-
<section
- vl-scene="hero"
- vl-effect="scene-hero-reveal"
- vl-timeline="view"
- vl-range="entry 0% cover 70%"
- vl-pin>
-
- <h1 class="vl-vt-shared-hero">
- Build motion-rich interfaces
- </h1>
-
- <img
- src="/hero.jpg"
- alt="Motion design system preview"
- class="vl-vt-shared-media"
- width="1200"
- height="675"
- />
-
- <p>
- Velora proves that HTML and CSS are enough to build premium motion.
- </p>
-
- <a href="/docs" class="vl-cta" vl-effect="icon-shift">
- Get started
- <svg aria-hidden="true" width="16" height="16">...</svg>
- </a>
-</section>
-
-
Feature Flow — Full Example
-
<section
- vl-scene="features"
- vl-effect="scene-feature-flow"
- vl-timeline="view">
-
- <!-- Each direct child flows in with cascading scroll-driven ranges -->
- <div class="vl-card">
- <div class="vl-card__title">Feature One</div>
- <p class="vl-card__body">Description</p>
+
- Override the default --vl-stagger-step (45ms) with one of the preset values:
+ A sticky element freezes its own anonymous view() progress. Children bind to the
+ named track timeline (--vl-scene) while the stage stays pinned.
-
-
-
Value
Delay per child
Feel
-
-
-
60ms
60ms
Quick, snappy
-
80ms
80ms
Balanced
-
100ms
100ms
Comfortable
-
120ms
120ms
Slightly cinematic
-
150ms
150ms
Deliberate pacing
-
200ms
200ms
Dramatic, slow cascade
-
-
-
<div vl-children="stagger" vl-stagger="120ms">
- <div>Plays at 0ms</div>
- <div>Plays at 120ms</div>
- <div>Plays at 240ms</div>
- <div>Plays at 360ms</div>
-</div>
-
-
Live Demo
-
-
-
Child 1
-
Fades up immediately.
-
-
-
Child 2
-
100ms after child 1.
-
-
-
Child 3
-
200ms after child 1.
-
-
-
Accessibility
+
Named presets (skin recipes)
- Scene presets and vl-children choreography all disable under
- prefers-reduced-motion: reduce — children appear in their final state instantly.
- Semantic structure (heading hierarchy, landmark roles) should be maintained regardless of motion.
+ Values like vl-scene="cinematic-hero" remain for compatibility. They ship in
+ scene-recipes.css via @velora/css/theme / full — they mix look + motion.
+ Prefer track/stage/acts for portable hosts.
-
Browser Support
+
Channels on children
- scene-hero-reveal, scene-layer-stack, and vl-children
- orchestrations use time-based delays and work in all modern browsers.
- scene-feature-flow and scene-story-pin use scroll-driven timelines and
- require Chrome 115+ / Edge 115+. Unsupported browsers see a static layout.
+ Use existing channels on stage children: vl-enter, vl-scroll,
+ vl-exit, etc. The scene clock drives when they play.
diff --git a/apps/docs/src/pages/timelines.astro b/apps/docs/src/pages/timelines.astro
index 7973c1d..c789373 100644
--- a/apps/docs/src/pages/timelines.astro
+++ b/apps/docs/src/pages/timelines.astro
@@ -2,67 +2,49 @@
import Base from "../layouts/Base.astro";
---
-
- Motion
+
+ Progress model
+ Timelines decide what drives progress. Effects decide what moves.
+ The scene engine shares one clock across stage children.
-
Timeline Modes
+
vl-timeline values
-
-
Value
-
Behavior
-
+
Value
Behavior
-
view
Scroll-driven via view(block) — element's viewport entry controls progress
-
scroll
Scroll-driven via scroll(root) — page scroll position controls progress
-
auto
Standard time-based (document timeline)
-
hover
Animation paused until hover
+
view
Progress from element / scene visibility (view() or named --vl-scene)
+
scroll
Progress from root scroll
+
auto
Time-based CSS animation
+
hover
Paused until hover
-
Range Presets
-
Pair vl-timeline="view" with vl-range to control the animation window:
-
-
-
-
Value
-
Range
-
-
-
-
entry
entry 0% entry 100%
-
entry-short
entry 15% cover 35%
-
entry-long
entry 0% cover 70%
-
cover
cover 0% cover 100%
-
contain
contain 0% contain 100%
-
custom
Uses --vl-range custom property
-
-
+
Scene clock
+
+ On [vl-scene][vl-timeline="view"], stage children use
+ animation-timeline: --vl-scene and ranges derived from
+ vl-act / vl-span / --vl-beats (default 8).
+
+
+ With vl-timeline="auto", the same acts map to
+ animation-delay: (act - 1) * --vl-beat. Pin/scrub are no-ops.
+
-
Boolean Modifiers
-
-
-
-
Attribute
-
Behavior
-
-
-
-
vl-pin
Sticky positioning for scroll-driven scenes
-
vl-scrub
Continuous linked motion (linear timing)
-
vl-once
Play animation only once (forwards fill)
-
-
+
Ranges
+
+ Presets via vl-range (entry, entry-short, cover, …)
+ still apply to standalone elements. Inside a pinned scene, prefer acts; use
+ vl-range only as an escape hatch.
+
-
Example
-
<div vl-effect="fade-up" vl-timeline="view" vl-range="entry-short" vl-once>
- Appears quickly as it enters the viewport, then stays visible.
-</div>
- An operational catalog for validating channels, ranges, timelines and states — editorial clarity and immediate feedback on every card.
+ Live contract surface for channels, scene engine, and params. Engine (motion-core) is host-agnostic; Skins/recipes are optional look.
Controles DX opcionais — motion entregue é só CSS. D/T/S ajustam duration, delay e playbackRate. Replay em vl-scene reposiciona scroll.
@@ -241,6 +254,21 @@
Motion API as composed a
+
+
+
+
Engine
+
motion-core
+
Host-agnostic scene + channel motion: vl-scene, vl-stage, vl-act, vl-enter / vl-scroll / vl-hover. Works with any UI host.
+
+
+
Skins
+
theme + recipes
+
Named look via data-editorial-theme and optional vl-scene="…" recipes. Not required for motion. See Skins.
+
+
+
+
Channel Architecture
@@ -320,9 +348,17 @@
Timeline Modes
Entrances and 3D
-
View-timeline entry effects — from basic fade-in to extended 3D behaviours.
+
View-timeline entry effects — prefer vl-enter for channel-first authorship; vl-effect remains a supported alias.
+
+ Channel-first · vl-enter
+
Stable CONTRACT extensions — same presets as vl-effect, bound to the enter channel.
+
reveal-cinematicdepth-entermask-sweep
+
+ vl-enter · reveal-cinematic
Reveal Cinematic
+ vl-enter · depth-enter
Depth Enter
+ vl-enter · mask-sweep
Mask Sweep
fade-in
Fade In
fade-up
Fade Up
slide-left
Slide Left
@@ -341,43 +377,36 @@
Entrances and 3D
Stage 3D
-
Bloco dedicado para efeitos e cenas 3D da API. Esta seção centraliza os casos que já estão estáveis e mantém espaço para a evolução do Stage 3D em paralelo.
+
Contrato reutilizável de palco 3D (perspective, preserve-3d, triggers). Demos de cubos ficam em Cube Triad (experimental).
Use vl-pin to keep a fixed anchor in view while the surrounding content advances through narrative steps.
+
vl-pin is numeric viewport heights on the track (vl-scene). Sticky subject is vl-stage. Values like top/center are not the scene-engine API (boolean vl-pin alone remains a legacy sticky helper).
-
- Pin Story - Large Stage
-
-
-
-
- Step 01 - Context Frame
-
The first block opens the narrative while the pinned anchor maintains the visual chapter reference.
-
-
- Step 02 - Range Tuning
-
Tune vl-range to control when each part enters. entry-short keeps the transition tight and precise.
-
-
- Step 03 - Scroll Scrub
-
With vl-scrub, the animation tracks scroll in real time — easy to calibrate rhythm and pacing.
-
-
- Step 04 - Cover Phase
-
Final phase — prepares the scene exit and hands off cleanly to the next block on the page.
-
-
- Step 05 - Exit Hand-off
-
Closes with vl-once to prevent replay and preserve reading state when scrolling back up.
-
+
+ Live · pin + scrub + acts
+
+
+
Act 1 · shared clock
+
Track · Stage · Acts
+
Act 2 enters on the same scene timeline.
+
Act 3–4 span · holds while the track scrubs.
+
Act 5 · hand-off
+
Scroll this card’s track. Motion is CSS-only (03c-scene-engine.css + channels). Kicker + title share vl-act="1" — same beat, overlapping range.
- pin + scrub
Pinned Scrub
- pin + range
Pin Center
+
+ Act overlap · same beat
+
+
+
Shared act 1
+
Title + kicker overlap
+
Act 2 only after act 1 window
+
+
+
Assign the same vl-act to stage children to choreograph overlap on one beat.
+
-
- Session Overlap Scroll Demo
-
-
-
- Section A - Base Layer
-
Section A holds as a sticky base layer while the scroll continues beneath it.
-
-
- Section B - Overlap
-
On scroll, Section B rises over A — layered reading maintained throughout.
-
-
- Section C - Top Layer
-
Finally, Section C enters over B and completes the overlap sequence.
-
+
+ Auto clock · beat delays
+
+
+
Beat 1 · immediate
+
Beat 2 · +1 beat delay
+
Beat 3 · +2 beat delay
-
+
vl-timeline="auto" maps acts to time delays (no scroll pin). Use for load-in sequences outside scroll stories.
+ Write pin + scrub timelines like GSAP — with vl-scene, vl-stage, and vl-act.
+ Look comes from the host UI (Showcase skin here; Tailwind in examples).
+
+ Acts 3–4 span — media scrub while the stage stays pinned.
+
+
Act 5 · CTA lands last
+
+
+
+
+
+
+
Host-agnostic
+
Same vl-*. Any UI.
+
+ Import @velora/css/motion-core only. Style with Tailwind (or anything).
+ Showcase / @velora/css/theme is the optional Velora look — not required for motion.
+
+ vl-scene="cinematic-hero" and friends still work via scene-recipes.css (theme).
+ New work should prefer track / stage / acts for host portability.
+