# Component Architecture

Mechanica separates route-level composition, reusable UI, domain data, state, and 3D rendering. The goal is that adding a machine or replacing a procedural preview with a GLB asset never requires editing the catalogue page, the viewer layout, or the core player controls.

## Dependency direction

```text
pages ─┬─> layouts
       ├─> components
       ├─> modules
       ├─> store
       └─> hooks

components ─┬─> modules
            ├─> store
            ├─> three
            └─> utils

three ─┬─> modules
       ├─> store
       └─> types

modules ─> types only
store   ─> types only
utils   ─> types only
```

Rules:

1. `modules/machines` owns machine data and schema only.
2. `three` owns Canvas, lighting, controls, picking, rendering modes, and procedural/GLTF model adapters.
3. `components/viewer` owns DOM panels around the Canvas.
4. `store` owns user-adjustable runtime state.
5. UI components cannot hardcode a specific machine; they consume `MachineRegistryEntry`.

## Route-level pages

### `CataloguePage`

Responsibilities:

- Reads all registry entries.
- Applies search, category, difficulty, and sort filters via `useCatalogueFilters`.
- Renders machine cards with favourites persisted in localStorage.
- Provides an instant catalogue experience with stable card dimensions.

### `ViewerPage`

Responsibilities:

- Resolves `:slug` to a `MachineRegistryEntry`.
- Initializes part render state from the registry and URL state.
- Hydrates viewer controls from URL parameters.
- Composes `ViewerScaffold`.

### `NotFoundPage`

Responsibilities:

- Provides accessible recovery for unknown routes or unknown machine slugs.
- Links back to the catalogue.

## Layout

### `AppShell`

Responsibilities:

- Applies persisted theme to `<html>`.
- Provides skip link and top navigation.
- Hosts the route outlet.
- Wraps route transitions with reduced-motion-aware Framer Motion transitions.

The shell is intentionally small. Viewer-specific sidebars and controls live below `pages/ViewerPage` so full-screen viewer routes can evolve independently from marketing or documentation routes.

## Shared UI components

Located in `src/components/ui`.

- `Button`: shared button variants with visible focus states.
- `Badge`: semantic status/category/difficulty labels.
- `Panel`: elevated glass panel surface.
- `Skeleton`: layout-stable loading shimmer primitives.

These components expose only styling and accessibility behavior. They do not import machine data or viewer state.

## Catalogue components

Located in `src/components/catalogue`.

- `CatalogueFilters`: controlled search/filter/sort inputs.
- `MachineCard`: registry-driven catalogue card with favourite action.
- `MachineGrid`: responsive card grid and empty state.

The card uses the registry thumbnail gradient as a temporary no-asset preview. When final thumbnails are generated, the schema can add `posterPath` while preserving the card API.

## Navigation components

Located in `src/components/navigation`.

- `TopNavigation`: logo, catalogue link, global catalogue search, theme toggle.

Global search navigates to `/?q=...` instead of maintaining duplicate search state.

## Viewer DOM components

Located in `src/components/viewer`.

- `ViewerScaffold`: responsive composition of sidebars, Canvas, toolbar, status bar, and drawer.
- `ComponentSidebar`: per-part selection, visibility, and opacity controls.
- `ControlPanel`: playback, RPM, time scale, exploded view, display mode, clipping, and annotation controls.
- `ViewerToolbar`: camera presets, reset, and copy-link workflow.
- `DetailDrawer`: selected component description and engineering specs.
- `StatusBar`: part counts, current machine, camera mode, display mode, and FPS.

The viewer panels talk only to the `viewerStore` and current `MachineRegistryEntry`. They do not know whether a model is procedural or GLTF.

## 3D components

Located in `src/three`.

- `SceneRoot`: Canvas, renderer settings, lighting, environment, grid, shadows, camera controls.
- `MachinePlaceholderModel`: data-driven procedural part visualization used before GLB assets land.
- `cameraPresets`: canonical front/back/left/right/top/isometric camera definitions.
- `materials`: shared engineering palette.

Future GLTF support should add a `GltfMachineModel` adapter beside `MachinePlaceholderModel`, then select the adapter by `machine.model.kind`.

## State contracts

- `preferencesStore`: persisted theme and favourites.
- `viewerStore`: transient machine viewer state such as selected part, visibility, opacity, playback, display mode, clipping, annotations, exploded view, and camera override.

State is deliberately split so shareable viewer state does not pollute persisted user preferences.

## Extension checklist for new components

1. Define props from registry/schema/store types instead of ad hoc objects.
2. Keep component files focused on one visual region or behavior.
3. Place reusable primitives in `components/ui`; place machine-specific panels in `components/viewer`.
4. Do not import `machineRegistry` directly from deeply nested UI unless the component is a catalogue or related-machine component.
5. Preserve keyboard access and visible focus for every interactive element.
