# Moonarc > Zero-runtime, ClientRouter-safe animation and motion components for Astro: 102 primitives (67 of them load no JavaScript) and, in Pro, 28 sections and 11 GPU effects. Every component states its JavaScript cost, measured from a real build, and its browser support. Primitives are MIT. Install: `npx astro add moonarc`. Import per component: `import Reveal from '@moonarc/core/Reveal'`. Full setup, per package manager and project type, with fixes: https://moonarc.dev/setup.md Runtime for your own scripts: `import { onMount, onPage } from '@moonarc/core/runtime'`. It binds now and after every navigation, never double-binds, and cleans up on astro:before-swap. Do not listen to astro:page-load directly: it does not fire without , and with one it can be lost for a whole page view when a navigation is interrupted after its swap. Shared runtime cost: 1.9 kB raw, 1.0 kB gzip, once per site. Each byte figure in this file says raw (as built, before compression) or gzip. Motion presets: set data-ma-preset="snap|ui|gentle|lively|ambient" on (or any subtree); every component resolves its curve, duration, travel and stagger from it. ## Components - [Accordion](https://moonarc.dev/components/accordion.md): Native
items whose height animates open and closed, with an optional one-at-a-time rule the browser enforces. Zero JavaScript: ::details-content is a grid whose row interpolates from 0fr to 1fr, so height-to-auto costs nothing to measure. Cost: 0 B JS. Support: newly (Chrome 131 · Firefox 143 · Safari 18.4). Intents: accordion, faq accordion, animate details summary, collapsible sections, height auto transition. - [Animated Beam](https://moonarc.dev/components/animated-beam.md): Sends packets of light along curves between nodes. The layout is a preset (satellites around a hub, a row, or a fan into one), computed on the server in percent, so the SVG paths and the slotted nodes share coordinates and nothing is measured. Each beam is one dash, sized as a fraction of its path's on-screen length (computed in CSS from the box's container units), whose offset runs from start to past the end, with a fainter tail behind it. Zero JS. Cost: 0 B JS. Support: widely (Chrome 120 · Firefox 118 · Safari 16). Intents: animated beam between elements, integration diagram animated lines, connecting beams hub and spokes, data flow lines animation, animated connection lines svg. - [Animated Icons](https://moonarc.dev/components/animated-icons.md): Six line icons that morph into a second state: menu to close, plus to close, copy to check, play to pause, sun to moon, and a check that draws itself. Each stroke is its own path moved by translate, rotate, scale, opacity and dash offset, so every pair works in every engine; play/pause also morphs with d: path() where the property exists. The state is a prop or comes from the button around it (aria-pressed, aria-expanded, data-state="done", data-on). Zero JavaScript. Cost: 0 B JS. Support: limited (Chrome 52 · Firefox 97 · not Safari). Intents: animated hamburger icon, menu to x icon animation, play pause morph icon, copy to check icon, sun moon icon animation, animated icons css. - [Animated List](https://moonarc.dev/components/animated-list.md): Shows notifications arriving one at a time: the new one drops in at the top, the older ones are pushed down, and the oldest slides out. Zero JavaScript: in interval mode one registered number runs over the period on every item and the item's time slot decides where it is. Every change is a transition on the preset curve, and no keyframe knows how many items there are. In live mode the host prepends items (newest first) and they grow in through @starting-style while the oldest leaves. Cost: 0 B JS. Support: newly (Chrome 125 · Firefox 129 · Safari 17.5). Intents: animated notification list, notifications one by one, activity feed animation, list items slide in stack, animated list astro, chat messages arriving in sequence. - [Animated Select](https://moonarc.dev/components/animated-select.md): A native select with an animated picker. Where the engine has appearance: base-select, the picker takes the tokens, the options arrive one after another through @starting-style with a delay from sibling-index(), the list leaves on allow-discrete and the checkmark is drawn. Elsewhere it is the native select with the same border and chevron, no animation. No imitated listbox: the keyboard, type-to-select, the value and the accessibility tree are the browser's. Zero JavaScript. Cost: 0 B JS. Support: limited (Chrome 138 · not Firefox · Safari 27). Intents: animated select, custom select css, styled dropdown native, select with animated options, customizable select, dropdown with stagger. - [Arrow Button](https://moonarc.dev/components/arrow-button.md): A button whose arrow slides out on hover as a new one slides in. Two copies of the icon sit in one clipped cell, one translating out while the other comes in on the preset's spring. direction rotates the cell so up, down and left travel the way they point. Hover is read from the containing link or button too; focus draws the same. Zero JavaScript. Cost: 0 B JS. Support: widely (every browser). Intents: arrow button hover, button arrow slides out, cta arrow animation, link arrow animation, arrow that moves on hover. - [Aurora Background](https://moonarc.dev/components/aurora.md): Ambient gradient field: three soft colour fields drifting at three coprime speeds, a slow hue rotation so the colours themselves move, and a film-grain layer stepped at 12 fps. No WebGL, no canvas, no blur filter: every layer is a transform on the compositor. Cost: 0 B JS. Support: widely (every browser). Intents: aurora background, gradient background animation, animated gradient blobs, ambient hero background astro, aurora without webgl. - [Avatar Stack](https://moonarc.dev/components/avatar-stack.md): A row of overlapping avatars with a count chip such as "+2 398". Lazy images or initials, overlapped by a negative margin with a ring in the surface colour. Hover the row and it spreads; hover one and it rises and its name appears above it in a CSS tooltip. Avatars are not tab stops unless they carry an href; the names live in the alt text and the chip has its own screen-reader line. The count is formatted with Intl at build. Zero JavaScript. Cost: 0 B JS. Support: widely (every browser). Intents: avatar stack, avatar group, overlapping avatars, avatar circles hover, joined by avatars, social proof avatars. - [Bar Grow](https://moonarc.dev/components/bar-grow.md): A bar chart whose bars grow from the baseline one after another when it scrolls into view; hovering a bar shows its value. Rendered on the server from the data: each bar is a flex child scaled from 0 to 1 on a per-index delay. Composes Reveal; no script of its own. The accessible name summarises the series. Cost: 0 B JS of its own · uses Reveal + runtime. Support: widely (every browser). Intents: animated bar chart, bars grow on scroll, css bar chart animation, stagger bars chart, tiny bar chart astro. - [Border Beam](https://moonarc.dev/components/border-beam.md): A beam of light travels around the edge of a card. A conic gradient behind two composited masks leaves only the ring; the start angle animates as a registered custom property. Pure CSS, inherits the parent radius. Cost: 0 B JS. Support: newly (Chrome 120 · Firefox 128 · Safari 16.4). Intents: border beam, animated border, glowing card border, light around card edge, moving border gradient. - [Browser Frame](https://moonarc.dev/components/browser-frame.md): A browser window around a screenshot or any content: the three lights, an address bar with a lock, optional tabs with one active. Static, zero JavaScript. The chrome scales with the frame's own width through container query units, and every colour is a theme token, so theme="dark" or "light" pins one look and "auto" follows the page. Cost: 0 B JS. Support: widely (Chrome 105 · Firefox 110 · Safari 16). Intents: browser window mockup, browser frame component, safari frame screenshot, mac window mockup, device frame astro. - [Bubble Text](https://moonarc.dev/components/bubble-text.md): Swells the letter under the cursor to the heaviest weight and lifts it; its neighbours follow at half and a quarter, and everything settles when the pointer leaves. Letters split on the server, neighbours found with :has(). Pure CSS on a variable font. Cost: 0 B JS. Support: widely (Chrome 105 · Firefox 121 · Safari 15.4). Intents: bubble text hover, text weight hover effect, letters swell under cursor, variable font hover, hover text bulge. - [Card Stack](https://moonarc.dev/components/card-stack.md): Cards stick to the top as you scroll and each one shrinks and dims as the next slides over it, as on Apple product pages. Zero JavaScript: sticky positioning plus each card's scale bound to the next card's view timeline. Up to eight cards. Cost: 0 B JS. Support: limited (Chrome 116 · not Firefox · Safari 26). Intents: card stack scroll, sticky stacking cards, stacked cards on scroll, apple style card stack, scroll stack astro. - [Carousel](https://moonarc.dev/components/carousel.md): A scroll-snap strip with previous/next buttons and dot markers that the browser generates and keeps in sync. Zero JavaScript. Touch, momentum, keyboard and snapping are native everywhere; the buttons and dots appear where ::scroll-button() and ::scroll-marker exist. Cost: 0 B JS. Support: limited (Chrome 135 · not Firefox · not Safari). Intents: carousel, slider, scroll snap carousel, image carousel astro, carousel without javascript, testimonial slider. - [Check Draw](https://moonarc.dev/components/check-draw.md): A checkbox whose tick is drawn. A label wraps a native input with appearance: none and an SVG beside it: the box fills on the fast token, then the tick (a path with pathLength 1) runs its dash offset from 1 to 0 on the preset curve. The indeterminate state draws a bar instead. The value submits, required and disabled work, the keyboard is the browser's. Zero JavaScript. Cost: 0 B JS. Support: widely (every browser). Intents: animated checkbox, checkbox with drawn check, checkmark animation, custom checkbox css, indeterminate checkbox, checkbox tick draws itself. - [Circular Text](https://moonarc.dev/components/circular-text.md): A ring of text turning slowly around an icon, a logo, or nothing. SVG text on a circle, justified to the full circumference so the loop has no seam, spun by one compositor rotation. Pure CSS; the centre is the slot. Cost: 0 B JS. Support: widely (every browser). Intents: circular text, text on a circle, rotating badge text, spinning text ring, text around icon. - [Code Tabs](https://moonarc.dev/components/code-tabs.md): A code block with tabs (for example npm, pnpm, bun) and a copy button per panel. Highlighted at build by Astro's own (Shiki) with light and dark themes as CSS variables, so it follows the page theme with no script. The tabs are radio inputs and :has(), so arrow keys and selection are native and the indicator slides on the preset. The only script is CopyButton's, shared; long lines scroll inside the panel. Cost: 0 B JS of its own · uses CopyButton + runtime. Support: widely (Chrome 117 · Firefox 129 · Safari 17.5). Intents: code block with tabs, npm pnpm yarn tabs, install command tabs, code tabs with copy button, shiki code tabs astro. - [Command Palette](https://moonarc.dev/components/command-palette.md): A ⌘K command palette: a native modal dialog with an input and a ranked list of links. ↑ ↓ move, ↵ follows the link through the ClientRouter, Escape closes and focus returns to where it was; results are re-rendered and each arrives through @starting-style on the stagger token. Items come from the server, from a JSON URL fetched once on the first open, or both. Without JavaScript the invoker still opens the dialog and the server-rendered items are plain links. Cost: 3.0 kB raw JS · 1.4 kB gzip · + runtime. Support: newly (Chrome 135 · Firefox 144 · Safari 26.2). Intents: command palette, cmd k search, keyboard search dialog, spotlight search astro, site search modal, command menu. - [Confetti](https://moonarc.dev/components/confetti.md): Fires a burst of paper confetti on load, on a click or on an ma:confetti event. One fixed canvas exists only while pieces are falling. Gravity, drag, launch speed and spread are custom properties declared per preset in the stylesheet: the script reads them and carries no constant. Also callable as confetti() from your own handler. Never fires under reduced motion. Cost: 2.4 kB raw JS · 1.3 kB gzip · + runtime + canvas. Support: widely (every browser). Intents: confetti on click, celebration animation, confetti burst success, party popper button, confetti astro without canvas-confetti, confetti after form submit, trigger confetti from javascript event. - [Copy Button](https://moonarc.dev/components/copy-button.md): A button that copies text to the clipboard: the icon turns into a check, the label says "Copied", and both come back after the ambient duration. The clipboard write is the only script; it sets one attribute, data-state, and writes the outcome into a visually hidden status node rendered after the button, so a screen reader hears it; the icon (AnimatedIcons) and the label faces are CSS. When the clipboard refuses, the button says and announces "Copy failed". Cost: 837 B raw JS · 489 B gzip · + runtime. Support: widely (Chrome 66 · Firefox 63 · Safari 13.1). Intents: copy to clipboard button, copy button with check icon, copy code button, clipboard button astro, copied feedback. - [Count Up](https://moonarc.dev/components/count-up.md): Counts a number up from zero to its value when it scrolls into view, with thousands separators, decimals, prefix and suffix. No script of its own: Reveal supplies the trigger, and the digits are CSS counters driven by a custom property transitioning from 0 to the target. The server HTML already shows the final number. Cost: 0 B JS of its own · uses Reveal + runtime. Support: newly (Chrome 91 · Firefox 128 · Safari 17). Intents: count up, animated number, number counter on scroll, statistics counter, countup astro. - [Countdown Flip](https://moonarc.dev/components/countdown-flip.md): A flip clock counting down to a date: days, hours, minutes, seconds, each a card whose top half folds down over the hinge when the number changes. The only script is one timer a second, set to the moment the next second begins, that writes the digits and stops while the tab is hidden; the flip is CSS. The server renders the time left at build for readers without JavaScript, or the done state when the target has already passed. Cost: 1.1 kB raw JS · 649 B gzip · + runtime. Support: widely (Chrome 55 · Firefox 54 · Safari 13.1). Intents: countdown flip clock, flip clock countdown, launch countdown timer, countdown to date animation, flip counter css. - [Counter Preloader](https://moonarc.dev/components/counter-preloader.md): A preloader that counts from 0 to 100 and then lifts like a curtain, on a fixed layer that never blocks the page: pointer-events none from the first frame, aria-hidden, the page rendered and usable beneath. The number is one registered integer printed through counter-set; the layer then translates off and ends hidden. It runs about two seconds, set by the tokens. once skips it for the rest of the session, on a reload and after every ClientRouter swap. Under reduced motion, or without @property, it never shows. Zero JavaScript. Cost: 0 B JS. Support: newly (Chrome 85 · Firefox 128 · Safari 17.2). Intents: preloader counter, page loader 0 to 100, loading screen counter, intro curtain, site preloader css, studio loading number. - [Cursor](https://moonarc.dev/components/cursor.md): A custom pointer that trails the real one: a dot, a ring that grows over links and buttons, or a label ("View") any element can ask for with data-cursor-label. One fixed element; the script writes the position and a state, CSS transitions the lag, the growth and the pill on the preset curve. Not installed on touch or under reduced motion. Cost: 1021 B raw JS · 574 B gzip · + runtime. Support: widely (every browser). Intents: custom cursor, cursor follower, cursor that says view over images, mouse follower ring, blend mode cursor, custom mouse pointer astro. - [Cursor Grid](https://moonarc.dev/components/cursor-grid.md): A field of cells that light up under the cursor and fade where it has been, with a slow idle sweep when nothing is touched. Zero JavaScript: every cell is an element whose own hover state decays on a transition, so the trail is the browser doing the work. Fills its positioned parent. Cost: 0 B JS. Support: widely (Chrome 105 · Firefox 121 · Safari 15.4). Intents: cursor grid, interactive grid background, hover grid cells, pointer reactive background, hero background reacts to mouse. - [Curtain](https://moonarc.dev/components/curtain.md): A full-viewport wipe between pages: the next page opens through an iris from where you clicked, or through blinds, a shutter, doors, pixels, staggered columns, a diagonal, or a title panel that carries the next page's name. It animates the browser's own root view-transition snapshots with clip-path and mask, on Astro's router; back plays the shape in reverse. The only script is the click point. Cost: 479 B raw JS · 266 B gzip. Support: newly (Chrome 120 · Firefox 144 · Safari 18). Intents: page curtain transition, iris page transition, full screen wipe between pages, view transition root clip-path, blinds page transition, pixel page transition astro. - [Dialog](https://moonarc.dev/components/dialog.md): A native modal that scales in over a blurred backdrop and scales out again, closes on Escape, the close button or a backdrop click, and traps focus, all handled by the browser. Zero JavaScript: the trigger uses the invoker command attribute; the exit is transition-behavior: allow-discrete. Cost: 0 B JS. Support: newly (Chrome 135 · Firefox 144 · Safari 26.2). Intents: modal dialog, animated modal, dialog open close animation, native dialog astro, modal without javascript. - [Dock](https://moonarc.dev/components/dock.md): A macOS-style dock: the tile under the pointer swells, its neighbours swell less, and the row pushes apart to make room. Zero JavaScript: :has() sets one size number on the hovered tile and the four around it, and the tiles transition their size on the preset curve. Keyboard focus magnifies the same way; touch gets a plain row of links. Cost: 0 B JS. Support: widely (Chrome 105 · Firefox 121 · Safari 15.4). Intents: macos dock, dock navigation, magnifying icons on hover, dock menu astro, floating dock bottom of page, icon bar that grows under the cursor. - [Dot Pattern](https://moonarc.dev/components/dot-pattern.md): A field of dots behind content, faded toward the edges, with an optional slow pulse. One tiled radial gradient and a mask; pure CSS. Fills its positioned parent. Cost: 0 B JS. Support: widely (Chrome 120 · Firefox 53 · Safari 15.4). Intents: dot pattern background, dotted background, dot grid, polka dot background css. - [Dotted Map](https://moonarc.dev/components/dotted-map.md): A world map drawn as a grid of dots, with markers that pulse. The land is a 1° bitmask from Natural Earth, drawn on the server as one : each run of land cells in a row is a segment, and a dash pattern of zero-length dashes with round caps turns it into dots: a few hundred segments, not five thousand circles. Markers ping on a delay from the stagger token and carry a title. Zero JS. Cost: 0 B JS. Support: widely (every browser). Intents: dotted world map, world map with markers, dot map svg, map with pulsing locations, regions map astro. - [Drawer](https://moonarc.dev/components/drawer.md): A bottom sheet that slides up over a scrim and can be dragged closed: it follows the finger, and on release springs back or leaves depending on distance and velocity, interruptible mid-flight. A native does the top layer, focus and Escape; the script is only the gesture. Cost: 933 B raw JS · 500 B gzip · + runtime. Support: newly (Chrome 135 · Firefox 144 · Safari 26.2). Intents: bottom sheet, drawer, draggable sheet, swipe to dismiss, mobile drawer astro, vaul alternative. - [Dynamic Island](https://moonarc.dev/components/dynamic-island.md): A black pill that changes shape with its state. auto → auto never animates, so every state declares its width, height and radius in rem; the active one is data-state on the element, set by your script, and a small style block rendered per instance maps each name to its lengths and shows the matching child. The shape transitions on the preset spring; the old content blurs out on the fast token and the new one arrives after it. Zero JavaScript. Cost: 0 B JS. Support: widely (every browser). Intents: dynamic island, morphing pill notification, island state animation, pill that changes shape, live activity pill, expanding notification pill. - [File Tree](https://moonarc.dev/components/file-tree.md): A project tree whose folders open with an animated height, a turning chevron and a folder glyph that tips open; rows can be lit up to say "this is the file you change". Zero JavaScript: folders are native
and the height is ::details-content laid out as a grid row from 0fr to 1fr, the Accordion technique nested as deep as the tree goes. Cost: 0 B JS. Support: newly (Chrome 131 · Firefox 143 · Safari 18.4). Intents: file tree, project structure tree, animated folder tree, directory tree astro, docs file explorer, nested details accordion. - [Filter Grid](https://moonarc.dev/components/filter-grid.md): Filter buttons over a grid of cards: the cards that stay slide to their new places, the ones that go fade out, the ones that return fade in. The motion is a same-document view transition, so the browser measures and moves them. The script toggles aria-pressed and hidden; each card is a transition group only for the duration through view-transition-name: match-element. Without JavaScript every card shows; under reduced motion they change places at once. Cost: 987 B raw JS · 535 B gzip · + runtime + morph. Support: newly (Chrome 137 · Firefox 144 · Safari 18.4). Intents: filterable grid, filter cards with animation, isotope style filter, portfolio filter astro, animated grid reflow, tag filter gallery. - [Footer Reveal](https://moonarc.dev/components/footer-reveal.md): The page content slides up to reveal a footer that is already in place underneath. No timeline and no script: the footer is position: sticky at the bottom of the scrollport with a fixed height, and the content in front carries a higher z-index and its own background, so the only motion is the scroll itself. On a page shorter than the viewport the footer simply sits below the content. Cost: 0 B JS. Support: widely (every browser). Intents: footer reveal on scroll, sticky footer reveal, footer behind content, parallax footer, content slides over footer. - [Glitch Text](https://moonarc.dev/components/glitch-text.md): Splits text into two coloured copies and jumps a few slices sideways for a fraction of a second, every few seconds; the rest of the time the text is clean. Two pseudo-element copies clipped to slices on step-end keyframes, so nothing tweens. Pure CSS, and completely still under reduced motion. Cost: 0 B JS. Support: widely (Chrome 55 · Firefox 54 · Safari 13.1). Intents: glitch text, rgb split text, glitch effect css, cyberpunk text animation, distorted text effect. - [Globe](https://moonarc.dev/components/globe.md): A turning globe of dots that you can drag. The land is the same 1° bitmask DottedMap draws from, sent as a downsampled mask in a JSON block and decoded on the client into rows of dots spread evenly by latitude; each frame projects them orthographically, front side only, depth as alpha, in three batched fills. Markers pulse on the ambient token. Drag has inertia; touch-action keeps the page scrolling. An SVG globe stands in without JavaScript. Cost: 2.8 kB raw JS · 1.4 kB gzip · + runtime + canvas. Support: widely (every browser). Intents: 3d globe, rotating globe with markers, cobe alternative, dotted globe canvas, interactive globe astro, draggable globe. - [Glyph Field](https://moonarc.dev/components/glyph-field.md): A field of braille dots that reads as a flowing contour map: two waves cross it, the colour turns along a sunset arc, and the cursor carves a trail that decays one dot at a time. No canvas and no frame loop: every cell is an element whose glyph is a CSS counter on a registered integer, the contours are noise computed on the server, and the waves are one stepping animation per row. ASCII and block sets are one prop away. Fills its positioned parent. Cost: 0 B JS. Support: newly (Chrome 125 · Firefox 128 · Safari 17.2). Intents: braille dot field, dot matrix background, ascii hero background, glyph field, ascii art background reacts to cursor, motion.dev style ascii hero, character field animation, terminal texture background, contour map background. - [Gradient Text](https://moonarc.dev/components/gradient-text.md): A gradient fill drifting slowly through the text with no seam at the loop point. Only the background position moves. Pure CSS; works on any inline or block text. Cost: 0 B JS. Support: widely (Chrome 120 · Firefox 49 · Safari 14). Intents: gradient text, animated gradient text, rainbow text, color shifting headline. - [Grid Pattern](https://moonarc.dev/components/grid-pattern.md): A hairline grid behind content, faded toward the edges, optionally drifting one cell at a time. Two repeating gradients and a mask; pure CSS. Fills its positioned parent. Cost: 0 B JS. Support: widely (Chrome 120 · Firefox 53 · Safari 15.4). Intents: grid background, grid pattern background, blueprint grid, faded grid lines background. - [Highlight Marker](https://moonarc.dev/components/highlight-marker.md): A highlighter sweeps across the phrases you marked, one after another, when the sentence scrolls into view. Each phrase is a real whose background grows from the left; wrapped lines are painted as separate strokes. Composes Reveal; no script of its own. Cost: 0 B JS of its own · uses Reveal + runtime. Support: widely (every browser). Intents: highlight text on scroll, marker highlight animation, highlighter sweep text, animated text highlight, mark animation css. - [Horizontal Scroll](https://moonarc.dev/components/horizontal-scroll.md): A strip of items slides sideways while the page scrolls down and the section stays pinned. Zero JavaScript: a sticky viewport and a translate bound to the section's view timeline. Where scroll timelines are missing it is a normal horizontally scrollable strip. Cost: 0 B JS. Support: limited (Chrome 115 · not Firefox · Safari 26). Intents: horizontal scroll section, scroll sideways on vertical scroll, pinned horizontal scroll, horizontal scrolling gallery astro. - [Hover Image Links](https://moonarc.dev/components/hover-image-links.md): A list of project links: hovering one floats its image beside the pointer, leaning the way the pointer moves, while the other links step back. One floating box per list with every image server-rendered in it; the script writes two lengths, a lean and an index, and CSS gives the follow its lag on the fast token. Keyboard focus and reduced motion show the image at a fixed spot; touch gets the list. Cost: 597 B raw JS · 359 B gzip · + runtime. Support: widely (Chrome 105 · Firefox 121 · Safari 15.4). Intents: hover image links, project list hover image follows cursor, link list with floating image, portfolio index hover preview, blog list hover cover, image reveal on link hover astro. - [Hover Video](https://moonarc.dev/components/hover-video.md): A poster card that plays a muted clip while the pointer or focus is on it and rewinds when it leaves. The card is a link, the video decoration behind it with preload="none", so nothing loads until a hover; coarse pointers get a play/pause button, reduced motion never autoplays. The script is play(), pause() and a rewind. Cost: 684 B raw JS · 364 B gzip · + runtime. Support: widely (every browser). Intents: play video on hover, hover to play preview, video card hover, muted autoplay on hover astro, portfolio video thumbnails, work grid video preview. - [Image Compare](https://moonarc.dev/components/image-compare.md): Compares a before and an after image with a line you drag between them. A native range input lies over the box, invisible, so dragging, clicking to jump, the arrow keys, touch and the screen reader are the browser's; the script writes its value to one custom property and the after image is clipped to it. Held, it follows with no lag; stepped, it glides on the fast token. Cost: 205 B raw JS · 177 B gzip · + runtime. Support: newly (Chrome 124 · Firefox 121 · Safari 16.5). Intents: before after slider, image comparison slider, compare two images drag, before after image astro, juxtapose images, split image reveal. - [Image Trail](https://moonarc.dev/components/image-trail.md): Small images pop up along the pointer's path and fade behind it. The images are a server-rendered pool of lazy elements; every `threshold` px the script positions the next one and restarts its keyframes, so nothing is created on move. The pop and the fade are CSS on the preset curve, the lifetime a duration token. On touch and under reduced motion the first image simply rests in the centre, under the slotted content. Cost: 872 B raw JS · 504 B gzip · + runtime. Support: widely (Chrome 105 · Firefox 110 · Safari 16). Intents: image trail on cursor, images follow mouse, photo trail hover effect, cursor image trail astro, hover image reveal along mouse path. - [Lightbox](https://moonarc.dev/components/lightbox.md): A thumbnail gallery whose images open full size: the image grows out of its own thumbnail on a same-document view transition and returns to it on close, and ← → move through the set. Built on Dialog morph: the dialog is native (Escape, the backdrop where closedby is supported, the close button, the focus trap), the growth is lib/morph, the caption and the count are a polite live region, and without JavaScript each thumbnail is a link to the full file. Cost: 972 B raw JS · 501 B gzip · + Dialog morph + runtime + morph. Support: newly (Chrome 111 · Firefox 144 · Safari 18). Intents: lightbox, image gallery lightbox, image zoom on click, photo grows from thumbnail, gallery modal astro, shared element transition image. - [Link Preview](https://moonarc.dev/components/link-preview.md): A link that shows a small card (image, title, one line, domain) after a moment on hover or focus, above everything, flipping when there is no room. The card is a manual popover anchored to the link; the script only shows and hides it, the wait is a CSS transition-delay on a duration token, and everything on the card is a prop at build time, so nothing is fetched. Touch gets the link alone. Cost: 671 B raw JS · 405 B gzip · + runtime. Support: newly (Chrome 125 · Firefox 147 · Safari 26). Intents: link preview on hover, hover card link, link hover card with image, link preview astro, hovercard, preview tooltip for links. - [Liquid Glass](https://moonarc.dev/components/liquid-glass.md): A glass pane that blurs and tints whatever is behind it. Every engine: backdrop blur and saturation, a specular rim, a tint from the tokens, a sheen that crosses on hover. The refraction at the rim is an SVG displacement map on its own backdrop-filter layer, built on the server from strength and edge and stretched to the box by the filter, so it works at any size with no measuring. Chromium bends the backdrop; Firefox and WebKit paint nothing on that layer and show the same glass without the bend. Zero JavaScript. Cost: 0 B JS. Support: limited (Chrome 76 · not Firefox · not Safari). Intents: liquid glass, glassmorphism css, frosted glass panel, glass card with refraction, apple liquid glass effect, backdrop blur card. - [Magnetic](https://moonarc.dev/components/magnetic.md): A button or icon is pulled toward the cursor while it is nearby and springs back when it leaves. An invisible field around the child lets clicks through to its neighbours; one pointermove listener on the document measures the pointer against it, and the pull is CSS translate on the active preset's spring. No pull under reduced motion, read on every move. Cost: 619 B raw JS · 391 B gzip · + runtime. Support: widely (every browser). Intents: magnetic button, button follows cursor, magnetic hover effect, cursor attraction button. - [Marquee](https://moonarc.dev/components/marquee.md): Infinite scrolling strip for logos, quotes or tags in any direction. The content is rendered twice (or repeat times) and the track moves by exactly one copy, so there is never a seam; a copy narrower than the strip stretches to fill it, so a short list never leaves a blank band. Pauses on hover; becomes a static scrollable strip under reduced motion. Pure CSS. Cost: 0 B JS. Support: widely (Chrome 120 · Firefox 53 · Safari 15.4). Intents: logo marquee, infinite scroll strip, logo loop, ticker, scrolling logos astro. - [Meteors](https://moonarc.dev/components/meteors.md): Streaks falling diagonally across a twinkling sky. Each meteor is one element with a bright head, rotated to its angle and sent along its own axis; start, delay, length and pace come from a seeded generator on the server, so the same seed always draws the same sky. Stars are two tiled gradient layers blinking in alternation. Zero JS; fills its positioned parent. Cost: 0 B JS. Support: widely (Chrome 105 · Firefox 110 · Safari 16). Intents: meteor shower background, falling stars animation, shooting stars css, meteors effect hero, starry night background. - [Noise](https://moonarc.dev/components/noise.md): Film grain over a gradient or image, blended and flickering at 12 fps. One SVG turbulence tile as a background whose translate steps; pure CSS, no canvas. Fills its positioned parent. Cost: 0 B JS. Support: widely (every browser). Intents: noise overlay, film grain effect, grain texture css, noisy background. - [Number Flow](https://moonarc.dev/components/number-flow.md): A number whose digits roll to the new value when it changes. Each column slides to its digit on the preset spring, thousands separators stay put, and leading columns collapse when the number gets shorter. The value is one custom property your code writes; every column derives its digit from it with round() and mod(). No script of its own. Cost: 0 B JS. Support: newly (Chrome 125 · Firefox 118 · Safari 15.4). Intents: number flow, rolling digits, odometer number animation, animated counter on change, slot machine digits css, number transition. - [Orb](https://moonarc.dev/components/orb.md): A sphere of light that breathes and slowly turns its colour. Three radial gradients on one element, soft at their edges so no blur filter is ever painted; the breath is a scale on the compositor and the colour shift is one registered number scaled to a drift angle every gradient adds to its hue. A conic highlight turns around the rim. Zero JS; centred in its positioned parent. Cost: 0 B JS. Support: newly (Chrome 85 · Firefox 128 · Safari 16.4). Intents: glowing orb background, breathing orb, ai orb animation, gradient sphere hero, siri orb css. - [Orbiting Circles](https://moonarc.dev/components/orbiting-circles.md): The children orbit the centre of their parent and stay upright. One transform animation per item (rotate, translate out, rotate back) from its start angle to a full turn, on the compositor, no wrapper. Start angles come from :nth-child, the count from :has(). Two instances at two radii are two rings; `reverse` sends one the other way. Zero JS. Cost: 0 B JS. Support: widely (Chrome 105 · Firefox 121 · Safari 15.4). Intents: orbiting icons, icons rotating around logo, orbit animation css, planets orbit integration logos, circular orbit icons astro. - [OTP Input](https://moonarc.dev/components/otp-input.md): A one-time code in cells, from one native input. Paste, SMS autofill, screen readers and Backspace only work in the single-input pattern, so the cells are drawn under the field and a monospace font with a computed letter-spacing puts each glyph in the middle of its cell. Full and valid, the check draws itself; :user-invalid tints the cells only after the reader has been there. Zero JavaScript. Cost: 0 B JS. Support: widely (Chrome 119 · Firefox 121 · Safari 16.5). Intents: otp input, one time code input, verification code boxes, pin input, sms code input, 6 digit code input css. - [Page Transition](https://moonarc.dev/components/page-transition.md): Animates a named region between pages: rise, zoom, wipe, scope, fade, slide, or the browser's own shared-element morph. Zero JavaScript of its own: Astro's drives view transitions, and the presets are keyframes on the active motion preset's curve. Cost: 0 B JS. Support: newly (Chrome 111 · Firefox 144 · Safari 18). Intents: page transition, view transitions astro, animate between pages, shared element transition, transition:name preset, route transition. - [Parallax](https://moonarc.dev/components/parallax.md): An element drifts at its own speed as it crosses the viewport, exactly in step with the scroll. Zero JavaScript: a translate bound to the element's own view timeline. Stack a few with different speeds for depth. Cost: 0 B JS. Support: limited (Chrome 115 · not Firefox · Safari 26). Intents: parallax, parallax scroll effect, background moves slower than foreground, scroll-driven parallax astro, parallax without javascript. - [Particles](https://moonarc.dev/components/particles.md): A field of drifting dots that part around the cursor, on a canvas that draws only while on screen in a visible tab. The count follows the area (capped), every constant is a custom property declared per preset, the colours are the theme's and are re-read when it changes. Without JavaScript a still dot pattern in CSS stands in; under reduced motion one frame is drawn. Cost: 1.6 kB raw JS · 960 B gzip · + runtime + canvas. Support: widely (every browser). Intents: particles background, floating dots interactive, particles.js alternative, dots avoid cursor, constellation background canvas. - [Persist Player](https://moonarc.dev/components/persist-player.md): An audio player that keeps playing while you navigate: the same