# XWUI3DAuroraBackground

Animated aurora backdrop. Two to four theme colours flow through each other as
organic, domain-warped curtains - a mesh-gradient hero background, drawn as one
fullscreen fragment shader rather than a displaced plane, so it stays smooth at
any resolution with no banding and effectively no vertex cost.

It is a **background**: the canvas is `aria-hidden` and unconditionally
pointer-transparent (there is no interactive mode - nothing in the field is
clickable), and whatever children the host mounted are re-homed into a content
layer **above** it (`preservesChildren`). The shader deliberately leaves alpha in
the gaps between ribbons, so the host's own `--bg-app` is a visible part of the
composite.

three.js loads in its own lazy chunk (dynamic import inside `mountScene()`), so
this component costs nothing to a consumer who never mounts it.

## Lifecycle

Rendering stops when the host scrolls out of the viewport (`IntersectionObserver`)
and when the tab is hidden (`visibilitychange`) - which matters more here than for
its siblings, since a full-bleed noise shader is the most expensive thing in this
family to leave running. Under `prefers-reduced-motion: reduce` it draws exactly
**one** frame and never opens a rAF loop: a still aurora, which is a perfectly good
gradient.

## Config

| Option | Type | Default | Notes |
|---|---|---|---|
| `colorTokens` | `{ a?, b?, c?, d? }` | `{ a: '--accent-primary', b: '--accent-light' }` | Each entry is a `--custom-property` resolved from the theme, or a literal colour. `c`/`d` optional - omitting them compiles a shader that mixes fewer colours. |
| `speed` | number | `1` | Flow rate, 0-8. `0` freezes the field. |
| `intensity` | number | `1` | Ribbon separation, 0-2. Above 1 they start clipping into flats. |
| `opacity` | number | `0.9` | Overall canvas alpha. |
| `angle` | number | `24` | Flow direction in degrees, clockwise from "to the right". Wrapped, not clamped. |
| `scale` | number | `1.4` | Noise feature size. Larger = smaller, busier ribbons. |
| `blurRadius` | number | `0` | CSS blur on the canvas, in px. Softens the ribbons for free. |
| `quality` | `'low' \| 'medium' \| 'high'` | `'high'` | Pixel ratio + noise octaves. **Recompiles the shader.** |
| `height` | string | `'100%'` | Host height as a CSS length. |
| `className` | string | - | Extra class on the root. |

Data: `seed?: number` - a phase offset in seconds, so a grid of these shows
different moments of the same aurora instead of looking cloned.

## Usage

```ts
import { XWUI3DAuroraBackground } from '@exonware/xwui/basic';

const aurora = new XWUI3DAuroraBackground(
  document.getElementById('hero')!,
  { seed: 3 },
  {
    colorTokens: { a: '--accent-primary', b: '--accent-light', c: '#a855f7' },
    speed: 0.8,
    angle: 35,
    blurRadius: 12,
  }
);

// Swap the whole palette. setColorTokens REPLACES the block rather than merging,
// which is the only way to go from four colours back to two.
aurora.logic.setColorTokens({ a: '#0d9488', b: '#a3e635' });

// After a runtime theme switch, CSS variables change silently - a canvas cannot
// inherit them, so re-read them explicitly.
aurora.refreshTheme();
```

As a custom element (`colorTokens` takes JSON):

```html
<xwui-3d-aurora-background
  color-tokens='{"a":"--accent-primary","b":"#38bdf8","c":"#a855f7"}'
  speed="0.7"
  height="520px"
>
  <h1>Build once. Ship everywhere.</h1>
</xwui-3d-aurora-background>
```
