Build a small, complete web app called Review room using the Vlak design system from https://vlak.dev.

The person using it is a designer reviewing six photographs with a project partner. They need to see what still needs a decision, inspect an image, and approve it or leave a specific request for changes. Make it clear, calm, and genuinely useful. You choose the layout and visual hierarchy. Use sentence case and plain US English.

This is a single-response build. Do not ask questions. Do not browse, call tools, install packages, use a canvas/artifact runtime, or use another model. The reference below is sufficient. Return source code, not an explanation or screenshot. Do not mention any model, provider, or benchmark in the interface. Do not add dependencies, network calls, analytics, authentication, generated images, external fonts, or a backend.

Runtime: React 19.2.4, React DOM 19.2.4, TypeScript/TSX, @noorddev/vlak-react 0.4.0. A supplied entry point renders your default-exported App and imports @noorddev/vlak-react/css followed by ./app.css. Only App.tsx and app.css may change. Use the real Vlak Button, Input, Badge, Dialog, DialogTitle, and Textarea components where appropriate; do not recreate their appearance with lookalike controls. Layout CSS is yours. Native elements are fine for the rest. Do not import your stylesheet from App.tsx.

Behavior:
1. Show all six items on first load, with title, image, project, and readable status. Start in the All filter. No selected detail panel should be open initially.
2. Provide a text input with accessible name "Search work". Match title and project, case-insensitively. Combine search with the status filter.
3. Provide buttons named exactly "All", "Needs review", "Approved", and "Changes requested". Show which filter is selected. Counts may be separate from the button's accessible name. An unmatched search must show a useful empty state and a "Clear filters" button.
4. Each visible item has one button with accessible name "Review [exact title]". That opens a Vlak Dialog with a large image, its title and project, its current status, and any saved feedback. The dialog must have an accessible name. Closing it, including Escape, returns focus to its opener.
5. In the dialog, provide "Approve", a textarea named "Feedback", and "Request changes". Approve changes the status to Approved. Request changes changes the status to Changes requested only when the trimmed feedback is nonempty. Otherwise keep the status unchanged and show a visible error. Save the feedback with that item. Keep the dialog open after either action so the result can be inspected. The dialog must also have a "Close review" button.
6. Store statuses and feedback in localStorage under "review-room-v1". Restore them after reload. Handle missing or malformed stored data without crashing. Search, filters, and the open dialog do not need to persist.
7. Respect the operating system's light/dark preference through Vlak tokens. Work at 390px and 1440px viewport widths without horizontal page scrolling. Use meaningful image alt text, visible focus states, keyboard-accessible controls, and touch-friendly targets. Handle long titles and the empty state with the same care as the initial screen.

Fixed items, in this order (copy the data, do not invent replacements):
[
  {"id":"01","title":"Field notes","project":"Polder","image":"/assets/01.jpg","alt":"Laundry beside a brick house overlooking fields.","status":"Needs review","feedback":""},
  {"id":"02","title":"A place to pause","project":"Polder","image":"/assets/02.jpg","alt":"Two chairs and a thermos beside the water.","status":"Needs review","feedback":""},
  {"id":"03","title":"Through the dike","project":"Noord","image":"/assets/03.jpg","alt":"A cyclist emerging from a concrete passage through a dike.","status":"Approved","feedback":""},
  {"id":"04","title":"Outside Café De Polder","project":"Polder","image":"/assets/04.jpg","alt":"A person and a dog outside Café De Polder.","status":"Changes requested","feedback":"Leave more room around the entrance."},
  {"id":"05","title":"The waiting place at the edge of the field","project":"Noord","image":"/assets/05.jpg","alt":"A roadside shelter in an open Dutch landscape.","status":"Needs review","feedback":""},
  {"id":"06","title":"Walking home","project":"Noord","image":"/assets/06.jpg","alt":"A person and a dog on a path beside open fields.","status":"Approved","feedback":""}
]

Vlak 0.4.0 reference (a fixed excerpt for every participant):
import { Button, Input, Badge, Dialog, DialogTitle, Textarea } from '@noorddev/vlak-react';
Button: native button props, variant?: 'primary' | 'ghost', size?: 'default' | 'sm'.
Input: native input props, label?: ReactNode, error?: ReactNode, hint?: ReactNode, plain?: boolean.
Badge: native span props, variant?: 'outline' | 'solid' | 'muted'.
Textarea: native textarea props, label?: ReactNode, feedback?: ReactNode.
Dialog: native dialog props except open/onClose, open: boolean, onClose?: () => void, dismissable?: boolean, lightDismiss?: boolean, closeLabel?: string. It uses a native modal dialog; control open in React state. Do not call showModal yourself.
DialogTitle: native heading props, as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'. It supplies the dialog's accessible name.
The installed stylesheet uses --bg (page background), --text (foreground), --text-secondary (muted text), --divider (border), --table-alt (subtle surface), --radius, --gutter, and --rs-gap. Use the actual supplied token names. The package loads its own Inter font. With no data-theme override, system preference applies. Do not force light mode.

Deliver exactly two fenced code blocks, no other text:
```tsx filename=App.tsx
[complete App.tsx, default-exporting App]
```
```css filename=app.css
[complete stylesheet]
```
