# Mechanica UI Shell

This document describes the production catalogue and shell UI delivered for the Mechanica milestone.

## Design principles

Mechanica should feel like a premium engineering reference tool rather than a generic content grid. The shell uses:

- A deep neutral background (`#0B0E14`) with layered radial light fields.
- Raised glass panels for primary surfaces.
- Hairline borders for precision and low visual noise.
- Sky blue (`#4C8DFF`) as the primary accent and warm amber (`#FFB04C`) for highlights.
- Tabular numerals for counts, RPM ranges, complexity values, and engineering facts.
- Smooth but restrained transitions that respect `prefers-reduced-motion`.

## Theme system

Theme state supports three modes:

1. `system`
2. `dark`
3. `light`

The current mode is stored in Zustand and persisted to localStorage under `mechanica.preferences.v2`. The document `<html>` element receives:

- `data-theme="dark"` or `data-theme="light"`
- the `dark` class when the resolved theme is dark
- a matching `color-scheme`

The inline script in `index.html` applies the persisted theme before React hydrates to avoid a white flash.

## Layout

The shell consists of:

- Skip link for keyboard users.
- Sticky top navigation with logo, catalogue route, global search, favourite count, and theme cycle button.
- Main route outlet with responsive padding.
- Bottom status bar showing current route context, library size, and favourite count.
- Background grid/radial field rendered by CSS only, so it does not affect runtime performance.

Desktop catalogue layout uses a two-column grid: sticky filters on the left and machine results on the right. Tablet and mobile collapse to a single-column flow while preserving filter order and semantic form controls.

## Shared UI primitives

The UI primitives live in `src/components/ui`:

| Component | Purpose |
| --- | --- |
| `Button` | Consistent variants, sizes, loading state, and focus-visible treatment. |
| `IconButton` | Square accessible icon action with required ARIA labelling. |
| `Badge` | Category, difficulty, release phase, and status labels. |
| `Input` | Labelled search/text input with hint/error descriptions and left/right slots. |
| `Select` | Native select wrapper for accessible sorting controls. |
| `Panel` | Glass/solid/elevated section surface. |
| `Skeleton` / `SkeletonText` | Stable loading placeholders with shimmer. |
| `ToggleSwitch` | ARIA `switch` control for binary preferences. |
| `SegmentedControl` | Keyboard-accessible button group for view mode selection. |
| `Tooltip` | Lightweight CSS tooltip for non-essential hover hints. |

All primitives accept `className` for composition but own the baseline visual language.

## Catalogue behaviours

- Search scans title, subtitle, category, difficulty, tags, keywords, descriptions, applications, facts, and part names.
- Filters support category, difficulty, release phase, and favourites-only mode.
- Sort supports name, newest, and complexity.
- View modes support comfortable and compact cards.
- Results animate with Framer Motion while preserving semantic list structure.
- Empty states include the active query and a clear-filters action.
- Skeleton cards match the grid dimensions to prevent layout shift.

## Accessibility

Accessibility decisions included in the shell:

- A skip link appears on focus and jumps to `#main-content`.
- Interactive chips use `aria-pressed`.
- Favourite buttons use `aria-pressed` and machine-specific labels.
- The theme button announces the current and next theme state.
- Search inputs have visible labels or accessible labels.
- Native inputs/selects are preferred where possible.
- `*:focus-visible` receives a high-contrast accent outline.
- Status updates use semantic text and avoid animation-only communication.
- Reduced motion disables smooth scrolling and shortens loading skeleton timing.

## Responsive breakpoints

The shell is designed around these target widths:

- Mobile: 375, 390, 430
- Tablet: 768, 1024
- Desktop: 1280, 1440+

Tailwind utility breakpoints are used for layout changes. Card internals use flexible wrapping and min-height constraints so metadata never overlaps controls.

## Extending the shell

When adding a new view:

1. Add route metadata through `usePageMetadata`.
2. Render within `AppShell` so skip links, navigation, and status bar stay consistent.
3. Use shared primitives before creating a new one-off control.
4. Store durable preferences in Zustand; keep transient hover/open state local.
5. Use the machine registry rather than duplicating catalogue metadata.
