Element: #301 Text scramble (motion/text) What it shows: A line of monospace text that decodes from random glyphs, locking one letter every 55ms from left to right. It re-runs on every loop and again on hover or focus. When to use: Security and crypto screens, a status label that just changed, a hacker-style heading or any short label that should feel like it is resolving. Spec: - `MotionStage` from `@codeatlasdev/ui` with `label="Scramble: a line of text decodes from random glyphs"` and `loop={2800}` - `const STEP = 40` redraws the random glyphs every 40ms; `const SETTLE = 55` locks the next letter every 55ms - `aria-label={target}` on the button keeps the real sentence as the accessible name; the flickering glyphs sit in a ` import { MotionStage, type MotionCtx } from '@codeatlasdev/ui'; const target = 'ENCRYPTED → DECRYPTED'; const glyphs = '!<>-_\\/[]{}=+*^?#0123456789'; const STEP = 40; // 40ms: how often the random glyphs are redrawn const SETTLE = 55; // 55ms per letter, linear: a constant pace with no easing let text = $state(target); let raf = 0; /** Decode left to right: letters before the cursor are final, the rest are random glyphs. */ function decode() { cancelAnimationFrame(raf); const start = performance.now(); let last = -STEP; const frame = (now: number) => { const t = now - start; if (now - last >= STEP) { last = now; const locked = Math.floor(t / SETTLE); text = [...target] .map((c, i) => (c === ' ' || i < locked ? c : glyphs[Math.floor(Math.random() * glyphs.length)])) .join(''); } if (t / SETTLE < target.length) raf = requestAnimationFrame(frame); else text = target; }; raf = requestAnimationFrame(frame); } /** Autoplay: every stage cycle decodes again; reduced motion shows the final text. */ const autoplay = (m: MotionCtx) => () => { const { cycle, reduced } = m; void cycle; if (reduced) { cancelAnimationFrame(raf); text = target; return; } decode(); return () => cancelAnimationFrame(raf); }; {#snippet children(m)}

Hover or focus the line to decode it again.

{/snippet}