<!-- 04_VISUAL/xwui/xwui-lib/xwui-lib-super/src/navigation/XWUIStepTrack/XWUIStepTrack.md -->
# XWUIStepTrack

An ordered set of steps joined by a connector that fills. One model (steps with a state), one geometry, three
semantics: `steps` is a wizard stepper (`nav` > `ol`, visited steps are buttons, the current one is
`aria-current="step"`), `tabs` is a tab strip with optional autoplay (`tablist`, the panels belong to the host), and
`list` is an ordered list for approval chains, strips of clickable cards and rising ladders of levels. Markers are
numbers, icons, avatars (a projected basic `XWUIAvatar`), dots or whole cards. Autoplay runs on the shared basic
playback controller (`_shared/playback`), so it pauses off screen and in a hidden tab, never starts under reduced
motion or on a coarse pointer, and always shows a Pause control. Contract: plnx `REF_06_GAPS.md` section 2.2, C03.

## Basic Usage

```example
file: examples/BasicUsage.ts
html: examples/BasicUsage.html
title: Basic Usage
description: Six-step connect wizard on step 4: visited steps are buttons, later steps wait, Next and Back move it.
```

```example
file: examples/AutoplayTour.ts
html: examples/AutoplayTour.html
title: Autoplay Tour
description: Icon tab strip that advances every 3.5 s with a visible Pause control; a pick stops it; the host owns the panel.
```

```example
file: examples/ApprovalChain.ts
html: examples/ApprovalChain.html
title: Approval Chain
description: A vertical chain of people: avatar markers with state badges, visible state pills, role and due date.
```

```example
file: examples/SequenceStrip.ts
html: examples/SequenceStrip.html
title: Sequence Strip
description: Clickable numbered cards on a rail with a travelling pulse; a column when the container is narrow.
```

```example
file: examples/LevelStairs.ts
html: examples/LevelStairs.html
title: Level Stairs
description: A rising ladder of maturity levels with a You are here marker; stacks below 640 px.
```

## Data

| Field | What it is |
| --- | --- |
| `steps[]` | `{ id, label, sub?, ordinal?, icon?, hue?, person?: { name, initials?, src?, hue? }, role?, state?, stateLabel?, reason?, optional?, href?, panelId? }`. Entries without an id or a label are dropped; a repeated id keeps the first. |
| `currentId` | The current step. Host-owned: `stepSelect` reports a change and the component moves to it. |
| `maxReachedId` | The furthest step reached. With `navigation: 'visited'` every step up to it stays reachable after going back. |
| `loading` | Skeleton steps, `aria-busy="true"`. |
| `error` | The message as `role="alert"` instead of the steps. |

`state` is `done`, `current`, `upcoming`, `error`, `locked`, `waiting`, `returned` or `running`. Unset, it is derived:
before the current step (or up to `maxReachedId`) done, at it current, after it upcoming. Tabs never derive done.
`icon` is a built-in glyph name (`check lock alert clock return spinner grid layout user users activity shield upload
refresh trend file dollar shuffle layers link flag plug key folder list eye play pause`) or SVG path data. `hue` is a
token NAME (`'teal'` resolves to `var(--xwui-hue-teal, var(--xwui-hue-slate))`); an undeclared name falls back to the
accent. `href` renders a reachable step as a link; only http, https, mailto, relative paths and `#fragment` pass.

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `semantics` | `'steps'` | `steps`, `tabs` or `list` (see above). |
| `marker` | `icon` for tabs, else `number` | `number`, `icon`, `avatar`, `dot` or `card`. |
| `layout` | `'row'` | `row`, `column`, `auto` (a row that becomes a column when narrow or crowded) or `stairs` (blocks rise toward the inline end; stacked when narrow). |
| `navigation` | `visited` for steps, `all` for tabs, `none` for list | Which steps are buttons. Locked steps are always `aria-disabled` buttons that report `blocked`. |
| `connector` | `rail-pulse` for cards, `line` for tabs, else `fill` | `fill` colours the connector from a done step into a reached one; `rail-pulse` draws one rail with a travelling dot. |
| `labelPlacement` | below for icon and avatar rows, else beside | Label beside or under the marker. |
| `autoplay` | none | `{ intervalMs, stopOnPick, pauseOffscreen, progress: 'bar' \| 'ring' \| 'none' }`. Interval floor 500 ms. |
| `compact` | `'auto'` | Steps semantics: `summary` always draws "Step n of total: label"; `auto` does when the container is below `compactBelow` OR the row cannot fit its labels. |
| `compactBelow` | `480` | Container width in CSS px for `auto` layout and compact. Measured on the container (ResizeObserver), not the viewport. |
| `summaryProgress` | `'bar'` | The summary's drawing: `bar` or `ring`. |
| `size` | `'md'` | `sm` or `md`. |
| `labels` | locale pack | `stepOf, done, current, upcoming, locked, error, waiting, returned, running, optional, play, pause, navLabel, here`; unset keys read `xwui.step_track.*`. |
| `title`, `ariaLabel`, `emptyText`, `skeletonSteps` | none, navLabel, pack, 4 | Heading, accessible name, empty text, skeleton count. |
| `hue` | page accent | Hue NAME for current and filled marks. |
| `pulseMs`, `pulseDelayMs` | 2400, 0 | Rail pulse timing; stagger several strips on one page with the delay. |
| `locale`, `numberingSystem` | page language, `'latn'` | Western digits unless `arab` or `auto`. |

## Events and methods

- `onStepSelect({ id, index, source })`: `source` is `pointer`, `keyboard`, `auto` (autoplay) or `api`.
- `onAutoplayChange(playing)`: the autoplay intent changed (Pause, Play, a pick, focus entering the strip).
- `onBlocked(id, reason)`: a locked or unreachable step was picked; nothing moved. `reason` is the step's `reason`, else `labels.locked`.
- `select(id)`, `getCurrentId()`, `getTabId(stepId)` (for the panel's `aria-labelledby`), `play()`, `pause()`,
  `isPlaying()`, `updateData(patch)`, `updateConfig(patch)`, `getElement()`, `destroy()`.
- `XWUIStepTrack.projectView(data, config)`: a still render for a parent view tree (no clock, reduced motion).
- Constructor: `new XWUIStepTrack(container, data, config?, createViewMount?, playback?)`; `playback` is the test seam
  `{ clock, environment }` of the shared controller.

## Accessibility and RTL

- `steps`: `nav aria-label` > `ol`; reachable steps are buttons (or links), the current one `aria-current="step"`,
  unreachable later steps are plain text, locked steps are `aria-disabled` buttons with the reason visible.
- `tabs`: `tablist` of `tab` buttons with `aria-selected`, `aria-controls` (the step's `panelId`) and a roving tab stop.
  Arrows follow the reading direction (mirrored in RTL), Up and Down in a column, Home and End jump; focus follows the
  selection; locked tabs are skipped. The strip scrolls on narrow screens and keeps the current tab in view.
- Autoplay: the Pause or Play control is visible whenever autoplay is configured (WCAG 2.2.2); keyboard focus inside the
  strip holds it; a pick stops it (`stopOnPick`); reduced motion starts it paused on the host's step; destroy stops the clock.
- Every state is spoken: a visible `stateLabel` pill or a hidden word (Completed, Locked, Needs attention, Returned,
  In progress, Waiting). Glyphs, weight and dashed edges go with every state colour.
- Text twin: connectors, rail, pulse, timers, stairs height and the "You are here" dot are `aria-hidden` and repeat
  what the list order, `aria-current` and the words already say.
- RTL: logical properties only; the fill, the rail pulse, the progress and the stairs follow the inline direction under a
  parent `dir="rtl"`. Names, roles and pills are `dir="auto"` isolates. Digits stay Western by default.

```api
```
