Create a UI prototype that reflects the following product initiative. **Plan name:** Pilot Training Booking Portal Use this as the initiative label: keep screens, copy, and structure aligned with this scope. ## Cirrus UI (follow this) - Dark-only: page/chrome `bg-cirrus-black`; cards/panels `bg-cirrus-medium-black` / `bg-cirrus-sterling-dark`. - Text: `text-cirrus-sterling`, `text-cirrus-white`; primary accent `bg-cirrus-blue-pure` / shadcn `bg-primary`. - No arbitrary hex in class names (no `bg-[#...]`). Focus: `outline-cirrus-blue-pure`. - Use shadcn semantic tokens where appropriate (`bg-background`, `text-foreground`, `border-border`). - **Layout (fixed — always apply):** Do **not** render login/sign-up/settings forms or other **primary task panels** inside a very narrow vertical strip. Give the form column a **comfortable minimum width** (e.g. `min-w-[min(100%,24rem)]`, `min-w-72`, or `max-w-md w-full` on a centered card). On **split-screen** layouts (marketing + form), each side must keep a **usable** width: use `grid`/`flex` with `min-w-0` on flex children **and** a sensible `min-w-*` on the form side so it never collapses to a few pixels wide. Inputs and buttons should span the form width (`w-full` inside the card), not sit in a hairline column. - **Visual system (fixed):** Use only the Cirrus roles above for color—**no** extra accent colors, rainbow gradients, or ad-hoc palette systems. **One** primary filled button treatment for the main action; links stay **text-style**, not a second “button” look. **One** consistent radius family per screen for cards and inputs (e.g. `rounded-lg` throughout the form). - **Content & claims:** Do **not** add regulatory, compliance, encryption, certification, or legal claims (e.g. FAA, “end-to-end encrypted”) unless they appear in the feature spec text below. Use **neutral** placeholders (e.g. `user@example.com`) unless the spec gives exact copy. - **Anti-clutter:** Do **not** add novelty pills, promo badges, or decorative stickers unless the spec requires them. Avoid demo-only “try X to see Y” hints unless specified. - **Hierarchy & spacing:** Prefer **one** clear card and **one** vertical rhythm for auth. Space with a simple scale (e.g. `space-y-4` / `gap-4`). Keep controls comfortably tappable (**~44px** min height for primary actions where appropriate). - **Motion & depth:** Keep motion **subtle**; skip parallax, heavy animation, or glassmorphism unless the spec asks. Use **one** shadow/elevation style for cards. - **When updating** (lead line says “Update the UI prototype”): **Refine** the existing layout—do not replace the whole page unless the revised spec requires it. Preserve the established structure (e.g. marketing column + form column) unless the spec says to change it. ## Cirrus design tokens (canonical `brain/cirrus-design-tokens.md`) Match colors, typography, spacing, and stack conventions below when generating styles and structure. ```markdown # Cirrus Aircraft UI — design tokens (reference) **Purpose:** All user-visible web UI for Cirrus initiatives must follow this **dark aviation** design system. **Source of truth:** Implement colors, spacing, typography, and CSS architecture in the app as described here; align `app/globals.css` with these definitions. This document tracks the **token values and patterns** below; the running app may add app-specific layers (e.g. chat surfaces) on top. ## Stack (must match) - **Next.js** App Router, **React**, **TypeScript** - **Tailwind CSS v4** — `@import "tailwindcss"`, optional `@import "tw-animate-css"`, **`@custom-variant dark (&:is(.dark *));`**, **`:root` custom properties**, and **`@theme inline`** for design tokens (not a legacy `tailwind.config` theme spread for Cirrus colors) - **shadcn/ui** (New York, CSS variables), **Radix** primitives, **cva** for variants, **`cn()`** (`clsx` + `tailwind-merge`) for class merging - **Lucide** for icons unless you use a Cirrus logo from `components/icons/` ## Non-negotiables 1. **Dark-only** — No light theme; tokens are set at `:root`. 2. **No arbitrary colors in class names** — Do **not** use `bg-[#hex]`, `text-[#hex]`, etc. Use Cirrus utilities (`bg-cirrus-black`, `text-cirrus-sterling`, …) or shadcn semantic tokens (`bg-background`, `text-primary`, …). 3. **Surfaces** — Page/chrome: `bg-cirrus-black` (`#1a1a1c`). Cards/panels: `bg-cirrus-medium-black` or `bg-cirrus-sterling-dark` as appropriate. 4. **Focus** — `outline-2 outline-cirrus-blue-pure` (or ring token alignment); avoid relying on default browser outline that clashes with dark UI. 5. **Disabled** — `disabled:cursor-not-allowed` with `cirrus-sterling-medium` / `cirrus-sterling-dark` for muted visuals. 6. **Motion** — Prefer `transition-colors` / `transition-all`, 150–300ms; use named animations from the theme when needed (`animate-fade-in`, `animate-accordion-down`, etc. — see **Animation tokens** below). ## Border radius `app/globals.css` maps Tailwind `rounded-*` utilities to **`--radius-*`** in `@theme inline`. Use a **small vocabulary** so boxes feel consistent: | Use | Utility | Notes | | --- | --- | --- | | **Standard boxes** — cards, columns, sheets’ inner panels, most bordered regions | `rounded-lg` or `rounded-md` or `rounded-box` | All three use the same value: **`--radius`** on `:root` (currently **0.75rem**), so pick one convention per feature and stick to it (`rounded-lg` is the usual choice). | | **Softer blocks** — primary/secondary buttons, tags, multiline composer | `rounded-xl` | Fixed **24px**; visually related controls share this curve. | | **Planning thread** — user message bubble (attachments + text) | `rounded-lg` | Same **12px** curve as the v0 preview card and spec panels in the same column so the chat reads as one surface system. | | **Pills & circles** — toggles, avatars, progress caps, single-line composer | `rounded-full` | | | **Tight chips** | `rounded-sm` / `rounded-tiny` | Nested labels, compact badges. | Avoid mixing **different** steps for the same kind of surface (e.g. don’t use `rounded-xl` on one kanban column and `rounded-md` on another unless there is a deliberate hierarchy). ## CSS architecture (summary) Canonical structure for the Cirrus app stylesheet: | Layer | Role | | --- | --- | | **Imports** | `tailwindcss`; optional `tw-animate-css`; `@custom-variant dark (&:is(.dark *));` | | **`:root`** | Cirrus palette, fuel gauge, feedback colors, **shadcn semantics** via `var(--cirrus-*)` (`--background`, `--foreground`, `--card`, `--primary`, …), **chart** `--chart-1`…`--chart-5`, **sidebar** (`--sidebar`, `--sidebar-primary`, …), **shadows** (`--shadow-dark-sm` / `-md` / `-lg`, `--shadow-outline`), **`--radius`** (0.75rem — default box curve; see **Border radius**). | | **`@theme inline`** | Tailwind v4 bridge: `--font-sans` / `--font-mono`, `--color-*` (semantic + Cirrus + fuel + feedback), **`--radius-*`**, **`--shadow-*`**, **`--breakpoint-*`**, **`--animate-*`** names pointing at keyframes. | | **`@layer base`** | Global `*` border/outline; `html { color-scheme: dark; }`; `body` background/color/fonts; **typography** as utility classes (single-scale definitions — see Typography). | | **`@layer components`** | e.g. **`.no-scrollbar`** (hide scrollbars while scrolling). | **Fonts (theme):** `--font-sans`: Inter stack (`'Inter', 'Inter Fallback', system-ui, …`); `--font-mono`: Geist Mono stack. **Shadows (CSS vars):** - `--shadow-dark-sm`: `0 1px 4px 0 rgba(0,0,0,0.55)` - `--shadow-dark-md`: `0 4px 12px 0 rgba(0,0,0,0.6)` - `--shadow-dark-lg`: `0 8px 24px 0 rgba(0,0,0,0.65)` - `--shadow-outline`: `0 0 0 1px var(--cirrus-blue-pure), 0 0 0 3px rgba(14,119,214,0.25)` ### Animation tokens (`animate-*`) Registered in `@theme inline` for use as Tailwind utilities: `animate-fade-in` · `animate-fade-out` · `animate-slide-in-from-right` · `animate-slide-out-to-right` · `animate-accordion-down` · `animate-accordion-up` Underlying **keyframes** (representative): - `fade-in` / `fade-out` — opacity (fade-in also uses a light `translateY`) - `slide-in-from-right` / `slide-out-to-right` — horizontal slide + opacity - `accordion-down` / `accordion-up` — height to/from `var(--radix-accordion-content-height)` ## Core palette (Tailwind utilities) | Token | Hex | Example | | --- | --- | --- | | `cirrus-black` | `#1a1a1c` | `bg-cirrus-black` page background | | `cirrus-black-low-opacity` | `rgba(26,26,28,0.25)` | Overlays / scrims | | `cirrus-medium-black` | `#2a2b2e` | `bg-cirrus-medium-black` | | `cirrus-sterling-dark` | `#363739` | `bg-cirrus-sterling-dark` cards | | `cirrus-sterling-medium` | `#707070` | Borders / muted | | `cirrus-sterling` | `#a5acaf` | `text-cirrus-sterling` body secondary | | `cirrus-sterling-light` | `#edeeef` | Light text/surfaces | | `cirrus-white` | `#ffffff` | `text-cirrus-white` | | `cirrus-blue-pure` | `#0e77d6` | Primary actions, links, focus | | `cirrus-blue-light` | `#59a6eb` | Accents | | `cirrus-blue-dark` | `#0154a0` | Darker primary states | | `cirrus-red-pure` | `#e8183e` | Destructive / error emphasis | | `cirrus-red-dark` | `#b00020` | | | `cirrus-orange` | `#f68038` | | ### Fuel gauge (data viz / gauges only) | Token | Hex | | --- | --- | | `fuel-red-pure` | `#ff1300` | | `fuel-yellow-pure` | `#feff05` | | `fuel-green-pure` | `#67f700` | Use sparingly for gauge-style UI. ### Feedback colors | Token | Hex | | --- | --- | | `feedback-error-pure` | `#ff3121` | | `feedback-error-medium` | `#c9271a` | | `feedback-error-dark` | `#8f1c13` | | `feedback-error-light` | `#fde8e6` | | `feedback-warning-pure` | `#ffd705` | | `feedback-warning-medium` | `#c9ab04` | | `feedback-warning-light` | `#fff9d6` | | `feedback-success-pure` | `#55cc00` | | `feedback-success-medium` | `#429f00` | | `feedback-success-dark` | `#2e6e00` | | `feedback-success-light` | `#eafad6` | ## shadcn semantic mapping (Cirrus) Semantic tokens are defined in `:root` using **Cirrus variables** (e.g. `--background: var(--cirrus-black)`) and exposed as Tailwind colors via `@theme inline`. Use `bg-background`, `text-foreground`, `bg-card`, `bg-primary`, `text-primary-foreground`, `bg-secondary`, `bg-muted`, `text-muted-foreground`, `bg-accent`, `bg-destructive`, `border-border`, `ring-ring`, sidebar tokens (`bg-sidebar`, …), and chart colors (`--chart-1`…`--chart-5`). | Semantic | Source | | --- | --- | | background | `var(--cirrus-black)` | | foreground | `var(--cirrus-white)` | | card / popover | `var(--cirrus-sterling-dark)` | | primary | `var(--cirrus-blue-pure)` | | secondary / muted / accent | `var(--cirrus-medium-black)` | | muted-foreground | `var(--cirrus-sterling)` | | destructive | `var(--cirrus-red-pure)` | | border / input | `var(--cirrus-sterling-medium)` | | ring | `var(--cirrus-blue-pure)` | | radius | `0.75rem` (`--radius`) | **Charts (`--chart-1` … `--chart-5`):** | Var | Hex | Role | | --- | --- | --- | | `--chart-1` | `#0e77d6` | Primary | | `--chart-2` | `#59a6eb` | Blue light | | `--chart-3` | `#55cc00` | Success | | `--chart-4` | `#ffd705` | Warning | | `--chart-5` | `#e8183e` | Destructive | **Sidebar:** `--sidebar` → `cirrus-medium-black`; foreground white; primary `cirrus-blue-pure`; accent `cirrus-sterling-dark`; border `cirrus-sterling-medium`; ring `cirrus-blue-pure`. ## Spacing scale (Tailwind token names) `xxxs` 4px · `xxs` 8px · `xs` 12px · `sm` 16px · `md` 20px · `xmd` 32px · `lg` 36px · `xl` 44px · `xxl` 52px · `xxxl` 60px · `giant` 80px Use with `p-*`, `m-*`, `gap-*`, `w-*`, `h-*` per the spacing scale in `@theme inline` when defined there (mirror in `globals.css` if not yet bridged). ### Border radius theme keys (`globals.css`) `--radius` on `:root` is **0.75rem**. In `@theme inline`, **`--radius-md`**, **`--radius-lg`**, and **`--radius-box`** all resolve to `var(--radius)` so standard containers align. Also: `--radius-tiny` (4px), `--radius-sm` (8px), `--radius-xl` (24px), `--radius-2xl` (36px), `--radius-rounded` (68px). ## Shadows - `shadow-dark-sm`, `shadow-dark-md`, `shadow-dark-lg` — values listed under **Shadows (CSS vars)** above - `shadow-outline` — dual ring using `--cirrus-blue-pure` ## Typography (apply single classes) Headings: `font-heading-xl` … `font-heading-4` Subheadings: `font-subheading-1` … `font-subheading-4` Subtitles: `font-subtitle-1`, `font-subtitle-2` Body: `font-body-1` … `font-body-5` Buttons / links: `font-button-1` … `font-button-4`, `font-textlink-1`, `font-textlink-2` Captions / tags: `font-caption-1`, `font-caption-2`, `font-tags`, `font-overline-1` Sizes and weights are defined as **fixed scales** in `@layer base` (see stylesheet): e.g. `font-heading-xl` at 2.5rem / 700; `font-body-1` at 1rem / 400; `font-button-1` at 1rem / 600; etc. No responsive breakpoint overrides unless you add them in CSS. ## Breakpoints `sm` 768px · `md` 1024px · `lg` 1280px · `xl` 1440px · `2xl` 1920px ## Component patterns (summarized) - **Client components:** `"use client"` for interactive UI. - **Structure:** Radix primitive + `cva` variants + `cn()` for class merging. - **Forms:** Floating-label patterns (e.g. `TextInput`, `Dropdown`) — align side-by-side rows with `items-end` so underlines stay aligned when one field expands. - **Layout:** `Header` / `Footer` patterns with Cirrus logos from `components/icons/` when branding is required. ## What to write in specs (`technicalNotes`) When the feature has UI, name **concrete** Tailwind classes and token names aligned with **`brain/cirrus-design-tokens.md`** (e.g. “primary CTA uses `Button` primary variant → `cirrus-blue-pure` / `bg-primary`”), and reference likely implementation paths (e.g. `components/ui/button`, `components/icons/`) as needed. --- ## CSS excerpt (illustrative — keep in sync with `app/globals.css`) ```css @import 'tailwindcss'; @import 'tw-animate-css'; @custom-variant dark (&:is(.dark *)); :root { /* … Cirrus core, fuel, feedback, then: */ --background: var(--cirrus-black); --foreground: var(--cirrus-white); --card: var(--cirrus-sterling-dark); /* … primary, secondary, muted, destructive, border, input, ring, radius … */ --chart-1: #0e77d6; /* … */ --shadow-dark-sm: 0 1px 4px 0 rgba(0, 0, 0, 0.55); --shadow-outline: 0 0 0 1px var(--cirrus-blue-pure), 0 0 0 3px rgba(14, 119, 214, 0.25); } @theme inline { --font-sans: 'Inter', 'Inter Fallback', system-ui, -apple-system, sans-serif; --font-mono: 'Geist Mono', 'Geist Mono Fallback', monospace; /* --color-* bridge for semantic + Cirrus + fuel + feedback */ /* --radius-*, --shadow-*, --breakpoint-*, --animate-* */ } ``` ``` ## Initiative context Pilots need a self-service way to book simulator training sessions without relying on manual coordination. This portal will provide authenticated pilots with a focused booking experience that lets them search available simulator sessions by location and aircraft model, review the session details needed to make a decision, and complete a booking against the source of truth for availability. The business outcome is to reduce scheduling friction for pilots and training operations staff while improving consistency and visibility into bookings. The portal must enforce pilot-only access through existing authentication, prevent self-service rescheduling, and ensure that booking attempts are validated at submission time so the same session cannot be double-booked through the portal. The user experience should stay narrow and task-oriented: discover sessions, filter them, book one, and confirm the result. The implementation should align with Cirrus web standards if new UI is needed, but the scope is intentionally limited to the booking workflow and related error states. Admin inventory management, cancellation, payment, and non-simulator training are out of scope. ## Features to express in the UI ### 1. Pilot access gate and booking entry points Implement pilot-only access control for the booking portal using existing authentication. This feature covers the entry experience, authorization checks, and the basic portal shell needed to safely expose booking functionality only to eligible users. It ensures unauthenticated users cannot view booking data and authenticated non-pilots cannot enter the booking flow. ### 2. Session discovery with location and aircraft model filters Build the session browsing experience that lets pilots find available simulator sessions by location and aircraft model. This feature covers the searchable/filterable list, the session detail fields needed for decision-making, and the empty-state behavior when no sessions match the selected filters. ### 3. Booking submission and availability validation Implement the core booking action that lets a pilot select a session and submit a booking request against the source of truth. This feature covers submission-time validation, duplicate-booking prevention, success handling, and failure states when the session is no longer available or the backend rejects the request. ### 4. Booking confirmation and detail view Provide the post-booking experience that confirms success and shows the pilot the booking details they need. This feature covers the success state, booking detail presentation, and access to booking information after completion within the portal if supported by the source data. ### 5. Booking error, empty-state, and no-reschedule safeguards Add the supporting states and guardrails that keep the portal clear and safe when no sessions match, when backend calls fail, or when a pilot attempts an unsupported action such as rescheduling. This feature ensures the portal communicates failures without exposing internal details and prevents self-service rescheduling from appearing anywhere in the flow. Requirements: - Match the Cirrus UI summary above; Next.js App Router, React, TypeScript, Tailwind v4, shadcn/ui, Radix. - **Layout:** Auth and primary forms must use a readable min-width card/column (see Cirrus UI — Layout). Never output a paper-thin form column. - **Discipline:** Follow Cirrus UI — Visual system, Content & claims, Anti-clutter, Hierarchy, Motion, and When updating. No invented badges or compliance copy. - Cover key screens and primary user flows with realistic placeholder content. - No real backend or API integration; focus on structure and UX.
Let me read the existing files before making changes, then write all components in planned parallel batches.
Now let me write all the UI components:
The Agent timed out. Type a new prompt to continue.