# Flow Particles (Moonarc)

Moves thousands of particles along an invisible current, leaving fading trails. Positions live in a float texture that a GPU pass moves along curl noise, which is divergence-free, so the particles swirl instead of bunching. Each frame they are drawn as points into a trail texture that fades, shown in two tones on the page's ground. The pointer drags the current with it. Every constant is a custom property re-read when the element's style changes. Without WebGL2 or a colour-renderable float texture, or without JavaScript, a still wisp of lines stands in. Fills its positioned parent.

- Pro block. Install: `npx shadcn@latest add @moonarc-pro/flow-particles` (license key required)
- Tier C · category background · trigger always, pointer
- Readout: `<FlowParticles count={14000}>`
- Browser support: widely (Chrome 56 · Firefox 51 · Safari 15); elsewhere: without WebGL2 or a colour-renderable float texture (EXT_color_buffer_float), a still wisp of curved lines
- Measured cost: 2.9 kB raw JS · 1.6 kB gzip · + runtime + canvas + gl, 11.4 kB raw in all (with dependencies 11.4 kB raw; CSS 5.2 kB raw)
- Page: https://moonarc.dev/components/flow-particles/

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `color` | `string` | `'oklch(0.66 0.2 292)'` | Trail colour; any CSS colour, theme tokens included. |
| `core` | `string` | `color lifted 50 % toward white` | The colour where trails are densest. |
| `count` | `number` | `14000` | Particles for a 1440 × 900 box; a card or a hero gets the same density (rounded up to a square texture, 16² to 512²). Read when the field is created. |
| `scale` | `number` | `2.2` | Current scale: eddies across the short side. |
| `speed` | `number` | `1` | Flow speed multiplier. |
| `trail` | `number` | `2.6` | How fast trails fade, per second. Lower is longer. |
| `drag` | `number` | `1` | How strongly the pointer drags the current; 0 turns it off. |

## Usage

```astro
<section class="relative min-h-[60vh]">
  <FlowParticles color="var(--primary)" />
  <h1 class="relative">Particles on a current</h1>
</section>
```

## Reduced motion

No loop: three seconds of flow are simulated at once and the trails drawn as a still; the pointer does not drag 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

- GPGPU: every particle is a texel (xy, age, seed); one fragment pass moves them all, and the point pass reads its position by gl_VertexID. There is no vertex buffer and no CPU work per particle.
- Full float for positions: half float rounds a slow step to zero past x = 0.5 and the flow turns into vertical lines on the right half. Trails stay half float.
- Curl of a noise potential: the velocity has no divergence, so particles circulate in eddies instead of draining into sinks.
- Trails at half the drawing buffer, faded by e^(−trail·dt) before the points are added: the fade is frame-rate independent and the target is a quarter of the pixels.
- Respawn from the particle's own seed and the time, not its position: positions are correlated, so hashing them clumped the newborns into dotted patches.

## Replaces

- Particles / flow field (React Bits Pro)
- GPGPU particle backgrounds

## Source

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