# Plasma (Moonarc)

Draws glowing ribbons of light drifting through each other: four sine fields interfere on the GPU, the sum folds into soft bands, and each band glows in a colour sliding between two tones with a hot core at its peak. The ground between the ribbons is the page, so it reads on either theme: neon on dark, pastel on light. The pointer draws the plasma toward it. Every constant is a custom property re-read when the element's style changes. Without WebGL2 or JavaScript a still two-tone glow stands in. Fills its positioned parent.

- Pro block. Install: `npx shadcn@latest add @moonarc-pro/plasma` (license key required)
- Tier C · category background · trigger always, pointer
- Readout: `<Plasma bands={1.6} glow={1}>`
- Browser support: widely (Chrome 56 · Firefox 51 · Safari 15); elsewhere: without WebGL2, a still glow in both tones
- Measured cost: 723 B raw JS · 487 B gzip · + runtime + shader + canvas + gl, 10.2 kB raw in all (with dependencies 10.2 kB raw; CSS 5.2 kB raw)
- Page: https://moonarc.dev/components/plasma/

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `color` | `string` | `'oklch(0.62 0.2 290)'` | First tone; any CSS colour, theme tokens included. |
| `second` | `string` | `'oklch(0.7 0.16 200)'` | Second tone the ribbons slide toward. |
| `core` | `string` | `first tone lifted 70 % toward white` | The hottest part of a ribbon. |
| `scale` | `number` | `3` | Field scale: larger is busier. |
| `speed` | `number` | `1` | Drift speed multiplier; accumulated, so a change never jumps. |
| `bands` | `number` | `1.6` | How many ribbons the field folds into. |
| `glow` | `number` | `1` | Ribbon brightness and width. |
| `pull` | `number` | `0.5` | How strongly the pointer draws the plasma; 0 turns the pointer off. |

## Usage

```astro
<section class="relative min-h-[60vh]">
  <Plasma color="var(--primary)" second="oklch(0.7 0.16 200)" />
  <h1 class="relative">Plasma background</h1>
</section>
```

## Reduced motion

No loop: one frame at a fixed moment, drawn once; the pointer does not pull it.

## With ClientRouter

Bound through the shared runtime: loop, observers and pointer listener are released before the swap and the WebGL context is lost on purpose after it; five round trips leave one context. Under transition:persist the canvas keeps its context and starts again on the next page.

## Craft

- Interference, not noise: four sines (one of them a ring whose centre drifts) sum to a field that never repeats in view and costs a handful of instructions per pixel.
- Folded by a cosine into bands and raised to the fourth power: thin bright ribbons with soft falloff, and real ground between them.
- The tone slides along the field value, so colour follows the shape of the ribbons instead of sweeping across the box.
- Premultiplied over a transparent canvas: neon on a dark page, pastel light on a light one, from the same two tokens.
- The pointer pulls the coordinates toward it with a gaussian falloff: the ribbons bend toward the cursor instead of a glow following it.

## Replaces

- Plasma (React Bits)
- Plasma / neon shader backgrounds

## Source

Pro block. The source is served by the license-gated registry: `npx shadcn@latest add @moonarc-pro/plasma` with a key in components.json (https://moonarc.dev/account/). Related free primitives: aurora.
