# Procedural Demo Set and Guided Tour Runtime

Milestone 4 ships a representative procedural machine set for the animation system. The demo set is intentionally data-driven: each machine module owns its geometry, part metadata, engineering facts, animation lifecycle, and guided tour content, while `proceduralDemoManifest.ts` provides a stable catalogue/runtime adapter for loading them without hard-coding viewer logic.

## Included procedural machines

| Machine | Category | Motion demonstrated | Primary highlighted parts |
| --- | --- | --- | --- |
| Four Stroke Petrol Engine | Engines | 720° Otto cycle with valve timing, piston travel, crankshaft/camshaft relationship | Piston, crankshaft, camshaft, intake valve, exhaust valve |
| Planetary Gearbox | Gearboxes & Drives | Sun/planet/ring epicyclic mesh and carrier rotation | Sun gear, planet gears, ring gear, carrier |
| Differential Gear | Gearboxes & Drives | Equal torque split with wheel speed difference while cornering | Ring gear, spider gears, side gears |
| Centrifugal Pump | Pumps & Fluid Systems | Impeller acceleration, volute pressure recovery, cavitation cueing | Impeller, volute, inlet, outlet, shaft |
| Geneva Drive | Mechanisms | Continuous crank rotation to intermittent indexed output | Driver, pin, Geneva wheel, locking disk |
| Ball Bearing | Structural / Other | Rolling contact, cage precession, load distribution | Inner race, outer race, balls, cage, load vector |
| Disc Brake Caliper | Structural / Other | Hydraulic clamp/release cycle, rotor drag, friction heat cueing | Rotor, caliper body, pads, pistons, hydraulic line |
| Wankel Rotary Engine | Engines | Eccentric rotor orbit, chamber volume change, port timing | Rotor, housing, eccentric shaft, intake port, exhaust port |

## Runtime loading

Use the manifest adapter for catalogue or viewer integrations:

```ts
import {
  loadProceduralDemoMachine,
  proceduralDemoMachineManifest,
} from '../src/modules/machines/procedural/demoRuntime';

const entry = proceduralDemoMachineManifest[0];
const machine = await loadProceduralDemoMachine(entry.id);

console.log(machine.title, machine.parts, machine.guidedTour);
```

For React views, use the hook:

```tsx
import { useProceduralDemoMachine } from '../src/modules/machines/procedural/demoRuntime';

export function DemoMachinePanel({ machineId }: { machineId: string }) {
  const { status, machine, error, reload } = useProceduralDemoMachine(machineId);

  if (status === 'loading') return <p>Loading machine…</p>;
  if (status === 'error') return <button onClick={reload}>{error?.message}</button>;
  if (!machine) return null;

  return (
    <section>
      <h1>{machine.title}</h1>
      <p>{machine.description}</p>
      <p>{machine.parts.length} modeled parts</p>
    </section>
  );
}
```

The normalizer accepts several common machine-module shapes (`default`, `machine`, `definition`, `Scene`, `animationModule`, `parts`, `engineeringFacts`, `guidedTour`) so the core catalogue remains resilient as future machines are added.

## Guided tours

`GuidedTourPlayer` is a GSAP-ticker-backed tour controller that advances steps using requestAnimationFrame timing through `gsap.ticker`. It supports:

- play, pause, resume, restart, stop
- manual next/previous step navigation
- looped or one-shot tours
- time scale adjustment
- reduced-motion mode with shortened step durations and instant camera moves
- lifecycle hooks: `onEnter`, `onFrame`, `onExit`
- host callbacks for camera poses, part highlighting, part isolation, annotations, explode factor, machine playback, and RPM

A viewer supplies a host object:

```ts
import {
  GuidedTourPlayer,
  createThreeCameraTourHost,
} from '../src/animations/tourRuntime';

const host = createThreeCameraTourHost(camera, {
  controls: orbitControls,
  highlightParts: (partIds) => setHighlightedParts(partIds),
  selectPart: (partId) => setSelectedPart(partId),
  setExplodeFactor: (explodeFactor) => setExplode(explodeFactor ?? 0),
  setMachinePlayback: (playback) => {
    if (playback === 'pause') animation.pause();
    else animation.play();
  },
  setRpm: (rpm) => animation.setRpm(rpm),
});

const player = new GuidedTourPlayer(machine.guidedTour, host, {
  defaultStepDurationSeconds: 5,
  loop: false,
});
```

React integrations should prefer `useGuidedTourPlayer`, which subscribes to snapshots and cleans up the GSAP ticker on unmount.

## UI controls

The new animation UI components are intentionally presentation-only:

- `AnimationTransport` renders playback, restart, step-through, RPM, time-scale, and loop controls.
- `GuidedTourOverlay` renders tour captions, step progress, keyboard controls, and direct step navigation.

They accept plain snapshots and callback objects, so they can be connected to the existing `MachineAnimationPlayer`, Zustand stores, or a page-level adapter without coupling the controls to machine-specific animation code.

## Authoring requirements for new machines

A new procedural machine should export at least:

1. A React scene component.
2. A standard animation module compatible with the milestone animation player.
3. Part metadata with stable IDs.
4. Engineering facts.
5. Guided tour steps using the `GuidedTourStepDefinition` shape.
6. A manifest entry with category, difficulty, keywords, RPM range, and featured part IDs.

Stable part IDs are important because they are used by:

- URL view-state sharing
- part visibility and opacity controls
- selected-part detail drawers
- guided-tour highlights
- annotations and labels
- accessibility announcements

## Reduced-motion behavior

Reduced-motion preference is detected with `prefers-reduced-motion: reduce` in `usePrefersReducedMotion`. When enabled:

- tour auto-start is suppressed unless explicitly allowed
- tour camera transitions are immediate
- default step durations are capped by `reducedMotionStepDurationSeconds`
- controls remain keyboard-accessible and fully functional

Machine animations should still honor their own reduced-motion policy, typically by starting paused and requiring explicit user playback.

## Quality checklist

Before marking a new machine production-ready:

- The loop has no visible discontinuity at the cycle seam.
- RPM scaling changes speed without changing kinematic relationships.
- Step-through advances to meaningful mechanical phases.
- Every selectable part has a human-readable name and useful description.
- Guided tour step highlights reference real part IDs.
- Camera poses avoid clipping through the model at desktop, tablet, and mobile aspect ratios.
- The scene is legible in solid, transparent, and wireframe display modes.
- Motion remains understandable at `0.1×` and does not become visually noisy at `3×`.
- Reduced-motion mode does not auto-animate camera or machine movement.
- All host subscriptions/tickers/tweens are disposed when leaving the viewer.
