# Procedural Demo Routing Integration

Milestone 4 now exposes the procedural animation lab as a mounted application route instead of a detached demo page.

## Mounted routes

The route adapter in `src/routes/proceduralDemoRoutes.tsx` recognises:

- `/procedural-demos`
- `/procedural-demos/:machineId`
- `/procedural-demo/:machineId`
- `/viewer/:machineId` when `machineId` is one of the procedural demo IDs
- `/machines/:machineId` when `machineId` is one of the procedural demo IDs
- `/machines/procedural/:machineId`

The current `src/App.tsx` mounts `ProceduralDemoPage` for machine routes and renders a premium catalogue landing view for `/`, `/catalogue`, `/catalog`, and `/procedural-demos`.

## Route utilities

Use these helpers when integrating with a different router shell:

```tsx
import {
  buildProceduralDemoPath,
  matchProceduralDemoRoute,
  ProceduralDemoRouteOutlet,
} from './routes/proceduralDemoRoutes';

const href = buildProceduralDemoPath('four-stroke-petrol-engine');
const match = matchProceduralDemoRoute(location.pathname, location.search);
```

`ProceduralDemoRouteOutlet` is router-neutral and can be embedded in a legacy shell without adding `react-router-dom`:

```tsx
<ProceduralDemoRouteOutlet
  pathname={window.location.pathname}
  search={window.location.search}
  fallback={<ExistingAppShell />}
/>
```

For React Router, mount `ProceduralDemoPage` directly:

```tsx
<Route path="/procedural-demos/:machineId" element={<ProceduralDemoPage />} />
<Route path="/viewer/:machineId" element={<ProceduralDemoPage />} />
```

## Direct typed imports

`ProceduralDemoExperience` now imports the catalogue directly:

```ts
import {
  getDefaultProceduralDemoId,
  getProceduralDemoMachine,
  listProceduralDemoMachines,
  requireProceduralDemoMachine,
} from './proceduralDemoCatalog';
```

There is no CommonJS `require()` indirection in the runtime path. The catalogue uses namespace imports for the eight procedural machine modules and normalises their exported definitions, scene components, animation modules, part metadata, engineering facts, and guided tours.

## Shareable state

The viewer updates the URL with:

- `rpm`
- `ts`
- `explode`
- `wire`
- `labels`
- `section`, `axis`, `cut`
- `selected`
- `hidden`
- `opacity`
- `cam`
- `target`

Example:

```text
/procedural-demos/wankel-rotary-engine?rpm=1200&ts=1.4&explode=0.8&wire=1&selected=rotor
```

The copy-link button emits an absolute URL with the same encoded view state.
