# State Management

Mechanica uses Zustand for durable user preferences and catalogue state. The store is implemented in `src/store/preferencesStore.ts`.

## Persisted state

The following fields persist to localStorage key `mechanica.preferences.v2`:

- `themeMode`
- `favourites`
- `catalogueQuery`
- `selectedCategories`
- `selectedDifficulties`
- `selectedPhases`
- `sortKey`
- `favouritesOnly`
- `catalogueViewMode`

Persisting catalogue state gives returning users the same reference-library context they last used. URL parameters still take precedence when present on initial catalogue load, so shared catalogue links remain reproducible.

## Theme state

`themeMode` can be `system`, `dark`, or `light`.

`useThemeEffect` resolves `system` against `prefers-color-scheme`, applies document classes, and keeps listening to system colour changes. `index.html` includes a small pre-React script that reads the same persisted state to avoid a flash of the wrong theme.

## Catalogue URL sync

`CataloguePage` reads URL parameters once on mount, writes those values into Zustand, and then mirrors subsequent filter changes back to the URL with `replace: true`. This makes search and filter states shareable without polluting browser history on every keystroke.

Parameters:

| Parameter | State |
| --- | --- |
| `q` | `catalogueQuery` |
| `category` | `selectedCategories` |
| `difficulty` | `selectedDifficulties` |
| `phase` | `selectedPhases` |
| `sort` | `sortKey` |
| `favourites` | `favouritesOnly` |
| `view` | `catalogueViewMode` |

## Favourites

Favourites are stored as machine slugs, not full machine objects. This keeps persistence resilient when registry metadata changes.

Actions:

- `toggleFavourite(slug)`
- `isFavourite(slug)`
- `clearFavourites()`

## Store ownership rules

- Durable preferences belong in Zustand.
- URL-reproducible catalogue controls may be mirrored between Zustand and search params.
- Hover, tooltip, drawer-open, and other transient component states should remain local.
- Future viewer state should use a separate viewer store so catalogue preferences do not become coupled to Three.js runtime state.
