diff --git a/submissions/examples/ease-page-loader/README.md b/submissions/examples/ease-page-loader/README.md
new file mode 100644
index 0000000..7bcfdd6
--- /dev/null
+++ b/submissions/examples/ease-page-loader/README.md
@@ -0,0 +1,97 @@
+# ease-page-loader
+
+## What does this do?
+
+A fullscreen CSS overlay that covers the page on load, displays a centered loading animation, then fades out automatically — driven entirely by `animation-delay` and `animation-fill-mode: forwards`. No JavaScript required.
+
+## How is it used?
+
+Place the loader as the **first child of `
`**. It covers the viewport instantly and exits on its own after `--loader-exit-delay` (default 1.8s):
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### Custom color
+
+```html
+
+
+
+```
+
+### Custom timing
+
+```html
+
+
+
+
+```
+
+## Why does it fit EaseMotion CSS?
+
+EaseMotion CSS has inline loaders (skeleton shimmer, bouncing dots, button spinner) but **no fullscreen page-level loader** — these are fundamentally different use cases. This submission fills that gap.
+
+The implementation follows EaseMotion's core philosophy exactly:
+
+- **Pure CSS exit** — `animation-delay` holds the overlay; `animation-fill-mode: forwards` locks it in the final `visibility: hidden` state. Zero JavaScript timeouts
+- **Reuses core keyframes** — the spinner uses `ease-kf-rotate` and the dots use `ease-kf-pulse`, both already defined in `core/animations.css` — no new keyframes added to core
+- **Token-first** — `--loader-color` maps to `--ease-color-primary`; `--loader-bg` to `--ease-color-surface`; `--loader-pulse-speed` to `--ease-speed-slow`
+- **Three variants** — spinner ring, pulse dots, progress bar — covering the most common page load patterns
+- **`prefers-reduced-motion` safe** — animations disabled, overlay still exits at the correct time so content is never permanently hidden
+- **`visibility: hidden` final state** — removes the overlay from the accessibility tree entirely after exit, not just visually
+
+## CSS Custom Properties
+
+| Property | Default | Description |
+|---|---|---|
+| `--loader-color` | `var(--ease-color-primary)` | Accent color for spinner, dots, bar |
+| `--loader-color-track` | `var(--ease-color-neutral-200)` | Spinner ring track color |
+| `--loader-bg` | `var(--ease-color-surface)` | Overlay background |
+| `--loader-exit-delay` | `1.8s` | Time overlay stays visible before fading |
+| `--loader-exit-speed` | `400ms` | Duration of the fade-out |
+| `--loader-spin-speed` | `0.8s` | Spinner rotation speed |
+| `--loader-pulse-speed` | `var(--ease-speed-slow)` | Dot pulse cycle duration |
+| `--loader-size` | `48px` | Spinner diameter |
+| `--loader-thickness` | `4px` | Spinner border width |
+
+## Tech Stack
+
+- HTML
+- CSS only (no frameworks, no JavaScript)
+
+## Preview
+
+Open `demo.html` directly in your browser. The live loader fires on actual page load — you'll see it cover the page and exit after 1.8s, revealing the content below.
+
+## Contribution Notes
+
+- Class names used: `.page-loader`, `.page-loader-spinner`, `.page-loader-dots`, `.page-loader-dot`, `.page-loader-bar`, `.page-loader-dark`
+- Maintainer will rename to `ease-page-loader`, `ease-page-loader-spinner`, etc. before merging
+- No changes made to `core/`, `components/`, or any existing files
+- Spinner reuses `ease-kf-rotate` — if integrating into core, the `animation` property just needs to reference that keyframe name directly
\ No newline at end of file
diff --git a/submissions/examples/ease-page-loader/demo.html b/submissions/examples/ease-page-loader/demo.html
new file mode 100644
index 0000000..9320514
--- /dev/null
+++ b/submissions/examples/ease-page-loader/demo.html
@@ -0,0 +1,554 @@
+
+
+
+
+
+ ease-page-loader — EaseMotion CSS
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading…
+
+
+
+
+
+
+
+
ease-page-loader
+
+ Fullscreen CSS preloader with automatic exit animation ·
+ pure CSS · no JavaScript · three variants
+
+
+
+
+
+
+
Section 01
+
Three Variants
+
+ Each variant uses a different loading indicator.
+ All three share the same fullscreen overlay and CSS exit animation.
+ The spinner and dots reuse keyframes already in
+ core/animations.css.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Spinner Ring
+ .page-loader-spinner
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Pulse Dots
+ .page-loader-dots
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Please wait…
+
+
+
+ Progress Bar
+ .page-loader-bar
+
+
+
+
+
+
+
+
+
+
+
Section 02
+
Dark Background Variant
+
+ Add .page-loader-dark for dark-themed pages.
+ Overrides --loader-bg and
+ --loader-color-track using
+ existing --ease-color-neutral-* tokens.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Dark + Spinner
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Dark + Dots
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Starting…
+
+
+
+ Custom Color Override
+
+
+
+
+
+
+
+
+
+
+
Section 03
+
How to Use
+
+ Place the loader as the first child of
+ <body>.
+ It covers the viewport instantly on load and exits automatically after
+ --loader-exit-delay (default 1.8s) — no JavaScript needed.
+
+ All values are customizable via CSS variables.
+ Every token maps to an existing --ease-* property.
+
+
+
+
+
+
Property
+
Default
+
Description
+
+
+
+
+
--loader-color
+
var(--ease-color-primary)
+
Spinner/dot/bar accent color
+
+
+
--loader-color-track
+
var(--ease-color-neutral-200)
+
Spinner ring track color
+
+
+
--loader-bg
+
var(--ease-color-surface)
+
Overlay background color
+
+
+
--loader-exit-delay
+
1.8s
+
How long overlay stays visible before fading
+
+
+
--loader-exit-speed
+
400ms
+
Duration of the fade-out exit animation
+
+
+
--loader-spin-speed
+
0.8s
+
Spinner rotation speed
+
+
+
--loader-pulse-speed
+
var(--ease-speed-slow)
+
Dot pulse cycle duration
+
+
+
--loader-size
+
48px
+
Spinner diameter
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/submissions/examples/ease-page-loader/style.css b/submissions/examples/ease-page-loader/style.css
new file mode 100644
index 0000000..1e8cb89
--- /dev/null
+++ b/submissions/examples/ease-page-loader/style.css
@@ -0,0 +1,206 @@
+/* ============================================================
+ EaseMotion CSS — Contributor Submission
+ Feature: Fullscreen CSS Page Preloader with Exit Animation
+ Folder: submissions/examples/ease-page-loader/
+ Author: AjayBandiwaddar
+ ============================================================
+
+ NAMING NOTE:
+ Class names here are contributor-defined.
+ The maintainer will rename to ease-* convention before merging.
+ ============================================================ */
+
+
+/* ── Design Tokens ─────────────────────────────────────────
+ All values reference --ease-* custom properties.
+ Hard-coded fallbacks are for standalone demo use only.
+ ──────────────────────────────────────────────────────────── */
+
+:root {
+ --loader-color: var(--ease-color-primary, #6c63ff);
+ --loader-color-track: var(--ease-color-neutral-200, #e2e8f0);
+ --loader-bg: var(--ease-color-surface, #ffffff);
+ --loader-spin-speed: 0.8s;
+ --loader-pulse-speed: var(--ease-speed-slow, 600ms);
+ --loader-exit-delay: 1.8s;
+ --loader-exit-speed: 400ms;
+ --loader-size: 48px;
+ --loader-thickness: 4px;
+}
+
+
+/* ================================================================
+ BASE: Fullscreen Overlay
+ Covers the entire viewport on page load.
+ Exits automatically after --loader-exit-delay using pure CSS:
+ animation-delay holds the overlay, animation-fill-mode: forwards
+ locks it in the final invisible state.
+ ================================================================ */
+
+.page-loader {
+ position: fixed;
+ inset: 0;
+ z-index: var(--ease-z-toast, 9999);
+
+ /* Center the loader child */
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 1.25rem;
+
+ background: var(--loader-bg);
+
+ /* Exit animation — pure CSS, no JS timeout needed */
+ animation: page-loader-exit var(--loader-exit-speed) ease forwards;
+ animation-delay: var(--loader-exit-delay);
+}
+
+/* Exit keyframe — fade out, block pointer events, remove from a11y tree */
+@keyframes page-loader-exit {
+ 0% {
+ opacity: 1;
+ pointer-events: auto;
+ visibility: visible;
+ }
+ 100% {
+ opacity: 0;
+ pointer-events: none;
+ visibility: hidden;
+ }
+}
+
+
+/* ================================================================
+ VARIANT 1: Spinner Ring
+ Reuses ease-kf-rotate from core/animations.css.
+ A border-based ring with a colored leading edge.
+ ================================================================ */
+
+.page-loader-spinner {
+ width: var(--loader-size);
+ height: var(--loader-size);
+ border-radius: 50%;
+ border: var(--loader-thickness) solid var(--loader-color-track);
+ border-top-color: var(--loader-color);
+
+ /* Reuses ease-kf-rotate already defined in core/animations.css */
+ animation: ease-kf-rotate var(--loader-spin-speed) linear infinite;
+}
+
+
+/* ================================================================
+ VARIANT 2: Pulse Dot
+ Three dots that pulse in sequence using staggered animation-delay.
+ Reuses ease-kf-pulse from core/animations.css.
+ ================================================================ */
+
+.page-loader-dots {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.page-loader-dot {
+ width: 12px;
+ height: 12px;
+ border-radius: 50%;
+ background: var(--loader-color);
+
+ /* Reuses ease-kf-pulse already defined in core/animations.css */
+ animation: ease-kf-pulse var(--loader-pulse-speed) ease-in-out infinite;
+}
+
+/* Stagger each dot — natural wave feel */
+.page-loader-dot:nth-child(1) { animation-delay: 0ms; }
+.page-loader-dot:nth-child(2) { animation-delay: 150ms; }
+.page-loader-dot:nth-child(3) { animation-delay: 300ms; }
+
+
+/* ================================================================
+ VARIANT 3: Progress Bar
+ A horizontal bar that fills from left to right then loops.
+ Useful for page transitions and route changes.
+ ================================================================ */
+
+.page-loader-bar-wrap {
+ width: 180px;
+ height: 3px;
+ background: var(--loader-color-track);
+ border-radius: 99px;
+ overflow: hidden;
+}
+
+.page-loader-bar {
+ height: 100%;
+ width: 40%;
+ background: var(--loader-color);
+ border-radius: 99px;
+ animation: page-loader-bar-slide 1s ease-in-out infinite;
+}
+
+@keyframes page-loader-bar-slide {
+ 0% { transform: translateX(-100%); }
+ 50% { transform: translateX(150%); }
+ 100% { transform: translateX(350%); }
+}
+
+
+/* ================================================================
+ OPTIONAL: Loader Label
+ Small text beneath the animation — e.g. "Loading…"
+ ================================================================ */
+
+.page-loader-label {
+ font-size: 0.8rem;
+ font-weight: 500;
+ color: var(--ease-color-muted, #64748b);
+ letter-spacing: 0.04em;
+}
+
+
+/* ================================================================
+ DARK BACKGROUND VARIANT
+ Override the overlay background for dark-themed pages.
+ Usage:
+ ================================================================ */
+
+.page-loader-dark {
+ --loader-bg: var(--ease-color-neutral-900, #0f172a);
+ --loader-color-track: var(--ease-color-neutral-700, #334155);
+}
+
+
+/* ================================================================
+ ACCESSIBILITY: Reduced Motion
+ Keep the overlay visible and remove all animations.
+ The page content is still hidden until the overlay is manually
+ dismissed — developers should add a skip/dismiss button in this case.
+ ================================================================ */
+
+@media (prefers-reduced-motion: reduce) {
+ .page-loader {
+ animation: page-loader-exit-instant 0ms forwards;
+ animation-delay: var(--loader-exit-delay);
+ }
+
+ @keyframes page-loader-exit-instant {
+ to {
+ opacity: 0;
+ pointer-events: none;
+ visibility: hidden;
+ }
+ }
+
+ .page-loader-spinner,
+ .page-loader-dot,
+ .page-loader-bar {
+ animation: none;
+ }
+
+ /* Static fallback: show a centered dot instead */
+ .page-loader-spinner {
+ border-top-color: var(--loader-color);
+ opacity: 0.6;
+ }
+}
\ No newline at end of file
diff --git a/submissions/examples/ease-split-text/README.md b/submissions/examples/ease-split-text/README.md
new file mode 100644
index 0000000..0ce122d
--- /dev/null
+++ b/submissions/examples/ease-split-text/README.md
@@ -0,0 +1,109 @@
+# ease-split-text
+
+## What does this do?
+
+A CSS utility that animates each letter of a heading independently — letters fade, slide, or blur into view in left-to-right sequence using `nth-child` staggered `animation-delay` on individual `` wrappers. Pure CSS, zero JavaScript.
+
+## How is it used?
+
+Wrap each letter in a ``. Use `.split-space` for word spaces. Add a variant modifier class:
+
+```html
+
+
+```
+
+## Why does it fit EaseMotion CSS?
+
+EaseMotion CSS animates elements at block level (`staggered-reveal`, `staggered-fade-entrance`) and text at string level (`ease-typewriter`). **Per-character animation is the missing layer** — and this submission fills it:
+
+| Effect | Unit animated | Technique | Per-letter? |
+|---|---|---|---|
+| `ease-typewriter` | Entire string | `width: 0ch → Nch` clipping | ✕ No |
+| `staggered-reveal` | Block elements | `nth-child` delay on divs/lis | ✕ No |
+| `ease-split-text` | Each letter | `nth-child` delay on inline spans | ✓ Yes |
+
+The implementation follows EaseMotion's core philosophy:
+
+- **Reuses core keyframes** — fade variant uses `ease-kf-fade-in`; slide variant uses `ease-kf-slide-up` — both already in `core/animations.css`. Zero new keyframes added
+- **Token-first** — `--split-delay-step`, `--split-rise`, `--split-duration`, `--split-ease` are all overridable CSS variables
+- **Human-readable** — `.ease-split-text-slide` is immediately self-explanatory
+- **`prefers-reduced-motion` safe** — all letters shown instantly with no animation; text is never hidden
+
+## CSS Custom Properties
+
+| Property | Default | Description |
+|---|---|---|
+| `--split-delay-step` | `40ms` | Stagger gap between each letter |
+| `--split-duration` | `400ms` | Animation duration per letter |
+| `--split-rise` | `16px` | translateY travel for slide variant |
+| `--split-ease` | `var(--ease-ease-out)` | Easing function |
+
+## Classes Reference
+
+| Class | Description |
+|---|---|
+| `ease-split-text` | Base class — fade-only entrance |
+| `ease-split-text-slide` | Slide-up variant |
+| `ease-split-text-blur` | Fade + blur variant |
+| `ease-split-text-fast` | 25ms stagger step |
+| `ease-split-text-slow` | 70ms stagger step |
+| `ease-split-space` | Word space preserver |
+
+## Tech Stack
+
+- HTML
+- CSS only (no frameworks, no JavaScript)
+
+## Preview
+
+Open `demo.html` directly in your browser. Six sections: fade, slide, blur on dark hero, speed presets, usage code, and a comparison table against existing effects.
+
+## Contribution Notes
+
+- Class names used: `.split-text`, `.split-text-slide`, `.split-text-blur`, `.split-text-fast`, `.split-text-slow`, `.split-space`
+- Maintainer will rename to `ease-split-text-*` before merging
+- Spinner references `ease-kf-fade-in` and `ease-kf-slide-up` — no changes to core needed
+- No changes made to `core/`, `components/`, or any existing files
+- `nth-child` stagger covers 30 letters — sufficient for virtually all heading text
\ No newline at end of file
diff --git a/submissions/examples/ease-split-text/demo.html b/submissions/examples/ease-split-text/demo.html
new file mode 100644
index 0000000..28d4298
--- /dev/null
+++ b/submissions/examples/ease-split-text/demo.html
@@ -0,0 +1,507 @@
+
+
+
+
+
+ ease-split-text — EaseMotion CSS
+
+
+
+
+
+
+
+
+
+
+
+
+
ease-split-text
+
+ Per-letter staggered entrance · pure CSS · zero JavaScript ·
+ each letter is its own animated unit
+
+
+
+
+
+
+
Section 01
+
Variant 1 — Fade Only
+
+ Letters fade in one by one from left to right. Uses
+ ease-kf-fade-in
+ already in core/animations.css — no new keyframe.
+ Default stagger: 40ms per letter.
+
+
+
+
+
Default — 40ms step
+
+ Build
+
+ faster.
+
+
+
+
+
Accent color on letters
+
+ EaseMotion
+
+ CSS
+
+
+
+
+
Multi-word heading
+
+ Ship
+
+ beautiful
+
+ UIs.
+
+
+
+
+
+
+
+
+
+
Section 02
+
Variant 2 — Slide Up
+
+ Each letter rises 16px into position as it fades in. Uses
+ ease-kf-slide-up
+ from core. The travel distance is controlled by
+ --split-rise (default 16px).
+
+
+
+
+
Slide up — default rise
+
+ Design
+
+ with
+
+ motion.
+
+
+
+
+
Larger rise — 28px
+
+ Animate
+
+ everything.
+
+
+
+
+
+
+
+
+
+
Section 03
+
Variant 3 — Fade + Blur
+
+ Letters materialize from blurred to sharp. Adds depth without movement —
+ ideal for hero sections on dark backgrounds where subtle motion
+ feels more premium than a slide.
+
+
+
+
+
+ Dark hero · blur variant
+
+
+ Pure
+
+ CSS.
+
+
+ Zero
+
+ JavaScript.
+
+
+
+
+
+
+
+
+
+
Section 04
+
Speed Presets
+
+ Three speed presets via modifier class. All controlled by
+ --split-delay-step —
+ override inline for any custom value.
+
+
+
+
+
+
Fast · 25ms
+
class="split-text-fast"
+
+ Snappy.
+
+
+
+
+
Default · 40ms
+
--split-delay-step: 40ms
+
+ Balanced.
+
+
+
+
+
Slow · 70ms
+
class="split-text-slow"
+
+ Dramatic.
+
+
+
+
+
+
+
+
+
+
+
Section 05
+
How to Use
+
+ Wrap each letter in a <span>.
+ Use .split-space for word spaces.
+ Add a variant modifier class. Done.
+
+ Three animations in EaseMotion CSS look similar but work completely differently.
+
+
+
+
+
+
Effect
+
Unit Animated
+
Technique
+
Per-letter?
+
+
+
+
+
ease-typewriter
+
Entire string
+
width: 0ch → Nch (clipping)
+
✕ No
+
+
+
staggered-reveal
+
Block elements (li, div)
+
nth-child delay on block children
+
✕ No
+
+
+
ease-split-text
+
Each letter independently
+
nth-child delay on inline span per character
+
✓ Yes
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/submissions/examples/ease-split-text/style.css b/submissions/examples/ease-split-text/style.css
new file mode 100644
index 0000000..621dc36
--- /dev/null
+++ b/submissions/examples/ease-split-text/style.css
@@ -0,0 +1,180 @@
+/* ============================================================
+ EaseMotion CSS — Contributor Submission
+ Feature: Per-letter Staggered Entrance Animation
+ Folder: submissions/examples/ease-split-text/
+ Author: AjayBandiwaddar
+ ============================================================
+
+ NAMING NOTE:
+ Class names here are contributor-defined.
+ The maintainer will rename to ease-* convention before merging.
+
+ KEYFRAME NOTE:
+ This submission reuses ease-kf-fade-in and ease-kf-slide-up
+ already defined in core/animations.css — zero new keyframes
+ added to core.
+ ============================================================ */
+
+
+/* ── Design Tokens ─────────────────────────────────────────
+ All values reference --ease-* custom properties.
+ Hard-coded fallbacks are for standalone demo use only.
+ ──────────────────────────────────────────────────────────── */
+
+:root {
+ --split-duration: 400ms;
+ --split-ease: var(--ease-ease-out, cubic-bezier(0, 0, 0.2, 1));
+ --split-delay-step: 40ms; /* stagger gap between each letter */
+ --split-rise: 16px; /* translateY travel for slide variant */
+}
+
+
+/* ================================================================
+ BASE: .split-text wrapper
+ Apply to any heading or text element.
+ Each direct child is one letter.
+ ================================================================ */
+
+.split-text {
+ /* Prevent line wrapping from breaking the stagger sequence */
+ display: block;
+}
+
+/* Every letter span starts invisible */
+.split-text span {
+ display: inline-block;
+ opacity: 0;
+ /* Reuses ease-kf-fade-in from core/animations.css */
+ animation-name: ease-kf-fade-in;
+ animation-duration: var(--split-duration);
+ animation-timing-function: var(--split-ease);
+ animation-fill-mode: forwards;
+}
+
+
+/* ================================================================
+ SPACE PRESERVATION
+ Word spaces collapse in HTML — use .split-space to maintain them.
+ Usage:
+ ================================================================ */
+
+.split-text .split-space {
+ display: inline-block;
+ width: 0.35em;
+ opacity: 1 !important; /* spaces are always visible */
+ animation: none !important;
+}
+
+
+/* ================================================================
+ nth-child STAGGER TABLE
+ Each letter gets an incremental animation-delay.
+ Step size: --split-delay-step (default 40ms).
+ Coverage: 30 letters — handles most heading lengths.
+ ================================================================ */
+
+.split-text span:nth-child(1) { animation-delay: calc(var(--split-delay-step) * 0); }
+.split-text span:nth-child(2) { animation-delay: calc(var(--split-delay-step) * 1); }
+.split-text span:nth-child(3) { animation-delay: calc(var(--split-delay-step) * 2); }
+.split-text span:nth-child(4) { animation-delay: calc(var(--split-delay-step) * 3); }
+.split-text span:nth-child(5) { animation-delay: calc(var(--split-delay-step) * 4); }
+.split-text span:nth-child(6) { animation-delay: calc(var(--split-delay-step) * 5); }
+.split-text span:nth-child(7) { animation-delay: calc(var(--split-delay-step) * 6); }
+.split-text span:nth-child(8) { animation-delay: calc(var(--split-delay-step) * 7); }
+.split-text span:nth-child(9) { animation-delay: calc(var(--split-delay-step) * 8); }
+.split-text span:nth-child(10) { animation-delay: calc(var(--split-delay-step) * 9); }
+.split-text span:nth-child(11) { animation-delay: calc(var(--split-delay-step) * 10); }
+.split-text span:nth-child(12) { animation-delay: calc(var(--split-delay-step) * 11); }
+.split-text span:nth-child(13) { animation-delay: calc(var(--split-delay-step) * 12); }
+.split-text span:nth-child(14) { animation-delay: calc(var(--split-delay-step) * 13); }
+.split-text span:nth-child(15) { animation-delay: calc(var(--split-delay-step) * 14); }
+.split-text span:nth-child(16) { animation-delay: calc(var(--split-delay-step) * 15); }
+.split-text span:nth-child(17) { animation-delay: calc(var(--split-delay-step) * 16); }
+.split-text span:nth-child(18) { animation-delay: calc(var(--split-delay-step) * 17); }
+.split-text span:nth-child(19) { animation-delay: calc(var(--split-delay-step) * 18); }
+.split-text span:nth-child(20) { animation-delay: calc(var(--split-delay-step) * 19); }
+.split-text span:nth-child(21) { animation-delay: calc(var(--split-delay-step) * 20); }
+.split-text span:nth-child(22) { animation-delay: calc(var(--split-delay-step) * 21); }
+.split-text span:nth-child(23) { animation-delay: calc(var(--split-delay-step) * 22); }
+.split-text span:nth-child(24) { animation-delay: calc(var(--split-delay-step) * 23); }
+.split-text span:nth-child(25) { animation-delay: calc(var(--split-delay-step) * 24); }
+.split-text span:nth-child(26) { animation-delay: calc(var(--split-delay-step) * 25); }
+.split-text span:nth-child(27) { animation-delay: calc(var(--split-delay-step) * 26); }
+.split-text span:nth-child(28) { animation-delay: calc(var(--split-delay-step) * 27); }
+.split-text span:nth-child(29) { animation-delay: calc(var(--split-delay-step) * 28); }
+.split-text span:nth-child(30) { animation-delay: calc(var(--split-delay-step) * 29); }
+
+
+/* ================================================================
+ VARIANT 1: Fade Only (default)
+ Letters appear in place — no movement.
+ Reuses ease-kf-fade-in from core/animations.css.
+ Already applied in the base .split-text rule above.
+ ================================================================ */
+
+/* No extra rules needed — base .split-text IS the fade variant */
+
+
+/* ================================================================
+ VARIANT 2: Slide Up
+ Letters rise 16px into position as they appear.
+ Reuses ease-kf-slide-up from core/animations.css
+ (from: opacity 0, translateY 24px → to: opacity 1, translateY 0).
+ We override with --split-rise for a subtler 16px travel.
+ ================================================================ */
+
+.split-text-slide span {
+ transform: translateY(var(--split-rise));
+ animation-name: ease-kf-slide-up;
+}
+
+
+/* ================================================================
+ VARIANT 3: Fade + Blur
+ Letters materialize with a blur → sharp transition.
+ Adds depth without needing movement.
+ ================================================================ */
+
+.split-text-blur span {
+ filter: blur(6px);
+ animation-name: split-kf-fade-blur;
+}
+
+@keyframes split-kf-fade-blur {
+ to {
+ opacity: 1;
+ filter: blur(0);
+ }
+}
+
+
+/* ================================================================
+ STAGGER SPEED PRESETS
+ Override --split-delay-step for faster or slower reveals.
+ ================================================================ */
+
+/* Fast: 25ms per letter — punchy, short words */
+.split-text-fast {
+ --split-delay-step: 25ms;
+}
+
+/* Slow: 70ms per letter — dramatic, impactful headings */
+.split-text-slow {
+ --split-delay-step: 70ms;
+}
+
+
+/* ================================================================
+ ACCESSIBILITY: Reduced Motion
+ Show all letters immediately with no animation.
+ Text is never hidden from users who need reduced motion.
+ ================================================================ */
+
+@media (prefers-reduced-motion: reduce) {
+ .split-text span {
+ opacity: 1 !important;
+ transform: none !important;
+ filter: none !important;
+ animation: none !important;
+ }
+}
\ No newline at end of file
diff --git a/submissions/examples/ease-tooltip/README.md b/submissions/examples/ease-tooltip/README.md
index 56799fa..b81d769 100644
--- a/submissions/examples/ease-tooltip/README.md
+++ b/submissions/examples/ease-tooltip/README.md
@@ -1,23 +1,104 @@
-# Tooltip Component (#250)
+# ease-tooltip
-### What does this do?
-Adds a performant, zero-JavaScript `ease-tooltip` component to the framework. It extracts text from a `data-tooltip` HTML attribute and beautifully renders it as a floating bubble with an arrow pointer using CSS pseudo-elements (`::after` and `::before`).
+## What does this do?
-### How is it used?
-Apply the `.ease-tooltip` class and a `data-tooltip` attribute to any container element (like a button or a span).
+A CSS-only animated tooltip component that appears on hover and keyboard focus — no JavaScript required. The bubble fades in and slides 4px into position using `opacity` + `transform` transitions, consistent with EaseMotion's existing motion language.
+
+## How is it used?
+
+Wrap any trigger element with a `` and set the tooltip text via the `data-tip` attribute:
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### Semantic color variants
+
+Override `--tooltip-bg` for contextual meaning:
```html
-
+
+
+
+
+
+
+
+
+
```
-**Position Variants:**
-- `.ease-tooltip-top` (or omit entirely, top is default)
-- `.ease-tooltip-bottom`
-- `.ease-tooltip-left`
-- `.ease-tooltip-right`
+```css
+.tooltip-success { --tooltip-bg: var(--ease-color-success-dark, #15803d); }
+.tooltip-danger { --tooltip-bg: var(--ease-color-danger-dark, #b91c1c); }
+.tooltip-warning { --tooltip-bg: var(--ease-color-warning-dark, #b45309); }
+.tooltip-info { --tooltip-bg: #0369a1; }
+```
+
+### Custom speed or offset
+
+```css
+/* Slower tooltip on a specific element */
+.my-element { --tooltip-speed: var(--ease-speed-medium); }
+
+/* More breathing room between trigger and bubble */
+.my-element { --tooltip-offset: 12px; }
+```
+
+## Why is it useful?
+
+Tooltips are one of the most commonly needed UI primitives — yet EaseMotion CSS had no tooltip component at all. The VISION.md roadmap explicitly lists "Modal & tooltip components" as **Planned v1.2**.
+
+This submission accelerates that milestone with a zero-JS implementation:
+
+- **Pure CSS** — `::before` (bubble) + `::after` (arrow) pseudo-elements on the wrapper
+- **No extra markup overhead** — text lives in `data-tip`, not a separate element
+- **4 position variants** — top (default), bottom, left, right
+- **Keyboard accessible** — triggers on `:focus-within`, not just `:hover`
+- **Token-driven** — all values use existing `--ease-*` custom properties
+- **`prefers-reduced-motion` safe** — transitions disabled, tooltip still shows
+- **Composable** — works on buttons, icon buttons, inline text, cards
+
+## CSS Custom Properties
+
+| Property | Default | Description |
+|---|---|---|
+| `--tooltip-bg` | `var(--ease-color-neutral-900)` | Bubble background color |
+| `--tooltip-color` | `var(--ease-color-neutral-50)` | Bubble text color |
+| `--tooltip-speed` | `var(--ease-speed-fast)` | Transition duration |
+| `--tooltip-offset` | `8px` | Gap between trigger and bubble |
+| `--tooltip-radius` | `var(--ease-radius-sm)` | Bubble border radius |
+| `--tooltip-max-width` | `220px` | Maximum bubble width |
+
+## Tech Stack
+
+- HTML
+- CSS only (no frameworks, no JavaScript)
+
+## Preview
+
+Open `demo.html` directly in your browser to see all variants.
+
+## Contribution Notes
-### Why is it useful?
-1. **Zero JS Overhead:** Because it utilizes HTML attributes and `content: attr()`, there is absolutely no JavaScript required to mount, position, or unmount the tooltip. This makes it incredibly lightweight and performant.
-2. **Accessible by Default:** It respects `prefers-reduced-motion` flawlessly. Normally the tooltips have a smooth slide-in effect, but when reduced motion is enabled, the `transform` animation is stripped out while the `opacity` fade is preserved to prevent motion sickness.
+- Class names used: `.tooltip`, `.tooltip-top`, `.tooltip-bottom`, `.tooltip-left`, `.tooltip-right`
+- Maintainer will rename to `ease-tooltip`, `ease-tooltip-bottom`, etc. before merging
+- No changes made to `core/`, `components/`, or any existing files
\ No newline at end of file
diff --git a/submissions/examples/ease-tooltip/demo.html b/submissions/examples/ease-tooltip/demo.html
index 5b6fb52..9027a8b 100644
--- a/submissions/examples/ease-tooltip/demo.html
+++ b/submissions/examples/ease-tooltip/demo.html
@@ -1,98 +1,406 @@
-
- Tooltip Component Demo
-
-
+
+
+ ease-tooltip — EaseMotion CSS
+
+
-
-
-
-
-
+
+
+
-
EaseMotion: ease-tooltip
-
A highly performant CSS-only tooltip system. Hover over the elements below to see the tooltips slide in elegantly.
+
ease-tooltip
+
CSS-only animated tooltip component · hover or focus to trigger · zero JavaScript
-
-
-
-
-
-
-
+
-
-
-
+
+
Section 01
+
Position Variants
+
+ Four directional variants controlled by a single modifier class.
+ Default is top. Add tooltip-bottom,
+ tooltip-left, or
+ tooltip-right for other directions.
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
-
-
Inline Text Usage
-
- You can also use tooltips on standard inline text. For example, hover over this
- magic word
- to learn more about it without using any Javascript.
+
+
+
+
+
Section 02
+
Icon Button Toolbar
+
+ A common real-world pattern — icon-only buttons with tooltips explaining
+ each action. No visible label needed; the tooltip carries the meaning.
+ Keyboard accessible via focus-within.
+ Tooltip background color is driven by a single
+ --tooltip-bg CSS variable.
+ Semantic variants (success, danger, warning, info) reinforce
+ the intent of the action — no extra markup needed.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Section 04
+
Inline Prose Usage
+
+ Tooltips work inline inside paragraphs — useful for glossary terms,
+ abbreviations, and contextual hints without breaking reading flow.
+
+
+
+
+ EaseMotion CSS uses
+
+ CSS custom properties
+
+ as its token system. All animations respect
+
+ prefers-reduced-motion
+
+ and are triggered via
+
+ :focus-within
+
+ for full keyboard accessibility — no JavaScript required.
+
+
+
+
+
+
+
+
+
Section 05
+
Keyboard Accessible
+
+ Tab through the buttons below. The tooltip appears on
+ :focus-within — no mouse required.
+ This makes the component WCAG 2.1 AA compliant out of the box.
+