# Viewer Animation and Guided Tour Integration

Milestone 4 now includes a runtime bridge between the standardized machine animation modules, guided tours, and viewer UI state.

## Runtime bridge

The integration layer is intentionally small and page-friendly:

- `src/animations/playerAdapter.ts` normalizes `MachineAnimationPlayer` snapshots and exposes a stable control surface: play, pause, resume, restart, stop, RPM, time scale, loop, seek, and step forward/back.
- `src/animations/guidedTourAdapter.ts` normalizes guided tour player snapshots and exposes start, pause, resume, restart, previous/next, and go-to-step controls.
- `src/components/animation/AnimationRuntimeBridge.tsx` owns a player instance, subscribes to snapshots, handles reduced-motion preferences, and feeds the existing `AnimationTransport` component through compatibility props.
- `src/components/animation/GuidedTourRuntimeBridge.tsx` owns a guided tour instance, subscribes to active-step/highlight/camera data, and feeds the existing `GuidedTourOverlay` component through compatibility props.

The bridge passes both the current snapshot and control callbacks to UI components. This completes the missing connection where `MachineAnimationPlayer` data reaches transport controls and where transport callbacks call the active player instance.

## Procedural demo experience

`src/modules/machines/procedural/ProceduralDemoExperience.tsx` is a complete, self-contained viewer composition for the eight procedural machines:

- four-stroke petrol engine
- planetary gearbox
- differential gear
- centrifugal pump
- Geneva drive
- ball bearing
- disc brake caliper
- Wankel rotary engine

It wires:

- procedural machine scene rendering inside React Three Fiber
- animation snapshots into scene props
- guided-tour highlighted part IDs into scene props
- per-part visibility and opacity
- selected/hovered/highlighted part state
- exploded view amount
- wireframe and label toggles
- camera presets
- detail drawer
- shareable URL state

The page adapter `src/pages/ProceduralDemoPage.tsx` can be mounted by the existing router at a route such as `/procedural/:machineId`, `/machines/:machineId/demo`, or as a fallback machine viewer route.

## Manifest validation

`src/modules/machines/procedural/proceduralDemoCatalog.ts` imports each machine module as a namespace and resolves the exact exported machine definition at runtime. This avoids fragile named-export drift while still validating that every required module resolves to a machine definition with a scene component, animation module, guided tour, and part metadata.

Use this during development or tests:

```ts
import { assertProceduralDemoCatalog } from './src/modules/machines/procedural/proceduralDemoManifest';

assertProceduralDemoCatalog();
```

The validation report is also exported as `proceduralDemoCatalogValidationReport`.

## URL state

The procedural viewer encodes the important share state into query parameters:

- `machine`
- `part`
- `explode`
- `wireframe`
- `labels`
- `camera`
- `hidden`
- `opacity`

The `Share` button writes the current URL to the clipboard.

## Router integration

To expose the demo page, import the page into the existing app router:

```tsx
import ProceduralDemoPage from './pages/ProceduralDemoPage';

// Example route element:
// <Route path="/procedural/:machineId" element={<ProceduralDemoPage />} />
```

If the app uses a custom page switch instead of React Router, render `<ProceduralDemoPage />` from the existing machine-view branch. The page reads `?machine=` first, then the last path segment, so both `/procedural?machine=wankel-rotary-engine` and `/procedural/wankel-rotary-engine` work.

## Maintainer verification notes

Because this pass cannot run the compiler here, verify the following APIs against the resolved dependency versions after install:

- `@react-three/drei`: `Environment`, `OrbitControls`, `ContactShadows`, and `Html` props.
- `@react-three/fiber`: `Canvas`, `useThree`, and the `makeDefault` controls registration behavior.
- Existing local components: exported names from `AnimationTransport`, `GuidedTourOverlay`, `MachineAnimationPlayer`, and `GuidedTourPlayer`.

The integration uses compatibility adapters for these local exports, but a local build should still confirm there are no project-specific lint restrictions around dynamic compatibility props.
