# ns-ui — AI-agent quickstart ns-ui is a personal React/Next.js component registry: 50 self-contained, dependency-light components (a Geist-dark "core" set + a deliberately flashy "loud" set). Every component installs as plain source you own — no runtime package, no MCP server. Install directly, zero config: npx shadcn add https://design.helpmarq.com/r/.json This drops component.tsx into your project (components/ui/.tsx) and pulls its npm deps via shadcn. No account, no API key. Requirements before you use any of these: - Colors MUST come from CSS custom properties already in scope: --background --foreground --muted --border --accent. Never hardcode hex — these components are light/dark theme-reactive only if those tokens exist in the host app's globals.css. - Peer deps: react 19+, Tailwind CSS v4 (components are styled entirely with Tailwind utility classes — no shipped CSS file). Fonts assumed Geist Sans / Geist Mono (components inherit font-family, they don't set it). Per-component npm deps listed below as "deps". Full behavioral detail (long form, one paragraph per component): https://design.helpmarq.com/llms-full.txt Each block below: ## [collection] — <one-line purpose> use when: <selection guidance — the problem it solves, not a restatement of the title> props: <condensed public prop signature: name, type, optionality, default, purpose> deps: <npm dependencies beyond react> install: npx shadcn add https://design.helpmarq.com/r/<name>.json ## ascii-dither-media [core] ASCII Dither Media — Luminance-to-glyph canvas renderer: ASCII, Bayer-dither, and dot-matrix modes with cursor-proximity resolve. use when: a background/ambient layer (ascii, dither, canvas). props: mode?: Mode // default: "ascii" src?: string // optional image URL; omit for the built-in animated noise field cellSize?: number // grid cell size in px; default: 14 cursorRadius?: number // cursor-proximity resolve radius in px; default: 140 className?: string ↳ Mode = "ascii" | "dither" | "dot" deps: (none) behavior: A full-bleed canvas engine that maps a source (animated flowing noise by default, or an image) to a luminance-driven monochrome glyph grid with three modes: ASCII characters in a density ramp, 4x4 Bayer-matrix dithered pixels, and dot-matrix circles sized by brightness. The cursor brightens and resolves nearby cells with a Gaussian falloff and eased trailing. Direct-DOM rAF loop with no React state, theme-aware glyph color, single static frame under prefers-reduced-motion. Window resize is debounced (150ms) so dragging a window edge doesn't spam the grid recompute or (in image mode) refetch/redecode the source on every event; a generation counter discards any image decode superseded by a newer resize before it can write stale-sized data. install: npx shadcn add https://design.helpmarq.com/r/ascii-dither-media.json ## cardio-baseline [core] Cardio Baseline — Text whose baseline is a live EKG trace: each beat fires a QRS spike that travels under the letters, throwing every glyph up the waveform before it spring-settles flat. use when: text with a live EKG baseline — each beat's QRS spike throws every glyph up the waveform before it spring-settles flat, firable imperatively via a ref for real events (deploys, messages); use for a heartbeat/pulse motif, not a generic reveal. props: children?: string // the text riding the trace; default: "SYSTEMS NOMINAL" bpm?: number // beats per minute from the internal timer; 0 = imperative-only; default: 50 className?: string deps: (none) behavior: A text component whose baseline is an EKG trace. Render one inline-block DOM span per glyph (measured once via offsetLeft/offsetWidth, remeasured on ResizeObserver and fonts.ready; baseline found with a zero-height inline-block marker span whose offsetTop is the baseline) plus one absolutely-positioned SVG holding a polyline trace and a sweep dot, all written by a single direct-DOM rAF loop with no React state on the hot path. The trace is a 1.5px #8f8f8f flatline at the text baseline; a 4px #ffffff sweep dot rides it at 320 px/s, wrapping at the right edge. Each beat injects a piecewise QRS-T kernel at the left edge — half-sine segments: Q dip +6px/40ms, R spike -46px/70ms, S dip +10px/50ms, T bump -8px/180ms — propagating right at 900 px/s as wave(x,t) = kernel(t - t0 - x/900), summed over active beats. While the kernel passes under a glyph's center the glyph is position-driven: translateY = wave(centerX) and rotation = atan(local slope, sampled ±4px) clamped ±9°, with velocity tracked so the handoff is continuous. Once the wave passes, the glyph rings down on an underdamped spring (k=140 s^-2, zeta=0.45 — two visible wobbles, then flat) while rotation decays exponentially. Polyline points sampled every 6px are rewritten in the same frame, and the dot's cy follows the wave under its x. Beats fire from a bpm prop timer (default 50, resting-clinical pace, each interval jittered +/-8% for a natural sinus-arrhythmia feel rather than a metronomic tick; timer lives in a separate effect so rate changes never reset glyph state) or imperatively via a ref handle beat() for real events (deploys, messages). The loop sleeps once every wave has exited the right edge and all glyph residuals are < 0.1px, waking on the timer or beat(). Under prefers-reduced-motion: static flatline plus typeset text, no dot, no timers, no listeners. Zero dependencies. install: npx shadcn add https://design.helpmarq.com/r/cardio-baseline.json ## caustic-coverflow [core] Caustic Coverflow — 3D coverflow gallery whose frosted-glass cards run a live caustic-light simulation — drifting light pools refract across each pane, and drag velocity fringes the focused card's edges with chromatic aberration that settles to zero at rest. use when: a gallery (coverflow, 3d, canvas). props: items?: CausticCoverflowItem[] // default: DEFAULT_ITEMS initialIndex?: number // starting focused card; defaults to the middle cardWidth?: number // card width in px (shrinks responsively on narrow containers); default: 264 cardHeight?: number // default: 330 className?: string aria-label?: string // default: "Coverflow gallery" ↳ CausticCoverflowItem = { title: string; meta?: string; seed?: number } deps: (none) behavior: A 3D coverflow gallery where every card sits behind frosted glass running a lightweight caustic-light simulation. RENDERING: DOM cards under a perspective-1200px stage, anchored at the stage center with translate(-50%,-50%) plus offset transforms (never absolute coords) — center card scale 1.0, side cards rotateY ±35° and scale 0.82, x-spacing 46% of card width, translateZ −60px per index of distance with explicit z-index depth sorting. Each card is a frosted pane: backdrop-filter blur(14px) saturate(1.1) over color-mix(--surface 60%, transparent), 1px --border, rounded-md, over a token-derived generated abstract thumb (grayscale value-noise field mixed from --surface/--border/--muted/--foreground, no external images). A per-card pointer-events-none Canvas 2D overlay (explicit style.width/height + dpr-capped-2 backing store — CSS inset never sizes a canvas) renders caustics: three radial gradients (radius 40% of card width, --foreground ink at alphas 0.10/0.07/0.05) whose centers travel incommensurate Lissajous paths with periods 7s/11s/13s and amplitude 30% of card size, drawn onto a fully cleared quarter-resolution offscreen buffer each tick (no alpha accumulation, ever) and upscaled with imageSmoothing for soft pool edges. Only the focused card and its two neighbors run live caustics; outer cards keep a fixed-phase static frame. CHROMATIC ABERRATION: focused card only — its rounded border restroked twice, offset ±k px horizontally, in red/blue channel inks split from the foreground token (rgba(fg.r,0,0) / rgba(0,0,fg.b)), composited 'lighter' on dark themes and source-over on light; k = min(6, |angular velocity in deg/s| × 0.04) where the focused card turns 35°/index, exponentially damped (τ≈100ms, settles < 500ms) with a 900ms forced-settle deadline. INTERACTION: pointer drag scrubs the continuous index (rubber-band past the ends); release applies momentum with friction 0.92/frame (fps-normalized) then hands off to a snap spring (k=170, ζ≈0.95) once |v| < 0.05 idx/s, itself under a 900ms forced-settle deadline so a flick can never oscillate forever; wheel steps one card per 260ms with a 250ms ease-out-expo tween; clicking a side card centers it (taps under 5px of travel); ArrowLeft/Right step with a visible token-relative focus ring on the stage; index dots below the stage navigate and mirror the active card via data-active. IDLE: pools keep drifting at half amplitude (ambient default look) capped at 30fps, blending back to full amplitude while interacting. REDUCED MOTION: no rAF loop, one static caustic frame per card, no aberration, navigation via instant 200ms CSS ease with no momentum. LIFECYCLE: all canvas inks derived from getComputedStyle tokens at mount and re-derived by a MutationObserver on documentElement class (thumbs and static frames regenerate per theme); IntersectionObserver pauses the loop offscreen and the loop fully sleeps when settled AND the tab is hidden; zero-size containers guard all drawing; hover is a 2px inner-wrapper lift plus border-foreground/25 so the rAF transform is never fought; every listener, observer, and rAF torn down on unmount. Demo: padded 'Field notes' gallery section on a surface card with mono eyebrow, muted subline, seven believable archive entries (generated thumbs, Geist Sans titles, mono date + index meta) and index dots below the stage. install: npx shadcn add https://design.helpmarq.com/r/caustic-coverflow.json ## caustic-select [core] Caustic Select — Single-select whose frosted-glass trigger and listbox sit over drifting caustic light pools; hovering or arrow-keying an option bends the caustics toward that row so the highlight reads as pressed into the glass. use when: a select control (listbox, form, canvas). props: options?: CausticSelectOption[] // default: DEFAULT_OPTIONS value?: string // controlled value; omit for uncontrolled defaultValue?: string onValueChange?: (value: string) => void label?: string // field label rendered above the trigger; default: "Region" placeholder?: string // default: "Select a region" disabled?: boolean // default: false name?: string // when set, renders a hidden input for form posts className?: string ↳ CausticSelectOption = { value: string; label: string; hint?: string; disabled?: boolean } deps: (none) behavior: Build a single-select (DOM trigger button + listbox panel) whose surfaces are real frosted glass: each surface stacks a canvas 2D layer, then a translucent bg-surface span with backdrop-blur + saturate that frosts the canvas beneath it, then the content. The canvases draw caustics as 6 (trigger) / 8 (panel) radial-gradient blobs summed with globalCompositeOperation 'lighter' at 0.06-0.10 alpha, colors mixed between --accent and --foreground, with EXPLICIT canvas style.width/height plus a DPR-2-clamped backing store, and a full clear + redraw every frame (no destination-in accumulation). Idle simmer: each blob drifts on independent sin/cos phase offsets at a 6-10 px/s peak (amplitude 10-16px with frequency = speed/amplitude), running only while the panel is open, onscreen (IntersectionObserver), and the tab is visible; the closed trigger shows one static frame and the rAF is fully asleep. Open: panel with transform-origin at the trigger top scales 0.96 to 1 over 180ms on cubic-bezier(0.16,1,0.3,1) via WAAPI while blob anchors start clustered at the origin and spring (k=60 s^-2, zeta=0.9, ~450ms settle) to positions redistributed evenly down the list height. Active-row lens: a radial displacement field of radius 56px pulls blob centers up to 6px toward the active row center plus a tight accent pool under the row; the lens position follows cursor-hover or keyboard-active targets (one unified target) on a spring k=140 s^-2, zeta=0.8, with a forced-settle deadline snapping it 1.0s after the last input; lens coordinates are panel-local offsets from getBoundingClientRect deltas, never absolute page coords. Keyboard: full listbox pattern — trigger aria-haspopup=listbox aria-expanded, Enter/Space/ArrowDown/ArrowUp open, focus moves to the listbox which tracks aria-activedescendant, Up/Down skip disabled options, Home/End, 500ms typeahead buffer with startsWith matching, Enter (or Space with an empty buffer) commits, Esc and outside pointerdown close and restore focus to the trigger, hover and keyboard drive the same lens. Ink is getComputedStyle-derived from --accent/--foreground at mount and re-derived live by a MutationObserver on documentElement class so both themes render correctly. prefers-reduced-motion: static frost texture at anchor targets, no drift or lens, instant open/close. Guard zero-size hosts before sizing canvases (the panel is display:none while closed), and tear down every rAF, WAAPI animation, observer, listener, and typeahead timer on unmount. Demo: a deployment-settings card with a labeled project input, a Region select over believable region/code option data, a Failover select, and a footer status line. install: npx shadcn add https://design.helpmarq.com/r/caustic-select.json ## chronicle-bar [core] Chronicle Bar — Determinate progress bar whose leading edge narrates each phase in typed mono, then docks it below the track as a timestamped milestone ledger. use when: a progress indicator (loader, typography, mono). props: value?: number // progress 0-100 (controlled); a decrease resets the ledger; default: 0 phases?: ChroniclePhase[] // phases in ascending order of `at`; default: DEFAULT_PHASES className?: string aria-label?: string // default: "Progress" ↳ ChroniclePhase = { at: number; label: string } deps: (none) behavior: A determinate progress bar whose fill front is a live narrator, pure DOM and zero deps. Track: 4px tall, transparent bed with a hairline border; fill #ededed; the leading edge is a 2px #006bff cursor block (the only accent), which fades out once the run completes. Fill width eases toward the controlled value (0-100) with cubic-bezier(0.22,1,0.36,1) over 450ms per value change, written direct-DOM (style.width/transform) from a single rAF loop that runs only while easing, typing, or docking, then sleeps. A font-mono text-sm caption is anchored to the leading edge (clamped inside track bounds, with a small gap below its baseline before the track) and types the current phase label at 24 chars/s; the first 3 glyphs scramble-decode from an A-Z/0-9/symbol charset for ~2 frames each before locking (a small decrypt-text dose). When the fill crosses a phase's `at` percent, the caption scales to 0.92 over 220ms ease-out (origin bottom-left) and fades, and a milestone docks below the track: a 2px x 8px vertical tick at the phase's percent position plus label and elapsed mm:ss.s in font-mono text-[11px] text-muted, edge-clamped so labels never overflow; milestones fade in over 260ms. A finished bar reads as a ledger of everything the loader did. Props: value 0-100 (controlled, a decrease resets the ledger and elapsed clock), phases {at, label}[]. Accessibility: progressbar role with live aria-valuenow, milestones announced through a visually-hidden polite live region. Under prefers-reduced-motion the fill jumps instantly, captions render fully typed, and ticks appear immediately. install: npx shadcn add https://design.helpmarq.com/r/chronicle-bar.json ## cipher-reel-otp [core] Cipher Reel OTP — 6-box code entry where each box is a tiny slot-machine cipher reel: keystrokes spin a canvas glyph strip into a weighted detent on the typed digit with an accent flash; backspace reverse-spins to blank and idle cells carry a faint ambient drift. use when: an OTP/verification-code input (input, form, canvas). props: length?: number // number of reel cells; fixed at mount; default: 6 label?: string // visible legend labelling the group; default: "Verification code" helperText?: string // muted helper line under the reels error?: boolean // flip true to shake the row and scramble the reels clear; default: false errorMessage?: string // helper line while error is set — the only place the error token appears; default: "That code didn't match. Try again." disabled?: boolean // default: false autoFocus?: boolean // default: false onChange?: (code: string) => void onComplete?: (code: string) => void className?: string deps: (none) behavior: Build a 6-box OTP control where every box is a tiny slot-machine cipher reel. RENDER: 6 real <input inputmode=numeric pattern=[0-9]* autocomplete=one-time-code maxLength=1> cells inside a fieldset+legend, each with a per-cell canvas overlay drawing a vertical mono glyph strip (0-9 first so digit d lives on row d, plus cipher glyphs #$%&*+); the input text and caret are transparent, the canvas is the visible face, and each canvas gets EXPLICIT style.width/height (replaced element — CSS inset does not size it), backing store at devicePixelRatio clamped to 2, full clear + redraw every frame. MOTION: a keystroke spins the reel ~2 rows at 14 rows/s decelerating at 30 rows/s^2, then a per-cell strip-rotation offset lands the typed digit in a detent spring (k=380 s^-2, zeta=0.6, ~0.15-row mechanical overshoot), total ~160-220 ms, with the cell border flashing --accent at 35% alpha for 120 ms on lock and a forced-settle deadline of 600 ms per reel so nothing can spin forever. Backspace reverse-spins 8 rows/s about 1.2 rows while fading to the blank state; paste and SMS autofill distribute digits with a 70 ms left-to-right stagger of the same spin; idle empty cells drift 0.15 rows/s at 25% alpha as the default ambient look. Error prop rising edge: the row shakes +-4 px for 3 damped cycles over 260 ms while every filled reel re-scrambles out over 240 ms and the code clears — motion carries the error, the --error token appears only on the helper text. INTERACTION: auto-advance on entry, Backspace on empty moves left, ArrowLeft/Right/Home/End navigate, focus selects, paste splits, aria-live polite helper announces completion and errors. PERFORMANCE: direct-DOM rAF with no React state on the hot path; each reel sleeps the instant it rests (a locked cell costs zero redraws), the loop pauses offscreen via IntersectionObserver and on document hidden with deadlines catching up on wake, zero-size containers guarded, every observer/listener/timeout torn down. THEME: glyph and accent ink parsed from getComputedStyle(--foreground/--accent) at mount and re-derived by a MutationObserver on documentElement class changes so both themes render live. REDUCED MOTION: digits render instantly with no spin or drift and a plain focus highlight. Hover and focus affordances are token-relative (border-foreground/25, ring-accent). install: npx shadcn add https://design.helpmarq.com/r/cipher-reel-otp.json ## counterpoise-tiers [core] Counterpoise Tiers — Pricing section rendered as a literal balance scale: two tier cards hang as pans from a canvas beam, billing toggle and feature checkmarks add weight, and beam-torque spring physics settles with one inertial overshoot to show which tier objectively outweighs the other. use when: a pricing table (canvas, physics, spring). props: left?: CounterpoiseTier // tier hung from the left pan; default: STARTER right?: CounterpoiseTier // tier hung from the right pan; default: PRO annualMultiplier?: number // annual billing price multiplier (0.8 = 20% off); default: 0.8 className?: string ↳ CounterpoiseTier = { name: string; tagline: string; monthlyPrice: number; cta: string; primary?: boolean; features: CounterpoiseFeature[] } deps: (none) behavior: Two pricing tiers rendered as literal balance-scale pans hanging from a canvas beam; billing toggle and feature checkmarks add weight and the beam settles with inertial overshoot to show which tier objectively outweighs the other, with idle ambient sway. RENDERING: a Canvas 2D layer draws fulcrum, beam, and chains as 2px strokes (--foreground beam/pivot/hooks, --border chains and fulcrum hatch), fully cleared and restroked every tick — no accumulation compositing; the two pans are real DOM pricing cards (bg-surface, rounded-md, 1px border) hung from the beam ends and positioned every frame via OFFSET transforms from the container center (translate from beam-end position + chain length, counter-rotate -0.35θ about the chain attachment so pans stay near level), never absolute canvas coordinates. Canvas sized with explicit style.width/height plus a devicePixelRatio-clamped backing store. PHYSICS: beam angle integrated per frame with semi-implicit Euler: th'' = -42(th - target) - 5.5 th' (stiffness 42 s^-2, damping 5.5 s^-1 → exactly one visible overshoot, settle < 1.4s), hard forced-settle deadline snap at 2.0s so stacked rapid toggles always resolve, tilt clamped ±9°. target = clamp(0.028·(weightR - weightL)); weight = monthlyPrice/10 + enabledFeatureCount. IDLE AMBIENT (default look): ±0.4° sine sway, 6s period, ramped in and suppressed for 4s after any interaction. INTERACTION: monthly/annual segmented toggle (rounded-sm) rescales both prices and re-targets the beam; six real feature checkboxes per tier add/remove weight through the same spring; hovering a tier card lifts it 2px (token shadow, border step) and previews a +0.3° tilt bias toward it; primary CTA in --accent, secondary ghost — accent appears nowhere else except focus rings. A font-mono caption under the fulcrum states the verdict ('Pro outweighs Starter by 2 features') and updates on settle, never mid-swing. REDUCED MOTION: beam and cards rendered instantly at the settled angle, no sway, discrete updates. PERF: direct-DOM rAF hot path (refs only, no React state per frame); loop sleeps when |omega| < 0.001 rad/s, no spring target pending, and sway is suppressed, with a timed wake when suppression ends; IntersectionObserver pauses offscreen and document.hidden pauses; zero-size container guard; canvas inks parsed from getComputedStyle tokens at mount with a MutationObserver on documentElement class re-deriving live; all listeners/observers/rAF/timers torn down on unmount. Demo is a full two-column pricing section: headline, muted subcopy, the scale as visual spine, Starter $19/mo vs Pro $49/mo with believable feature lists and CTAs, muted mono footnote. install: npx shadcn add https://design.helpmarq.com/r/counterpoise-tiers.json ## crack-compare [core] Crack Compare — Before/after comparison slider whose divider is a living Voronoi crack seam — fast drags spawn branching micro-fissures, slow drags heal them shut, and release settles with a 1px specular glint traveling the fracture. use when: a comparison view (slider, before after, voronoi). props: before?: ReactNode // left layer — revealed as the seam moves right; default: <div className="h-full w-full bg-surface" /> after?: ReactNode // right layer — clipped along the crack seam; default: <div className="h-full w-full bg-background" /> initial?: number // initial split position 0..1; default: 0.5 seedCount?: number // Voronoi seed count feeding the seam's cell walls; default: 140 jag?: number // max horizontal jag of the seam in px; default: 18 spawnVelocity?: number // |vx| in px/s above which micro-fissures branch off the seam; default: 600 label?: string // aria label for the hidden native range input; default: "Comparison position" onChange?: (value: number) => void // fires on release and keyboard change with the split 0..1 className?: string deps: (none) behavior: A before/after comparison slider whose divider is a living crack seam instead of a straight line. Two absolutely-stacked DOM layers (arbitrary before/after children) sit in a rounded-md border-border frame; the after layer is clipped by a CSS clip-path polygon that follows a jagged seam polyline, and a single DPR-aware canvas overlay draws the hairline crack strokes on top. Seam geometry: seed ~140 Poisson-disc points across the pane; at sample rows spaced ~0.55 cell-heights apart, find the nearest and second-nearest seeds to (handleX, y) and solve the point on their perpendicular bisector — an exact Voronoi cell wall from half-plane math — clamped to ±18px of the handle, giving x-offsets stored relative to the handle so the seam translates with it and only re-jags when the handle crosses into a new cell (nearest-seed id change), with new offsets eased in exponentially. Motion: handle x follows the pointer through a taut spring (k=170 s⁻², zeta=0.85, no wobble) integrated semi-implicitly in one direct-DOM rAF loop that writes the clip-path polygon string, the handle transform, and all canvas strokes with zero React state on the hot path and sleeps whenever settled. While dragging with |vx| > 600 px/s, spawn 2–4 micro-fissure branches (30–70px two-segment polylines, stroke alpha mapped to velocity, capped at 28) anchored to seam offsets; once speed drops below threshold each fissure retracts tip-first over 300ms ease-out. On pointer release the seam settles on the same spring, then a 1px specular dash ~56px long travels the full seam arc-length over 450ms. Seam strokes are token-derived, not hardcoded: the RGB is read off the resolved --foreground CSS custom property on mount and re-sampled via a MutationObserver on documentElement class changes, so the crack, its ghost pass, and the glint stay visible against both light and dark before/after content — 1px 0.32-alpha hairline plus a 0.75px-offset 0.5px 0.10-alpha ghost pass. Interaction: pointer capture on a 40px-wide full-height handle strip with a 28px glass grip chip (rounded-sm, border/background/shadow all color-mix'd off --foreground so the glass affordance reads on light and dark alike, backdrop-blur), a hidden native range input (sr-only, step 2) so arrow keys move 2% per press with a focus-visible accent outline echoed onto the grip, onChange fired on release/keyboard only, and a ResizeObserver rebuild preserving the split fraction. prefers-reduced-motion drops the canvas and spring entirely for a straight 1px bg-border divider with standard instant compare behavior. Zero dependencies. install: npx shadcn add https://design.helpmarq.com/r/crack-compare.json ## decrypt-text [core] Decrypt Text — Scramble-to-decode text reveal with left-to-right character locking. use when: the classic scramble-to-decode reveal — monospace glyphs churn and lock into the final string left to right; use for a one-shot on-mount/on-trigger reveal, not a persistent cursor-driven effect. props: text: string delay?: number // ms before the first character locks; default: 150 stagger?: number // ms between character locks (left to right); default: 55 ambient?: number // ms between idle glitches re-scrambling a few characters; 0 = off; default: 0 className?: string replayKey?: number // bump to replay the animation; default: 0 deps: (none) behavior: A scramble-to-decode text reveal: monospace glyphs churn randomly and lock into the final string left to right with a per-character stagger, the currently resolving character brightened, unresolved characters dimmed. No layout jitter (mono charset), final text exposed via aria-label with churning spans aria-hidden, instant render under prefers-reduced-motion. install: npx shadcn add https://design.helpmarq.com/r/decrypt-text.json ## drape-menu [core] Drape Menu — Dropdown whose panel is a live verlet cloth pinned to the trigger — it falls and drapes like an awning, labels ride the weave, the cursor billows the fabric, and close yanks it back up. use when: a menu (dropdown, cloth, physics). props: label?: string // trigger label; also the menu's aria-label; default: "Workspace" items?: DrapeMenuItem[] // default: DEFAULT_ITEMS onSelect?: (id: string) => void minWidth?: number // cloth/panel width floor in px (widens to match a wider trigger); default: 264 className?: string ↳ DrapeMenuItem = { id: string; label: string; shortcut?: string; icon?: ReactNode; separatorBefore?: boolean } deps: (none) behavior: Build a dropdown menu whose panel is a live 2D verlet cloth pinned along its top edge to the trigger's bottom edge. Simulate a 10x14 point grid with structural constraints only and 3 relaxation iterations per frame; gravity 2400 px/s^2, velocity damping 0.99 per step. On open the vertices start compressed at the trigger's bottom edge and fall freely, draping taut in roughly 380-500 ms — emergent from the physics, not tweened. A Canvas 2D layer underneath draws per-quad fold shading from a vertex-normal approximation (horizontal stretch = sheen toward the lighter ink, lateral lean = shadow toward the darker ink), with every drawn color derived from getComputedStyle CSS tokens (--surface/--border/--foreground/--background) at mount and re-derived live via a MutationObserver on the documentElement class so both themes shade correctly. Menu items are real DOM nodes (role=menu/menuitem) anchored to designated vertex rows: each item's transform is its anchor vertex translate plus a rotation from the local row slope clamped to +/-6 degrees, and each label fades in over 120 ms once its anchor row's vertical velocity drops below 8 px/s. Cursor proximity billows the weave: an upward force F = 900 * exp(-d^2 / (2*60^2)) px/s^2 on vertices within ~150 px of the pointer. Close yanks every vertex back to the trigger point on a per-vertex critically damped spring (k = 120 s^-2, zeta = 1.0) and unmounts once max displacement is under 0.5 px. Hot path is refs-only direct-DOM in a single rAF loop that sleeps when max per-frame displacement is under 0.02 px and wakes on pointermove/open/close; ResizeObserver re-derives cloth width from the trigger rect with a zero-size guard, and all listeners, observers, and the canvas are torn down on close/unmount. Full menu semantics: aria-expanded trigger, arrow-key navigation, Home/End, Enter selects, Esc closes and returns focus to the trigger, outside click closes; hovered/focused items get a token-relative bg-surface highlight plus an accent left rail and accent focus-visible ring. Under prefers-reduced-motion render a plain dropdown with a 150 ms opacity/scale-98% fade and no cloth or canvas. install: npx shadcn add https://design.helpmarq.com/r/drape-menu.json ## dynamic-weight-text [core] Dynamic Weight Text — Letters morph variable-font weight by cursor proximity — pure typography interaction. use when: letters continuously morph variable-font weight by cursor proximity — pure typography, no particles/canvas/color, no discrete reveal moment; use for an ambient, subtle hover-driven headline. props: text: string minWeight?: number // default: 300 maxWeight?: number // default: 800 sigma?: number // gaussian falloff radius in px; default: 90 className?: string deps: (none) behavior: A headline whose individual letters morph between a light and a heavy variable-font weight based on horizontal cursor proximity with a Gaussian falloff, easing smoothly as the pointer moves and settling back when it leaves. Pure typography — no color, no particles. Direct-DOM rAF loop, real text in aria-label, static under prefers-reduced-motion. install: npx shadcn add https://design.helpmarq.com/r/dynamic-weight-text.json ## fling-segment [core] Fling Segment — Segmented control with a visibly grabbable pill (grip dots, hover lift) — fling it, it coasts on real release velocity, rubber-bands off the ends, and snaps into the nearest detent. Optional one-shot intro fling demos the mechanic on first view. use when: an interactive control (form, segmented, physics). props: options?: FlingSegmentOption[] // default: DEFAULT_OPTIONS value?: string // controlled value; omit for uncontrolled defaultValue?: string onValueChange?: (value: string) => void // fires once per selection change — on detent commit, never per-frame introFling?: boolean // opt-in one-shot self-demo: a beat after mount the pill is flung to the far segment, coasts, and captures into the detent. Plays exactly once, never loops, is skipped under reduced motion, and is permanently cancelled by any pointer or keyboard interaction.; default: false className?: string aria-label?: string // default: "View" ↳ FlingSegmentOption = { value: string; label: string } deps: (none) behavior: Segmented control whose selection pill is grabbable: drag and release it anywhere along the track and it coasts on real release velocity (mean of pointer samples from the last 80 ms) under exponential friction v*=exp(-4.5*dt), rubber-bands off the track edges (beyond-track displacement rendered scaled 0.35, spring back k=320 zeta=0.9), and below 300 px/s captures into the nearest segment detent via a spring k=280 zeta=0.8 with one small overshoot. Click and keyboard remain instant no-drag paths: measure the target segment's width first (segments may differ) and glide both x and width with a critically damped spring k=220 zeta=1, ~260 ms. Pure DOM — the pill is an absolutely-positioned node driven by offset transforms relative to its layout slot on a direct-DOM rAF loop, zero React state on the hot path; a 1 s forced-settle deadline guarantees physics never jitters forever; the loop sleeps at a velocity epsilon and pauses offscreen via IntersectionObserver. role=radiogroup of role=radio buttons: ArrowLeft/Right/Up/Down move selection, Home/End jump to first/last, Space/Enter commit the focused segment, focus ring uses the accent token, and onValueChange fires once on detent commit, never per-frame. Reduced motion: the pill repositions instantly and drag release selects the nearest segment with no coast. Grabbability is advertised visually: the pill carries a six-dot grip affordance at its right edge and lifts (deeper shadow, brighter dots) when the selected segment is hovered, with cursor-grab/grabbing. Optional introFling prop plays a one-shot scripted self-demo ~2.5 s after mount — the pill is flung to the far segment, coasts, nudges the end rubber band, and captures into the detent; it never loops, is skipped under reduced motion, and is permanently cancelled by any pointer or keyboard interaction. All ink is token-relative CSS — no canvas. install: npx shadcn add https://design.helpmarq.com/r/fling-segment.json ## flock-stack [core] Flock Stack — Avatar stack that mills as a live boids flock and resolves into the classic overlapping row on hover, with the +N badge appearing only once the formation settles. use when: an avatar (boids, physics, hover). props: members?: FlockMember[] // flocking avatars (<=12 recommended; sim is O(n^2)); default: DEFAULT_MEMBERS overflow?: number // count in the "+N" badge shown once the flock resolves; default: 3 avatarSize?: number // avatar diameter in px; default: 28 className?: string // default: "h-[120px]" aria-label?: string ↳ FlockMember = { name: string; initials?: string; src?: string } deps: (none) behavior: A team avatar stack that never sits still: 7 DOM avatar circles (28 px, initials, ring-2 ring-background) mill inside a bounded card region as a real boids flock driven by a canvas-free vector sim (separation r34/w1.4, alignment r60/w0.6, cohesion r90/w0.5, max speed 60 px/s, soft-wall 300 px/s^2 ramping inside 24 px of the edge, damping pow(0.98, dt*60)). Hovering or keyboard-focusing the container ramps a per-avatar seek force toward its slot in the classic -8 px overlap right-aligned row from 0 to weight 2.2 over 400 ms, summed into the same three rules with arrival slowdown inside 40 px, so the tidy group photo is itself a settled flocking state. When every agent is within 2 px of its slot at under 1 px/s the +N badge fades in over 200 ms; release ramps the seek off over 400 ms and the flock disperses back to milling. Transforms are written per-frame on a refs-only direct-DOM rAF loop that pauses offscreen (IntersectionObserver) and on document.hidden, and genuinely sleeps once resolved and settled below 0.5 px/s until hover exit; ResizeObserver re-derives bounds and slots with zero-size and zero-length-vector guards. Hovering an individual avatar once resolved lifts it 3 px and shows a token-styled name tooltip. All colors are CSS token classes (bg-surface, border-border, ring-background) so both themes self-adapt. prefers-reduced-motion renders the static resolved row with the badge always visible. install: npx shadcn add https://design.helpmarq.com/r/flock-stack.json ## frostbite-switch [core] Frostbite Switch — iOS-style switch whose OFF state freezes over: seeded dendritic frost feathers creep in from the track edges over a frosted-glass film, with sparkle grain that glistens at idle; switching ON drives a melt front ahead of the sliding thumb with droplet run-off. use when: a toggle switch (toggle, canvas, particles). props: checked?: boolean // controlled state; omit for uncontrolled defaultChecked?: boolean // default: false onCheckedChange?: (checked: boolean) => void disabled?: boolean // default: false className?: string aria-label?: string // default: "Toggle" deps: (none) behavior: Build an iOS-style toggle (real <button role=switch aria-checked>, 52x30 track, 26px thumb, rounded-full) with three overlay layers above the thumb, all clipped to the track: a frosted-glass span (backdrop-filter blur+brightness, translucent white film) and two canvas 2D layers (crystal + sparkle, DPR clamp 2, explicit style width/height since canvas is a replaced element). On switch-to-OFF, mulberry32-seeded dendritic spines creep in from the right/top/bottom track edges (2px steps at 140 px/s, gentle curvature, some fingers stall early), throwing alternating side needles at ~60 deg every 2-3 steps; longer needles fork sub-barbs (depth 0-2, ~700ms total, deterministic per state-change so each freeze traces a fresh pattern). Crystals render in three passes so ice reads on both themes: wide translucent white haze, a cold shade stroke (definition on light surfaces and the thumb), and a bright cold-cast ice body, widths tapering 1.15 to 0.5px by depth, plus a rim-frost stroke around the pill edge; the glass layer fades in with growth so the thumb blurs beneath the ice. The sparkle canvas carries seeded grain dots and four-point glints; idle OFF glisten mutates only that layer's style opacity at 0.25 Hz (no redraw), paused offscreen via IntersectionObserver and when the document is hidden; rAF fully sleeps at end states. On switch-to-ON a spatial melt front sweeps left-to-right over 450ms, always a few px ahead of the thumb's leading edge: canvases clip to the frozen side, a white wet-gleam gradient marks the front, the glass layer recedes via clip-path inset, and 3-5 droplets detach when the front passes them (gravity 1200 px/s^2, 400ms lifetime, elongated body + white highlight); the thumb slide starts 120ms into the melt on a spring (k=170 s^-2, zeta=0.85, one small overshoot) and the track ramps an accent glow. All ink derives from --foreground/--background via getComputedStyle at mount (cold-cast toward blue: r*0.93, b*1.06+6) and re-derives on a MutationObserver watching documentElement class changes; theme is detected by background luminance. Accent focus-visible ring, token-relative hover border, disabled renders all layers at 40% opacity with no glisten, prefers-reduced-motion swaps to two static frames (full crystal OFF / clear ON) with a snapping thumb. Guard zero-size tracks before seeding; tear down every observer, listener, and rAF on unmount and free the crystal arrays. install: npx shadcn add https://design.helpmarq.com/r/frostbite-switch.json ## glass-button [core] Glass Button — Liquid-glass button with translucent blurred surface and press states. use when: the default general-purpose button — translucent liquid-glass surface with hover lift and press states; use for any ordinary CTA, not a destructive action needing deliberate confirmation. props: (extends ButtonHTMLAttributes<HTMLButtonElement>) deps: (none) behavior: A liquid-glass button: translucent blurred surface, thin light border, subtle hover lift and press scale, visible keyboard focus ring, for a dark minimal (Geist-style) design system. install: npx shadcn add https://design.helpmarq.com/r/glass-button.json ## glass-panel [core] Glass Panel — Container-level liquid glass: blur, saturation, noise grain, specular rim, graduated shadow ramp. use when: a card (surface, glass, container). props: (extends HTMLAttributes<HTMLDivElement>) deps: (none) behavior: A liquid-glass container surface built as a layer stack: backdrop blur with saturation boost, tiled SVG noise grain blended over the fill, an inset specular rim lit from above, and a four-step graduated shadow ramp for depth, with children rendered above the glass. Works over any moving or static backdrop, both themes. install: npx shadcn add https://design.helpmarq.com/r/glass-panel.json ## heatwave-ledger [core] Heatwave Ledger — Dense ops table where rows above a heat threshold shimmer like air over asphalt — live DOM text refracts through an animated SVG displacement filter while cold rows sit dead-still behind hairline borders. use when: a table (data viz, svg filter, displacement). props: rows?: LedgerRow[] // table data — rows with heat >= threshold shimmer; default: DEFAULT_ROWS threshold?: number // heat score at/above which a row is hot; default: 70 title?: string // card title; default: "Server load — last 24h" timestamp?: string // mono timestamp shown beside the title; default: "updated 09:41:07 UTC" className?: string ↳ LedgerRow = { id: string; service: string; region: string; reqs: number; p95: number; heat: number } deps: (none) behavior: Dense data table where rows above a heat threshold visibly shimmer like air over asphalt: real content refracts via an animated SVG displacement filter while cold rows sit dead-still with 1px hairline borders — the hot/cold contrast IS the piece; warmth is implied by motion, never by hue (no orange anywhere). RENDERING: semantic DOM <table> (sortable headers with real client-side comparators, selectable checkbox rows) inside a padded rounded-md surface card, plus (a) one inline SVG <filter> per hot-row slot with instance-unique ids (useId): feTurbulence type=fractalNoise baseFrequency='0.008 0.02' numOctaves=2 feeding feDisplacementMap; each hot <tr> gets style.filter=url(#heat-<id>) so its actual text/cells refract; and (b) a pointer-events:none overlay canvas over the tbody (explicit style.width/height, dpr-scaled backing store, clipped to the tbody band) drawing per-hot-row edge haze: two 24px vertical-fade gradient strips off each hot row's top and bottom edges, ink = --accent mixed 20% into --muted at alpha 0.08. MOTION: displacement scale oscillates 1.5→3.0px on a per-row sine (period 2.2s, phase offset 0.4s per sorted row index — resorting re-phases the field); turbulence seed re-randomized every 4s for non-looping shimmer; SVG attribute writes throttled to 30fps inside one shared rAF that walks ONLY the hot-row list and fully clears/redraws the haze canvas each frame (no accumulation). Hover or focus-within on a hot row eases its displacement to 0 over 120ms (legibility snap), back over 400ms on leave, with a forced completion deadline at 500ms so fast hover-scrubs never strand rows mid-wobble. INTERACTION: header sort (sorting by heat re-phases shimmer), checkbox selection with token-relative fill (surface step + 1px foreground/muted mix ring via color-mix), hover raises row background one surface step (bg-foreground/[0.04]). TOKENS: haze ink derived from getComputedStyle(--accent, --muted) at mount, re-derived live via MutationObserver on documentElement class. SLEEP/TEARDOWN: rAF stops entirely when no row exceeds threshold or all hot rows are hover-frozen (scales pinned to 0, canvas cleared); IntersectionObserver pauses offscreen; ResizeObserver with zero-size tbody guard; all listeners/observers/rAF torn down on unmount. REDUCED MOTION: no filter, no canvas — hot rows get a static 2px --accent left rule and slightly elevated surface fill. DEMO: dashboard card 'Server load — last 24h' with mono timestamp, 10 believable ops rows (service, region, req/s, p95 ms, heat score), 3 hot at default threshold 70, footer row count + pagination stub, demo-level threshold segmented control. install: npx shadcn add https://design.helpmarq.com/r/heatwave-ledger.json ## hold-to-confirm [core] Hold to Confirm — Press-and-hold destructive action — monochrome ink pours up from the press point, release early and it recoils. use when: a press-and-hold DESTRUCTIVE confirm — ink pours up from the press point and recoils if released early; use whenever an action needs deliberate hold-to-confirm, not a plain single-tap button. props: children: ReactNode confirmedLabel?: ReactNode // default: "Done" holdMs?: number // default: 1200 onConfirm?: () => void className?: string deps: (none) behavior: A destructive-action button requiring press-and-hold, rendered as a canvas ink fill: holding pours monochrome ink (foreground token) up from the press point with a live rippling meniscus edge, subtle grain, and a pressure microshake as it nears the top; the label inverts over the ink via a difference blend. Releasing early (including pointercancel or blur) recoils the ink with an elastic damped spring; when the fill completes, the button pops with one spring overshoot and the label swaps. Works with pointer and keyboard (hold Space/Enter). Canvas colors derive from computed CSS tokens and re-derive on theme change; the rAF loop sleeps when settled and pauses offscreen; prefers-reduced-motion still holds-to-confirm but renders a plain clean fill with no waves, grain, shake, or pop. install: npx shadcn add https://design.helpmarq.com/r/hold-to-confirm.json ## ligature-melt [core] Ligature Melt — Headline whose glyphs liquefy near the cursor — an SVG gooey filter fuses neighbors into temporary ligatures that spring apart on leave, with a faint field drifting the melt on its own at rest. use when: glyphs liquefy and fuse into gooey ligatures near the cursor via an SVG filter, drifting even at rest and springing apart on leave; use for a squishy, organic headline, not a legibility-first reveal. props: text?: string // headline text — rendered as real, selectable DOM glyphs; default: "SURFACE TENSION" sigma?: number // gaussian falloff radius of the melt field in px; default: 70 swell?: number // max extra scale at zero distance (0.35 → 1.35x); default: 0.35 pull?: number // max translation toward the cursor in px — creates the overlap that goos; default: 6 blur?: number // feGaussianBlur stdDeviation at full field strength — ramps down to near-zero at rest; default: 6 className?: string deps: (none) behavior: A headline where characters near the cursor liquefy into temporary ligatures. One span per glyph inside a container carrying CSS filter: url(#goo); the inline SVG filter is feGaussianBlur into an feColorMatrix with alpha row 0 0 0 19 -9 (blur + threshold), so overlapping glyph edges fuse into metaball necks. Text stays real DOM — selectable and SEO-safe, the filter is visual only. A Gaussian field (sigma 70px) around a field center scales affected glyphs to 1 + swell*g and translates them toward the field by up to `pull` px so edges overlap and goo; total line width stays constant by redistributing the induced width surplus as compression across out-of-field spans each frame with line start/end pinned. At rest — no pointer involved — a synthetic field sweeps back and forth across the line on its own at half the hover amplitude, so the melt is the default look, not a hover-only trick; a real pointer takes over the field immediately. The feGaussianBlur stdDeviation itself ramps off the same field's peak value (near-zero away from any activity, up to the `blur` prop at the field's peak) instead of sitting at a constant blobby value, so idle text reads crisp except where it's actually melting. Per-span state (scale x/y, dx) lives in plain arrays written as transforms by a direct-DOM rAF loop — no React state on the hot path. Approach eases via lerp (~0.15/frame on hover, ~0.035/frame ambient); on pointer leave (including pointerup/pointercancel) every span snaps back on an underdamped spring (k = 170 s^-2, zeta = 0.55) with visible surface-tension overshoot as the ligatures pinch apart, then ambient drift resumes. The root carries role="button" and tabIndex=0 so the mechanic has a keyboard/focus equivalent too: tabbing in melts the line centered on itself (same field math as a parked cursor) with a token-colored focus-visible ring, and blur releases it on the same spring. The loop never fully sleeps — since the ambient field never settles, an IntersectionObserver pauses it offscreen instead. Spans are measured once via offsetLeft/offsetWidth and remeasured on ResizeObserver. Under prefers-reduced-motion the filter is removed and the text renders static and crisp with no listeners, no ambient loop. Zero dependencies. install: npx shadcn add https://design.helpmarq.com/r/ligature-melt.json ## lodestone-hero [core] Lodestone Hero — Full-bleed hero where the headline exists twice: crisp DOM type above, and beneath it a canvas field of iron-filing strokes solved from a two-pole dipole field, so the type visibly iron-files into existence as the cursor approaches and CTA hover bends the whole field toward the button. use when: a hero whose headline exists twice — crisp DOM type over a Canvas 2D field of iron-filing strokes that bend toward the cursor and snap toward the CTA on hover; zero deps, best when the headline itself should feel physically alive. props: eyebrow?: string // mono eyebrow line above the headline; default: "FIELD-ALIGNED INFRASTRUCTURE" headlineLines?: string[] // display headline, one string per rendered line — this is the letter-mask source; default: ["Every signal bends", "toward your stack"] subcopy?: string // muted supporting copy under the headline; default: "Lodestone routes traffic the way a magnet organizes iron filings: declare the pole, and every request, retry, and rollback aligns itself. No orchestration YAML, no drift." primaryCta?: { label: string; href: string } // primary accent CTA — its center is the fixed anchor pole; default: { label: "Deploy the field", href: "#deploy" } secondaryCta?: { label: string; href: string } // ghost secondary CTA; default: { label: "Read the docs", href: "#docs" } stats?: { value: string; label: string }[] // three mono stats for the bordered strip below the CTAs; default: [ { value: "12ms", label: "p99 route solve" }, { value: "99.98%", label: "field uptime" }, { value: "4,200+", label: "clusters aligned" }, ] maskFilings?: number // filings rejection-sampled inside the headline letter-mask; default: 1800 ambientFilings?: number // sparse ambient filings outside the mask; default: 600 className?: string deps: (none) behavior: A full-bleed hero where the headline exists twice: crisp DOM type above, and beneath it a Canvas 2D field of iron-filing strokes solved from a two-pole dipole field (cursor pole + fixed anchor pole behind the primary CTA). The canvas sits absolutely under the DOM copy with pointer-events none so every CTA stays interactive. A letter-mask is built by drawing the headline text into an offscreen canvas using the font shorthand read from the live DOM headline via getComputedStyle, aligned and x-scaled to each line span's measured rect; ~1,800 filing positions are rejection-sampled inside the mask plus ~600 sparse ambient filings outside (counts halved when devicePixelRatio >= 2 and viewport < 900px), each filing a 6-10px line segment stored in structure-of-arrays Float32Arrays. Field model: cursor pole strength 1.0 (radial plus mild tangential swirl), anchor pole 0.7 (pure radial, its position computed as a getBoundingClientRect offset from the container origin, never page coords); contribution = strength / max(r, 48)^2; filing target angle = atan2 of the summed vector, chased per frame with angle += delta * (1 - exp(-dt*10)) for a critically-damped no-overshoot feel. CTA hover/focus springs the anchor pole 0.7 to 1.4 over 250ms ease-out-expo; pointerleave decays the cursor pole to 0 over 600ms; both are time-based tweens whose duration is the forced-settle deadline (under the 800ms budget), so no spring can hunt forever. After 500ms pointer idle, angles drift on 2-octave value noise at plus/minus 8 degrees and 0.1Hz inside a 12s breath envelope with a real rest phase. Ink is parsed from getComputedStyle tokens at mount and re-derived live via a MutationObserver on documentElement class: mask filings alpha 0.25 to 0.9 by field magnitude in --foreground, ambient filings 0.06 to 0.18 in a --muted/--border mix, and --accent permitted only on the ~5% of filings nearest the anchor pole while the CTA is hovered or focused; strokes are batched into 16 alpha buckets per color group so the draw loop sets style once per batch, with a full clear + redraw each frame (no destination-in accumulation). The canvas is sized as a replaced element: style.width/height set explicitly from the measured rect, backing store scaled by DPR (clamped 2). The rAF loop sleeps when the max per-filing angular delta drops below 0.001 rad, no pole tween is active, and the ambient drift is in its rest phase (a timeout wakes the next breath); IntersectionObserver pauses offscreen, zero-size containers bail, ResizeObserver resamples the letter-mask, document.fonts.ready rebuilds it after webfont swap, and every listener, observer, timer, and rAF is torn down on unmount. Under prefers-reduced-motion one static solved frame renders (anchor pole only, cursor pole off) and the loop never starts. Demo is the full weighted composition: full-bleed hero on bg-background with mono eyebrow, 2-line Geist Sans 600 display headline (the mask source), muted sub-copy, accent primary CTA + ghost secondary (rounded-sm, token-relative hover/focus), and a thin bordered strip of three mono stats. install: npx shadcn add https://design.helpmarq.com/r/lodestone-hero.json ## loupe-slider [core] Loupe Slider — Slider read through a circular magnifying loupe riding the thumb: the tick beneath sits sharp at 1.8x inside the lens while the rest of the scale rests soft-focus; rubber-banding past the bounds wobbles the magnification on release. use when: a slider read through a circular magnifying loupe that rides the thumb, sharpening the tick beneath it while the rest of the scale stays soft-focus; use for precise value-reading (audio scrub, zoom level), not a destructive confirm gesture. props: value?: number // controlled value; omit for uncontrolled defaultValue?: number // default: 50 min?: number // default: 0 max?: number // default: 100 step?: number // default: 1 tickStep?: number // minor tick interval in value units; auto-derived when omitted majorEvery?: number // every Nth minor tick is major and labeled; default: 5 formatLabel?: (v: number) => string // tick label text (drawn on canvas) formatValue?: (v: number) => string // aria-valuetext for the current value onValueChange?: (v: number) => void className?: string aria-label?: string // default: "Value" deps: (none) behavior: Build a single-value slider whose readout is a 44px circular magnifying loupe riding the thumb. RENDER: canvas 2D draws the tick scale + labels twice from cached layers rebuilt only on size/theme change — a sharp layer supersampled at 2x dpr (so magnified pixels stay crisp) and a soft base derived from it once via ctx.filter blur(1.5px) into an offscreen canvas (9-tap ring-average fallback when ctx.filter is unsupported). Per frame: full clear, soft layer at 55% alpha, then a circular clip centered on the loupe (radius 22 x mag/1.8), clearRect inside the clip to knock out the soft pass, and the sharp layer drawn through translate(lens) scale(mag) translate(-lens) at 1.8x. No per-frame filter work, no alpha accumulation. Canvas gets EXPLICIT style.width/height (replaced element — inset does not size it); DPR clamp 2. Thumb (2x16px foreground hairline in a 24px focus circle) and loupe ring (44px, border-border, hover border-foreground/40) are DOM nodes on offset transforms from the container's top-left anchor, never absolute canvas coords. MOTION: loupe position springs after the thumb at k=180 s^-2, zeta=0.75 for slight optical lag; the ring also scales mag/1.8 so the wobble reads refractive. Dragging past min/max maps overshoot x0.3 capped 24px; release springs home k=260, zeta=0.7 while magnification wobbles 1.8 -> 2.0 -> 1.8 on a damped half-sine over 350ms. Forced-settle deadline 1.0s covers springs AND wobble. Direct-DOM rAF: sleeps at velocity epsilon (0.05px / 0.5px/s), pauses offscreen via IntersectionObserver and on document.hidden, zero-size containers guarded before any draw. INTERACTION: focusable thumb with role=slider, aria-valuemin/max/now/valuetext, aria-orientation; ArrowLeft/Right/Up/Down +-step, PageUp/Down +-10 steps, Home/End; keyboard and external value changes glide on the same k=260 spring with the loupe chasing; pointer drag with setPointerCapture pins the thumb while the loupe lags; accent focus-visible ring with background ring-offset. TOKENS: all canvas ink (--foreground, --border) and the mono label font are read via getComputedStyle at mount and re-derived by a MutationObserver on documentElement class changes, rebuilding the blur layer on theme flip — works in both themes. REDUCED MOTION: thumb and loupe reposition instantly, no wobble; the 1.8x magnification itself stays (informational, not decorative). Tick generation: minor interval prop or auto 1/2/5-decade nice step, every Nth tick major + labeled, count capped at 240, custom formatLabel. Controlled/uncontrolled value, typed props with defaults so the bare component mounts. Tear down rAF, ResizeObserver, IntersectionObserver, MutationObserver, and the visibilitychange listener on unmount. DEMO: audio playback card on a padded surface — loupe scrub slider over an m:ss timestamp scale with live mono readout, skip/play/pause transport, plus a second instance as a waveform zoom-level control labeled in percent. install: npx shadcn add https://design.helpmarq.com/r/loupe-slider.json ## magnetic-dock [core] Magnetic Dock — Cursor-proximity magnification row with Gaussian falloff — macOS-dock physics for any children. use when: a macOS-dock-style row that magnifies items under cursor proximity with Gaussian falloff; use for an icon/action dock or nav row, not for showing scroll/read position through a document. props: children: ReactNode gain?: number // max extra scale at zero distance (0.55 → 1.55x); default: 0.55 sigma?: number // gaussian falloff radius in px; default: 80 lift?: number // upward shift in px at full magnification; default: 16 className?: string deps: (none) behavior: A horizontal dock that magnifies its children based on cursor proximity with a Gaussian distance falloff: items scale up and lift as the pointer nears, neighbors swell progressively less, everything settles back with interruptible easing on leave. Direct-DOM rAF loop with no React state on the hot path, transform-origin bottom, static under prefers-reduced-motion. install: npx shadcn add https://design.helpmarq.com/r/magnetic-dock.json ## mercury-minimap [core] Mercury Minimap — TOC minimap where scroll progress is a column of liquid mercury — a gooey SVG blob climbs the rail, absorbs section ticks, teardrops under fast scroll, and bulges toward hovered ticks. use when: a scroll-position TOC/minimap where a gooey mercury blob climbs a rail and absorbs section ticks as you scroll; use to show progress through a long document, not for magnifying items in an icon row. props: sections?: MinimapSection[] // explicit section list; omitted → auto-discovered via `selector` (label from data-minimap-label or id) selector?: string // querySelectorAll used when `sections` is omitted; default: "section[id]" offset?: number // read-line as a fraction of viewport height — a section is "reached" when its top passes this line; default: 0.35 stiffness?: number // spring stiffness for the blob (px/s² per px of error); default: 120 damping?: number // spring damping (slightly under critical → settle wobble); default: 20 className?: string ↳ MinimapSection = { id: string; label: string } deps: (none) behavior: Build a fixed-right table-of-contents minimap where scroll progress renders as liquid mercury inside a 48px-wide, 60vh-tall SVG rail. Use one goo filter (feGaussianBlur stdDeviation 4 into an feColorMatrix with alpha row 0 0 0 19 -9) over a liquid group filled with the foreground token: a 4px rounded-rect column from rail top to the blob, a leading r=7 blob circle, and per-section r=4 circles that start hidden; outside the filter, draw crisp unfilled r=4 ticks stroked with the muted token at each section's evenly mapped y. Map window scroll through the sections' document offsets piecewise-linearly to a target y, and drive the blob with a semi-implicit Euler spring (stiffness 120, damping 20, slightly underdamped so stops land with a droplet wobble) integrated in a requestAnimationFrame loop that writes only via setAttribute, reads scroll from a ref set by a passive listener, and sleeps when velocity and error settle. Stretch the blob volume-preservingly by velocity — scaleY = 1.06 + clamp(|v|*0.004, 0, 0.74), scaleX = 1/sqrt(scaleY) — shifted a few px toward the travel direction, with a small constant bias baked into the 1.06 floor so the blob still reads as a teardrop (not a plain circle) at rest, not just while moving; fast scroll further stretches the leading edge. When the blob passes within 6px of a tick, reveal that tick's hidden circle inside the goo group (the filter renders the merge) and fade the outline tick; scrolling back up re-hides it so the goo neck snaps and releases the dot. On pointer within 24px of a tick, grow a helper circle in the goo group from r 0 to 5 positioned 60% of the way from the column toward the tick so the liquid bulges at the cursor; clicking a tick smooth-scrolls its section into view. Geist Mono text-xs labels slide in from translateX(-8px) to 0 over 150ms ease-out on rail hover, muted by default and foreground when active. Under prefers-reduced-motion swap the whole goo layer for a plain 2px filled line plus dots with instant active states and no animation loop. Auto-discover section[id] elements when no sections prop is given. install: npx shadcn add https://design.helpmarq.com/r/mercury-minimap.json ## moire-dial [core] Moire Dial — Weighted rotary knob tuned like a radio: counter-rotating line gratings shimmer with moire interference, and a hidden word only resolves at the detent. use when: a rotary value dial (canvas, moire, knob). props: message?: string // hidden word that resolves out of the interference at alignment; default: "SIGNAL" pitch?: number // grating pitch in px — one 1px line every `pitch` px; default: 6 gear?: number // grating radians per dial radian — radio-vernier ratio; default: 0.15 initialAngle?: number // starting dial angle in degrees (reduced motion forces 0 = aligned); default: -132 friction?: number // angular velocity decay in s^-1 while coasting after a flick; default: 3.5 fieldHeight?: number // interference field height in px; default: 224 className?: string aria-label?: string // default: "Moire tuning dial" deps: (none) behavior: A weighted rotary knob whose feedback channel is optical interference, built on a DPR-clamped (max 2) Canvas 2D field. Two fine-line gratings (1px strokes at ~0.5 alpha derived live from the --foreground token, 6px pitch, re-derived via a MutationObserver on theme-class changes so both themes stay legible): grating A is fixed and carries a hidden message as a locally phase-inverted region — the message glyphs are rasterized offscreen to an alpha mask (singularity-text sampling pattern) and inside the mask A's line phase is offset by half a pitch, so the word only gains contrast when the overlay aligns; grating B is an oversized pre-rendered square that rotates with the dial angle through a radio-vernier gear ratio (~0.15), its phase chosen so its lines coincide with A's background lines at zero rotation. Both gratings are pre-rendered to offscreen canvases and composited per frame. Knob: 160px disc, bg-surface with border-border ring, a 24-tick ring layer rotating rigidly with the dial, a needle that lags the ring through a second-order spring (k=120 s^-2, zeta=0.75, weighted Inertial-Dial feel), and a font-mono ALIGNMENT percent readout below. Interaction: pointer-capture drag maps pointer angle about the knob center to ring angle with smoothed angular velocity; on release omega integrates under friction decay 3.5 s^-1 (flick spins, coasts, settles). Detent: within +-4 deg of alignment a snap spring (k=200 s^-2, zeta=0.9) pulls to exact zero with one tiny overshoot and the readout ticks to 100%. A single direct-DOM rAF loop is the sole writer (canvas draw, ring/needle transforms, readout text, slider value — no React state on the hot path) and sleeps when |omega| < 0.02 rad/s and needle error < 0.05 deg. Keyboard a11y via a visually hidden range input (arrows step 2 deg, aria-valuetext reports percent aligned, short detent grace so steps can escape the band). Under prefers-reduced-motion the dial renders the aligned state statically with the word legible and steps instantly with no loop. Zero dependencies. install: npx shadcn add https://design.helpmarq.com/r/moire-dial.json ## needle-stepper [core] Needle Stepper — Bounded numeric stepper with a large mono value readout, prominent -/+ buttons, and a labeled history strip: an inertial needle swings to each committed value while the strip advances, etching the last 20 adjustments with the newest mark highlighted. use when: a numeric stepper (spinbutton, input, canvas). props: value?: number // controlled value; omit for uncontrolled defaultValue?: number // default: 20 min?: number // default: 0 max?: number // default: 100 step?: number // default: 1 label?: string // accessible name for the spinbutton; default: "Value" unit?: string // unit suffix rendered beside the value, e.g. "°C" onValueChange?: (value: number) => void disabled?: boolean // default: false className?: string deps: (none) behavior: Build a bounded numeric stepper whose VALUE is the visual hero, paired with a labeled adjustment-history strip. RENDER: real spinbutton (input type=text inputmode=numeric with role=spinbutton, aria-valuemin/max/now) rendered as a large mono readout (text-3xl, ch-sized width so an optional unit suffix hugs the digits, transparent until hover/focus), flanked by prominent 44px -/+ buttons with bold icons; beside it a ~80px-wide strip column with a tiny mono 'history' header over a canvas drum; canvas is a replaced element so set style.width/height EXPLICITLY plus a dpr-scaled (clamp 2) backing store. MOTION: needle x = value mapped across strip width with 10px travel insets; underdamped spring k=120 s^-2, zeta=0.45 (two visible oscillations), forced-settle deadline 900ms backstopping a velocity-epsilon sleep. Each committed adjustment advances the strip 26px downward over 600ms ease-out (event-driven scroll retarget, never continuous, so the rAF loop sleeps between commits). Pen trace: pruned array of the last 20 (value, strip-position) points drawn as a polyline plus dots each frame after a FULL clearRect, alpha fading 0.9 -> 0.2 by age index — no destination-in fading; the NEWEST etch mark is highlighted with a solid dot plus halo ring so the latest adjustment is unmistakable. An --error band at 16% alpha appears ONLY on the edge currently hit (value at min or max), so red always reads as 'at the limit'; clamping fires a hard-stop needle quiver, +-2px, 2 cycles over 180ms, decaying. Hold-repeat on -/+: 400ms delay then 12 steps/s via setTimeout+setInterval, needle riding continuously; timers cleared on pointerup/leave/cancel and unmount. KEYBOARD: ArrowUp/Down +-step, Shift+Arrow +-10 steps, Home/End to min/max, Escape reverts typing, typed entry clamps and commits on Enter/blur with a proportional swing; buttons aria-disabled at bounds, focus-visible rings accent, hover borders token-relative (foreground/30, never white/NN). INK: needle/trace from --foreground, drum feed lines and pen carriage from --border, bound band from --error — all read via getComputedStyle at mount and re-derived by a MutationObserver on documentElement class changes, then statically redrawn, so both themes render correctly. REDUCED MOTION: needle jumps instantly, trace renders statically, no strip animation, no quiver. PERF: direct-DOM rAF with no React state on the hot path, loop sleeps when spring/quiver/scroll all settle, IntersectionObserver pauses offscreen, zero-size drum guard before drawing, ResizeObserver re-derives px mapping (trace stores values, not px), every listener/observer/timer torn down on unmount. install: npx shadcn add https://design.helpmarq.com/r/needle-stepper.json ## particle-hero [core] Particle Hero — Full-viewport hero with a cursor-reactive WebGL particle field and staggered text reveal. use when: a hero with a real WebGL particle field the cursor repels — an elastic void that trails the pointer — plus staggered text reveal; the only hero in this set with npm deps (three, @react-three/fiber, motion), so pick it when true GPU depth is worth the heavier install. props: eyebrow?: string // default: "ns-ui" headline?: string // default: "Interfaces with gravity." subline?: string // default: "A registry of components built one at a time, each earning its place." cta?: string // default: "Browse components" ctaHref?: string onCtaClick?: () => void deps: three, @react-three/fiber, motion behavior: A dark full-viewport hero section: a WebGL particle field of thousands of small gray dots that drift gently, and the cursor acts as a reversed-polarity magnet — dots within roughly 170px are displaced outward along the (dot - cursor) direction with a smooth falloff, opening an elastic void that trails the pointer and springs back to rest when it leaves. No glow, no halo, no linking lines; brightness and dot size never change. Behind it sits a staggered spring-physics text reveal (mono eyebrow, large tight headline, muted subline) and a single accent CTA, with a radial vignette keeping edges quiet. Strictly monochrome dots from the muted token, no accent. Static dot-grid fallback without WebGL, reduced-motion respected (drift and repulsion frozen). install: npx shadcn add https://design.helpmarq.com/r/particle-hero.json ## particle-tunnel-scrub [core] Particle Tunnel Scrub — Scroll scrubs a camera through a monochrome point tunnel — velocity stretches dots into motion streaks, cursor drift adds parallax, and mono section labels at fixed depths snap into focus as you fly past. use when: scroll flies a camera through a 3D particle tunnel with velocity-streaked dots and mono labels snapping into focus at fixed depths; use for a flythrough narrative, not a content-crossfade story or an instrument/HUD readout. props: labels?: string[] // section labels pinned at fixed depths along the tunnel; default: ["01 SIGNAL", "02 NOISE", "03 FIELD", "04 VOID"] pointCount?: number // points seeded in the cylinder shell; default: 3000 className?: string deps: (none) behavior: Build a scroll-scrubbed particle tunnel section: a 400vh wrapper with a position:sticky full-viewport Canvas 2D inside it, roughly 3000 points seeded in a cylinder shell (radius 120-900 world units, depth 0-4000) and projected manually with scale = 600/(z - camZ), culling anything behind the camera. Read scroll progress from the section's getBoundingClientRect in a passive scroll listener that writes a plain variable, map it to camZ = p*3600, and drive everything from a direct-DOM rAF loop with no React state on the hot path that sleeps once scroll, pointer parallax, and springs are all settled. Keep an EMA (alpha=0.12) of scroll velocity and stretch each point into a motion streak along its per-frame projected delta with length clamp(|v|*0.06, 0, 40)px, relaxed back to dots by a spring (k=60, zeta=0.8) when scrolling stops; add cursor parallax by lerping camera x/y at 0.08/frame toward pointer offset from viewport center times 0.04. Points are drawn from the live --foreground token (read via getComputedStyle at mount, re-derived through a MutationObserver on <html> class changes) with alpha rising 0.3 to 1.0 proportional to 1/(z - camZ), so near/far contrast stays correct in both light and dark themes instead of a fixed gray ramp tuned for one background. A theme-token radial-gradient vignette (transparent center to var(--background) at the edges) sits over the canvas to sell the tunnel depth on the static pre-scroll frame. Overlay four Geist Mono labels (text-sm tracking-widest) centered on screen at fixed world depths 700/1600/2500/3400 and write their opacity, blur, and scale directly to style each frame: fully focused within +-300 units of camZ, falling to opacity 0 and blur 6px over the next 900 units, scale running 0.92 to 1.08 through the pass so they fly by. Under prefers-reduced-motion draw one static starfield frame (also theme-aware and re-derived on theme change) and render the labels as a normal stacked list that fades in over 200ms via IntersectionObserver. install: npx shadcn add https://design.helpmarq.com/r/particle-tunnel-scrub.json ## respire-field [core] Respire Field — Text input whose focus ring is a living membrane: a noise-displaced canvas loop that breathes on idle, dilates on focus, sends a peristaltic pulse from the caret on each keystroke, constricts and quivers on error, and exhales once on valid submit. use when: a general-purpose text input whose focus ring is a breathing membrane that pulses per keystroke and constricts on error; use for any field needing organic focus/validation feedback, not specifically passwords. props: error?: boolean // constricts the membrane -3px, quivers once, blends stroke toward red; default: false exhaleKey?: number // bump after a valid submit to trigger the single 8px exhale; default: 0 className?: string // classes for the wrapper; input styling is internal (extends Omit<InputHTMLAttributes<HTMLInputElement>, "className">) deps: (none) behavior: Build a text input whose focus ring is a living membrane. Keep a real, fully native <input> (focus, selection, autofill intact, aria-invalid mirroring the error prop) and overlay a decoration-only aria-hidden <canvas> (position absolute, inset -24px, pointer-events none). Critical sizing: a canvas is a replaced element, so absolute + inset does NOT stretch it — on every resize set both the backing store (css size * devicePixelRatio, dpr capped at 2) AND style.width/height explicitly, or the membrane renders dpr-times too large as a giant polygon. Compute the membrane as a closed loop of 96 points parameterized around the input's rounded-rect perimeter (6px corner radius, positions plus outward normals precomputed on resize), each point displaced along its outward normal by 2-octave value noise sampled on a closed ring (the noise2(s*3, t*0.15) frequency mapped onto a circle of radius 3/2pi so the loop has no seam), displacement clamped to the 24px overhang so the ring always hugs the field. Draw the displaced ring as a closed Catmull-Rom spline (bezier segments, tangents (p2-p0)/6) — 96 linear segments leave each corner arc with ~1 sample and read as sharp angles. Stroke colors come from CSS tokens resolved via getComputedStyle on documentElement at mount (--muted, --foreground, --error with #ea001d fallback, normalized through a scratch canvas fillStyle) and re-resolved by a MutationObserver watching the documentElement class, so theme flips restyle the membrane live. Idle breath: 1.5px amplitude on a 4.5s sine period. Focus: base offset glides 0 to +6px over 350ms on cubic-bezier(0.22, 1, 0.36, 1) via a Newton-Raphson bezier solver, breath amplitude rises to 2.5px, stroke lerps the muted token toward the foreground token. Keystroke: on each input event, map the caret x (measureText with the input's computed font, selectionStart in try/catch with end-of-value fallback for email inputs) to the top-edge perimeter position and launch a Gaussian pulse (sigma 0.06 normalized perimeter, 5px amplitude) as two wavefronts traveling opposite directions at 1.2 perimeters/s, decaying with tau 0.6s. Error prop: constrict -3px, quiver at 14Hz/1.2px for 500ms on the rising edge, stroke blends toward the error token at 0.6 alpha (status use only). Valid submit (bumped exhaleKey prop): breath amplitude spikes +8px and decays over 700ms cubic ease-out. Stroke stays 1px. All animation runs on a direct-DOM rAF loop with locals/refs only, no React state on the hot path; the loop sleeps when the input is blurred and every transient has settled below 0.05px, waking on focus, input, error, exhale, or theme changes, and an IntersectionObserver parks it entirely while the field is offscreen. All listeners and the Resize/Mutation/Intersection observers are torn down on unmount. prefers-reduced-motion: no canvas, standard 1px border-border (error state switches the border to the error red) with the default focus ring. Zero dependencies; Geist dark tokens (bg-surface field, text-foreground, rounded-sm). install: npx shadcn add https://design.helpmarq.com/r/respire-field.json ## ripple-unfold [core] Ripple Unfold — Media reveal driven by a height-field water sim: a ripple front sweeps from the trigger point, popping grid tiles open as the wave crosses them and refracting revealed tiles like wet glass; the cursor keeps stirring the water after full reveal. use when: media display (canvas, reveal, wave sim). props: src?: string // image URL; omitted → a token-derived generative artwork is drawn tileSize?: number // target tile edge in px; cols/rows derive from container size; default: 32 threshold?: number // |h| a tile must see before it pops open; default: 0.12 refraction?: number // max source-rect refraction offset in px per unit wave gradient; default: 6 impulse?: number // wave height injected per cursor move after full reveal; default: 0.35 className?: string // default: "aspect-[16/10]" aria-label?: string // default: "Media revealed by a ripple wave" deps: (none) behavior: A media surface behind a coarse tile grid on a single DPR-aware Canvas 2D (DPR clamp 2), image pre-drawn to an offscreen canvas (or a token-derived generative artwork when no src is given). A height-field wave sim runs on a grid matched to tile resolution (~28x18 cells, tile ≈ 32px at 900px width; cols derived from width/32, zero-size guarded): classic discrete wave equation — v[c] += (4-neighbor avg − h[c]) * 0.5 per step, h += v, global damping ×0.985/step, 2 sim steps per frame, Neumann edges. Trigger (IntersectionObserver at 0.35 visibility, or first pointer entry) injects impulse h=1.0 at the trigger cell; a tile pops open when local |h| > 0.12 — scale 0.6→1 on a spring (k=90 s⁻², ζ=0.7) plus a rotateX-style vertical squash 35%→0 over 320ms with cubic-bezier(0.22,1,0.36,1); reveal = drawImage of that tile's source rect. Revealed tiles refract: source rect offset by (gradient of h) × 6px for a wet-glass shimmer. If the coarse wave dies below threshold before reaching the corners, stragglers are flush-scheduled outward from the trigger cell so the reveal always completes. After full reveal, pointermove injects impulse 0.35 at the cursor cell, throttled to one per frame. Pre-reveal tiles draw a border-token hairline, a faint foreground lift, and an accent-alpha shimmer proportional to |h| — every drawn color derived from --border/--accent/--foreground/--surface/--muted via a getComputedStyle probe at mount and re-derived live via MutationObserver on documentElement class changes, so both themes render correctly. The rAF loop is the sole writer (no React state on hot paths) and sleeps when max|h| < 0.004 AND max|v| < 0.004 and all tile springs are settled; it wakes on pointer or trigger and pauses offscreen via IntersectionObserver. IntersectionObserver, ResizeObserver (recompute grid, guard 0x0), MutationObserver, and all pointer listeners are torn down on unmount. Pure media surface: role=img with aria-label, no click behavior. Under prefers-reduced-motion tiles reveal instantly in a single paint with zero wave distortion, static image thereafter. install: npx shadcn add https://design.helpmarq.com/r/ripple-unfold.json ## rule-sparkline [core] Rule Sparkline — Inline KPI sparkline grown over an elementary cellular-automaton texture — the Wolfram rule is picked by the series' volatility, one generation column per data point. use when: a sparkline (canvas, data viz, cellular automaton). props: data?: number[] // series values, oldest → newest; one CA generation per point; default: DEFAULT_DATA cellSize?: number // CA cell height in px; default: 3 entranceMs?: number // entrance sweep duration in ms; default: 900 strokeWidth?: number // polyline stroke width in px; default: 1.5 formatValue?: (value: number, index: number) => string // scrub readout formatter; default: defaultFormat className?: string // default: "h-14" aria-label?: string // default: "KPI sparkline" deps: (none) behavior: An inline KPI sparkline on a single DPR-aware (clamp 2) Canvas 2D where the backdrop is an elementary 1D cellular automaton that reads the data instead of decorating it. CA: cells 3px tall, state vector vertical, one generation COLUMN per data point advancing left to right — each data point extrudes the next generation. The Wolfram rule is selected by the series' coefficient of variation (stddev/mean, zero-mean and zero-size guarded): cv < 0.08 → rule 4 (sparse), 0.08–0.2 → rule 108, 0.2–0.4 → rule 110, > 0.4 → rule 30 (chaotic). The seed row derives from the first value's IEEE-754 bits through a mulberry32 walk so identical data reproduces identical texture. The CA is computed once per data update and painted to a cached offscreen canvas in --foreground ink at 8–14% per-cell hashed alpha — never per frame. Motion is entrance-only: CA and the --accent polyline reveal left→right over 900ms with cubic-bezier(0.22,1,0.36,1) — the CA via a clip-rect (source-rect blit) sweep, the line via canvas setLineDash([pathLen*frac, pathLen]) dash-offset; a data push extrudes only the new tail generations and re-sweeps just that region over 200ms. Cursor scrub: a vertical hairline eases to the snapped nearest-point x with a critically damped spring (k=250 s^-2, zeta=1.0) plus an accent dot on the line and a font-mono DOM readout positioned by direct transform writes; the wrapper is focusable and left/right arrows step the readout. rAF exists only during entrance/tail sweeps and unsettled scrub — cancelled otherwise, the texture is the ambient interest. All drawn colors (--foreground, --accent, --muted) are read via getComputedStyle at mount and re-derived (offscreen CA repainted) by a MutationObserver on documentElement class changes so both themes survive; ResizeObserver recomputes the cell grid and geometry; every observer/listener/rAF torn down on unmount. prefers-reduced-motion: finished CA texture and full line painted instantly, scrub readout still works with the hairline snapping instead of easing. Demo: three stacked metric tiles (calm Revenue / moderate Latency / volatile Errors) on a surface card with mono labels, large tabular numbers, success/error delta pills, and per-tile RULE/CV captions so the rule-vs-volatility mapping is visible by comparison. install: npx shadcn add https://design.helpmarq.com/r/rule-sparkline.json ## scan-sweep-stats [core] Scan Sweep Stats — Dashboard KPI grid under an observatory radar: a 1px accent arm sweeps the panel once per 12s with sonar rings, and each stat card counts up and lights its border only the instant the wedge crosses its bearing, then settles back to muted until the next revolution. use when: a KPI stat tile (canvas, radar, sweep). props: stats?: ScanStat[] // KPI cards, clockwise activation order falls out of their bearings; default: DEFAULT_STATS title?: string // default: "Network observatory" degPerSec?: number // sweep speed in degrees per second (30 = one revolution per 12s); default: 30 wedgeDeg?: number // soft sector width trailing the arm, in degrees; default: 24 toleranceDeg?: number // transit window around a card's bearing, in degrees; default: 2 className?: string ↳ ScanStat = { label: string; value: number; format?: (v: number) => string; delta?: string; icon?: ReactNode } deps: (none) behavior: Dashboard KPI grid under an observatory radar with sweep-gated activation. RENDERING: one Canvas 2D layer (dpr backing store clamp 2, explicit style.width/height because a canvas is a replaced element that ignores inset for sizing) under a DOM grid of 6 KPI cards (rounded-md, 1px --border, --surface fill) inside a padded bg-background panel. Radar pivot fixed at the panel's top-left padding corner (24,24). Arm: 1px leading line in --accent — the only accent ink in the piece — rotating at 30°/s (12s per revolution); wedge: 24° soft sector trailing the arm painted as a conic gradient, --foreground alpha 0.10 at the arm fading to 0 at the trailing edge. SONAR RINGS: one ring emitted per full revolution, stroked circle expanding at 320px/s, alpha 0.18→0 over its travel to the panel diagonal, held in a pruned list capped at 3 and re-stroked after an explicit full clearRect each frame — never destination-in fading, the accumulation trap is designed out. CARD ACTIVATION: each card's bearing from the pivot is computed from DOM rects measured relative to the panel origin (offset coords, never absolute page coords), recomputed on ResizeObserver; when the unwrapped sweep angle passes within ±2° of a card's bearing the card wakes exactly once per pass (per-card next-transit angle re-arms +360° on trigger): value counts up to target over 900ms ease-out-expo in font-mono tabular figures via direct textContent writes, border-color animates --border→--accent over 200ms then decays back over 1.6s via inline rgb mix cleared to the class token at rest, and the trend delta fades in over 300ms; the card then rests with muted text (values dimmed, never zeroed). Every wake carries a hard 1800ms end time, so a card crossed twice quickly re-targets (wakeAt reset) instead of stacking tweens. INTERACTION: hovering or focusing a card replays its count-up and raises the surface with a token-relative foreground-alpha overlay, but never grants the accent border — accent stays sweep-earned; clicking the pivot button toggles pause/resume with a visible mono PAUSED tag; a 1Hz font-mono UTC clock and a per-revolution SWEEP counter frame the panel. REDUCED MOTION: no sweep, no rings, no loop; all six cards render settled at final values with static borders; hover raise stays pure CSS. TOKENS: wedge/ring/arm/border inks parsed from getComputedStyle(--foreground/--accent/--border) at mount and re-derived live via MutationObserver on documentElement class; both themes screenshot-gated. PERFORMANCE: refs-only direct-DOM hot path (no React state per frame); rAF pauses offscreen via IntersectionObserver and on document.hidden, sleeps while paused once all card tweens hit their hard ends, guards zero-size panels; ResizeObserver, IntersectionObserver, MutationObserver, clock interval, pointerenter/focus listeners, and rAF all torn down on unmount. DEMO: full weighted dashboard panel titled 'Network observatory' with believable ops KPIs — Revenue $128.4k (+4.2%), p95 latency 182ms (-11ms), Uptime 99.98%, Churn 1.2% (-0.1), Active nodes 3,412 (+86), Error rate 0.07% — each with a small stroke icon, never a lone sweeping arm. install: npx shadcn add https://design.helpmarq.com/r/scan-sweep-stats.json ## scroll-caliper [core] Scroll Caliper — A vernier caliper pinned to a scroll container's edge whose spring-damped jaws close over the active section's extent while a mono readout ticks px and percent, tick marks streaking with velocity-scaled motion blur. use when: a vernier-caliper HUD pinned to a scroll container's edge that measures the active section with a live px/percent readout; use as a scroll-position instrument, not a narrative or a 3D flythrough. props: children?: ReactNode // scrollable content; sections are matched via sectionSelector sectionSelector?: string // selector for measurable sections inside the scroller; default: "[data-section]" jawStiffness?: number // jaw spring stiffness in s^-2 (near-critical chase); default: 120 jawDamping?: number // jaw damping ratio (1 = critical); default: 0.9 needleStiffness?: number // readout needle stiffness in s^-2 (softer, visible over-settle); default: 90 needleDamping?: number // readout needle damping ratio; default: 0.55 className?: string // default: "h-[480px]" deps: (none) behavior: A vernier caliper instrument, ~48px wide, pinned to the right edge of a bounded overflow-y scroll container it measures. Built in SVG (tick scale, vernier subscale on the lower jaw, jaw blades, beam spine) plus a DOM font-mono readout chip; every transform is written directly in a rAF loop via refs, never React state. Sections are detected with an IntersectionObserver (root = the scroller) on [data-section] children, active = most visible pixels. The jaws map the active section's top/bottom to container-space y and chase those targets with a spring k=120 s^-2, zeta=0.9 (near-critical, a hair of lag); the readout needle (percent of the section swept past the container center) rides a softer spring k=90 s^-2, zeta=0.55 so it visibly over-settles and wobbles when scrolling stops. Tick scale: minor graduations every 2px (--border ink), majors every 8px and long index lines every 40px (--foreground ink), path d rebuilt only on resize and translated by -(scrollTop % 8) per frame so the scale scrolls with content. Motion blur: a duplicated tick layer offset along the scroll direction with opacity clamp(|v|/3000, 0, 0.6) and blur clamp(|v|/200, 0, 10)/2 px, velocity from per-frame scrollTop delta exponentially smoothed at alpha 0.2, layer removed entirely at rest for crispness. Section change flashes the readout label accent for 200ms and updates a throttled visually-hidden live region ('Section 2 of 4, 38%'); the instrument itself is aria-hidden and read-only, no fake affordances. The scroll listener is passive and only wakes the loop; the loop sleeps when 150ms have passed since the last scroll AND all three springs are inside the settle epsilon (|x-target| < 0.05, |v| < 0.05). All SVG ink is currentColor via token classes (text-border, text-foreground, text-accent only on the active-value marker) so both themes restyle live with zero numeric color reads; the readout chip is bg-surface with border-foreground/20. Guards: zero-height containers skip rebuild, zero-height sections never divide, IntersectionObserver/ResizeObserver/scroll listener/flash and announce timers all torn down on unmount. prefers-reduced-motion: jaws and needle snap instantly, no blur layer, no wobble. install: npx shadcn add https://design.helpmarq.com/r/scroll-caliper.json ## sediment-stack [core] Sediment Stack — Toast stack with real gravity — notifications thud into a jostling heap, errors sink under their own mass, and the pile resettles when one is dismissed. use when: a toast/notification stack (notification, physics, gravity). props: duration?: number // ms before a toast auto-dismisses (paused on hover); 0 disables; default: 6000 gravity?: number // px/s^2 downward; default: 1800 restitution?: number // bounce energy kept on impact, 0..1; default: 0.15 initial?: SedimentToastInput[] // toasts present at mount className?: string // default: "h-96" aria-label?: string // default: "Notifications" ↳ SedimentToastInput = { severity?: SedimentSeverity; title: string; message?: string; duration?: number } deps: (none) behavior: A toast system where notifications fall under real gravity and pile into a jostling heap at the base of a docked surface. RENDERING: real DOM toast cards (severity icon, title, mono message, dismiss button, role=status/alert) whose translate/rotate transforms are written per-frame by a rigid-body-lite 2D sim — refs only on the hot path, no React state, no canvas. Each card's collision proxy is a rounded box: a row of circles of half-card-height radius along the card midline (corner circles plus midline fill), so corners round off and nothing tunnels through edge gaps; container floor and walls are static planes. MOTION: gravity 1800 px/s^2 at fixed 120Hz substeps; restitution 0.15 applied only above an 80 px/s impact threshold; tangential Coulomb friction mu 0.85 at every contact; angular damping 0.92/frame framerate-normalized via pow(0.92, dt*60); mass by severity error=3 / warning=2 / info=1 so heavier bodies displace lighter ones on impact and errors migrate toward the pile floor. Toasts spawn from the top, x round-robined across up to 4 jittered tray-width slots (vs. a single fixed edge) so the pile heaps rather than sliding in flat from one side, with vx jitter +/-40 px/s and rotation jitter +/-4 deg; each arrival's impact impulse briefly jostles the pile. The physics floor sits a few px above the tray's visible bottom edge (a shorter inner sim frame inside the clipped outer box) so a rotated card's corner overhang never reads as clipped. SLEEP: the whole sim parks when every body holds |v| < 3 px/s and |omega| < 0.02 rad/s for 12 consecutive frames; spawn, dismiss, hover, drag, and resize wake it. Auto-dismiss default 6s per toast, paused on hover; oldest layers fade to opacity 0.55 as newer sediment lands. Dismissing removes the collision body instantly (150ms opacity fade on the card) and the sediment above resettles under gravity. INTERACTION: hover lifts the card 2px and applies a shadow tinted from the --foreground token (derived via getComputedStyle at mount and re-derived by a MutationObserver watching the documentElement class for theme flips); drag right past 80px dismisses, under-threshold release springs back with k=180, zeta=0.9 while the held card goes kinematic so the pile leans on it. Severity color appears only as a 3px left rail using var(--error)/var(--warning)/var(--success); everything else is neutral tokens (bg-surface, border-border, hover:border-foreground/20, accent focus ring on dismiss buttons). REDUCED MOTION: classic static vertical list, newest on top, instant add/remove with 150ms opacity fades, no physics. Imperative handle exposes push/dismiss/clear. ResizeObserver re-derives floor and walls (zero-size container guarded, coincident-center collision normals fall back to vertical); every rAF, observer, listener, and timer is torn down on unmount. install: npx shadcn add https://design.helpmarq.com/r/sediment-stack.json ## signal-terrain [core] Signal Terrain — Unknown-Pleasures ridgeline chart whose live history recedes into scrolling ambient noise terrain, dented gravitationally by the cursor. use when: an Unknown-Pleasures ridgeline chart where live history recedes into scrolling noise terrain, dented by the cursor; use for a live/ambient data feed with a generative-landscape feel, not when trend direction is the point. props: series?: number[] // data samples, oldest → newest; newest enters at the front row; default: EMPTY cols?: number // vertices per ridgeline; default: 96 rows?: number // ridgeline count (back to front); default: 40 ambientAmplitude?: number // ambient noise height in px at the front row; default: 18 dataAmplitude?: number // data peak height in px at the front row; default: 68 glideMs?: number // ms for the history to glide one row back after a push; default: 600 dentSigma?: number // gaussian radius of the cursor dent in screen px; default: 90 dentDepth?: number // max cursor dent depth in px; default: 26 className?: string // default: "h-96" aria-label?: string // default: "Live signal terrain" deps: (none) behavior: An Unknown-Pleasures wireframe landscape on a DPR-aware Canvas 2D: ~96 columns by 40 rows of ridgeline polylines drawn back to front, each row stroked then filled below with the theme's surface/background token so nearer ridges occlude farther ones (painter's-algorithm ridgeline trick); row y-spacing eases quadratically so rows compress at the horizon and row width narrows ~35% toward the back. Height per vertex = ambient + data: ambient is 2-octave value noise scrolling toward the viewer at 0.06 u/s with 18px amplitude scaled up toward the front; data is a series prop (number[]) where sample age maps to row depth, so each new sample enters at the front row and the whole history glides one row back over 600ms with cubic-bezier(0.22,1,0.36,1) interpolation between fractional row offsets, the chart's history literally receding into ambient terrain. The cursor dents the mesh with a screen-space gaussian (sigma 90px, max depth 26px), plus a soft foreground-token glow bloomed at the dent center so the interaction reads clearly: dent amount lerps toward full at 0.12/frame while hovered and releases through an underdamped spring (k=70 s^-2, zeta=0.6) for one visible rebound. Stroke fades from 1.5px foreground-token color at the front row to 1px muted-token color at ~25% opacity at the horizon. Fill and stroke colors are resolved from CSS custom properties (--surface/--background, --foreground, --muted) at mount and re-derived via a MutationObserver on the document root's class attribute, so the terrain repaints correctly on theme toggle without a remount. Data and pointer live in refs; a single rAF loop is the only writer and pauses when the element leaves the viewport. Under prefers-reduced-motion: no noise scroll, no dent, a static render of the current series redrawn instantly on data change or theme change. With an empty series it idles as pure atmosphere; with no noise it reads as a strict chart. install: npx shadcn add https://design.helpmarq.com/r/signal-terrain.json ## slide-to-shatter [core] Slide to Shatter — Frosted-glass confirm slider where drag distance drives Voronoi crack density — release early and the cracks heal on a spring; complete the travel and the pane explodes into tumbling glass shards revealing the confirmed state. use when: a frosted-glass CONFIRM slider — drag distance grows Voronoi cracks that heal if you stop early, and shatter into glass shards on full travel; use for a destructive confirm action, not a plain value-reading input. props: label?: string // mono label etched on the glass; default: "SLIDE TO CONFIRM" confirmedLabel?: string // label revealed once the pane shatters; default: "CONFIRMED" width?: number // default: 320 height?: number // default: 56 shardCount?: number // approximate Voronoi cell count — cracks while dragging, shards on commit; default: 48 onConfirm?: () => void resetKey?: number // bump to restore the pane and replay; default: 0 className?: string deps: (none) behavior: A frosted-glass confirm slider where destruction IS the progress indicator: a 320×56 DOM track in the house glass recipe (light: bg-white/60 with a black/15 border; dark: bg-white/[0.06] with a white/10 border; backdrop-blur-xl, inset top specular, rounded-md) carries a DPR-aware canvas overlay and a 48px grabbable thumb, itself theme-split (black-tinted border/fill on light, white-tinted on dark) so it reads against the pane in both modes. On mount, seed ~48 Poisson-disc points across the track and compute exact Voronoi cells once via half-plane bisector clipping; deduped cell walls become crack polylines, each assigned a reveal threshold t from its distance to the thumb origin, and the same cells are reused later as shard polygons. Dragging (pointer capture, progress in a ref, thumb transform set in a rAF loop, zero React state on the hot path) strokes every polyline with t<p segment-by-segment from its near end — 1px rgba(255,255,255,0.35) hairline plus a 0.75px-offset 0.5px rgba(255,255,255,0.12) ghost for glass depth — and past p=0.6 the whole track shudders ±0.5px per frame. Release early and p springs back to 0 (stiffness 220, damping 26) so the cracks retract along the same t-mapping, healing for free. The thumb is a full role="slider": Arrow/Up/Down keys nudge progress by 0.08, Home/End jump to the ends, and Enter/Space confirm outright, each keyboard step rendering once without waking the rAF loop. At p≥0.98 (by drag or key) the DOM glass hides instantly and the canvas flips to shard mode: each Voronoi cell tumbles outward from the thumb at 120–420px/s under 1800px/s² gravity with ±3rad/s spin, fading over 700ms; after ~900ms the canvas clears, revealing a bg-surface row with a check icon and mono CONFIRMED. The rAF loop sleeps whenever settled, and prefers-reduced-motion drops the canvas entirely for a plain slide with an instant confirmed swap. install: npx shadcn add https://design.helpmarq.com/r/slide-to-shatter.json ## solargraph-hero [core] Solargraph Hero — Hero card whose canvas behaves like a long-exposure photograph: cursor movement burns light streaks that never clear per frame, only decay on a 4s half-life, accumulating a light painting of the session. use when: a hero whose canvas behaves like a long-exposure photograph — cursor movement burns light trails that persist and decay over ~4s, building an ambient light-painting rather than reacting live; zero deps, best for a quieter, card-style hero. props: children?: ReactNode // hero copy / CTAs — rendered above the canvas, fully interactive halfLifeMs?: number // exposure decay half-life in ms; default: 4000 maxStrokeAlpha?: number // per-stroke alpha ceiling; repeated passes asymptote instead of whiting out; default: 0.35 intro?: boolean // scripted 2s figure-eight on load so the exposure shows before any input; default: true className?: string deps: (none) behavior: A hero card whose background canvas behaves like a long-exposure photograph — persistence, not live emission. Two offscreen accumulation buffers (never cleared per frame) hold pure white intensity strokes and are composited onto a visible DPR-clamp-2 canvas sitting behind fully clickable DOM hero copy (canvas pointer-events none, pointer tracked on the hero root). Pointer samples are exponentially smoothed and joined as quadratic curves through midpoints, line width 1.5 + clamp(speed/1200, 0, 1.5) px with shadowBlur 12 for glow; each segment lands in buffer A with 60% probability (primary tint) or buffer B (secondary). Decay is framerate-independent: every frame paint destination-out black at alpha = 1 - exp(-dt/tau), tau = halfLife/ln2 (~4s half-life), and strokes draw at globalAlpha 0.35 so repeated passes asymptote instead of whiting out. Tint is applied at composite time via a source-in fill of each intensity buffer, stacked source-over then lighter — so the recolor pass is inherent and a theme flip re-tints the whole accumulated exposure on the next composite. Theme mode is chosen from the derived --background luminance via getComputedStyle at mount and re-derived live through a MutationObserver on documentElement class: dark composites with CSS mix-blend-mode screen using --accent (60%) and --foreground (40%) tints; light flips to multiply with tints from --muted and a --border/--muted mix so trails darken instead of vanishing on white. The rAF loop tracks an energy scalar (sum of recent stroke alpha, decaying with the same tau) and sleeps when no pointermove for 500ms AND energy < 0.02 (wiping the invisible residue), wakes on pointermove, pauses offscreen via IntersectionObserver; ResizeObserver resizes buffers preserving the exposure via a scaled copy and guards zero-size containers; all observers and listeners torn down on unmount. On load a scripted 2s figure-eight (Lissajous) drives the pointer so the exposure photographs before any real input; a real pointermove cancels it. Under prefers-reduced-motion: one seeded synthetic static exposure along the figure-eight at low alpha, no accumulation, no loop, re-rendered on resize and theme change. Demo is a full hero composition: padded surface card, mono eyebrow, Geist Sans 600 tight-tracked H1, muted subhead, dual CTA row (accent primary with accent-hover, ghost secondary with border-foreground/20 hover and accent focus ring), and a 4-mark grayscale trust-logo row. install: npx shadcn add https://design.helpmarq.com/r/solargraph-hero.json ## strandline [core] Strandline — Changelog timeline drawn as a beach strand: each release arrives as a foam crest sweeping an arc in from the now edge, breaks at its chronological position, pops a marker in with a spring, and recedes leaving an etched tide-ring — later waves wash past older marks so ring density reads as event history. use when: a timeline (canvas, changelog, wave). props: events?: StrandlineEvent[] // chronological events, oldest first — oldest breaks nearest the now edge; default: DEFAULT_EVENTS autoplay?: number // waves auto-launched on mount (0 disables the intro tide); default: 3 className?: string // default: "h-80" aria-label?: string // default: "Release timeline strand" ↳ StrandlineEvent = { date: string; version: string; title: string; body: string } deps: (none) behavior: Timeline drawn as a beach strand via wave-deposition. RENDERING: a Canvas 2D layer sits behind DOM marker nodes inside a padded surface card; the horizontal timeline axis is stroked 1px --border at 62% of canvas height, with the 'now' edge at the right and chronological positions laid out so the OLDEST event breaks nearest the water — each later wave must reach further up-strand, which is exactly what lets it wash past earlier markers. WAVE: the active crest travels a quadratic-bezier arc from the right edge toward the target event x at 420px/s with ease-out-expo arrival (duration = arcLength/420, hard forced-settle deadline at dur+150ms, never epsilon-based); the crest front is 48 short stroked segments (3-9px long) jittered ±3px perpendicular to the arc tangent in --foreground at alpha 0.5 with falloff over a 60px trailing comb, and the crest's leading 1px line is stroked in --accent — the ONLY accent ink, the active incoming crest; a faint --foreground wetted-arc trail glows behind it. BREAK: on arrival, 24 foam flecks spawn with initial speed 60-140px/s, upward spray angles, gravity 300px/s², life 600ms, emission staggered over a 250ms burst window, held in a pruned splice-on-death array; the event's 24px DOM marker (border ring on surface, small commit icon) pops in with an underdamped spring (k=250, zeta=0.5) from scale 0.6 to 1.0 overshooting ~1.06, settling under 500ms with a forced-settle deadline of 800ms. RESIDUE: each wash appends one arc stroke (--muted, alpha 0.12, crescent bowed seaward with jittered rotation and span) to a per-marker segment list capped at 3 with the oldest shifted out; rings are re-stroked from the lists every frame after a FULL clearRect — no destination-in decay, avoiding the quantize-forever trap. Later waves passing an existing marker append a ring without touching the marker. After the break the wetted arc recedes back toward the now edge over 550ms. INTERACTION: a next/prev control pair (plus counter) advances or retreats 'now' — next queues the next event's wave (queue drains sequentially), prev pops the queue, cancels an in-flight wave into a non-depositing recede, or undeposits the last marker and prunes its rings; hover or keyboard focus on a stranded marker replays its swash once via a short 110px mini-arc (no new residue ring) and raises a DOM detail card (title, version+date, one-line body) positioned by offset transform from the container origin above the marker's settled coordinate, with a no-fly-in first show. On mount an autoplay intro queues the first 3 waves so the ambient tide is the default look. REDUCED MOTION: all markers render pre-stranded with synthesized ring histories (min(3, n-i) rings each), no waves, controls disabled, hover/focus still raises the card statically. ACCEPTANCE: all inks (--border axis, --foreground foam/flecks, --muted rings, --accent crest) derived via getComputedStyle at mount and re-derived by a MutationObserver on documentElement class that re-strokes the scene; rAF sleeps when there is no active or queued wave, the fleck array is empty, and all marker springs are settled; IntersectionObserver pauses offscreen; zero-size containers guard the loop; canvas sized with explicit style.width/height plus a dpr-clamped backing store; every listener, observer, and frame torn down on unmount. DOM markers and the detail card take offset transforms from the container origin, never absolute canvas coords. install: npx shadcn add https://design.helpmarq.com/r/strandline.json ## terminator-date-field [core] Terminator Date Field — Masked date input whose popover calendar doubles as a moon-phase almanac: every day cell carries a canvas moon with a real synodic terminator, the field icon tracks the focused date's phase live, and committing runs an eclipse transit across the chosen numeral. use when: a date picker (input, calendar, canvas). props: value?: Date | null // controlled selected date; omit for uncontrolled defaultValue?: Date | null // default: null onValueChange?: (date: Date) => void label?: string // default: "Date" disabled?: boolean // default: false className?: string deps: (none) behavior: Build a date input whose popover calendar doubles as a moon-phase almanac. RENDER: masked text input (MM/DD/YYYY, digits auto-slashed, full validation with revert-on-blur) plus a popover role=grid month calendar of 42 real button cells (role=gridcell, roving tabindex); ONE canvas absolutely positioned behind the whole grid draws all 42 moon glyphs (14px discs) at cell centers measured via getBoundingClientRect after a double-rAF layout settle, plus a 20px canvas in the input's trailing icon slot; both canvases get EXPLICIT style.width/height and dpr-clamped backing stores (a canvas is a replaced element — inset never sizes it). PHASE MATH: mean synodic month 29.530588853 d, reference new moon epoch 2000-01-06 18:14 UTC, sampled at local noon; f = ((days since epoch) mod syn)/syn; illuminated fraction k = (1 - cos(2*pi*f))/2; disc stroked --border, lit region --foreground at 85% alpha, terminator drawn as a semi-ellipse with x-radius r*|cos(2*pi*f)|, lit limb right while waxing (f < 0.5) and left while waning, ellipse sweep direction flipping crescent vs gibbous. MOTION: trailing icon crossfades 150ms (dual-alpha draw, cleared per frame) whenever focus movement or typing changes the previewed date; committing from the grid fires an eclipse transit — a foreground corona behind the chosen numeral occluded by an opaque background-ink shadow disc sweeping left-to-right over 420ms ease-out-expo, clipped to the cell, with the entire grid canvas cleared and all 42 moons redrawn every frame (zero accumulation), then the popover closes and focus returns to the input; month changes re-measure and re-lay glyphs after cell layout settles (double rAF + ResizeObserver). rAF runs only during crossfade/transit and is parked offscreen (IntersectionObserver) and on document.hidden — the static almanac costs zero frames. INTERACTION: Arrows move a day/week, Home/End week edges, PageUp/Down month, Shift+PageUp/Down year (view follows focus), Enter/click commits, Esc or outside pointerdown closes (Esc returns focus), ArrowDown in the input opens; aria-selected and aria-current=date on cells; phase name (e.g. Waxing gibbous) in every cell's accessible label and as visible helper text with percent illumination under the field. REDUCED MOTION: no transit or crossfade, instant selection and close; static moons stay as information. TOKENS: all canvas ink parsed from getComputedStyle(--foreground/--border/--background) at mount and re-derived via MutationObserver on documentElement class; hover/focus affordances token-relative (foreground-alpha tints, accent focus rings). Guard zero-size grids before measuring, and tear down every rAF, timer, observer, and document listener on unmount. install: npx shadcn add https://design.helpmarq.com/r/terminator-date-field.json ## tide-gauge-password [core] Tide Gauge Password — Password field with a canvas water tank behind the masked text: entropy raises the tide on a damped spring, keystrokes slosh a real 1D heightfield wave, deletions pull the level back down. use when: a password field specifically — a canvas water tank behind the masked text where entropy raises the tide and keystrokes slosh a real wave; use when strength itself should be legible, not for general text input. props: label?: string // visible label text above the field; default: "Password" name?: string // default: "password" placeholder?: string defaultValue?: string // uncontrolled initial value value?: string // controlled value; omit for uncontrolled onValueChange?: (value: string) => void autoComplete?: string // default: "new-password" required?: boolean // default: false disabled?: boolean // default: false className?: string deps: (none) behavior: Build a password field (real <input type=password>, visible label, standard semantics untouched) with a canvas 2D water tank behind the masked text, clipped to the field's rounded-sm 6px bounds. Size the canvas with EXPLICIT style.width/height plus dpr-scaled bitmap (replaced element — inset does not size it). Strength = length + charset-class entropy (pool 26/26/10/33, 72 bits caps the gauge) mapped 0-100 to water level percent; drive the level with a damped spring k=90 s^-2, zeta=0.55 (~8% overshoot then settle). Simulate a 1D heightfield with one column per 4 px: neighbor-coupling wave speed ~140 px/s, per-frame velocity damping 0.985; each keystroke injects a -6 px surface impulse at the caret's approximate x (charCount * measured mask-glyph width, spread over a 5-column kernel), deletions inject +4 px and lower the target, and the reveal toggle drops a 4 px ripple at the eye-icon x. Fill = mix(--muted, --accent, level fraction) at 20% alpha with a 1.5 px surface line at 60% alpha; full clear + redraw every frame — never accumulating destination-in alpha. rAF sleeps when max column |v| < 0.02 px/frame AND |level-target| < 0.3 px, with a 1.2 s forced-settle deadline (extra damping pulls flat, 2 s hard snap) and pauses offscreen via IntersectionObserver plus document visibility; guard zero-size containers before simulating. All canvas ink is read via getComputedStyle at mount and re-derived by a MutationObserver watching documentElement class changes so both themes render correctly. Reveal toggle is a real button with aria-pressed; aria-describedby points at a visually-hidden polite live region announcing Weak/Fair/Strong, mirrored by a small aria-hidden mono readout. Accent focus-within ring and token-relative hover border. prefers-reduced-motion renders a static fill bar at target height with instant height changes and no waves. Tear down every listener, observer, and rAF on unmount. install: npx shadcn add https://design.helpmarq.com/r/tide-gauge-password.json ## updraft-dropzone [core] Updraft Dropzone — File dropzone as a thermal field: dragging spawns rising accent convection wisps, accepted drops buoy off the drop point and squash-land into a docked queue rack, rejected files sink and fade. use when: a drag-and-drop upload zone (file upload, form, canvas). props: defaultFiles?: { name: string; size: number; type: string }[] // files shown pre-docked in the queue rack; default: [] accept?: string[] // allowed types: extensions (".png") or mime ("image/png", "image/*"); empty = any; default: [] maxSizeBytes?: number // default: 8 * 1024 * 1024 onFilesChange?: (files: UpdraftFile[]) => void className?: string aria-label?: string // default: "Upload files" ↳ UpdraftFile = { id: string; name: string; size: number; type: string } deps: (none) behavior: Build a file dropzone as a thermal field: a canvas 2D wisp layer over the zone (canvas-over-control pattern, explicit style.width/height because a canvas is a replaced element) plus DOM file chips animated with direct-DOM transforms, and a hidden <input type=file multiple> behind a real browse button. DRAGOVER: spawn convection wisps at 18/s (cap 30 live) from the zone floor biased toward the dragged pointer's column, rising 30-60 px/s with sinusoidal x-wobble amplitude 6px period 1.2s, life 1.5-2.5s, drawn as short quadratic strokes at peak alpha 0.12 from --accent with a sin-envelope fade; pruned particle array with a full clear + redraw per frame, never destination-in fades. ACCEPTED CHIP: chips are DOM list items anchored to their dock slots and flown with OFFSET transforms measured from drop point to slot center: a 900 px/s^2 buoyancy boost for the first 180ms feeding a near-critically damped spring pull to the slot, horizontal sway +-10px at 2 Hz with a zeta~0.5 decay envelope, landing squash scaleY 0.88 held 120ms then sprung back with k=300 s^-2 zeta=0.6; multi-drop flights stagger 90ms (chips hidden at the drop offset until their turn) so flights never overlap, and every chip carries a forced-settle deadline of 1.4s. REJECTED CHIP: spawns at the drop point inside the zone, sinks 40px max under 600 px/s^2 gravity while fading over 500ms, then is removed; the rejection reason (type not accepted / exceeds size limit) is announced via a polite aria-live status line. INTERACTION: zone is focusable role=button with Enter/Space opening the picker, aria-describedby points at the accepted-types + max-size rules line, docked chips are focusable list items removable via Delete/Backspace or an explicit remove button with focus handed to a neighbor. Validation supports extensions (.png), exact mime, and mime wildcards (image/*) plus a per-file byte limit. REDUCED MOTION: no wisps, chips appear docked instantly, dragover falls back to the static token-border accent highlight. ENGINE: all canvas ink parsed from getComputedStyle CSS tokens at mount and re-derived live via a MutationObserver on documentElement class so both themes render correctly; single direct-DOM rAF loop that sleeps when all chips are docked and all wisps dead, pauses offscreen via IntersectionObserver and on document hide, guards zero-size zones and zero-size chips before animating, and tears down every listener, observer, and frame on unmount. Hover/focus/dragover affordances are token-relative (border-foreground/25, ring-accent, border-accent), never hardcoded white. install: npx shadcn add https://design.helpmarq.com/r/updraft-dropzone.json ## vapor-countdown [core] Vapor Countdown — Live countdown where each digit change is a phase transition: the outgoing digit sublimates into grains on curl-noise wind while the incoming digit condenses from the same cloud. use when: a countdown timer (canvas, particles, typography). props: targetDate?: Date | string | number // countdown target — Date, ISO string, or epoch ms; defaults to 24h from mount labels?: readonly [string, string, string] | null // mono labels under the HH / MM / SS groups; null hides the row; default: DEFAULT_LABELS className?: string deps: (none) behavior: A live HH MM SS countdown rendered as monochrome grains on a DPR-aware Canvas 2D over a real <time> element (aria-live=off, tabular Geist Sans 600, visually transparent) so screen readers get truth and reduced motion gets a static visible countdown with the canvas hidden. After document.fonts.ready, rasterize digits 0-9 once on an offscreen canvas sized to one tabular digit cell, sampling alpha > 128 at a 3px stride, capped at 2500 grains per digit, stored in Float32Array pools (x, y, vx, vy, hx, hy). Each second boundary a setTimeout tick updates the DOM digits and, for every changed column, runs a phase transition: outgoing grains move to a vapor pool with a 600-900ms per-grain lifespan, driven by wind equal to the curl of a 2-octave value-noise field (field scale 0.008, per-grain speed 40-90 px/s, biased upward) with alpha fading over life; incoming grains spawn from the departing cloud region with slight jitter and spring to their new glyph homes with k=90 s^-2, zeta=0.55, per-frame drag 0.92, dt clamped to 32ms, so a full swap reads settled in ~800ms. Grains draw as 2x2 fillRect in the live computed foreground color (read via getComputedStyle on a digit element, re-read on documentElement class/data-theme mutation and OS color-scheme change so a live theme toggle repaints correctly with one forced wake) with alpha 0.5 + 0.5*min(1, speed/500); vapor multiplies in its life fade. The rAF loop wakes on each tick and sleeps when every column has grains within 0.5px of home with |v| < 2 and no live vapor; settled columns (hours, minutes) skip physics entirely and draw one flat pass, so seconds churn constantly while hours stay typographically calm. Canvas overdraws the layout box (110px headroom) so rising vapor never clips. Props: targetDate (Date | string | epoch ms, default 24h out), labels row in font-mono text-muted beneath the groups. Zero dependencies. install: npx shadcn add https://design.helpmarq.com/r/vapor-countdown.json ## warp-lattice [core] Warp Lattice — Card grid on a magnetized hairline lattice — the cursor bends the grid lines and the DOM cards sample the same displacement field, riding the bent sheet. use when: cards (canvas, grid, cursor). props: labels?: string[] // mono label per card (3x2 grid by default); default: DEFAULT_LABELS cell?: number // lattice cell size in px; default: 32 sampleStep?: number // sampling interval along each line in px; default: 8 sigma?: number // gaussian falloff radius of the field in px; default: 140 peakBend?: number // maximum line bend in px (peaks at r = sigma); default: 22 cursorLerp?: number // smoothed-cursor lerp per frame — flicks lag, the sheet relaxes behind them; default: 0.14 className?: string // default: "min-h-[520px]" aria-label?: string // default: "Card grid on a cursor-warped lattice" deps: (none) behavior: A functional 3x2 DOM card grid drawn over its own full-bleed canvas lattice, where the lattice is the magnetized medium. Lattice: 32px cells, every line sampled every 8px, stroked with the theme's --border token (read via getComputedStyle at mount, re-read on a MutationObserver watching documentElement's class list so dark/light toggles stay correctly weighted) with alpha rising 0.25 to 0.6 inside the field. One pure displacement function shared by canvas and cards: pull = (cursor - p) * A * exp(-r^2 / (2 * 140^2)), A tuned for a 22px peak bend, magnitude clamped to 0.35r so lines never cross the pointer. At rest (no pointer) the field target drifts a slow lissajous orbit at 0.16 of full strength so the lattice always has ambient motion instead of sitting dead flat; hovering overrides the target with the real cursor at full strength. The cursor/idle position itself is smoothed at lerp 0.14 per frame so flicks lag and the sheet visibly relaxes behind fast moves. Cards translate field(center) * 0.35; the nearest hovered card gets 0.6x field plus scale 1.02 and a #006bff border — the only accent. A single direct-DOM rAF loop writes both canvas and card transforms with no React state, sleeps once a steady hover position has fully caught up, and is paused by an IntersectionObserver while the lattice is off screen. pointerleave eases everything back down to the ambient idle state with the same interruptible lerp. prefers-reduced-motion: static flat lattice, static cards, hover reduced to a border highlight. Zero dependencies. install: npx shadcn add https://design.helpmarq.com/r/warp-lattice.json ## aurora-flow-chart [loud] Aurora Flow Chart — Area chart whose fill is a live aurora curtain — series values drive curtain height per column, a cool-to-warm hue band tracks local trend direction (falling cool, rising warm), the noise-warped top edge drifts even at rest, and data updates glide the curve to its new shape with a staggered ease. use when: an area chart whose fill is a live aurora curtain — height tracks values, hue tracks trend direction (cool falling, warm rising); use when trend direction itself is the story and you need a real tooltip/axis, not an ambient backdrop. props: data?: AuroraPoint[] // series points, oldest → newest; updates glide the curtain to the new curve; default: DEFAULT_DATA height?: number // chart height in px (width is fluid); default: 300 yTicks?: number // horizontal gridline divisions above the baseline; default: 4 glideMs?: number // ms for a column to glide to its new height after a data update; default: 600 formatValue?: (v: number) => string // value formatter for tick captions and the tooltip; default: defaultFormat showLegend?: boolean // show the falling/rising hue legend; default: true className?: string aria-label?: string // default: "Aurora flow chart" ↳ AuroraPoint = { label: string; value: number } deps: (none) behavior: Build an area chart component where the fill IS an aurora curtain, rendered on a DPR-clamped (max 2) Canvas 2D with a DOM layer for axis captions, legend, and tooltip (font-mono, text-muted). Curtain: for each 2px x-column, interpolate the normalized series value to a column height, warp the top edge with deterministic 2-octave value noise (0.65/0.35 octave weights, smoothstep interpolation) at amplitude 6% of column height drifting 0.05 noise-u/s, and fill the strip with a vertical alpha falloff pow(1 - y/h, 1.6) from the warped top edge down to the baseline. Implement the falloff as two pre-baked 1x256 alpha-strip offscreen canvases tinted at the cool and warm ramp endpoints, blended per column via globalAlpha by a mix value 0.5 + localSlope*14 clamped 0..1 (slope measured over a 4-index window: falling = cooler teal, rising = warmer magenta), plus a 1.5px luminous cap in the hsl-interpolated hue riding the warped edge. Every drawn color derives from theme tokens read via getComputedStyle on documentElement (--background, --foreground, --border, --accent), with the aurora ramp endpoints keyed to background luminance (bright HSL L=60 on dark, deep L=37 on light so the curtain reads on white), re-derived live by a MutationObserver watching documentElement class changes that rebakes the strips. Motion: data updates glide each column start-to-target with cubic-bezier(0.22,1,0.36,1) over 600ms, staggered 4ms per column left to right; ambient drift runs whenever visible via a direct-DOM rAF loop with zero React state on the hot path. Interaction: pointermove shows a DOM tooltip (label, value, delta) snapped to the nearest data point with a crosshair that spring-follows pointer x at k=200 s^-2 zeta=1, and a 3px accent-token dot rides the warped top edge at the active point (accent reserved for this interaction only); arrow keys step the active point when the wrapper is focused (token-relative accent focus ring). Performance: full stop offscreen via IntersectionObserver (drift time accumulator pauses), paint rate capped to 30fps when the pointer has been idle over 5s and no glide or spring is in flight, wake on pointer or re-entry; prefers-reduced-motion renders a single static frame with noise at t=0, no drift or glide (data changes repaint instantly, tooltip still works). Guard zero-size containers and empty series before normalizing (nice-ceil the max, never divide by zero), and tear down the rAF, static rAF, IntersectionObserver, ResizeObserver, MutationObserver, and all pointer/keyboard listeners on unmount. Y-gridlines use the border token at reduced alpha with mono DOM captions; a small legend maps the two ramp endpoints to falling/rising. install: npx shadcn add https://design.helpmarq.com/r/aurora-flow-chart.json ## core-sample-scroll [loud] Core Sample Scroll — Pinned scroll story — the viewport becomes a geological core cross-section and scroll drives a drill bit descending through procedurally banded strata, with content panels crossfading per band and a mono HUD ticking depth. use when: a pinned scroll story where the viewport becomes a geological core sample and a drill bit descends through strata as DOM content panels crossfade per band; use for a long-form narrative with distinct content sections, not an abstract flythrough or a real-image reveal. props: bands?: CoreSampleBand[] // strata content, top → bottom; band 4 (index 3) carries the accent vein; default: DEFAULT_BANDS totalDepth?: number // depth in meters the HUD reads at full scroll; default: 128 trackVh?: number // scroll-track height in vh; the sticky stage is always 100vh; default: 250 className?: string ↳ CoreSampleBand = { id: string; label: string; title: string; body: string; spec: string } deps: (none) behavior: Build a pinned scroll story: a 250vh scroll track wrapping a position:sticky 100vh stage. One full-stage Canvas 2D layer draws a geological core cross-section: 5 strata bands (thickness 12-28% of stage height each), each filled with 2-octave value-noise grain (3px cells) quantized to 3 gray levels interpolated between --border and --muted, with slightly different quantization thresholds per band so bands read distinct in monochrome; exactly one accent vein — a 1.5px --accent polyline at a fixed depth inside band 4. Grain is rendered ONCE per resize/theme into an offscreen band atlas and blitted per frame — never per-frame noise. DRILL: center-left column with a mono-weight chevron bit and drill string stroked in --foreground plus faint depth ticks; depth target = scrollProgress * totalDepth and the rendered depth eases with depth += (target-depth)*(1-exp(-dt*8)) (~120ms lag), with a forced-settle deadline that snaps to target 250ms after the last scroll event so the HUD never ticks forever. While |depth velocity| > 2px/s the bit tip emits 12-particle chip-spray batches (life 400ms, gravity-integrated, pruned array with an explicit full clear per frame — no destination-in accumulation). CAMERA: the scene is overscanned ~1.22x and the canvas translates at 0.15x scroll delta plus a scale 1.00→1.06 across full progress; a DOM label layer rides the identical camera via an offset CSS transform (never absolute canvas/page coords). CONTENT: 5 DOM panels stacked in a right column (45% width, padded surface card rounded-md); when the eased depth crosses a band threshold the outgoing panel fades/slides -12px and the incoming fades/slides in from +12px over 350ms cubic-bezier(0.22,1,0.36,1). HUD: stage-corner font-mono depth readout in meters with 2 decimals updated via direct DOM every frame while moving; the band label gains --accent only while inside the vein band. INTERACTION: band labels along the left edge are focusable buttons that scroll the track to that band; hovering/focusing a label draws a 1px --foreground top-rule on its band in the canvas. REDUCED MOTION: no pin choreography — a static labeled cross-section rendered at full depth, panels as a normal stacked list, HUD frozen. ENGINEERING: all strata/grain/vein/HUD inks derived from getComputedStyle tokens at mount with a MutationObserver on documentElement class re-deriving live and regenerating the band atlas on theme flip; canvas sized via explicit style.width/height with a dpr-scaled backing store (sticky inset does not size a replaced element); rAF sleeps when |depth - target| < 0.1px and the chip list is empty; IntersectionObserver pauses the loop offscreen; zero-size stage guard; scroll listener passive and removed with all observers/rAF on unmount; no React state on the hot path. install: npx shadcn add https://design.helpmarq.com/r/core-sample-scroll.json ## erosion-trail [loud] Erosion Trail — The cursor is a river — dragging across a live topographic map carves a channel into the heightfield, marching-squares isolines reflowing into canyon walls with a faint waterline; release and sediment heals the terrain back over ~6 seconds. At rest the sheet stays alive: contours drift in a slow traveling ripple and sediment specks trickle downhill continuously. use when: a generative terrain surface (topographic, cursor, canvas). props: gridSize?: number // heightfield resolution per axis (nodes); default: 96 contourStep?: number // elevation gap between isolines; every 5th index line renders brighter; default: 0.08 brushSigma?: number // gaussian carve-brush radius (sigma) in screen px; default: 28 carveRate?: number // carve rate in elevation units per second at full depth; default: 0.9 healTau?: number // healing time constant in seconds (95% healed ≈ 3·tau); default: 2.2 showReadout?: boolean // font-mono corner readout of cursor grid coords; default: true className?: string // default: "h-96" aria-label?: string // default: "Topographic map — drag to carve a river channel" deps: (none) behavior: Build a full-bleed Canvas 2D topographic map where the cursor is a river that carves persistent channels. Keep a 96x96 Float32Array heightfield: a fixed base from deterministic 2-octave value noise (hash-sin lattice, 0.65/0.35 octave weights, ~3.4 features across the sheet) minus a separate carve-delta layer, plus a low-frequency ambient drift term — a static per-node noise phase map sampled as sin(phase − elapsed·speed) at amplitude ≈0.42× the contour step, one full cycle ≈10s — rebuilt into a field array per frame so the isolines read as slowly traveling ripples even with no input. Render isolines via marching squares on the coarse grid every 0.08 elevation between the frame's min and max, batched into two Path2D strokes: hairline 0.75px #2e2e2e minors with every 5th contour index (k % 5 === 0) at 1px #8f8f8f — handle both saddle cases (5 and 10) with double segments and lazily interpolate only crossed edges. Layer ~42 ambient sediment specks (1.4px dots, #8f8f8f, fading in/out over a 3-7s randomized lifespan) that trickle continuously along the downhill gradient of the static base heightfield, independent of drag, with a slow noise-driven nudge when the local slope is near flat so nothing stalls; respawn at a random point on exiting the canvas or expiring. Carving: on pointer-down drag (setPointerCapture, touch-none), a Gaussian brush with sigma = 28px subtracts carve delta along the segment between velocity-smoothed pointer samples (head lerps 0.25/frame toward the raw pointer to prevent scalloping) at 0.9 elevation/s, scaled by inverse speed — full depth below 80 px/s tapering linearly to 0.25x at 400 px/s so dwelling digs canyons — stamped every half-sigma along the segment with the per-frame deposit split across stamps, delta clamped to 1. Waterline: while the pointer is down only, nodes whose carve delta exceeds 0.12 within 40px of the recent trail (ring buffer of the last 10 smoothed points) fill as cell rects in rgba(0,107,255,0.35) — the single accent, earned by interaction. Healing: every frame each node's delta decays exponentially toward zero with tau = 2.2s (95% healed around 6.5s) so contours visibly breathe back. Direct-DOM rAF loop with no React state on the hot path: the ambient drift and sediment keep it running continuously while the sheet is on screen, paused via IntersectionObserver once scrolled offscreen and resumed on re-entry; pointerdown/up layer the carve state on top without changing the scheduling. Include a font-mono corner readout of cursor grid coords updated via textContent in the pointermove handler, DPR-aware sizing capped at 2 with a ResizeObserver redraw, and a prefers-reduced-motion fallback that renders one static contour frame with no drift, no sediment, no carving, and no waterline. Zero dependencies, house tokens only. install: npx shadcn add https://design.helpmarq.com/r/erosion-trail.json ## event-horizon-command [loud] Event Horizon Command — Cmd-K palette where fuzzy-match results orbit the input as label pills — orbital radius is inverse match score, so the gravity sim is the ranking: an empty query leaves every command in calm staggered orbits, typing pulls strong matches into tight fast orbits while weak ones destabilize, fling off and despawn, and Enter consumes the winner into the horizon glow. use when: a command palette (cmd k, orbit, physics). props: commands?: CommandItem[] // default: DEFAULT_COMMANDS placeholder?: string // default: "Type a command" defaultOpen?: boolean // palette starts open; ⌘K / Ctrl+K toggles, Esc closes; default: true closeOnSelect?: boolean // close the palette after a command is consumed; default: false onSelect?: (item: CommandItem) => void onOpenChange?: (open: boolean) => void autoTypeQuery?: string // demo scripting: auto-types this query character by character, looping autoTypeLoopMs?: number // loop period for the auto-typed query, ms; default: 6000 className?: string // default: "h-[560px]" ↳ CommandItem = { id: string; label: string; category?: string } deps: (none) behavior: Build a Cmd-K command palette where fuzzy-match results orbit the input as pills and the gravity sim IS the ranking visualization. Rendering is hybrid: a real <input> (role=combobox, aria-expanded, aria-controls, aria-activedescendant, focus trapped while open, toggled by Cmd/Ctrl+K, closed by Esc) plus an sr-only listbox (role=listbox/option) for a11y; each result is a DOM label pill positioned per-frame via style.transform from the sim so text stays crisp, over a single Canvas 2D layer (DPR clamped to 2) that draws orbit trails and the horizon glow ring. Fuzzy matching is a self-contained scored subsequence (consecutive-run bonus, word-start bonus, gap penalty, query-length confidence — no fuse.js). An EMPTY query is neutral, never unstable: every command gets a staggered pseudo-score across 0.62..0.28 so all of them ride calm distinct orbits (distinct radii mean distinct Kepler speeds, so initial clusters shear apart into even spacing), and clearing the query returns everything to that calm band. Motion: each result gets target radius r = 70 + (1 - score) * 220 px around the input center (plus small deterministic per-id jitter, radii squashed to fit the container with zero-size guards); a radial spring pulls toward it with k = 40 s^-2, zeta = 0.8, while tangential speed omega = 1.6 * sqrt(120 / r) rad/s keeps tighter orbits faster (Kepler-flavored). Every keystroke re-scores and retargets radii, glided with cubic-bezier(0.22,1,0.36,1) over 450 ms. Scores below 0.25 destabilize: 400 px/s^2 outward acceleration plus a 500 ms fade, then despawn — the despawned pill is set opacity 0 AND visibility hidden so it can never be clicked at a stale position. CRITICAL coordinate frame: pills are DOM nodes anchored at left-1/2 top-1/2, so their per-frame transform must receive OFFSETS from the field center (cos/sin * r), while the canvas draws at absolute coords (center + offset); feeding pills absolute coords doubles the center and piles everything into the bottom-right corner. Enter consumes the highlighted winner: radius decays exp(-t/120ms) into the horizon, scale 1 -> 0.6 and opacity -> 0 over 260 ms, onSelect fires at consumption with a brief accent flash in the glow. Trails are a pruned segment list redrawn onto the main canvas each frame with alpha = 0.3 * exp(-age / 0.24 s) and a hard 1 s max age, so ink provably dissolves within ~1 s wherever motion stops — never an accumulating offscreen canvas with destination-in fades, because 8-bit alpha quantization floors out and leaves a permanent scribble residue. Query confidence (mean of the top-3 scores) breathes the horizon glow radius between 24 and 48 px. Keyboard: ArrowUp/Down cycle the highlight (accent ring on the highlighted pill via token classes, never hex), Enter selects, Esc closes, clicking a pill selects. The rAF loop is ambient while open but fully pauses when the palette is closed or offscreen (IntersectionObserver), and every listener, observer, and the demo auto-type timer is torn down on unmount. All drawn colors (glow, trails, horizon ring) are derived from getComputedStyle CSS tokens (--foreground/--accent/--border) at mount and re-derived live via a MutationObserver on documentElement class changes so both themes render correctly. Under prefers-reduced-motion render a plain static ranked DOM listbox with standard styling and zero canvas. Include an optional autoTypeQuery prop that scripts a character-by-character query on a loop for demos: the first pass starts promptly (first character ~400 ms after mount) so an early default screenshot catches a mid-query state, later cycles clear the query for a brief calm-orbit beat before retyping, and any real user keystroke permanently stops the script. install: npx shadcn add https://design.helpmarq.com/r/event-horizon-command.json ## frost-scrub [loud] Frost Scrub — Scroll-scrubbed defroster — a pinned full-bleed image behind rippled shower glass anneals from heavy frost with chromatic fringing to optical clarity, sealed by a specular sweep. use when: a pinned scroll-scrubbed WebGL shader that anneals a full-bleed image from frosted shower glass to clarity as you scroll; use to reveal a real photo/image, not an abstract or generative scene. props: src?: string // image url; omit for a generated monochrome studio still alt?: string // default: "Image annealing from frosted glass to optical clarity" caption?: string // mono caption on the side rail; default: "SCROLL TO ANNEAL" maxOffset?: number // px of refraction offset at full frost; default: 42 frostRadius?: number // px radius of the 5-tap frost scatter at full frost; default: 10 dispersion?: number // chromatic dispersion step between R/G/B offset scales; default: 0.012 className?: string onProgress?: (p: number) => void // rendered (lerped) progress 0–1, called from the rAF loop deps: (none) behavior: Build a pinned scroll-scrub frosted-glass reveal: a 300vh section holds a position:sticky h-screen pane; behind a rippled shower-glass shader sits a full-bleed image (prop src, else a monochrome studio still — sphere, wall glow, ground shadow, film grain — generated once on an offscreen canvas so the bare component is network-free). Raw WebGL 1, zero deps: one fullscreen triangle-strip quad and a single fragment shader. A 256x256 seamlessly-tiling RGBA noise texture is generated once on the CPU from two octaves of periodic sin-hash value noise (house noise2 on a wrapped lattice); central-difference gradients pack a normal map into RG with ripple height in B, sampled in the shader at gl_FragCoord in CSS px over REPEAT wrap. Refraction offset = normal.xy * pow(1-p, 1.6) * 42px; chromatic dispersion samples R/G/B at offset scales 1.0 / 1.012 / 1.024 so fringing lives on every ripple edge; frost scatter = 5-tap Poisson blur at radius (1-p)*10px; frost also lifts the pane toward white (mix 0.22 at full frost) with ripple-height shading; a white specular band (smoothstep width 0.08 along a diagonal UV axis) crosses the pane exactly once as p runs 0.92 to 1.0. Scroll model: a passive window scroll listener writes target progress (-rect.top / (sectionHeight - viewportHeight), clamped 0-1) to a closure variable; a direct-DOM rAF loop lerps rendered progress toward it at 0.12/frame, snaps and sleeps when |target - current| < 0.001, and wakes on scroll only — no React state anywhere on the hot path, fully reversible in both directions. Overlay side rail in font-mono: vertical-rl caption SCROLL TO ANNEAL, a 1px track filled via scaleY transform, and a zero-padded live percent, all updated by textContent/style writes inside the same loop (plus an optional onProgress callback). If WebGL or shader compile is unavailable, fall back to a plain object-cover img with CSS blur(12px * (1-p)) driven by the same lerp. Under prefers-reduced-motion render a single shader frame at p=1 — clear image with a faint frost vignette confined to the pane edges via an edge-frost uniform — and collapse the section to one viewport with no listeners. install: npx shadcn add https://design.helpmarq.com/r/frost-scrub.json ## knockout-404 [loud] Knockout 404 — 404 numerals rendered as literal absence — destination-out punches the glyphs through a token surface plane to reveal a deep grain void with drifting motes, defined by a bright stencil bevel rim and an inner wall-light glow so the digits read instantly in both themes, edges springing outward near the cursor. use when: a 404/error page (typography, negative space, canvas). props: glyph?: string // the carved numerals; default: "404" message?: string // muted line floating in the punched negative space; default: "This page drifted into the void." primaryLabel?: string // default: "Take me home" primaryHref?: string // default: "/" secondaryLabel?: string // default: "Contact support" secondaryHref?: string // default: "#support" className?: string deps: (none) behavior: Build a full 404 page where the numerals are literal absence: a single full-viewport Canvas 2D layer redrawn with an EXPLICIT FULL CLEAR every frame in this order — (a) void backdrop: a 128px seamless value-noise grain tile precomputed once per theme (recolored in --muted, alpha 0.2, tiled at device resolution) over a deep token base (--background crushed 60% toward black in dark, background mixed 16% toward foreground in light so the void reads CLEARLY dimmer than the surface in BOTH themes — the interior/surface gap is the legibility floor), plus 12 drifting motes (1-2px squares, --muted alpha 0.3, 4px/s on wrapped paths inside the glyph bounding box); (b) surface plane: an offscreen plane canvas refilled solid --surface; (c) carve: destination-out drawImage of an offscreen glyph canvas ('404', Geist Sans 600, font-size min(38vw, 62vh), rasterized after document.fonts.ready, centered at 46% height) so the numerals become holes showing layer (a) — because the plane is refilled fresh each frame, destination-out alpha can never accumulate or quantize; (c2) inner wall-light: a static offscreen glow layer — the undisplaced outline stroked in muted-mixed-45%-toward-foreground with layered shadowBlur (max(14px, 7% of font-size) and 2.4x that) then clipped to the holes via destination-in against the glyph mask, rebuilt per resize/theme — so the cut walls catch light and the digit interiors read as carved depth; (d) rim: the glyph outline restroked at 1.5px in border-mixed-55%-toward-foreground as the crisp definition stroke, plus two ±0.75px offset strokes in border-mixed-80%-toward-foreground (catch-light) and border-mixed-55%-toward-background (inner shadow) tones for an engraved stencil bevel bright enough that 404 reads at a glance. EDGE INTERACTION: threshold a half-res alpha mask of the glyph, Moore-neighbor trace its contours (outer loops and the 0's counter), arc-length resample to ~400 points with two smoothing passes and outward normals (oriented away from ink via mask probe); cursor proximity with gaussian falloff sigma 120px displaces points outward up to 6px along their normals; each point returns on a spring (k=520 s^-2, zeta~0.72, one ~3% overshoot, settle < 400ms) with a forced-settle deadline: cursor influence dies at 600ms idle and a hard deadline at 1400ms snaps displacement and velocity to zero; the displaced rim is restroked from the point list every frame. INTERACTION MODEL: pointermove/pointerdown nudge edges; DOM copy ('This page drifted into the void.') and two CTAs — 'Take me home' (accent primary, rounded-sm, hover accent-hover) and 'Contact support' (ghost bordered, hover border-foreground/40) — float below the punched area, positioned by an OFFSET transform from the container center (never absolute canvas coords), both keyboard-focusable with token-relative accent focus rings; an sr-only h1 keeps semantics. HOUSEKEEPING: all inks parsed from getComputedStyle tokens at mount with a MutationObserver on documentElement class that re-derives colors AND regenerates the grain tile + glyph canvas per theme; canvas sized via explicit style.width/style.height plus a dpr-clamped (2) backing store and setTransform; rAF is direct-DOM with zero React state on the hot path and sleeps when cursor idle > 500ms and all edge springs are under epsilon (motes freeze on sleep, redraw resumes on wake) after a 2.2s ambient intro; IntersectionObserver and document.hidden pause the loop; zero-size containers guarded; every listener, observer, and rAF torn down. REDUCED MOTION: one static carved frame, motes frozen, no edge displacement, no pointer listeners. Demo composes the complete page: top strip with mono logotype and one nav link, carved 404 centered, muted copy line, the two CTAs, and a hairline footer with mono status text 'ERR 404 / route unresolved'. install: npx shadcn add https://design.helpmarq.com/r/knockout-404.json ## prism-drag-split [loud] Prism Drag Split — A frosted prism strip rides the cursor across a headline, magnifying the text beneath it and tearing it into velocity-driven RGB channel slices that snap back with spring overshoot. use when: a frosted prism strip rides the cursor across a headline, magnifying it and tearing it into velocity-driven RGB channel slices that snap back with overshoot; use for a glitchy, chromatic-aberration headline moment, not a soft/organic one. props: text?: string // default: "REFRACTION" stripWidth?: number // prism strip width in px; default: 120 stiffness?: number // spring stiffness (N/m-ish, px units); default: 300 damping?: number // spring damping coefficient; default: 24 mass?: number // spring mass; default: 1 dispersionGain?: number // px of red-channel offset per px/s of strip velocity; default: 0.018 maxDispersion?: number // channel offset clamp in px; default: 14 magnify?: number // scale of the refracted clones inside the strip; default: 1.06 className?: string deps: (none) behavior: A frosted prism strip that rides the cursor across a headline and refracts the text beneath it — spatial, physical refraction, not a global hover filter. Pure DOM, zero deps. Base headline (Geist Sans 600) split into per-char spans with kerning and ligatures disabled so split and continuous layouts register exactly. The prism is an absolutely-positioned 120px strip: overflow-hidden, backdrop-blur-md, bg-background/85 occluding fill, a 1px border (black/10 in light, white/10 in dark) and inset specular shadow (dark or light highlight per theme) per the glass recipe, and a 12px mask fade on both vertical content edges. The refracted-content layer inside the strip carries a fixed near-black tint (bg-[#0a0a0a]/90, independent of the page theme) so the three full-width clones of the headline in pure #ff0000/#00ff00/#0000ff with mix-blend-screen recombine to near-white where aligned in both light and dark mode — screen blending onto a near-white light-mode surface would otherwise wash the channel text to invisible. Each clone is scaled 1.06 about the strip's current center and counter-translated by -stripX so glyphs stay registered with the base — a lens, not a sticker. The strip follows the cursor via a manual spring integrator (stiffness 300, damping 24, mass 1, semi-implicit Euler) in a rAF loop with position and velocity held in refs and styles written via el.style.transform — no React state on the hot path, loop sleeps when settled. Channel dispersion is velocity-proportional: red dx = clamp(v × 0.018, ±14px), blue mirrored, green fixed, so a stationary strip shows converged text and dragging tears it into RGB slices. When the strip clears a glyph's center the rAF loop toggles a class on that span directly, springing it from a 6px offset (signed by travel direction) back to rest over 350ms with cubic-bezier(0.34,1.56,0.64,1) overshoot. On pointerleave the strip springs back to center rest. Under prefers-reduced-motion there is no rAF: the strip pins statically at 38% of the headline with fixed ±6px channel offsets so the frozen dispersion still reads as the concept. install: npx shadcn add https://design.helpmarq.com/r/prism-drag-split.json ## singularity-text [loud] Singularity Text — Headline as a monochrome particle cloud — the cursor is a gravity well that eats letters into an orbital accretion ring, then releases them to spring back into typeset. use when: a hero built from ONLY a headline, no surrounding CTA/copy layout — rendered as a particle cloud the cursor pulls into an orbiting accretion ring and releases to spring back into type; zero deps, use when the headline alone should be the whole scene. props: text?: string // default: "SINGULARITY" gravity?: number // well strength G in px³/s²; accel a = G / max(d², 24²); default: 4_000_000 captureRadius?: number // px — pointer distance inside which the well owns a particle; default: 180 springK?: number // spring stiffness k in s⁻² for the return-home phase; default: 90 damping?: number // damping ratio ζ; < 1 gives visible overshoot as letters reform; default: 0.55 className?: string deps: (none) behavior: Build a hero headline rendered as a monochrome particle cloud on a single DPR-aware Canvas 2D positioned over a visually hidden real h1 (opacity-0 so semantics and a11y survive; under prefers-reduced-motion the canvas is hidden and the static h1 shows instead). On mount, after document.fonts.ready, draw the headline (Geist Sans 600, clamp(3rem,9vw,7rem)) to an offscreen canvas, getImageData, and sample alpha>128 on a 3px stride into one Float32Array of (x,y,vx,vy,hx,hy) capped near 5k particles — no React state anywhere on the hot path, pointer position lives in closure variables on a direct-DOM rAF loop. Physics integrates with dt clamped to 32ms: the cursor is a gravity well with a 180px capture radius; inside it each particle gets radial acceleration a = G/max(d², 24²) with G around 4e6 px³/s² plus a tangential component 0.6x the radial so particles spiral into orbit instead of beelining; particles within 48px of the cursor render 1.6x brighter (via globalAlpha, clamped to 1) as 2-4px velocity-aligned streaks — that band is the accretion ring — over a thin guide circle at r=36 (alpha 0.15) colored from the --muted token. Outside the well or on pointerleave, particles spring home with k=90 s⁻² and ζ=0.55 (underdamped, so letters visibly overshoot as they reform) with 0.92/frame velocity drag. Fill and stroke resolve from the --foreground CSS custom property (read via getComputedStyle(document.documentElement), re-read on a MutationObserver watching <html class> so a theme flip repaints particles in the correct color instead of going invisible on light) with per-particle alpha 0.5-1 keyed to speed, and sleep the rAF loop when every particle is within 0.5px of home and the cursor has left. Pointermove engages the well, pointerleave releases everything, no click behavior. install: npx shadcn add https://design.helpmarq.com/r/singularity-text.json