{
  "$schema": "https://ui.shadcn.com/schema/registry.json",
  "name": "moonarc",
  "homepage": "https://moonarc.dev",
  "items": [
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "accordion",
      "type": "registry:component",
      "title": "Accordion",
      "description": "Native <details> 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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "accordion",
          "faq accordion",
          "animate details summary",
          "collapsible sections",
          "height auto transition"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "details-content",
            "allow-discrete",
            "details-name"
          ],
          "fallback": "items open and close instantly",
          "line": "Chrome 131 · Firefox 143 · Safari 18.4"
        },
        "readout": "<Accordion exclusive>"
      },
      "files": [
        {
          "path": "components/moonarc/Accordion.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "animated-beam",
      "type": "registry:component",
      "title": "Animated Beam",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "background"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "animated beam between elements",
          "integration diagram animated lines",
          "connecting beams hub and spokes",
          "data flow lines animation",
          "animated connection lines svg"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "container-units",
            "css-exp"
          ],
          "fallback": "without container units or hypot() the lines draw solid in the packet colour and nothing travels",
          "line": "Chrome 120 · Firefox 118 · Safari 16"
        },
        "readout": "<AnimatedBeam layout=\"hub\" nodes={5}>"
      },
      "files": [
        {
          "path": "components/moonarc/AnimatedBeam.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "animated-icons",
      "type": "registry:component",
      "title": "Animated Icons",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "animated hamburger icon",
          "menu to x icon animation",
          "play pause morph icon",
          "copy to check icon",
          "sun moon icon animation",
          "animated icons css"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "limited",
          "needs": [
            "d-path"
          ],
          "fallback": "play ↔ pause cross-fades instead of morphing where d: path() is not a CSS property (Safari)",
          "line": "Chrome 52 · Firefox 97 · not Safari"
        },
        "readout": "<AnimatedIcons icon=\"menu\">"
      },
      "files": [
        {
          "path": "components/moonarc/AnimatedIcons.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "animated-list",
      "type": "registry:component",
      "title": "Animated List",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "animated notification list",
          "notifications one by one",
          "activity feed animation",
          "list items slide in stack",
          "animated list astro",
          "chat messages arriving in sequence"
        ],
        "trigger": [
          "always",
          "load"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "property",
            "css-math",
            "has",
            "starting-style",
            "allow-discrete",
            "grid-rows-animation"
          ],
          "fallback": "without round() or registered properties the interval mode shows the first items still; live items appear at once",
          "line": "Chrome 125 · Firefox 129 · Safari 17.5"
        },
        "readout": "<AnimatedList interval=\"base\" max={4}>"
      },
      "files": [
        {
          "path": "components/moonarc/AnimatedList.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "animated-select",
      "type": "registry:component",
      "title": "Animated Select",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "animated select",
          "custom select css",
          "styled dropdown native",
          "select with animated options",
          "customizable select",
          "dropdown with stagger"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "limited",
          "needs": [
            "base-select",
            "picker",
            "sibling-index",
            "starting-style",
            "allow-discrete"
          ],
          "fallback": "Firefox, and Safari before 27, show the native select styled with the token border and the chevron; the picker is the platform's and nothing animates",
          "line": "Chrome 138 · not Firefox · Safari 27"
        },
        "readout": "<AnimatedSelect name=\"model\" options={models}>"
      },
      "files": [
        {
          "path": "components/moonarc/AnimatedSelect.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "arrow-button",
      "type": "registry:component",
      "title": "Arrow Button",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "arrow button hover",
          "button arrow slides out",
          "cta arrow animation",
          "link arrow animation",
          "arrow that moves on hover"
        ],
        "trigger": [
          "hover"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<ArrowButton direction=\"right\">"
      },
      "files": [
        {
          "path": "components/moonarc/ArrowButton.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "aurora",
      "type": "registry:component",
      "title": "Aurora Background",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "background"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "aurora background",
          "gradient background animation",
          "animated gradient blobs",
          "ambient hero background astro",
          "aurora without webgl"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<Aurora duration={22}>"
      },
      "files": [
        {
          "path": "components/moonarc/Aurora.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "avatar-stack",
      "type": "registry:component",
      "title": "Avatar Stack",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "avatar stack",
          "avatar group",
          "overlapping avatars",
          "avatar circles hover",
          "joined by avatars",
          "social proof avatars"
        ],
        "trigger": [
          "hover"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<AvatarStack people={people} max={5} count={2403}>"
      },
      "files": [
        {
          "path": "components/moonarc/AvatarStack.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "bar-grow",
      "type": "registry:component",
      "title": "Bar Grow",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/reveal.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets. Add <script is:inline>(f=>addEventListener('astro:after-swap',f,f()))(()=>document.documentElement.dataset.maJs=1)</script> to your <head> as well, so entrances can hide content only when JS runs.",
      "categories": [
        "data"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 3043,
        "intents": [
          "animated bar chart",
          "bars grow on scroll",
          "css bar chart animation",
          "stagger bars chart",
          "tiny bar chart astro"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<BarGrow data={[…]}>"
      },
      "files": [
        {
          "path": "components/moonarc/BarGrow.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "border-beam",
      "type": "registry:component",
      "title": "Border Beam",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "background"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "border beam",
          "animated border",
          "glowing card border",
          "light around card edge",
          "moving border gradient"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "property",
            "mask-image"
          ],
          "fallback": "the beam holds still at its start angle",
          "line": "Chrome 120 · Firefox 128 · Safari 16.4"
        },
        "readout": "<BorderBeam duration={6}>"
      },
      "files": [
        {
          "path": "components/moonarc/BorderBeam.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "browser-frame",
      "type": "registry:component",
      "title": "Browser Frame",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "browser window mockup",
          "browser frame component",
          "safari frame screenshot",
          "mac window mockup",
          "device frame astro"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "container-units"
          ],
          "line": "Chrome 105 · Firefox 110 · Safari 16"
        },
        "readout": "<BrowserFrame url=\"https://moonarc.dev\">"
      },
      "files": [
        {
          "path": "components/moonarc/BrowserFrame.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "bubble-text",
      "type": "registry:component",
      "title": "Bubble Text",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "text"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "bubble text hover",
          "text weight hover effect",
          "letters swell under cursor",
          "variable font hover",
          "hover text bulge"
        ],
        "trigger": [
          "hover"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "font-variation",
            "has"
          ],
          "line": "Chrome 105 · Firefox 121 · Safari 15.4"
        },
        "readout": "<BubbleText min={400} max={800}>"
      },
      "files": [
        {
          "path": "components/moonarc/BubbleText.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "card-stack",
      "type": "registry:component",
      "title": "Card Stack",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "scroll"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "card stack scroll",
          "sticky stacking cards",
          "stacked cards on scroll",
          "apple style card stack",
          "scroll stack astro"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "limited",
          "needs": [
            "scroll-timeline",
            "timeline-scope"
          ],
          "fallback": "cards still stack with sticky positioning, without the shrink (Firefox, Chrome 115)",
          "line": "Chrome 116 · not Firefox · Safari 26"
        },
        "readout": "<CardStack scale={0.92}>"
      },
      "files": [
        {
          "path": "components/moonarc/CardStack.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "carousel",
      "type": "registry:component",
      "title": "Carousel",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "carousel",
          "slider",
          "scroll snap carousel",
          "image carousel astro",
          "carousel without javascript",
          "testimonial slider"
        ],
        "trigger": [
          "click",
          "pointer"
        ],
        "support": {
          "baseline": "limited",
          "needs": [
            "scroll-snap",
            "scroll-marker"
          ],
          "fallback": "a swipeable, keyboard-scrollable snap strip without buttons or dots (Firefox, Safari)",
          "line": "Chrome 135 · not Firefox · not Safari"
        },
        "readout": "<Carousel perView={3}>"
      },
      "files": [
        {
          "path": "components/moonarc/Carousel.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "check-draw",
      "type": "registry:component",
      "title": "Check Draw",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "animated checkbox",
          "checkbox with drawn check",
          "checkmark animation",
          "custom checkbox css",
          "indeterminate checkbox",
          "checkbox tick draws itself"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<CheckDraw name=\"terms\" label=\"I agree\" required>"
      },
      "files": [
        {
          "path": "components/moonarc/CheckDraw.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "circular-text",
      "type": "registry:component",
      "title": "Circular Text",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "text"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "circular text",
          "text on a circle",
          "rotating badge text",
          "spinning text ring",
          "text around icon"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<CircularText duration={18}>"
      },
      "files": [
        {
          "path": "components/moonarc/CircularText.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "code-tabs",
      "type": "registry:component",
      "title": "Code Tabs",
      "description": "A code block with tabs (for example npm, pnpm, bun) and a copy button per panel. Highlighted at build by Astro's own <Code> (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.",
      "registryDependencies": [
        "https://moonarc.dev/r/contrast.json",
        "https://moonarc.dev/r/copy-button.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 2559,
        "intents": [
          "code block with tabs",
          "npm pnpm yarn tabs",
          "install command tabs",
          "code tabs with copy button",
          "shiki code tabs astro"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "has",
            "starting-style",
            "clipboard"
          ],
          "fallback": "panels switch without the fade",
          "line": "Chrome 117 · Firefox 129 · Safari 17.5"
        },
        "readout": "<CodeTabs id=\"install\" tabs={[…]}>"
      },
      "files": [
        {
          "path": "components/moonarc/CodeTabs.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "command-palette",
      "type": "registry:component",
      "title": "Command Palette",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/dialog.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "C",
        "pro": false,
        "jsBytes": 3048,
        "jsBytesWithShared": 4770,
        "intents": [
          "command palette",
          "cmd k search",
          "keyboard search dialog",
          "spotlight search astro",
          "site search modal",
          "command menu"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "dialog",
            "command",
            "starting-style"
          ],
          "fallback": "without invoker commands the trigger is the script's (or polyfill's); without @starting-style results appear at once; without closedby (Safari) the script closes it on a tap on the backdrop",
          "line": "Chrome 135 · Firefox 144 · Safari 26.2"
        },
        "readout": "<CommandPalette hotkey=\"k\">"
      },
      "files": [
        {
          "path": "components/moonarc/CommandPalette.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "confetti",
      "type": "registry:component",
      "title": "Confetti",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/confetti-fn.json",
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/canvas.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "pointer"
      ],
      "meta": {
        "tier": "C",
        "pro": false,
        "jsBytes": 2506,
        "jsBytesWithShared": 5919,
        "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"
        ],
        "trigger": [
          "load",
          "click"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<Confetti trigger=\"click\" for=\"#celebrate\">"
      },
      "files": [
        {
          "path": "components/moonarc/Confetti.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "copy-button",
      "type": "registry:component",
      "title": "Copy Button",
      "description": "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\".",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/animated-icons.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 837,
        "jsBytesWithShared": 2559,
        "intents": [
          "copy to clipboard button",
          "copy button with check icon",
          "copy code button",
          "clipboard button astro",
          "copied feedback"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "clipboard"
          ],
          "fallback": "the error face, because the clipboard API needs a secure context",
          "line": "Chrome 66 · Firefox 63 · Safari 13.1"
        },
        "readout": "<CopyButton value=\"npx astro add moonarc\">"
      },
      "files": [
        {
          "path": "components/moonarc/CopyButton.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "count-up",
      "type": "registry:component",
      "title": "Count Up",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/reveal.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets. Add <script is:inline>(f=>addEventListener('astro:after-swap',f,f()))(()=>document.documentElement.dataset.maJs=1)</script> to your <head> as well, so entrances can hide content only when JS runs.",
      "categories": [
        "text"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 3043,
        "intents": [
          "count up",
          "animated number",
          "number counter on scroll",
          "statistics counter",
          "countup astro"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "property",
            "counter-style"
          ],
          "fallback": "the final number, shown at once",
          "line": "Chrome 91 · Firefox 128 · Safari 17"
        },
        "readout": "<CountUp to={2847}>"
      },
      "files": [
        {
          "path": "components/moonarc/CountUp.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "countdown-flip",
      "type": "registry:component",
      "title": "Countdown Flip",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "data"
      ],
      "meta": {
        "tier": "C",
        "pro": false,
        "jsBytes": 1157,
        "jsBytesWithShared": 2879,
        "intents": [
          "countdown flip clock",
          "flip clock countdown",
          "launch countdown timer",
          "countdown to date animation",
          "flip counter css"
        ],
        "trigger": [
          "load"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "clip-path"
          ],
          "line": "Chrome 55 · Firefox 54 · Safari 13.1"
        },
        "readout": "<CountdownFlip to={launch} done=\"Launched.\">"
      },
      "files": [
        {
          "path": "components/moonarc/CountdownFlip.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "counter-preloader",
      "type": "registry:component",
      "title": "Counter Preloader",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "loading"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "preloader counter",
          "page loader 0 to 100",
          "loading screen counter",
          "intro curtain",
          "site preloader css",
          "studio loading number"
        ],
        "trigger": [
          "load"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "property",
            "counter-set"
          ],
          "fallback": "without @property the layer is never visible (the registered probe that reveals it does not exist) and the page shows at once",
          "line": "Chrome 85 · Firefox 128 · Safari 17.2"
        },
        "readout": "<CounterPreloader once>"
      },
      "files": [
        {
          "path": "components/moonarc/CounterPreloader.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "cursor",
      "type": "registry:component",
      "title": "Cursor",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "pointer"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 1021,
        "jsBytesWithShared": 2743,
        "intents": [
          "custom cursor",
          "cursor follower",
          "cursor that says view over images",
          "mouse follower ring",
          "blend mode cursor",
          "custom mouse pointer astro"
        ],
        "trigger": [
          "pointer"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<Cursor mode=\"label\">"
      },
      "files": [
        {
          "path": "components/moonarc/Cursor.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "cursor-grid",
      "type": "registry:component",
      "title": "Cursor Grid",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "pointer"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "cursor grid",
          "interactive grid background",
          "hover grid cells",
          "pointer reactive background",
          "hero background reacts to mouse"
        ],
        "trigger": [
          "pointer",
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "has"
          ],
          "line": "Chrome 105 · Firefox 121 · Safari 15.4"
        },
        "readout": "<CursorGrid cols={32} rows={16}>"
      },
      "files": [
        {
          "path": "components/moonarc/CursorGrid.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "curtain",
      "type": "registry:component",
      "title": "Curtain",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "transition"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 479,
        "jsBytesWithShared": 571,
        "intents": [
          "page curtain transition",
          "iris page transition",
          "full screen wipe between pages",
          "view transition root clip-path",
          "blinds page transition",
          "pixel page transition astro"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "view-transitions",
            "has",
            "clip-path",
            "mask-image",
            "mask-composite",
            "property"
          ],
          "fallback": "an instant swap between pages",
          "line": "Chrome 120 · Firefox 144 · Safari 18"
        },
        "readout": "<Curtain mode=\"iris\">"
      },
      "files": [
        {
          "path": "components/moonarc/Curtain.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "dialog",
      "type": "registry:component",
      "title": "Dialog",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/morph.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "modal dialog",
          "animated modal",
          "dialog open close animation",
          "native dialog astro",
          "modal without javascript"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "command",
            "starting-style",
            "allow-discrete",
            "dialog"
          ],
          "fallback": "without invoker commands the trigger needs polyfill (an inline handler of 403 B raw); without @starting-style and allow-discrete the modal opens and closes without motion; without closedby (Safari) a backdrop click does nothing, and Escape and the close button still close it",
          "line": "Chrome 135 · Firefox 144 · Safari 26.2"
        },
        "readout": "<Dialog command=\"show-modal\">"
      },
      "files": [
        {
          "path": "components/moonarc/Dialog.astro",
          "type": "registry:component"
        },
        {
          "path": "components/moonarc/internal/DialogMorph.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "dock",
      "type": "registry:component",
      "title": "Dock",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "macos dock",
          "dock navigation",
          "magnifying icons on hover",
          "dock menu astro",
          "floating dock bottom of page",
          "icon bar that grows under the cursor"
        ],
        "trigger": [
          "hover"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "has"
          ],
          "fallback": "without :has() the tiles keep their size and the labels stay hidden",
          "line": "Chrome 105 · Firefox 121 · Safari 15.4"
        },
        "readout": "<Dock magnify={1.6}>"
      },
      "files": [
        {
          "path": "components/moonarc/Dock.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "dot-pattern",
      "type": "registry:component",
      "title": "Dot Pattern",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "background"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "dot pattern background",
          "dotted background",
          "dot grid",
          "polka dot background css"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "mask-image"
          ],
          "line": "Chrome 120 · Firefox 53 · Safari 15.4"
        },
        "readout": "<DotPattern size={20}>"
      },
      "files": [
        {
          "path": "components/moonarc/DotPattern.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "dotted-map",
      "type": "registry:component",
      "title": "Dotted Map",
      "description": "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 <path>: 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.",
      "registryDependencies": [
        "https://moonarc.dev/r/land.json",
        "https://moonarc.dev/r/geo.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "background"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "dotted world map",
          "world map with markers",
          "dot map svg",
          "map with pulsing locations",
          "regions map astro"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<DottedMap markers={[…]} density=\"medium\">"
      },
      "files": [
        {
          "path": "components/moonarc/DottedMap.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "drawer",
      "type": "registry:component",
      "title": "Drawer",
      "description": "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 <dialog> does the top layer, focus and Escape; the script is only the gesture.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "C",
        "pro": false,
        "jsBytes": 933,
        "jsBytesWithShared": 2655,
        "intents": [
          "bottom sheet",
          "drawer",
          "draggable sheet",
          "swipe to dismiss",
          "mobile drawer astro",
          "vaul alternative"
        ],
        "trigger": [
          "click",
          "pointer"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "command",
            "starting-style",
            "allow-discrete",
            "dialog"
          ],
          "fallback": "without invoker commands the trigger needs polyfill; without closedby (Safari) a tap on the scrim does nothing, and the drag and Escape still close the sheet",
          "line": "Chrome 135 · Firefox 144 · Safari 26.2"
        },
        "readout": "<Drawer threshold={0.35}>"
      },
      "files": [
        {
          "path": "components/moonarc/Drawer.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "dynamic-island",
      "type": "registry:component",
      "title": "Dynamic Island",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "dynamic island",
          "morphing pill notification",
          "island state animation",
          "pill that changes shape",
          "live activity pill",
          "expanding notification pill"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<DynamicIsland states={states} state=\"music\">"
      },
      "files": [
        {
          "path": "components/moonarc/DynamicIsland.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "file-tree",
      "type": "registry:component",
      "title": "File Tree",
      "description": "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 <details> 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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "file tree",
          "project structure tree",
          "animated folder tree",
          "directory tree astro",
          "docs file explorer",
          "nested details accordion"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "details-content",
            "grid-rows-animation"
          ],
          "fallback": "folders open at once",
          "line": "Chrome 131 · Firefox 143 · Safari 18.4"
        },
        "readout": "<FileTree open={[\"src\"]}>"
      },
      "files": [
        {
          "path": "components/moonarc/FileTree.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "filter-grid",
      "type": "registry:component",
      "title": "Filter Grid",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/morph.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 987,
        "jsBytesWithShared": 3508,
        "intents": [
          "filterable grid",
          "filter cards with animation",
          "isotope style filter",
          "portfolio filter astro",
          "animated grid reflow",
          "tag filter gallery"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "view-transitions",
            "match-element"
          ],
          "fallback": "without view transitions the cards change places at once; without match-element the grid cross-fades and no card slides",
          "line": "Chrome 137 · Firefox 144 · Safari 18.4"
        },
        "readout": "<FilterGrid multi>"
      },
      "files": [
        {
          "path": "components/moonarc/FilterGrid.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "footer-reveal",
      "type": "registry:component",
      "title": "Footer Reveal",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "scroll"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "footer reveal on scroll",
          "sticky footer reveal",
          "footer behind content",
          "parallax footer",
          "content slides over footer"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<FooterReveal height=\"20rem\">"
      },
      "files": [
        {
          "path": "components/moonarc/FooterReveal.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "glitch-text",
      "type": "registry:component",
      "title": "Glitch Text",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "text"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "glitch text",
          "rgb split text",
          "glitch effect css",
          "cyberpunk text animation",
          "distorted text effect"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "clip-path"
          ],
          "line": "Chrome 55 · Firefox 54 · Safari 13.1"
        },
        "readout": "<GlitchText period={4}>"
      },
      "files": [
        {
          "path": "components/moonarc/GlitchText.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "globe",
      "type": "registry:component",
      "title": "Globe",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/land.json",
        "https://moonarc.dev/r/geo.json",
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/canvas.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "background"
      ],
      "meta": {
        "tier": "C",
        "pro": false,
        "jsBytes": 2837,
        "jsBytesWithShared": 6250,
        "intents": [
          "3d globe",
          "rotating globe with markers",
          "cobe alternative",
          "dotted globe canvas",
          "interactive globe astro",
          "draggable globe"
        ],
        "trigger": [
          "always",
          "pointer"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<Globe markers={[…]} speed={8} draggable>"
      },
      "files": [
        {
          "path": "components/moonarc/Globe.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "glyph-field",
      "type": "registry:component",
      "title": "Glyph Field",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "pointer"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "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"
        ],
        "trigger": [
          "pointer",
          "always"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "property",
            "css-math",
            "counter-style",
            "counter-set",
            "has"
          ],
          "fallback": "without mod() the waves stop and the field shows the server-drawn contours; without @property the hover lights and releases in one step instead of decaying glyph by glyph",
          "line": "Chrome 125 · Firefox 128 · Safari 17.2"
        },
        "readout": "<GlyphField cols={48} rows={20}>"
      },
      "files": [
        {
          "path": "components/moonarc/GlyphField.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "gradient-text",
      "type": "registry:component",
      "title": "Gradient Text",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "text"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "gradient text",
          "animated gradient text",
          "rainbow text",
          "color shifting headline"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "bg-clip-text"
          ],
          "line": "Chrome 120 · Firefox 49 · Safari 14"
        },
        "readout": "<GradientText duration={6}>"
      },
      "files": [
        {
          "path": "components/moonarc/GradientText.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "grid-pattern",
      "type": "registry:component",
      "title": "Grid Pattern",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "background"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "grid background",
          "grid pattern background",
          "blueprint grid",
          "faded grid lines background"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "mask-image"
          ],
          "line": "Chrome 120 · Firefox 53 · Safari 15.4"
        },
        "readout": "<GridPattern size={32}>"
      },
      "files": [
        {
          "path": "components/moonarc/GridPattern.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "highlight-marker",
      "type": "registry:component",
      "title": "Highlight Marker",
      "description": "A highlighter sweeps across the phrases you marked, one after another, when the sentence scrolls into view. Each phrase is a real <mark> whose background grows from the left; wrapped lines are painted as separate strokes. Composes Reveal; no script of its own.",
      "registryDependencies": [
        "https://moonarc.dev/r/reveal.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets. Add <script is:inline>(f=>addEventListener('astro:after-swap',f,f()))(()=>document.documentElement.dataset.maJs=1)</script> to your <head> as well, so entrances can hide content only when JS runs.",
      "categories": [
        "text"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 3043,
        "intents": [
          "highlight text on scroll",
          "marker highlight animation",
          "highlighter sweep text",
          "animated text highlight",
          "mark animation css"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<HighlightMarker text=\"…**two phrases**…\">"
      },
      "files": [
        {
          "path": "components/moonarc/HighlightMarker.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "horizontal-scroll",
      "type": "registry:component",
      "title": "Horizontal Scroll",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "scroll"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "horizontal scroll section",
          "scroll sideways on vertical scroll",
          "pinned horizontal scroll",
          "horizontal scrolling gallery astro"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "limited",
          "needs": [
            "scroll-timeline"
          ],
          "fallback": "a horizontally scrollable strip without pinning (Firefox)",
          "line": "Chrome 115 · not Firefox · Safari 26"
        },
        "readout": "<HorizontalScroll length={3}>"
      },
      "files": [
        {
          "path": "components/moonarc/HorizontalScroll.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "hover-image-links",
      "type": "registry:component",
      "title": "Hover Image Links",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "pointer"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 597,
        "jsBytesWithShared": 2319,
        "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"
        ],
        "trigger": [
          "pointer",
          "hover"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "has"
          ],
          "fallback": "without :has() the box stays hidden",
          "line": "Chrome 105 · Firefox 121 · Safari 15.4"
        },
        "readout": "<HoverImageLinks size={220}>"
      },
      "files": [
        {
          "path": "components/moonarc/HoverImageLinks.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "hover-video",
      "type": "registry:component",
      "title": "Hover Video",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/animated-icons.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 684,
        "jsBytesWithShared": 2406,
        "intents": [
          "play video on hover",
          "hover to play preview",
          "video card hover",
          "muted autoplay on hover astro",
          "portfolio video thumbnails",
          "work grid video preview"
        ],
        "trigger": [
          "hover"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<HoverVideo poster=\"…\">"
      },
      "files": [
        {
          "path": "components/moonarc/HoverVideo.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "image-compare",
      "type": "registry:component",
      "title": "Image Compare",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 205,
        "jsBytesWithShared": 1927,
        "intents": [
          "before after slider",
          "image comparison slider",
          "compare two images drag",
          "before after image astro",
          "juxtapose images",
          "split image reveal"
        ],
        "trigger": [
          "pointer",
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "clip-path",
            "has",
            "range-vertical"
          ],
          "fallback": "without :has() the line glides while held too; without vertical ranges, orientation=\"vertical\" keeps a horizontal range over the box, so its line follows a sideways drag",
          "line": "Chrome 124 · Firefox 121 · Safari 16.5"
        },
        "readout": "<ImageCompare start={50}>"
      },
      "files": [
        {
          "path": "components/moonarc/ImageCompare.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "image-trail",
      "type": "registry:component",
      "title": "Image Trail",
      "description": "Small images pop up along the pointer's path and fade behind it. The images are a server-rendered pool of lazy <img> 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.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets. Add <script is:inline>(f=>addEventListener('astro:after-swap',f,f()))(()=>document.documentElement.dataset.maJs=1)</script> to your <head> as well, so entrances can hide content only when JS runs.",
      "categories": [
        "pointer"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 872,
        "jsBytesWithShared": 2594,
        "intents": [
          "image trail on cursor",
          "images follow mouse",
          "photo trail hover effect",
          "cursor image trail astro",
          "hover image reveal along mouse path"
        ],
        "trigger": [
          "pointer"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "container-units"
          ],
          "line": "Chrome 105 · Firefox 110 · Safari 16"
        },
        "readout": "<ImageTrail images={[…]} threshold={80}>"
      },
      "files": [
        {
          "path": "components/moonarc/ImageTrail.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "lightbox",
      "type": "registry:component",
      "title": "Lightbox",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/morph.json",
        "https://moonarc.dev/r/dialog.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 972,
        "jsBytesWithShared": 4015,
        "intents": [
          "lightbox",
          "image gallery lightbox",
          "image zoom on click",
          "photo grows from thumbnail",
          "gallery modal astro",
          "shared element transition image"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "dialog",
            "view-transitions"
          ],
          "fallback": "without view transitions, or under reduced motion, the dialog opens as a plain dialog; without closedby (Safari) a backdrop click does nothing, and Escape and the close button still close it",
          "line": "Chrome 111 · Firefox 144 · Safari 18"
        },
        "readout": "<Lightbox columns={3}>"
      },
      "files": [
        {
          "path": "components/moonarc/Lightbox.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "link-preview",
      "type": "registry:component",
      "title": "Link Preview",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 671,
        "jsBytesWithShared": 2393,
        "intents": [
          "link preview on hover",
          "hover card link",
          "link hover card with image",
          "link preview astro",
          "hovercard",
          "preview tooltip for links"
        ],
        "trigger": [
          "hover"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "popover",
            "anchor",
            "starting-style",
            "allow-discrete"
          ],
          "fallback": "without anchor positioning the script places the card under the link; without the popover attribute the link is a link",
          "line": "Chrome 125 · Firefox 147 · Safari 26"
        },
        "readout": "<LinkPreview delay=\"base\">"
      },
      "files": [
        {
          "path": "components/moonarc/LinkPreview.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "liquid-glass",
      "type": "registry:component",
      "title": "Liquid Glass",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "liquid glass",
          "glassmorphism css",
          "frosted glass panel",
          "glass card with refraction",
          "apple liquid glass effect",
          "backdrop blur card"
        ],
        "trigger": [
          "hover"
        ],
        "support": {
          "baseline": "limited",
          "needs": [
            "backdrop-filter",
            "backdrop-svg"
          ],
          "fallback": "Firefox and Safari show the glass (blur, saturation, rim, tint, sheen) without the rim refraction; the displacement layer paints nothing there (measured, 0 pixels differ)",
          "line": "Chrome 76 · not Firefox · not Safari"
        },
        "readout": "<LiquidGlass strength={40} blur=\"10px\">"
      },
      "files": [
        {
          "path": "components/moonarc/LiquidGlass.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "magnetic",
      "type": "registry:component",
      "title": "Magnetic",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "pointer"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 619,
        "jsBytesWithShared": 2341,
        "intents": [
          "magnetic button",
          "button follows cursor",
          "magnetic hover effect",
          "cursor attraction button"
        ],
        "trigger": [
          "pointer",
          "hover"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<Magnetic strength={0.4}>"
      },
      "files": [
        {
          "path": "components/moonarc/Magnetic.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "marquee",
      "type": "registry:component",
      "title": "Marquee",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "loop"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "logo marquee",
          "infinite scroll strip",
          "logo loop",
          "ticker",
          "scrolling logos astro"
        ],
        "trigger": [
          "always",
          "hover"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "mask-image"
          ],
          "line": "Chrome 120 · Firefox 53 · Safari 15.4"
        },
        "readout": "<Marquee duration={16}>"
      },
      "files": [
        {
          "path": "components/moonarc/Marquee.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "meteors",
      "type": "registry:component",
      "title": "Meteors",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "background"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "meteor shower background",
          "falling stars animation",
          "shooting stars css",
          "meteors effect hero",
          "starry night background"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "container-units"
          ],
          "line": "Chrome 105 · Firefox 110 · Safari 16"
        },
        "readout": "<Meteors count={12} angle={135}>"
      },
      "files": [
        {
          "path": "components/moonarc/Meteors.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "noise",
      "type": "registry:component",
      "title": "Noise",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "background"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "noise overlay",
          "film grain effect",
          "grain texture css",
          "noisy background"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<Noise opacity={0.08}>"
      },
      "files": [
        {
          "path": "components/moonarc/Noise.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "number-flow",
      "type": "registry:component",
      "title": "Number Flow",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "data"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "number flow",
          "rolling digits",
          "odometer number animation",
          "animated counter on change",
          "slot machine digits css",
          "number transition"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "css-math"
          ],
          "fallback": "the value as plain text, updated only by a re-render",
          "line": "Chrome 125 · Firefox 118 · Safari 15.4"
        },
        "readout": "<NumberFlow value={1284}>"
      },
      "files": [
        {
          "path": "components/moonarc/NumberFlow.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "orb",
      "type": "registry:component",
      "title": "Orb",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "background"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "glowing orb background",
          "breathing orb",
          "ai orb animation",
          "gradient sphere hero",
          "siri orb css"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "property"
          ],
          "fallback": "the sphere breathes; the hue does not drift",
          "line": "Chrome 85 · Firefox 128 · Safari 16.4"
        },
        "readout": "<Orb hue={250} pulse={0.06}>"
      },
      "files": [
        {
          "path": "components/moonarc/Orb.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "orbiting-circles",
      "type": "registry:component",
      "title": "Orbiting Circles",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "background"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "orbiting icons",
          "icons rotating around logo",
          "orbit animation css",
          "planets orbit integration logos",
          "circular orbit icons astro"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "has"
          ],
          "fallback": "pass `count`; without :has() and without count the items stack at one angle",
          "line": "Chrome 105 · Firefox 121 · Safari 15.4"
        },
        "readout": "<OrbitingCircles radius={100} duration={20}>"
      },
      "files": [
        {
          "path": "components/moonarc/OrbitingCircles.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "otp-input",
      "type": "registry:component",
      "title": "OTP Input",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "otp input",
          "one time code input",
          "verification code boxes",
          "pin input",
          "sms code input",
          "6 digit code input css"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "has",
            "user-invalid"
          ],
          "fallback": "without :has() the cells keep their resting border and the check never shows; the input itself is unchanged",
          "line": "Chrome 119 · Firefox 121 · Safari 16.5"
        },
        "readout": "<OtpInput length={6} name=\"code\" required>"
      },
      "files": [
        {
          "path": "components/moonarc/OtpInput.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "page-transition",
      "type": "registry:component",
      "title": "Page Transition",
      "description": "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 <ClientRouter /> drives view transitions, and the presets are keyframes on the active motion preset's curve.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "transition"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "page transition",
          "view transitions astro",
          "animate between pages",
          "shared element transition",
          "transition:name preset",
          "route transition"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "view-transitions"
          ],
          "fallback": "an instant swap between pages",
          "line": "Chrome 111 · Firefox 144 · Safari 18"
        },
        "readout": "<PageTransition name=\"hero\" preset=\"rise\">"
      },
      "files": [
        {
          "path": "components/moonarc/PageTransition.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "parallax",
      "type": "registry:component",
      "title": "Parallax",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "scroll"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "parallax",
          "parallax scroll effect",
          "background moves slower than foreground",
          "scroll-driven parallax astro",
          "parallax without javascript"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "limited",
          "needs": [
            "scroll-timeline"
          ],
          "fallback": "the element stays in place (Firefox)",
          "line": "Chrome 115 · not Firefox · Safari 26"
        },
        "readout": "<Parallax speed={0.3}>"
      },
      "files": [
        {
          "path": "components/moonarc/Parallax.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "particles",
      "type": "registry:component",
      "title": "Particles",
      "description": "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.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/canvas.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "background"
      ],
      "meta": {
        "tier": "C",
        "pro": false,
        "jsBytes": 1630,
        "jsBytesWithShared": 5043,
        "intents": [
          "particles background",
          "floating dots interactive",
          "particles.js alternative",
          "dots avoid cursor",
          "constellation background canvas"
        ],
        "trigger": [
          "always",
          "pointer"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<Particles reach={120} links={0}>"
      },
      "files": [
        {
          "path": "components/moonarc/Particles.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "persist-player",
      "type": "registry:component",
      "title": "Persist Player",
      "description": "An audio player that keeps playing while you navigate: the same <audio> element is carried into the next page by Astro's router, so position, volume and playback never restart. Native controls, zero JavaScript of its own. Put it in the layout; every page gets the one that is already playing.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "transition"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "persistent audio player astro",
          "music keeps playing between pages",
          "transition:persist audio",
          "site-wide player view transitions",
          "audio survives navigation"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "fallback": "without the router the player is a normal audio element that restarts with the page",
          "line": "every browser"
        },
        "readout": "<PersistPlayer src=\"/audio/loop.mp3\">"
      },
      "files": [
        {
          "path": "components/moonarc/PersistPlayer.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "phone-frame",
      "type": "registry:component",
      "title": "Phone Frame",
      "description": "A generic phone frame around a screenshot or any content, with three cut-outs (island, notch, punch), a home bar, and no logo, buttons or brand. The chrome scales with the frame's width through container query units and shares BrowserFrame's tokens; scroll drifts content taller than the screen up and back on a translate keyframe, paused under the pointer. Zero JavaScript.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "phone mockup",
          "iphone frame css",
          "device frame screenshot",
          "mobile mockup scrolling",
          "app screenshot frame",
          "phone frame no brand"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "container-units"
          ],
          "line": "Chrome 105 · Firefox 110 · Safari 16"
        },
        "readout": "<PhoneFrame model=\"island\" src={shot} scroll>"
      },
      "files": [
        {
          "path": "components/moonarc/PhoneFrame.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "pill-nav",
      "type": "registry:component",
      "title": "Pill Nav",
      "description": "A floating pill of links whose active pill glides to the page you chose. Zero JavaScript: the server marks the current link, the pill carries a view-transition-name, and under ClientRouter the browser slides it across the swap; a faint pill follows hover and focus through anchor positioning.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "pill navigation",
          "floating nav pill",
          "sliding active indicator nav",
          "nav with animated indicator",
          "navbar pill astro",
          "tab bar that slides between pages"
        ],
        "trigger": [
          "click",
          "hover"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "view-transitions",
            "vt-class",
            "anchor",
            "has"
          ],
          "fallback": "without anchor positioning there is no hover pill; without view transitions, or without ClientRouter, the active pill moves at once; without view-transition-class it slides on the browser's default timing instead of the preset",
          "line": "Chrome 125 · Firefox 147 · Safari 26"
        },
        "readout": "<PillNav current=\"/work/\">"
      },
      "files": [
        {
          "path": "components/moonarc/PillNav.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "popover",
      "type": "registry:component",
      "title": "Popover",
      "description": "A popover that opens beside its trigger, flips when there is no room, closes on outside click or Escape, and animates in and out. Zero JavaScript: the popover attribute, anchor positioning and @starting-style do all of it.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "popover",
          "tooltip popover",
          "anchored popup",
          "dropdown without javascript",
          "popover api astro"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "popover",
            "anchor",
            "starting-style",
            "allow-discrete"
          ],
          "fallback": "without anchor positioning it opens as a small sheet at the bottom of the viewport",
          "line": "Chrome 125 · Firefox 147 · Safari 26"
        },
        "readout": "<Popover placement=\"bottom\">"
      },
      "files": [
        {
          "path": "components/moonarc/Popover.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "price-switch",
      "type": "registry:component",
      "title": "Price Switch",
      "description": "A monthly / yearly toggle whose prices roll to the other amount instead of swapping. The thumb slides, the period label changes places, and a \"save\" badge appears on the yearly option. Two native radios, :has() and NumberFlow. Zero JavaScript; both prices are in the HTML as text for assistive tech.",
      "registryDependencies": [
        "https://moonarc.dev/r/number-flow.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "data"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "pricing toggle monthly yearly",
          "price switch animation",
          "billing period toggle",
          "animated pricing switch",
          "pricing table toggle astro"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "has",
            "css-math",
            "starting-style",
            "allow-discrete"
          ],
          "fallback": "without round() and mod() the price is plain text that changes in place with the period; without @starting-style the badge appears without its entrance",
          "line": "Chrome 125 · Firefox 129 · Safari 17.5"
        },
        "readout": "<PriceSwitch monthly={12} yearly={115}>"
      },
      "files": [
        {
          "path": "components/moonarc/PriceSwitch.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "progress",
      "type": "registry:component",
      "title": "Progress",
      "description": "A bar that fills to its value when it scrolls into view, with the number counting up beside it, or a ring with the number in the middle. No script of its own: Reveal is the trigger and CountUp the number; the fill is one translate transition, the ring one dash offset. The server HTML already shows the final state.",
      "registryDependencies": [
        "https://moonarc.dev/r/reveal.json",
        "https://moonarc.dev/r/count-up.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets. Add <script is:inline>(f=>addEventListener('astro:after-swap',f,f()))(()=>document.documentElement.dataset.maJs=1)</script> to your <head> as well, so entrances can hide content only when JS runs.",
      "categories": [
        "loading"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 3043,
        "intents": [
          "progress bar",
          "animated progress bar on scroll",
          "skill bar",
          "percentage bar animation"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "property",
            "counter-style"
          ],
          "fallback": "the bar fills; the number appears without counting",
          "line": "Chrome 91 · Firefox 128 · Safari 17"
        },
        "readout": "<Progress value={62}>"
      },
      "files": [
        {
          "path": "components/moonarc/Progress.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "progressive-blur",
      "type": "registry:component",
      "title": "Progressive Blur",
      "description": "An edge that blurs what scrolls under it, more the closer it gets: a few bands, each with a backdrop blur twice the last and a mask that keeps it to its own slice, so the blur ramps instead of stepping. Nothing animates: the content moving beneath is the motion. Without backdrop-filter the edge fades to a colour. Zero JS.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "background"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "progressive blur edge",
          "gradient blur bottom of list",
          "blurred fade scroll edge",
          "apple style progressive blur",
          "backdrop blur gradient css"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "backdrop-filter",
            "mask-image"
          ],
          "fallback": "a gradient to the panel colour instead of a blur",
          "line": "Chrome 120 · Firefox 103 · Safari 18"
        },
        "readout": "<ProgressiveBlur direction=\"bottom\" layers={5}>"
      },
      "files": [
        {
          "path": "components/moonarc/ProgressiveBlur.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "prompt-input",
      "type": "registry:component",
      "title": "Prompt Input",
      "description": "The AI prompt box: a form with a textarea that grows with its content through field-sizing, a model select, an attachment button that is a real file input, and a send button that dims until something is typed and spins while the form carries data-pending. Zero JavaScript by default; submitOnEnter adds a measured script: Enter sends, Shift+Enter breaks the line, and an IME composition is never interrupted.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/animated-select.json",
        "https://moonarc.dev/r/spinner.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "ai prompt input",
          "chat input box",
          "growing textarea",
          "textarea autosize css",
          "prompt box with model picker",
          "chatgpt style input"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "field-sizing",
            "has"
          ],
          "fallback": "without field-sizing the textarea keeps its rows and a vertical resize handle; without :has() the send button does not dim",
          "line": "Chrome 123 · Firefox 152 · Safari 26.2"
        },
        "readout": "<PromptInput models={models} attachments submitOnEnter>"
      },
      "files": [
        {
          "path": "components/moonarc/PromptInput.astro",
          "type": "registry:component"
        },
        {
          "path": "components/moonarc/internal/PromptInputSubmitOnEnter.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "reading-toc",
      "type": "registry:component",
      "title": "Reading TOC",
      "description": "A table of contents that lights up as you read. The list is server-rendered from items (Astro's own headings shape works), the links are plain anchors, and one passive scroll listener sets aria-current on the link of the last heading above the reading line, which is the only thing the script does. The indicator is CSS from that attribute. Works inside a scrolling box as well as on the page, follows jumps from its own links, and is dropped before every navigation.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "scroll"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 899,
        "jsBytesWithShared": 2621,
        "intents": [
          "table of contents highlight on scroll",
          "active heading toc",
          "scrollspy",
          "on this page navigation",
          "reading progress toc"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<ReadingToc for=\"article\" items={headings}>"
      },
      "files": [
        {
          "path": "components/moonarc/ReadingToc.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "retro-grid",
      "type": "registry:component",
      "title": "Retro Grid",
      "description": "A perspective grid floor sliding toward the viewer. Two repeating gradients on one plane rotated in 3D; the motion is a translate of exactly one cell on the compositor, so the loop has no visible seam and never repaints. A mask fades the horizon. Zero JS; fills its positioned parent.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "background"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "retro grid background",
          "synthwave grid",
          "perspective grid floor",
          "moving grid background hero",
          "tron grid css"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "mask-image"
          ],
          "fallback": "the grid without the horizon fade",
          "line": "Chrome 120 · Firefox 53 · Safari 15.4"
        },
        "readout": "<RetroGrid angle={65} cellSize={60}>"
      },
      "files": [
        {
          "path": "components/moonarc/RetroGrid.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "ripple",
      "type": "registry:component",
      "title": "Ripple",
      "description": "Rings expand from a point and fade, one after another, like a pulse. Each ring is an element scaling and fading on its own delay; pure CSS, compositor only. Fills its positioned parent.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "background"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "ripple effect",
          "pulsing rings",
          "radar pulse background",
          "concentric circles animation"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<Ripple count={4}>"
      },
      "files": [
        {
          "path": "components/moonarc/Ripple.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "rotating-text",
      "type": "registry:component",
      "title": "Rotating Text",
      "description": "Cycles through a list of words in place. Each word rises in, holds, and leaves upward, and the box is sized to the widest word so the surrounding text never shifts. Pure CSS.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "text"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "rotating words",
          "word cycle animation",
          "flip words",
          "animated headline words",
          "text loop astro"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "property"
          ],
          "fallback": "words crossfade in place without the vertical travel",
          "line": "Chrome 85 · Firefox 128 · Safari 16.4"
        },
        "readout": "<RotatingText period={1600}>"
      },
      "files": [
        {
          "path": "components/moonarc/RotatingText.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "scroll-expand",
      "type": "registry:component",
      "title": "Scroll Expand",
      "description": "An image that starts narrow and rounded and opens to the full width as it scrolls into view. The layout never changes: the element is full width from the start and a clip-path inset with its rounding shrinks it, animated on the element's own view() timeline; the content inside scales up a touch for depth. Without scroll timelines it is simply full width. Zero JavaScript.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "scroll"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "image expands on scroll",
          "scroll zoom image full width",
          "container scroll expand",
          "scroll expand media",
          "hero image grows on scroll"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "limited",
          "needs": [
            "scroll-timeline",
            "clip-path"
          ],
          "fallback": "full width, static (Firefox)",
          "line": "Chrome 115 · not Firefox · Safari 26"
        },
        "readout": "<ScrollExpand from={0.6} radius=\"2rem\">"
      },
      "files": [
        {
          "path": "components/moonarc/ScrollExpand.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "scroll-progress",
      "type": "registry:component",
      "title": "Scroll Progress",
      "description": "A hairline along the top of the viewport that fills as the page is read. Zero JavaScript: its scale is bound to the document's scroll timeline, so nothing listens to scroll and it is never a frame behind.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "scroll"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "scroll progress bar",
          "reading progress indicator",
          "page scroll indicator",
          "progress bar on scroll astro"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "limited",
          "needs": [
            "scroll-timeline"
          ],
          "fallback": "the bar is not rendered (Firefox)",
          "line": "Chrome 115 · not Firefox · Safari 26"
        },
        "readout": "<ScrollProgress height={2}>"
      },
      "files": [
        {
          "path": "components/moonarc/ScrollProgress.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "reveal",
      "type": "registry:component",
      "title": "Scroll Reveal",
      "description": "Entrance on scroll that plays once and stays, staggers its children, scrubs with the scroll position when asked, honours reduced motion, and keeps working after every ClientRouter navigation. Server HTML stays readable without JavaScript.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets. Add <script is:inline>(f=>addEventListener('astro:after-swap',f,f()))(()=>document.documentElement.dataset.maJs=1)</script> to your <head> as well, so entrances can hide content only when JS runs.",
      "categories": [
        "scroll"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 1321,
        "jsBytesWithShared": 3043,
        "intents": [
          "scroll reveal",
          "fade in on scroll",
          "animate on scroll",
          "AOS alternative",
          "stagger children on scroll",
          "scroll-linked reveal",
          "view transitions safe reveal"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "fallback": "scrub uses animation-timeline: view() where it exists and, everywhere else, a scroll listener that measures the same entry range; from=\"clip\" wipes with mask-size (Chrome 120, Firefox 53, Safari 15.4) and simply appears before that",
          "line": "every browser"
        },
        "readout": "<Reveal stagger={60}>"
      },
      "files": [
        {
          "path": "components/moonarc/Reveal.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "scroll-scrub",
      "type": "registry:component",
      "title": "Scroll Scrub",
      "description": "Bind translate, scale, rotate and opacity to the scroll position: the element goes from the start values you give to neutral across a range of its own passage through the viewport, exactly in step. Zero JavaScript.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "scroll"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "scroll linked animation",
          "scrub animation with scroll",
          "animate on scroll position",
          "scroll-driven transform",
          "scrolltrigger scrub alternative"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "limited",
          "needs": [
            "scroll-timeline"
          ],
          "fallback": "the end state, static (Firefox)",
          "line": "Chrome 115 · not Firefox · Safari 26"
        },
        "readout": "<ScrollScrub y={80} scale={0.9}>"
      },
      "files": [
        {
          "path": "components/moonarc/ScrollScrub.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "shimmer-button",
      "type": "registry:component",
      "title": "Shimmer Button",
      "description": "A highlight sweeps across the body of a button on a loop; hover lifts it on the preset's hover travel and adds a ring, and focus draws the same. One pseudo-element gradient whose position animates: no layout, though every frame repaints the button's own box. Renders a <button> or an <a>. Zero JavaScript.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "shimmer button",
          "shiny button",
          "animated cta button",
          "button with light sweep",
          "glowing button astro"
        ],
        "trigger": [
          "always",
          "hover"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<ShimmerButton duration={3}>"
      },
      "files": [
        {
          "path": "components/moonarc/ShimmerButton.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "shiny-text",
      "type": "registry:component",
      "title": "Shiny Text",
      "description": "A highlight sweeps across the text every few seconds. The text keeps its own colour; the shine is a gradient clipped to a repeated copy on top, and only its position animates. Pure CSS.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "text"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "shiny text",
          "shimmer text",
          "text highlight sweep",
          "glossy text animation",
          "shine effect on text"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "bg-clip-text"
          ],
          "line": "Chrome 120 · Firefox 49 · Safari 14"
        },
        "readout": "<ShinyText duration={3}>"
      },
      "files": [
        {
          "path": "components/moonarc/ShinyText.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "skeleton",
      "type": "registry:component",
      "title": "Skeleton",
      "description": "Placeholder lines, optionally with an avatar, shimmering while content loads. The shimmer is a gradient texture whose position moves; pure CSS. Marks itself busy for assistive tech.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "loading"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "skeleton loader",
          "loading placeholder",
          "shimmer loading",
          "content placeholder animation"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<Skeleton lines={3}>"
      },
      "files": [
        {
          "path": "components/moonarc/Skeleton.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "sparkline",
      "type": "registry:component",
      "title": "Sparkline",
      "description": "A small line chart that draws itself from left to right when it scrolls into view; the last point lands and pulses. The SVG is rendered on the server from the data, the line is uncovered by a clip that sweeps from its left edge to its right, and the accessible name summarises the series. Composes Reveal; no script of its own.",
      "registryDependencies": [
        "https://moonarc.dev/r/reveal.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets. Add <script is:inline>(f=>addEventListener('astro:after-swap',f,f()))(()=>document.documentElement.dataset.maJs=1)</script> to your <head> as well, so entrances can hide content only when JS runs.",
      "categories": [
        "data"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 3043,
        "intents": [
          "sparkline",
          "animated line chart",
          "svg line draw on scroll",
          "tiny chart astro",
          "trend line animation"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "clip-path"
          ],
          "line": "Chrome 55 · Firefox 54 · Safari 13.1"
        },
        "readout": "<Sparkline data={[…]}>"
      },
      "files": [
        {
          "path": "components/moonarc/Sparkline.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "spinner",
      "type": "registry:component",
      "title": "Spinner",
      "description": "An indeterminate arc whose length breathes while it rotates, so it looks like it is working rather than spinning a fixed wedge. One SVG circle, pure CSS; announces itself as a status.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "loading"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "loading spinner",
          "css spinner",
          "indeterminate loader",
          "spinner astro"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<Spinner size={20}>"
      },
      "files": [
        {
          "path": "components/moonarc/Spinner.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "split-flap",
      "type": "registry:component",
      "title": "Split Flap",
      "description": "A departures board: every character spins through the alphabet and locks, one cell after another, when the board scrolls into view. Each glyph is a CSS counter on a registered integer that transitions from blank to the letter, and a flap turns once per step. Composes Reveal; no script of its own. The server HTML already reads the final text.",
      "registryDependencies": [
        "https://moonarc.dev/r/reveal.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets. Add <script is:inline>(f=>addEventListener('astro:after-swap',f,f()))(()=>document.documentElement.dataset.maJs=1)</script> to your <head> as well, so entrances can hide content only when JS runs.",
      "categories": [
        "text"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 3043,
        "intents": [
          "split flap text",
          "departures board animation",
          "airport board text",
          "flip board letters",
          "solari board css"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "counter-set",
            "property",
            "counter-style"
          ],
          "fallback": "the final text, shown at once",
          "line": "Chrome 91 · Firefox 128 · Safari 17.2"
        },
        "readout": "<SplitFlap text=\"DEPARTURES\">"
      },
      "files": [
        {
          "path": "components/moonarc/SplitFlap.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "split-text",
      "type": "registry:component",
      "title": "Split Text",
      "description": "Splits a string into words, characters or lines on the server and reveals them with a capped stagger when they scroll into view. One string to screen readers, zero script of its own.",
      "registryDependencies": [
        "https://moonarc.dev/r/reveal.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets. Add <script is:inline>(f=>addEventListener('astro:after-swap',f,f()))(()=>document.documentElement.dataset.maJs=1)</script> to your <head> as well, so entrances can hide content only when JS runs.",
      "categories": [
        "text"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 3043,
        "intents": [
          "split text animation",
          "animate words on scroll",
          "staggered text reveal",
          "character reveal",
          "text animation astro"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "fallback": "scrub uses animation-timeline: view() (Chrome 115, Safari 26); elsewhere every word is full",
          "line": "every browser"
        },
        "readout": "<SplitText step={45}>"
      },
      "files": [
        {
          "path": "components/moonarc/SplitText.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "spotlight",
      "type": "registry:component",
      "title": "Spotlight",
      "description": "A soft radial light follows the cursor over a card and fades in only while hovered. One pointermove listener writes two custom properties; the light itself is a CSS gradient. Bound through the shared runtime, so it survives navigation.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "pointer"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 340,
        "jsBytesWithShared": 2062,
        "intents": [
          "spotlight card",
          "cursor light effect",
          "hover glow follows mouse",
          "radial gradient follows cursor",
          "spotlight hover astro"
        ],
        "trigger": [
          "pointer",
          "hover"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "mask-composite"
          ],
          "line": "Chrome 120 · Firefox 53 · Safari 15.4"
        },
        "readout": "<Spotlight radius={240}>"
      },
      "files": [
        {
          "path": "components/moonarc/Spotlight.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "stagger-menu",
      "type": "registry:component",
      "title": "Stagger Menu",
      "description": "A burger that opens a full-screen menu (or a top sheet, or a side panel) whose items arrive one after another and leave in reverse. No script: a native modal dialog opened by the invoker command (focus trap, Escape, backdrop click and the focus returning to the burger are the browser's), and each item is a @starting-style transition delayed by its index on the stagger token. A link to a place on the same page carries a one-line onclick that closes the menu.",
      "registryDependencies": [
        "https://moonarc.dev/r/animated-icons.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "fullscreen menu",
          "staggered menu items",
          "burger menu overlay",
          "hamburger menu animation astro",
          "menu items animate in one by one",
          "mobile nav overlay"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "command",
            "starting-style",
            "allow-discrete",
            "dialog"
          ],
          "fallback": "without invoker commands the burger needs polyfill (an inline handler of 403 B raw); without @starting-style the menu opens without the stagger; without closedby (Safari) a backdrop click does nothing, and Escape and the close button still close it",
          "line": "Chrome 135 · Firefox 144 · Safari 26.2"
        },
        "readout": "<StaggerMenu side=\"full\">"
      },
      "files": [
        {
          "path": "components/moonarc/StaggerMenu.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "stateful-button",
      "type": "registry:component",
      "title": "Stateful Button",
      "description": "One submit button with four faces (idle, pending with a spinner, done with a check that draws itself, error) and a width that follows the label. The state is data-state on the button, set by the prop, by your script, or inherited from a form that carries data-pending. The faces are clipped to a bound derived from the label, so nothing is measured, and only the face that shows is in the accessibility tree. Zero JavaScript of its own.",
      "registryDependencies": [
        "https://moonarc.dev/r/spinner.json",
        "https://moonarc.dev/r/animated-icons.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "loading button",
          "submit button with spinner",
          "button success state",
          "stateful button",
          "button that shows sending and done"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<StatefulButton state=\"pending\">"
      },
      "files": [
        {
          "path": "components/moonarc/StatefulButton.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "sticky-banner",
      "type": "registry:component",
      "title": "Sticky Banner",
      "description": "An announcement ribbon that sticks to the top of the page and folds away when dismissed, the content below sliding up on the preset curve. Zero JavaScript: a non-modal dialog closed by a form with method=\"dialog\", a grid row that :has() collapses, and an exit through allow-discrete. remember inlines 286 B raw that keep it closed across pages.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "announcement banner",
          "sticky top banner dismissible",
          "promo bar",
          "cookie bar without javascript",
          "site notice ribbon",
          "banner that remembers dismissal"
        ],
        "trigger": [
          "load",
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "dialog",
            "has",
            "allow-discrete",
            "grid-rows-animation"
          ],
          "fallback": "without allow-discrete the ribbon disappears at once; the row still folds on :has()",
          "line": "Chrome 117 · Firefox 129 · Safari 17.4"
        },
        "readout": "<StickyBanner id=\"launch\" remember>"
      },
      "files": [
        {
          "path": "components/moonarc/StickyBanner.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "sticky-reveal",
      "type": "registry:component",
      "title": "Sticky Reveal",
      "description": "Steps on the left scroll by; one visual on the right stays put and changes with them. Each step names its own view timeline, the visuals are stacked in a sticky cell, and each visual's opacity and travel are bound to its step through timeline-scope. Without scroll timelines, or in a narrow container, the steps and visuals interleave in one column so every step still meets its own visual. Zero JavaScript.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "scroll"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "sticky scroll reveal",
          "scroll steps with sticky image",
          "features scroll with changing image",
          "sticky scroll section",
          "scrollytelling astro"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "limited",
          "needs": [
            "scroll-timeline",
            "timeline-scope"
          ],
          "fallback": "one column: each step followed by its own visual (Firefox, and every browser below 40 rem of container width)",
          "line": "Chrome 116 · not Firefox · Safari 26"
        },
        "readout": "<StickyReveal steps={[…]} top=\"10vh\">"
      },
      "files": [
        {
          "path": "components/moonarc/StickyReveal.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "stroke-draw",
      "type": "registry:component",
      "title": "Stroke Draw",
      "description": "A headline's outline draws itself glyph by glyph when it scrolls into view, then the fill comes in. SVG text with one stroked <tspan> per character, a dash longer than any outline offset to zero on a per-index delay. Composes Reveal; no script of its own. The server HTML holds the finished text.",
      "registryDependencies": [
        "https://moonarc.dev/r/reveal.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets. Add <script is:inline>(f=>addEventListener('astro:after-swap',f,f()))(()=>document.documentElement.dataset.maJs=1)</script> to your <head> as well, so entrances can hide content only when JS runs.",
      "categories": [
        "text"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 3043,
        "intents": [
          "text stroke animation",
          "draw text outline svg",
          "handwritten headline animation",
          "svg text stroke dashoffset",
          "outline text draw on scroll"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<StrokeDraw text=\"Draw.\">"
      },
      "files": [
        {
          "path": "components/moonarc/StrokeDraw.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "switch",
      "type": "registry:component",
      "title": "Switch",
      "description": "A toggle that springs. It is a native checkbox with role=\"switch\" and appearance: none (the input is the track, its ::before the thumb), so the value submits, required and disabled work, Space flips it, and the thumb travels on the preset curve with a bounce under the snap and lively presets. Zero JavaScript.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "toggle switch",
          "animated switch",
          "checkbox as switch",
          "ios style toggle",
          "switch with spring",
          "settings toggle"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<Switch name=\"alerts\" label=\"Email me\" checked>"
      },
      "files": [
        {
          "path": "components/moonarc/Switch.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "tabs",
      "type": "registry:component",
      "title": "Tabs",
      "description": "Tabs with an indicator that slides to the selected one and panels that fade in. Zero JavaScript: the tabs are radio inputs, so keyboard and selection are native, and :has() turns the checked index into the indicator's position.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "tabs",
          "animated tab indicator",
          "sliding underline tabs",
          "tabs without javascript",
          "segmented control"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "has",
            "starting-style"
          ],
          "fallback": "panels switch without the fade (or the slide)",
          "line": "Chrome 117 · Firefox 129 · Safari 17.5"
        },
        "readout": "<Tabs direction>"
      },
      "files": [
        {
          "path": "components/moonarc/Tabs.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "text-roll",
      "type": "registry:component",
      "title": "Text Roll",
      "description": "A label rolls upward into a copy of itself on hover, letter by letter from the left, and rolls back when the pointer leaves. Two copies in one clipped cell, one translate per character on a per-index delay. Pure CSS; works from the link or button around it.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "text"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "text roll hover",
          "rolling link text",
          "hover text flip up",
          "letter roll animation",
          "text roll motion primitives"
        ],
        "trigger": [
          "hover"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<TextRoll text=\"Get started\">"
      },
      "files": [
        {
          "path": "components/moonarc/TextRoll.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "text-scramble",
      "type": "registry:component",
      "title": "Text Scramble",
      "description": "Random characters resolve into the real text from left to right when it scrolls into view, on load, or on hover. The server HTML is the final string; a small requestAnimationFrame loop does the rest and never runs under reduced motion.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "text"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 921,
        "jsBytesWithShared": 2643,
        "intents": [
          "text scramble",
          "decrypt text effect",
          "hacker text animation",
          "scramble letters into words",
          "decode text on scroll"
        ],
        "trigger": [
          "scroll",
          "hover",
          "load"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<TextScramble speed={30}>"
      },
      "files": [
        {
          "path": "components/moonarc/TextScramble.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "theme-toggle",
      "type": "registry:component",
      "title": "Theme Toggle",
      "description": "Cycles system → light → dark, and the page changes theme through a circle that grows from the click, on a same-document view transition. ThemeScript in <head> stores the choice, applies it before paint and after every swap and exposes the API; ThemeToggle's own script only advances the choice and wraps the change (its storageKey prop is ThemeScript's). Without view transitions, or under reduced motion, the theme switches at once. Without ThemeScript, which includes a page without JavaScript, the toggle is hidden. The icon is AnimatedIcons (sun to moon).",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/animated-icons.json",
        "https://moonarc.dev/r/theme-script.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "C",
        "pro": false,
        "jsBytes": 1062,
        "jsBytesWithShared": 2784,
        "intents": [
          "dark mode toggle",
          "theme toggle with animation",
          "theme switch circle transition",
          "view transition dark mode",
          "light dark system toggle astro"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "view-transitions",
            "clip-path"
          ],
          "fallback": "an instant switch",
          "line": "Chrome 111 · Firefox 144 · Safari 18"
        },
        "readout": "<ThemeToggle origin=\"click\">"
      },
      "files": [
        {
          "path": "components/moonarc/ThemeToggle.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "tilt",
      "type": "registry:component",
      "title": "Tilt",
      "description": "A card leans toward the cursor in 3D, lifts slightly, catches a glare, and settles back on the active preset's spring when the cursor leaves. The pointer writes two custom properties; everything visible is CSS. Never binds under reduced motion.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "pointer"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 588,
        "jsBytesWithShared": 2310,
        "intents": [
          "tilt card",
          "3d hover card",
          "card tilts on mouse move",
          "parallax tilt effect",
          "vanilla-tilt astro"
        ],
        "trigger": [
          "pointer",
          "hover"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<Tilt max={12}>"
      },
      "files": [
        {
          "path": "components/moonarc/Tilt.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "toast",
      "type": "registry:component",
      "title": "Toast",
      "description": "Notifications that slide in, stack behind each other, push up as new ones arrive, and expand into a list on hover. Raise one from anywhere with toast() or a DOM event; timers pause while the stack is hovered or focused and while the tab is hidden, and the region is a polite live region. The stack geometry is CSS reading one custom property per toast.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/toast-fn.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "C",
        "pro": false,
        "jsBytes": 1063,
        "jsBytesWithShared": 2785,
        "intents": [
          "toast notification",
          "sonner alternative",
          "stacked toasts",
          "notification stack",
          "toast astro"
        ],
        "trigger": [
          "click",
          "hover"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "starting-style"
          ],
          "fallback": "toasts appear without the entrance",
          "line": "Chrome 117 · Firefox 129 · Safari 17.5"
        },
        "readout": "toast({ title: 'Saved' })"
      },
      "files": [
        {
          "path": "components/moonarc/Toast.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "tracing-beam",
      "type": "registry:component",
      "title": "Tracing Beam",
      "description": "A line beside an article fills as it is read, with a dot at its head. One registered percentage animates on the article's own view() timeline, and both the fill's height and the head's position read that value. Without scroll timelines the line is full and still. Correct for an article shorter than the viewport too. Zero JavaScript.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "scroll"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "tracing beam",
          "article progress line",
          "scroll progress beside content",
          "vertical reading progress",
          "beam follows scroll"
        ],
        "trigger": [
          "scroll"
        ],
        "support": {
          "baseline": "limited",
          "needs": [
            "scroll-timeline",
            "property"
          ],
          "fallback": "a full, static line with the dot at its end (Firefox)",
          "line": "Chrome 115 · not Firefox · Safari 26"
        },
        "readout": "<TracingBeam color=\"var(--action)\">"
      },
      "files": [
        {
          "path": "components/moonarc/TracingBeam.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "typewriter",
      "type": "registry:component",
      "title": "Typewriter",
      "description": "Types a string one character at a time in any font, with a caret that stays solid while typing and blinks once idle. Pure CSS: every character is a span whose display animates on its own delay.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "text"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "typewriter effect",
          "typing animation",
          "type text one character at a time",
          "terminal typing effect astro"
        ],
        "trigger": [
          "load"
        ],
        "support": {
          "baseline": "limited",
          "needs": [
            "display-animation"
          ],
          "fallback": "every character still types in turn, held at zero size by the font-size in the same keyframes until then (Firefox)",
          "line": "Chrome 116 · not Firefox · Safari 18"
        },
        "readout": "<Typewriter speed={45}>"
      },
      "files": [
        {
          "path": "components/moonarc/Typewriter.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "underline-hover",
      "type": "registry:component",
      "title": "Underline Hover",
      "description": "A link underline that enters from the left on hover and leaves to the right, so the exit continues the entrance instead of rewinding it. One background gradient, no pseudo-element, wraps across lines. Pure CSS; triggered by the link around it.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "text"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "underline hover animation",
          "link underline slide in",
          "animated underline css",
          "underline left to right hover",
          "nav link underline effect"
        ],
        "trigger": [
          "hover"
        ],
        "support": {
          "baseline": "widely",
          "needs": [],
          "line": "every browser"
        },
        "readout": "<UnderlineHover thickness=\"0.08em\">"
      },
      "files": [
        {
          "path": "components/moonarc/UnderlineHover.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "vanish-input",
      "type": "registry:component",
      "title": "Vanish Input",
      "description": "Placeholders that take turns, and text that blurs away on submit. A native input in your form: the first suggestion is the placeholder attribute, the rest cycle in an aria-hidden overlay driven by one registered number, so their entrances are transitions on the preset curve. A small script listens for submit on the document and, only when your handler prevented the default, splits the value into characters that rise and blur out on the stagger token.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 604,
        "jsBytesWithShared": 2326,
        "intents": [
          "placeholders and vanish effect",
          "input with rotating placeholder",
          "text vanishes on submit",
          "animated placeholder input",
          "search input hints cycle",
          "waitlist input animation"
        ],
        "trigger": [
          "click",
          "always"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "property",
            "has",
            "css-math"
          ],
          "fallback": "without @property or round() only the first placeholder shows; without :has() the native placeholder shows through the overlay",
          "line": "Chrome 125 · Firefox 128 · Safari 16.4"
        },
        "readout": "<VanishInput placeholders={hints} name=\"email\">"
      },
      "files": [
        {
          "path": "components/moonarc/VanishInput.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "video-dialog",
      "type": "registry:component",
      "title": "Video Dialog",
      "description": "A poster with a breathing play button that opens the video in a dialog: a file with native controls, or an embed. The dialog is Dialog (native, invoker-opened, optionally morphing out of the poster); the script does what a closed dialog will not: play on open, pause on close, and for an embed set the iframe src on open and blank it on close so nothing loads or keeps playing behind a closed dialog.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json",
        "https://moonarc.dev/r/dialog.json",
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "ui"
      ],
      "meta": {
        "tier": "B",
        "pro": false,
        "jsBytes": 604,
        "jsBytesWithShared": 2326,
        "intents": [
          "video modal",
          "play video in dialog",
          "hero video popup",
          "youtube embed modal astro",
          "video lightbox",
          "poster with play button opens video"
        ],
        "trigger": [
          "click"
        ],
        "support": {
          "baseline": "newly",
          "needs": [
            "dialog",
            "command"
          ],
          "fallback": "without invoker commands the poster needs polyfill to open the dialog, and plays nothing until it does; without JavaScript a file plays with its native controls and an embed's frame is a link to the player",
          "line": "Chrome 135 · Firefox 144 · Safari 26.2"
        },
        "readout": "<VideoDialog morph>"
      },
      "files": [
        {
          "path": "components/moonarc/VideoDialog.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "weight-wave",
      "type": "registry:component",
      "title": "Weight Wave",
      "description": "A wave of boldness rolls through the letters of a line, each character animating its font weight on its own delay. Pure CSS. Continuous with a variable font; steps between available weights otherwise.",
      "registryDependencies": [
        "https://moonarc.dev/r/base.json"
      ],
      "docs": "Import '@/styles/moonarc.css' once and put <style is:inline>@layer theme, base, components, utilities;</style> first in your <head>, so component CSS never ranks below your resets.",
      "categories": [
        "text"
      ],
      "meta": {
        "tier": "A",
        "pro": false,
        "jsBytes": 0,
        "jsBytesWithShared": 92,
        "intents": [
          "variable font animation",
          "font weight wave",
          "text weight animation",
          "animate font-weight",
          "wavy bold text"
        ],
        "trigger": [
          "always"
        ],
        "support": {
          "baseline": "widely",
          "needs": [
            "font-variation"
          ],
          "line": "Chrome 62 · Firefox 62 · Safari 11"
        },
        "readout": "<WeightWave min={300} max={800}>"
      },
      "files": [
        {
          "path": "components/moonarc/WeightWave.astro",
          "type": "registry:component"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "theme-script",
      "type": "registry:component",
      "title": "Theme script",
      "description": "ThemeToggle's half for <head>: one inline script that puts the stored or the system theme on <html> before the first paint and again after every ClientRouter swap, and gives the toggle window.__maTheme.",
      "docs": "Put <ThemeScript /> in your <head> (import ThemeScript from '@/components/moonarc/ThemeScript.astro'): it applies the stored theme before the first paint, and ThemeToggle stays hidden without it.",
      "files": [
        {
          "path": "components/moonarc/ThemeScript.astro",
          "type": "registry:component"
        },
        {
          "path": "lib/moonarc/theme.ts",
          "type": "registry:lib"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "runtime",
      "type": "registry:lib",
      "title": "Runtime",
      "description": "Lifecycle substrate: onMount, onPage, prefersReducedMotion, refresh. Survives ClientRouter navigation.",
      "files": [
        {
          "path": "lib/moonarc/runtime.ts",
          "type": "registry:lib"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "base",
      "type": "registry:file",
      "title": "Base tokens",
      "description": "Theme-aware motion and colour tokens; declares the cascade-layer order.",
      "files": [
        {
          "path": "moonarc.css",
          "type": "registry:file",
          "target": "src/styles/moonarc.css"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "gsap",
      "type": "registry:lib",
      "title": "GSAP adapter",
      "description": "gsap.context() per page view, revert before swap, ScrollTrigger refresh after paint and fonts.",
      "dependencies": [
        "gsap"
      ],
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json"
      ],
      "files": [
        {
          "path": "lib/moonarc/gsap.ts",
          "type": "registry:lib"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "lenis",
      "type": "registry:lib",
      "title": "Lenis adapter",
      "description": "One Lenis for the life of the document, resynced after every swap.",
      "dependencies": [
        "lenis"
      ],
      "files": [
        {
          "path": "lib/moonarc/lenis.ts",
          "type": "registry:lib"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "canvas",
      "type": "registry:lib",
      "title": "Canvas helper",
      "description": "The shared half of every canvas component: fit (ResizeObserver, DPR ≤ 2), loop (sleeps in a hidden tab), visible, onTheme, colors, num, ms.",
      "files": [
        {
          "path": "lib/moonarc/canvas.ts",
          "type": "registry:lib"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "confetti-fn",
      "type": "registry:lib",
      "title": "confetti()",
      "description": "A burst of paper from a point on one fixed canvas that exists only while pieces fall; physics from custom properties.",
      "registryDependencies": [
        "https://moonarc.dev/r/canvas.json",
        "https://moonarc.dev/r/runtime.json"
      ],
      "files": [
        {
          "path": "lib/moonarc/confetti.ts",
          "type": "registry:lib"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "toast-fn",
      "type": "registry:lib",
      "title": "toast()",
      "description": "Raises a notification in the page's <Toast /> region: it dispatches ma:toast on document, so it works after every navigation and costs nothing on a page without a region.",
      "docs": "Raise a toast from any script: import { toast } from '@/lib/moonarc/toast', then toast({ title: 'Saved' }). The page needs one <Toast />.",
      "files": [
        {
          "path": "lib/moonarc/toast.ts",
          "type": "registry:lib"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "geo",
      "type": "registry:lib",
      "title": "Geography",
      "description": "Land-mask lookup, sphere and map projections, evenly spread dot rows. Shared by DottedMap and Globe.",
      "files": [
        {
          "path": "lib/moonarc/geo.ts",
          "type": "registry:lib"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "land",
      "type": "registry:lib",
      "title": "Land mask",
      "description": "A 1° land bitmask of the world from Natural Earth 110m (public domain), imported on the server only.",
      "files": [
        {
          "path": "lib/moonarc/land.ts",
          "type": "registry:lib"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "contrast",
      "type": "registry:lib",
      "title": "Readable code",
      "description": "readableCode(): a Shiki transformer that moves each token colour in OKLCH lightness until it reads at 4.5 : 1 on its panel. Build time only.",
      "files": [
        {
          "path": "lib/moonarc/contrast.ts",
          "type": "registry:lib"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "morph",
      "type": "registry:lib",
      "title": "Morph",
      "description": "Same-document view transitions, once: vt() with html[data-ma-vt] and the fallbacks, morphOpen / morphClose for a dialog that grows out of its trigger. Shared by Dialog morph, Lightbox and FilterGrid.",
      "files": [
        {
          "path": "lib/moonarc/morph.ts",
          "type": "registry:lib"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "form",
      "type": "registry:lib",
      "title": "Form",
      "description": "bindForms(): every form[data-ma-form] posts with fetch and still posts natively without JavaScript: a pending lock, status texts, done / exists / error, a record for the thanks page that never holds the email, the value back after a failure. Shared by HeroWaitlist and the templates.",
      "registryDependencies": [
        "https://moonarc.dev/r/runtime.json"
      ],
      "files": [
        {
          "path": "lib/moonarc/form.ts",
          "type": "registry:lib"
        }
      ]
    },
    {
      "$schema": "https://ui.shadcn.com/schema/registry-item.json",
      "name": "theme",
      "type": "registry:theme",
      "title": "Theme",
      "description": "The theme contract with its default light and dark values: shadcn variable names, --ma-brand with its derived brand and neutral scales, the accent and status colours, the four tones and what each re-declares inside it, radius and density. Every Pro section reads it; a tweakcn or shadcn theme pasted over it wins.",
      "cssVars": {
        "light": {
          "ma-brand": "oklch(0.5433 0.0974 235)",
          "background": "var(--ma-neutral-50)",
          "foreground": "var(--ma-neutral-900)",
          "card": "oklch(1 0 0)",
          "card-foreground": "var(--ma-neutral-900)",
          "popover": "oklch(1 0 0)",
          "popover-foreground": "var(--ma-neutral-900)",
          "primary": "var(--ma-brand-600)",
          "primary-foreground": "var(--ma-neutral-50)",
          "secondary": "var(--ma-neutral-100)",
          "secondary-foreground": "var(--ma-neutral-900)",
          "muted": "var(--ma-neutral-100)",
          "muted-foreground": "var(--ma-neutral-600)",
          "accent": "var(--ma-neutral-100)",
          "accent-foreground": "var(--ma-neutral-900)",
          "destructive": "oklch(0.55 0.19 25)",
          "destructive-foreground": "var(--ma-neutral-50)",
          "border": "var(--ma-neutral-200)",
          "input": "var(--ma-neutral-500)",
          "ring": "var(--ma-brand-600)",
          "ma-card-shadow": "var(--ma-shadow-1), var(--ma-shadow-2)",
          "ma-success": "oklch(0.5 0.13 150)",
          "ma-success-foreground": "var(--ma-neutral-50)",
          "ma-warning": "#ac5700",
          "ma-warning-foreground": "var(--ma-neutral-50)",
          "ma-info": "var(--primary)",
          "ma-info-foreground": "var(--primary-foreground)",
          "ma-accent-foreground": "var(--ma-neutral-900)",
          "ma-tone-ink-foreground": "var(--ma-neutral-100)",
          "ma-tone-brand-foreground": "var(--ma-neutral-50)",
          "ma-tone-muted-card": "oklch(1 0 0 / 60%)",
          "ma-tone-muted-shadow": "var(--ma-shadow-1)",
          "ma-dim": "0.75",
          "ma-sec-floor": "0.75",
          "ma-sec-floor-brand": "0.9",
          "radius": "0.625rem",
          "ma-radius-sm": "calc(var(--radius) * 0.6)",
          "ma-radius-md": "calc(var(--radius) * 0.8)",
          "ma-radius-lg": "var(--radius)",
          "ma-radius-xl": "calc(var(--radius) * 1.4)",
          "ma-radius-2xl": "calc(var(--radius) * 1.8)",
          "ma-radius-3xl": "calc(var(--radius) * 2.2)",
          "ma-radius-4xl": "calc(var(--radius) * 2.6)",
          "ma-density": "1",
          "ma-shadow-1": "0 1px 2px rgb(0 0 0 / 0.06)",
          "ma-shadow-2": "0 8px 24px -12px rgb(0 0 0 / 0.25)",
          "ma-shadow-3": "0 32px 64px -32px rgb(0 0 0 / 0.5)"
        },
        "dark": {
          "background": "var(--ma-neutral-950)",
          "foreground": "var(--ma-neutral-100)",
          "card": "var(--ma-neutral-900)",
          "card-foreground": "var(--ma-neutral-100)",
          "popover": "var(--ma-neutral-900)",
          "popover-foreground": "var(--ma-neutral-100)",
          "primary": "var(--ma-brand-400)",
          "primary-foreground": "var(--ma-neutral-950)",
          "secondary": "var(--ma-neutral-800)",
          "secondary-foreground": "var(--ma-neutral-100)",
          "muted": "var(--ma-neutral-800)",
          "muted-foreground": "var(--ma-neutral-400)",
          "accent": "var(--ma-neutral-800)",
          "accent-foreground": "var(--ma-neutral-100)",
          "destructive": "oklch(0.7 0.17 25)",
          "destructive-foreground": "var(--ma-neutral-950)",
          "border": "oklch(1 0 0 / 10%)",
          "input": "var(--ma-neutral-600)",
          "ring": "var(--ma-brand-400)",
          "ma-card-shadow": "inset 0 1px 0 oklch(1 0 0 / 5%)",
          "ma-success": "oklch(0.78 0.14 150)",
          "ma-success-foreground": "var(--ma-neutral-950)",
          "ma-warning": "oklch(0.8 0.14 65)",
          "ma-warning-foreground": "var(--ma-neutral-950)",
          "ma-info": "var(--primary)",
          "ma-info-foreground": "var(--primary-foreground)",
          "ma-accent-foreground": "var(--ma-neutral-900)",
          "ma-tone-ink-foreground": "var(--ma-neutral-100)",
          "ma-tone-brand-foreground": "var(--ma-neutral-50)",
          "ma-tone-muted-card": "color-mix(in oklab, var(--foreground) 6%, transparent)",
          "ma-tone-muted-shadow": "inset 0 1px 0 color-mix(in oklab, var(--foreground) 5%, transparent)"
        }
      },
      "css": {
        ":root[data-theme='dark']:not(.dark)": {
          "--background": "var(--ma-neutral-950)",
          "--foreground": "var(--ma-neutral-100)",
          "--card": "var(--ma-neutral-900)",
          "--card-foreground": "var(--ma-neutral-100)",
          "--popover": "var(--ma-neutral-900)",
          "--popover-foreground": "var(--ma-neutral-100)",
          "--primary": "var(--ma-brand-400)",
          "--primary-foreground": "var(--ma-neutral-950)",
          "--secondary": "var(--ma-neutral-800)",
          "--secondary-foreground": "var(--ma-neutral-100)",
          "--muted": "var(--ma-neutral-800)",
          "--muted-foreground": "var(--ma-neutral-400)",
          "--accent": "var(--ma-neutral-800)",
          "--accent-foreground": "var(--ma-neutral-100)",
          "--destructive": "oklch(0.7 0.17 25)",
          "--destructive-foreground": "var(--ma-neutral-950)",
          "--border": "oklch(1 0 0 / 10%)",
          "--input": "var(--ma-neutral-600)",
          "--ring": "var(--ma-brand-400)",
          "--ma-card-shadow": "inset 0 1px 0 oklch(1 0 0 / 5%)",
          "--ma-success": "oklch(0.78 0.14 150)",
          "--ma-success-foreground": "var(--ma-neutral-950)",
          "--ma-warning": "oklch(0.8 0.14 65)",
          "--ma-warning-foreground": "var(--ma-neutral-950)",
          "--ma-info": "var(--primary)",
          "--ma-info-foreground": "var(--primary-foreground)",
          "--ma-accent-foreground": "var(--ma-neutral-900)",
          "--ma-tone-ink-foreground": "var(--ma-neutral-100)",
          "--ma-tone-brand-foreground": "var(--ma-neutral-50)",
          "--ma-tone-muted-card": "color-mix(in oklab, var(--foreground) 6%, transparent)",
          "--ma-tone-muted-shadow": "inset 0 1px 0 color-mix(in oklab, var(--foreground) 5%, transparent)"
        },
        "@media (prefers-color-scheme: dark)": {
          ":root:not([data-theme='light']):not(.light):not(.dark)": {
            "--background": "var(--ma-neutral-950)",
            "--foreground": "var(--ma-neutral-100)",
            "--card": "var(--ma-neutral-900)",
            "--card-foreground": "var(--ma-neutral-100)",
            "--popover": "var(--ma-neutral-900)",
            "--popover-foreground": "var(--ma-neutral-100)",
            "--primary": "var(--ma-brand-400)",
            "--primary-foreground": "var(--ma-neutral-950)",
            "--secondary": "var(--ma-neutral-800)",
            "--secondary-foreground": "var(--ma-neutral-100)",
            "--muted": "var(--ma-neutral-800)",
            "--muted-foreground": "var(--ma-neutral-400)",
            "--accent": "var(--ma-neutral-800)",
            "--accent-foreground": "var(--ma-neutral-100)",
            "--destructive": "oklch(0.7 0.17 25)",
            "--destructive-foreground": "var(--ma-neutral-950)",
            "--border": "oklch(1 0 0 / 10%)",
            "--input": "var(--ma-neutral-600)",
            "--ring": "var(--ma-brand-400)",
            "--ma-card-shadow": "inset 0 1px 0 oklch(1 0 0 / 5%)",
            "--ma-success": "oklch(0.78 0.14 150)",
            "--ma-success-foreground": "var(--ma-neutral-950)",
            "--ma-warning": "oklch(0.8 0.14 65)",
            "--ma-warning-foreground": "var(--ma-neutral-950)",
            "--ma-info": "var(--primary)",
            "--ma-info-foreground": "var(--primary-foreground)",
            "--ma-accent-foreground": "var(--ma-neutral-900)",
            "--ma-tone-ink-foreground": "var(--ma-neutral-100)",
            "--ma-tone-brand-foreground": "var(--ma-neutral-50)",
            "--ma-tone-muted-card": "color-mix(in oklab, var(--foreground) 6%, transparent)",
            "--ma-tone-muted-shadow": "inset 0 1px 0 color-mix(in oklab, var(--foreground) 5%, transparent)"
          }
        }
      },
      "docs": "Import '@/styles/moonarc-theme.css' once (after moonarc.css). Set --ma-brand in your own :root to recolour every section; see https://moonarc.dev/docs/theming/ and https://moonarc.dev/theme/. The dark roles apply under a .dark class, under data-theme=\"dark\" on <html> (@moonarc/theme-script sets it from a stored choice) and in a dark system, so a dark block of your own needs all three selectors. Tailwind's dark: variant follows .dark (the CLI's @custom-variant line); for data-theme, make that line @custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));",
      "files": [
        {
          "path": "moonarc-theme.css",
          "type": "registry:file",
          "target": "src/styles/moonarc-theme.css"
        }
      ]
    }
  ]
}