# Flowstage Motion — integration reference

Four vanilla JavaScript SVG modules. No dependencies, build step, package registry, or framework adapter is required. This is a source-download distribution.

## Files

Download `lib/motion.css` and `lib/motion.js` relative to the Flowstage site root. Keep both files in your application's `lib/` directory. The scripts create `window.FlowstageMotion`.

```html
<link rel="stylesheet" href="./lib/motion.css">
<div id="signal"></div>
<script src="./lib/motion.js"></script>
<script>
  const signal = FlowstageMotion.mount(document.getElementById('signal'), {
    type: 'path-pulse',
    speed: 1,
    autoplay: true,
    reducedMotion: false,
    label: 'An event travels from the input to the output.'
  });
</script>
```

The container fills the width of its parent. The SVG uses a `480 × 260` viewBox and keeps its aspect ratio. Give the parent a max-width when needed. No application data is fetched or transmitted by the runtime.

## Modules

| Type | Anatomy | Behavior | Static reduced-motion state |
| --- | --- | --- | --- |
| `path-pulse` | Input node, curved wire, gradient pulse, output node | A short lilac/pink signal travels along a path using a normalized dash offset. | A pulse remains midway along the connection. |
| `orbit` | Core, two elliptical tracks, three signal dots | Dot positions follow ellipses at different speeds. | Dots stay at distinct positions on the tracks. |
| `draw-path` | Input, junction, three output nodes, four segments | The trunk and each branch draw in sequence, hold, and fade before restarting. | All three output connections are visible. |
| `state-morph` | Shape, waiting ring, completion mark, state label | Corresponding cubic Bézier control points interpolate between a circle and a rounded square. The label moves through queued, processing, ready. | Rounded square and ready mark. |

## Options

`FlowstageMotion.mount(container, options)` returns one instance. Container must be a DOM element; invalid containers and unknown types throw.

| Option | Default | Meaning |
| --- | --- | --- |
| `type` | `'path-pulse'` | One of the four type names above. |
| `speed` | `1` | Finite number, clamped to `0.25`–`3`. Non-numbers throw. |
| `autoplay` | `true` | `false` starts paused. |
| `reducedMotion` | `false` | `true` forces a static view. `false` still respects the system preference. |
| `label` | Module description | Accessible SVG title. Assigned as text, never HTML. |

## Instance API

| Method / property | Result |
| --- | --- |
| `play()` | Requests playback, unless reduced motion or a hidden document prevents it. Returns the instance. |
| `pause()` | Freezes the current animation position. Returns the instance. |
| `setSpeed(number)` | Changes speed without resetting progress. Same validation as the option. Returns the instance. |
| `setReducedMotion(boolean)` | Enables or clears the local static preference. Cannot override system reduced motion. Returns the instance. |
| `restart()` | Resets timeline to zero and keeps the current play/pause preference. Returns the instance. |
| `getState()` | Returns `{ type, playing, requestedPlaying, reducedMotion, systemReducedMotion, speed, destroyed }`. |
| `element` | The generated `.fsm` wrapper. |
| `destroy()` | Cancels animation, removes preference/visibility listeners and the generated wrapper. Safe to call twice. |

The container receives a `flowstage:motionchange` event with `event.detail` equal to `getState()` when controls or preferences change. It is not dispatched every animation frame. `playing` describes effective playback; `requestedPlaying` preserves the user's intent while the document is hidden or reduced motion is active.

## Playback controls

Provide a visible pause control for any automatically looping animation. For example:

```js
const button = document.querySelector('#toggle');
function update() {
  const state = signal.getState();
  button.disabled = state.reducedMotion;
  button.textContent = state.requestedPlaying ? 'Pause animation' : 'Play animation';
}
button.addEventListener('click', () => {
  signal.getState().requestedPlaying ? signal.pause() : signal.play();
});
document.getElementById('signal').addEventListener('flowstage:motionchange', update);
update();
```

Call `signal.destroy()` in a component cleanup or before replacing the containing view. Multiple instances are supported; SVG IDs are unique within one runtime load. Load the runtime once per document.

## Tokens

Override CSS variables on a container's `.fsm` descendant. These values are scoped to each module.

```css
#signal .fsm {
  --fsm-accent: #b9a2ff;
  --fsm-pink: #e5add0;
  --fsm-wire: #555b68;
  --fsm-text: #ededf0;
  --fsm-muted: #9298a5;
  --fsm-panel: #15181e;
}
```

## Accessibility and behavior

Each SVG has `role="img"`, a title, and a description. Do not use the animation as the only indication of an application's live status; keep real status in ordinary visible text outside the illustrative SVG. OS reduced-motion changes are observed immediately. Animation work stops while the document is hidden. Local reduced-motion toggles can add a static preference but cannot cancel the system setting.

The library only constructs SVG elements from its own geometry. `label` is inserted with `textContent`. It accepts no arbitrary SVG markup or remote scripts. Review downloaded source before integrating it.

## Complete standalone export

The gallery's **Copy HTML** action embeds the actual CSS and JavaScript source into a complete HTML document, preserving the selected type, speed, and local reduced-motion choice. Save it as an `.html` file to run offline. A pause control and a visible reduced-motion message are included. The smaller **Copy snippet** action assumes the two library files have already been saved under `./lib/`.
