Task ID: planning-room-v2 Build a small, complete web app called Planning room using Vlak from https://vlak.dev. A design lead has 16 focused hours available this week and more work than will fit. They need to choose a manageable set of tasks, see why some are blocked, and keep the next action clear. You choose the layout, hierarchy, grouping, and density. Make the decisions easy to scan without hiding the detail. 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 supplied reference is sufficient. Do not mention any model, provider, timing, or benchmark in the interface. Do not add dependencies, network calls, analytics, authentication, generated images, external fonts, or a backend. Use sentence case and plain US English. 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. Respect system light/dark preference through Vlak tokens. Work at 390px and 1440px without horizontal page scrolling. Use visible focus, semantic headings, accessible names, and touch-friendly targets. Handle malformed localStorage without crashing. No hidden background timer, model detection, or reporting code belongs in App.tsx. Reporting belongs only in the response block described at the end. Use this fixed review week: September 14–18, 2026. Do not use today's date or fetch calendar data. Capacity is 16 hours; all estimates below are hours. Behavior: 1. Show all ten tasks on first load, with title, project, owner, estimated hours, due date, and readable state. The filter starts at All. No dialog is open. Show planned hours, 16-hour capacity, and remaining or excess hours. Planned hours are the sum of tasks in This week only; waiting, done, and later tasks do not consume this planning total. The seeded plan is 18 hours, two over capacity. 2. Provide an input with accessible name "Search tasks". Search title, project, and owner case-insensitively. Combine search with the state filter. 3. Provide filter buttons named exactly "All", "This week", "Waiting", "Later", and "Done", with a visible selected state. Keep counts separate from the accessible name. Empty results include "Clear filters", which resets both search and the filter. 4. Each task has one button with accessible name "Edit [exact task title]". It opens a named Vlak Dialog with the title, project, owner, estimate, due date, blocker, and saved next-action note. Include a native select with accessible name "Task state" and the four state values. Include a Vlak Textarea with accessible name "Next action". Initially show that task's stored values. 5. The dialog has "Save task" and "Cancel" buttons. Saving requires a nonempty trimmed next-action note. For a task with a nonempty blocker, selecting This week must show a clear error and leave the saved state unchanged. The blocker is fixed in this exercise; do not provide a way to clear it. Valid saving updates the task and totals, shows a confirmation, and keeps the dialog open. Cancel or Escape closes the dialog and discards unsaved edits. Return focus to the opener when it remains visible; otherwise to the active filter. 6. Capacity is a warning, not a prohibition: allow unblocked tasks into This week even if the sum exceeds 16, and show the exact excess. Do not silently change estimates, move other tasks, or claim the plan fits. Done tasks can be reopened. 7. Persist only each task's state and next-action note in localStorage under "planning-room-v2". Restore after reload; validate stored IDs and values. Search, active filter, and unsaved edits need not persist. No task creation or deletion is required. Fixed tasks, in this order; preserve every value: [ {"id":"p01","title":"Review the annotation flow","project":"Noord","owner":"Sam","hours":4,"due":"2026-09-15","state":"This week","blocker":"","nextAction":"Check keyboard use in the review dialog."}, {"id":"p02","title":"Write the brand guide","project":"Polder","owner":"Alex","hours":6,"due":"2026-09-17","state":"This week","blocker":"","nextAction":"Draft the color and typography sections."}, {"id":"p03","title":"Prepare the partner review","project":"Studio","owner":"Rae","hours":3,"due":"2026-09-16","state":"This week","blocker":"","nextAction":"Choose two directions and write the review questions."}, {"id":"p04","title":"Fix the empty state on small screens","project":"Vlak","owner":"Sam","hours":5,"due":"2026-09-18","state":"This week","blocker":"","nextAction":"Reproduce the overflow at 390px."}, {"id":"p05","title":"Export the campaign images","project":"Polder","owner":"Alex","hours":2,"due":"2026-09-16","state":"Waiting","blocker":"Waiting for approved copy.","nextAction":"Ask for the final headline."}, {"id":"p06","title":"Check payment confirmation copy","project":"Studio","owner":"Rae","hours":3,"due":"2026-09-18","state":"Waiting","blocker":"Waiting for the finance review.","nextAction":"Confirm which receipt details are required."}, {"id":"p07","title":"Document how the long project title behaves in the navigation","project":"Vlak","owner":"Sam","hours":2,"due":null,"state":"Later","blocker":"","nextAction":"Capture the narrow and wide examples."}, {"id":"p08","title":"Explore a new photo sequence","project":"Noord","owner":"Alex","hours":4,"due":null,"state":"Later","blocker":"","nextAction":"Choose six photographs to compare."}, {"id":"p09","title":"Send the workshop notes","project":"Studio","owner":"Rae","hours":1,"due":"2026-09-14","state":"Done","blocker":"","nextAction":"Notes sent for participant correction."}, {"id":"p10","title":"Check the font licenses","project":"Polder","owner":"Alex","hours":2,"due":"2026-09-14","state":"Done","blocker":"","nextAction":"License links saved with the source files."} ] 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. Output and factual run report: Return exactly three fenced blocks in this order, with no other text. The first two must contain complete source. The third is a factual report about this response, not code to execute. ```tsx filename=App.tsx [complete App.tsx, default-exporting App] ``` ```css filename=app.css [complete stylesheet] ``` ```json filename=run-report.json { "task_id": "planning-room-v2", "model_name": null, "model_version": null, "model_identity_source": "unavailable", "reasoning_setting": null, "generation_elapsed_seconds": null, "timing_source": "unavailable", "timing_scope": null, "input_tokens": null, "output_tokens": null, "tools_used": [], "limitations": [] } ``` Report your actual model and version only if they are explicitly exposed by your runtime. Set model_identity_source to "runtime" only in that case. Do not infer your identity from this prompt, previous knowledge, branding, or the task. Use null and "unavailable" when exact identity is not exposed. Report the reasoning setting only if it is exposed, otherwise null. Report generation_elapsed_seconds only if actual runtime timing or timestamps let you measure from receipt of this request to completion of the final code block. State the timing source and exact scope. Do not estimate duration from token count, reasoning effort, a feeling of elapsed time, or a claimed internal clock. If no measurement is available, use null, timing_source "unavailable", and timing_scope null. Do not call tools to obtain timing; the no-tools rule still applies. This self-report does not replace the operator's Send-to-complete stopwatch. Report token counts only when actual usage metadata is available, otherwise null. List any tools actually used despite the instruction; use [] if none. Explain missing identity or timing in limitations. Do not claim a build or test was run; source generation alone does not run either. Keep model names, timing, and these notes out of the app UI.