<!-- 04_VISUAL/xwui/xwui-lib/xwui-lib-super/src/display/XWUIBeamLayer/XWUIBeamLayer.md -->
# XWUIBeamLayer

A full-size SVG overlay that draws beams between anchors. An anchor is a percent point of the layer or a measured element
(an element or a selector, re-measured with `ResizeObserver`), so one layer links scene nodes, hub diagrams, portal cards and
ordinary page elements alike. Beams are lines, quadratic or cubic curves, or elbows, with a direction, travelling dots or a
marching dash, pulse bursts, state tones, labels, optional hover and selection, and a list of the connections for assistive
technology when beams carry meaning. It composes nothing: the host owns the nodes; the layer only draws between them.

## Basic Usage

```example
file: examples/BasicUsage.ts
html: examples/BasicUsage.html
title: Basic Usage
description: Two percent anchors joined by a flowing quadratic beam.
```

## Placement

The layer root is `position: absolute; inset: 0`, so it fills the nearest positioned ancestor: put its container inside the
host (`position: relative`) with `display: contents` or as a plain block. It never takes pointer events itself
(`pointer-events: none`); `--xwui-beam-layer-z` (default 1) sets its stacking order, so nodes above it stay clickable.

## Data

| Field | Shape |
| --- | --- |
| `anchors[]` | `{ id, x?, y?, el?, side?, label? }`: `x`, `y` in percent (mirrored under RTL); or `el` (element or selector, looked up inside the host, then the document); `side` `center` (default), `top`, `bottom`, `start`, `end` (start and end follow the reading direction); `label` names the anchor in the text twin |
| `beams[]` | `{ id, from, to, shape?, curvature?, tone?, hue?, direction?, flow?, speed?, pulse?, state?, label? }` |
| `selectedId` | the selected beam id or null (host-owned; `beamSelect` reports a change) |

Beam fields: `shape` `line` (default), `quadratic`, `cubic`, `elbow`; `curvature` quadratic bend as a share of the length (0.25),
cubic handle reach (0.5), elbow turn position (0.5); `tone` `brand` (default), `ok`, `warn`, `bad`, `info`, `muted`; `hue` a
named hue (`--xwui-hue-<name>`) that wins over the tone; `direction` `forward` (default), `reverse`, `both`, `none`; `flow`
`off` (default), `dots`, `dash`; `speed` multiplier (1); `pulse` a repeating burst plus a ping at the middle; `state` `idle`
(default), `active` (brighter, wider), `error` (bad tone, short broken line, no flow), `paused` (sparse dash, no flow).

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `nonScalingStroke` | `true` | Stroke width in screen pixels whatever the scale. |
| `mirrorInRtl` | `true` | Mirror percent anchors and quadratic bends under `dir="rtl"`. |
| `pointerEvents` | `'none'` | `'beams'`: beams take hover and click through a wide hit stroke, and a keyboard list is added. |
| `maxDots` | `3` | Most travelling dots per beam (one per 40 px of length). |
| `describe` | `'none'` | `'hidden-list'`: a visually hidden list of the connections ("Plan to Website embed: Active"). |
| `ariaLabel` | `xwui.beam_layer.title` | Accessible name of that list. |
| `pulseMs` | `900` | Length of one `pulse()` burst. |

## Events and methods

Events: `onBeamSelect(id)`, `onBeamHover(id | null)`, `onAnchorsMeasured({ resolved, unresolved[], width, height })`; the same
go out on the host as bubbling DOM events `beam-select`, `beam-hover`, `anchors-measured` (for `<xwui-beam-layer>`).

Methods: `pulse(id)` (one burst; a second call restarts it), `remeasure()` (measure now: call it when anchors MOVE without
resizing, such as a rotating orbit; resizes and direction changes are measured on their own), `select(id)`, `getSelectedId()`,
`pause()` / `play()` (host-level motion pause), `isMoving()`, `updateData(patch)`, `updateConfig(patch)`, `getElement()`,
`destroy()`. `XWUIBeamLayer.projectView(data, config)` composes a still layer into a parent's view tree (percent anchors only).

## States

| State | What shows |
| --- | --- |
| empty | `data-state="empty"`: an empty SVG, no list |
| measuring | `data-state="measuring"`, `data-waiting=<n>`: beams whose element anchors have no box yet are not drawn (never to a corner); `anchorsMeasured.unresolved` names them |
| ready | every beam drawn; before the first measurement percent anchors draw in a 100 x 100 box, labels and pings wait for the measured box |
| reduced motion, off screen, hidden tab, host pause | `--still`: dots and dashes stand still; a `pulse()` burst is a steady highlight for its duration |

## Accessibility and RTL

The SVG is `aria-hidden`: a drawing is never the only carrier of meaning. With `describe: 'hidden-list'` or
`pointerEvents: 'beams'` the layer adds the connections as text, each anchor name in its own `<bdi>`. With `pointerEvents:
'beams'` that list is a `listbox`: Tab enters it and it becomes visible while it holds focus; ArrowDown and ArrowUp move (the
ends wrap), Home and End jump, Enter and Space select; focusing an option highlights its beam. Selection is a wider stroke with a
halo plus `aria-selected`, never colour alone; paused and error have their own dash patterns. RTL: direction comes from the
parent `dir`; percent anchors and quadratic bends mirror (`mirrorInRtl`), measured elements are where the browser laid them out
and `start` / `end` sides follow the direction. Motion is CSS only (`stroke-dashoffset`), and stops under reduced motion in JS
and CSS.

## Tokens

Colours: `--accent-primary`, `--xwui-health-on-track`, `--xwui-health-at-risk`, `--xwui-health-off-track`, `--xwui-hue-sky`,
`--text-secondary`, named hues through `hueVar`. Knobs: `--xwui-beam-layer-z`, `-stroke`, `-stroke-strong`, `-dot`, `-dash`,
`-dash-gap`, `-label-halo`. The nine core hue names (`violet`, `cyan`, ...) exist only in xwflow-neon; elsewhere they fall
back to slate, so pass the extended names (`purple`, `sky`, `teal`, `indigo`, `fuchsia`, `rose`, `slate`, `yellow`).

```api
```
