Search origin to destination
Enter your origin and destination stations and pick a travel date. The search is a ruled table, not a card, so origin and destination stay aligned in a strict column and a single control on the rule swaps them.
winter-metro is a metro booking application for riders who need to move from an origin station to a destination station with certainty. The product intent is drawn directly from the authoritative requirement: build a metro booking app with exactly eight pages. The app is public transport infrastructure rendered as software — a rider searches for a route, compares available journeys and fares, books and pays for a ticket, and holds a valid ticket for travel. A returning rider can revisit their bookings, reopen a ticket, and cancel a booking when applicable.
The audience is the commuter or traveller standing in the cold, often on a phone, who needs speed, legibility, and trust rather than delight. The interface is treated as transit-authority wayfinding: coded colour, ruled tables, strict columns, and unmistakable type. Success means a rider completes a booking and has a valid ticket available at the station.
winter-metro is a custom-UI web application with an application-owned backend. It delivers exactly eight pages: Landing, Search, Journeys, Booking, Payment, Ticket, Bookings, and Booking Details. Two accepted human personas use it: the Metro Rider and the Booking Manager / Account Holder.
The current delivery covers the full booking lifecycle: anonymous entry and identity interaction on Landing, journey search, journey comparison and selection, traveller detail entry and booking confirmation, payment and confirmation, issued-ticket viewing, a revisitable booking list, and a focused booking detail view with cancellation when applicable. Booking and payment state persists so a confirmed booking produces a retrievable ticket and later supports viewing or cancellation.
Narrow exclusions: no adjacent capabilities beyond the accepted eight-page booking lifecycle are in scope. No account-management module, no loyalty programme, no admin console, no operator-facing tooling, and no third-party marketplace are introduced. Identity interaction is embedded in Landing because the app must support self-service enrollment and returning verification within the exact eight-page limit.
winter-metro is delivered as a first-party application with its own custom interface and its own backend. The application owns the rider's identity, booking records, payment state, and issued tickets. A verified account is required before confirming a booking, paying, viewing protected tickets, or managing bookings; the anonymous entry point is Landing, where a rider can understand the product and begin a search or establish identity.
Landing, Search, and Journeys are reachable without signing in, so a rider can evaluate routes and fares before committing. Booking, Payment, Ticket, Bookings, and Booking Details require a verified account because they create, hold, or expose durable rider-specific state — a commitment, a payment, an entitlement, or a value transfer bound to the correct participant.
Everything described in this document is current. No future-horizon capabilities are accepted, and none are planned into the current pages or acceptance criteria.
No reference directive in this project declares content_source authority, so no source content inventory is included.
FR-1 — Build a metro booking app. (explicit) As a Metro Rider, I should use a metro booking application so that I can book and hold a valid metro ticket.
FR-2 — The app must contain exactly 8 pages. (explicit) As a Metro Rider, I should move through exactly eight pages — Landing, Search, Journeys, Booking, Payment, Ticket, Bookings, and Booking Details — so that the product stays within its stated scope.
FR-3 — Anonymous entry and product explanation. (required_inference) As a Metro Rider, I should land on an anonymous entry surface that explains the metro booking app and guides me into journey search or identity interaction.
FR-4 — Self-service enrollment and returning verification embedded in Landing. (required_inference) As a Metro Rider, I should establish identity from Landing — enrolling myself or verifying a returning account — so that I can reach protected booking work without leaving the eight-page limit.
FR-5 — Search for a metro journey. (required_inference) As a Metro Rider, I should enter origin, destination, and travel date or time so that I can find available journeys.
FR-6 — Compare available journeys and fares. (required_inference) As a Metro Rider, I should see available metro journeys or fare options in a comparable form so that I can choose the right one.
FR-7 — Select a journey. (required_inference) As a Metro Rider, I should select one journey so that I can proceed to book it.
FR-8 — Enter traveller details and confirm the booking. (required_inference) As a Metro Rider, I should enter traveller details and confirm the selected journey so that a booking is created.
FR-9 — Pay for the booking and receive confirmation. (required_inference) As a Metro Rider, I should pay for the selected booking so that it is confirmed.
FR-10 — View the issued ticket. (required_inference) As a Metro Rider, I should view the valid travel ticket for a completed booking so that I can present it for travel.
FR-11 — Find upcoming or past bookings. (required_inference) As a Booking Manager / Account Holder, I should browse my upcoming and past bookings so that I can find the one I need.
FR-12 — Review an individual booking. (required_inference) As a Booking Manager / Account Holder, I should open a booking and review its journey, traveller details, fare, and status so that I can confirm what I hold.
FR-13 — Cancel a booking when applicable. (required_inference) As a Booking Manager / Account Holder, I should cancel a booking when cancellation applies so that I am not held to a journey I no longer need.
FR-14 — Persist booking and payment state. (required_inference) As a Booking Manager / Account Holder, I should have my confirmed booking and payment state persist so that a confirmed booking produces a retrievable ticket and later supports viewing or cancellation.
The Metro Rider is the primary human actor in winter-metro. Their context is a station or a phone in the cold, where the cost of ambiguity is a missed train. Their primary goal is to move from an origin station to a destination station with certainty: find a route, choose a journey, book it, pay for it, and hold a valid ticket at the station.
Their distinct accepted responsibilities are searching for a journey by origin, destination, and travel date or time; comparing available journeys and fares; selecting one journey; entering traveller details and confirming the booking; paying and receiving confirmation; and viewing the issued ticket. They are the initiator of the entire booking lifecycle.
Their relevant inputs and decisions are the origin and destination stations, the travel date or time, the choice among competing journeys on line code, departure, arrival, duration, changes, and fare, the traveller details, and the payment details. Their key decision is which journey to commit to, made against a departure-board comparison rather than a marketing pitch.
They interact with the Booking Manager / Account Holder role as the same human in a different mode: the rider who books is the person who later returns to find that booking. They interact with the application's identity interaction on Landing when they need to reach protected booking work, and with the payment step when they commit money.
Their observable success is a confirmed booking and a valid ticket available at the station. Their observable failure states are a search that returns nothing, a journey that disappears before booking, a declined payment, or a ticket that cannot be retrieved — each of which they can recover from without losing their work.
The Booking Manager / Account Holder is a rider who also maintains their own booking account. Their context is return and reuse: they are not starting from zero, they are looking for something they already hold. Their primary goal is to find, reuse, or cancel their own bookings without re-entering everything.
Their distinct accepted responsibilities are browsing upcoming and past bookings, opening an individual booking to review its journey, traveller details, fare, and status, opening the associated ticket, and cancelling a booking when cancellation applies. They also depend on persisted booking and payment state so that a confirmed booking remains retrievable across sessions.
Their relevant inputs and decisions are which booking to open, whether the booking still matches their need, and whether to cancel. Their key decision is whether to keep or cancel a booking, made against the booking's status and travel date.
They interact with the Metro Rider role as the same human in a different mode: the booking they manage is the booking they made. They interact with the application's identity interaction on Landing to verify their returning account before any protected booking state is shown.
Their observable success is being able to find, reuse, or cancel their own bookings without re-entering everything. Their observable failure states are a booking list that cannot be retrieved, a booking that is not found or not owned, or a cancellation that fails — each of which leaves the prior state intact and offers a retry or a route back to Bookings.
The creative direction is authoritative for this section. The muse is Massimo Vignelli, and the headline idea is Metro wayfinding as interface — Vignelli discipline for winter-metro. A metro booking app is public transport infrastructure rendered as software; the register is trust, speed, legibility, and the quiet authority of a system that works. The result should look like it belongs to a transit authority, not a SaaS template.
Colour tokens — light mode
| Role | Hex | Use |
|---|---|---|
| Background | #F4F1EA | Warm paper-white ground across all pages |
| Surface | #FFFFFF | Pure white panels for data surfaces |
| Text | #111111 | All type, rules, and primary controls — the authority |
| Primary | #111111 | Primary controls and structural rules |
| Accent | #E63329 | The single signal red: active line, CTA, selected journey, live ticket state |
| Muted | #6B6B6B | Metadata, labels, secondary rows |
| Line code — blue | #1A5FB4 | 4px line-identity bars and category tags only |
| Line code — yellow | #F2B705 | 4px line-identity bars and category tags only |
| Line code — green | #2E7D32 | 4px line-identity bars and category tags only |
Proportion: 70% paper/white, 20% black, 10% colour codes. The three coded line colours are applied only as 4px line-identity bars and category tags, never as decoration. Signal red is the single action colour across all eight pages, so red always means "this is the one".
Typography
clamp(64px, 12vw, 128px); UI sizes 40 / 28 / 20 / 16 / 14 / 12. Labels 11px ALL-CAPS tracked +0.12em.Shape language
Hard edges: zero border-radius on cards, buttons, and inputs. Structure comes from 1px and 2px black rules, not shadows. Colour-coded 4px bars mark lines and categories. Circles appear only where they carry meaning — line bullets, platform dots, the ticket punch-hole motif. Controls are rectangles with a visible 2px black border and a solid black fill on active state.
Layout
A strict 12-column grid, flush-left, ragged-right, asymmetric. Search is a ruled table, not a card: origin and destination as two aligned label/value rows separated by a hairline, with a swap control on the rule. Journeys render as a dense departure-board table — line code, departure, arrival, duration, changes, fare — with ruled rows and tabular numerals, sorted by departure. The ticket is a bordered document with punched corners and a horizontal perforation rule. Section transitions are full-width horizontal rules with a small ALL-CAPS section label sitting on the rule.
Imagery
Diagrammatic, not photographic. A simplified geometric metro diagram — straight lines, 45° bends, station dots — is the hero image and reappears as a faint watermark behind section rules. Small pictograms for entrance, platform, coach, and exit. No stock photography of trains or people. The ticket is rendered as a document object, not a mockup.
Avoid
Rounded cards, soft shadows, hover-lift on list items; blue or indigo primary buttons on white; gradient blobs, glassmorphism, frosted panels; Inter, Roboto, Arial, Helvetica, Open Sans, Lato, Poppins, system-ui; photographic hero imagery of trains, stations, or commuters; more than the three coded line colours plus red used as accents; centred hero headline with subtext beneath and a button under it; icon-only navigation without ALL-CAPS text labels. The generic indigo/blue-on-white SaaS template is forbidden for this project.
Readable text and controls stay whole at every viewport: headlines, wordmarks, labels, numbers, cards' text, and controls stay entirely inside the viewport and their container at 375px, 768px, and 1280px, wrapping or scaling (for example font-size: clamp(...) with its mobile size) to fit, and no other element covers any part of them. Imagery, decoration, and motion follow the creative direction and may be cropped, bled off an edge, rotated, overlapped, or cut as the direction asks, as long as they cover no readable text or control. Moving and scrollable content may cross the viewport or container edge by design and is judged by whether it actually moves or scrolls and whether every item becomes fully readable as it passes. With prefers-reduced-motion, a usable static arrangement wraps items into rows or allows horizontal scrolling so each item can be brought fully into view.
The public entry — Landing — is a full-viewport composition on the warm paper ground #F4F1EA. The dominant element is a large geometric metro diagram: three coloured lines (red #E63329, blue #1A5FB4, yellow #F2B705) crossing the right two-thirds of the viewport at 45° angles with station dots, bleeding off the right and bottom edges. The left column holds a stacked display headline in black Archivo 800 — WINTER METRO set at clamp(64px, 12vw, 128px), tight leading, three lines, flush-left, spanning from the left margin to the first diagram line — with a single 2px black rule beneath it and a one-line subhead at 20px. Beneath that, the ruled search table (From / To / Date) sits with a solid red rectangular Search button pinned flush-left. No centred text, no gradient, no blue button, no floating card.
The signature moves carry through the whole product: the journey results as a departure-board table with ruled rows, ALL-CAPS column headers on a black band, tabular numerals, and line-code colour bars in the first column — a table, never a grid of cards; section transitions built from a full-width 2px black rule with a small ALL-CAPS label sitting on the rule and the section's colour code as a 24px bar at the left end; the ticket as a printed document with a white panel, 2px black border, perforation rule across the middle, punched circular corners, a centred QR code, and fare and line code in tabular numerals under the rule; search as a ruled form with label/value rows aligned in a strict column, separated by hairlines, and a swap control sitting on the rule between origin and destination; and one signal red used as the single action colour across all eight pages — selected journey, active step, primary button, live ticket state — so red always means "this is the one".
Interaction Model: Static (direction) Motion Tempo: still Hero Dimensionality: flat
Landing Hero Motion Brief
prefers-reduced-motion, the hero renders as the same static composition with no cascade and no wipe; journey rows appear fully formed, selection is indicated by the red state change alone, and the ticket QR appears immediately without fading. All content remains fully readable and every control remains reachable.NFR-1 — Exact page count. (explicit) The application must contain exactly 8 pages: Landing, Search, Journeys, Booking, Payment, Ticket, Bookings, and Booking Details. Rationale: the authoritative requirement states "make 8 pages" and the planning scope fixes the count at exactly 8.
NFR-2 — Identity continuity for protected state. (required_inference) A verified account is required before confirming a booking, paying, viewing protected tickets, or managing bookings. Rationale: these actions create or expose durable rider-specific state — a commitment, a payment, an entitlement, or a value transfer — that must remain bound to the correct participant.
NFR-3 — Anonymous reachability of pre-commitment surfaces. (required_inference) Landing, Search, and Journeys must be reachable without a verified account so a rider can evaluate routes and fares before committing. Rationale: the accepted journey begins anonymously and only requires identity at the point of commitment.
NFR-4 — Persistence of booking and payment state. (required_inference) Booking and payment state must persist so a confirmed booking produces a retrievable ticket and later supports viewing or cancellation. Rationale: the accepted lifecycle includes returning to a booking in a later session.
NFR-5 — Legibility and viewport integrity. (explicit, from the creative direction) Readable text and controls stay whole at 375px, 768px, and 1280px, wrapping or scaling to fit, with no element covering them. Rationale: the audience is a commuter on a phone who needs certainty at a glance.
NFR-6 — Reduced-motion support. (explicit, from the creative direction) With prefers-reduced-motion, the product provides a usable static arrangement in which every item can be brought fully into view. Rationale: motion is functional, not decorative, and must never be the only way to reach content.
NFR-7 — Tabular numerals for time, fare, and platform data. (explicit, from the creative direction) Times, fares, and platform numbers use tabular numerals. Rationale: comparison across ruled rows depends on column alignment.
NFR-8 — Backend integration. (required_inference) The application requires backend integration to hold identity, bookings, payment state, and tickets. Rationale: the accepted lifecycle cannot be completed with client-only state.
[Default — not specified by user][Default — not specified by user][Default — not specified by user][Default — not specified by user][Default — not specified by user]Constraints
#F4F1EA, white surfaces, black type and rules, one signal red #E63329, three coded line colours used only as 4px bars and category tags, Archivo typography, hard edges, and ruled tables. (explicit)Assumptions
[Default — not specified by user][Default — not specified by user]#1A5FB4, yellow #F2B705, green #2E7D32).#E63329, the single action colour used across all eight pages for the selected journey, active step, primary button, and live ticket state.
Winter-metro · Public transport, rendered as software
Search a route, compare journeys and fares, and hold a valid ticket at the station. A metro booking tool built like transit signage — coded, ordered, unmistakable.
A verified account is required to confirm a booking, pay a fare and hold an issued ticket. Search and compare journeys without one; enroll or verify here when you are ready to commit.
winter-metro moves you from one station to another with certainty — search, compare, book, pay, and travel on a valid ticket.
Enter your origin and destination stations and pick a travel date. The search is a ruled table, not a card, so origin and destination stay aligned in a strict column and a single control on the rule swaps them.
Available journeys read as a departure board: line code, departure, arrival, duration, changes and fare on ruled rows, sorted by departure, so you can weigh certainty against cost at a glance.
Confirm the traveller details, pay for the booking and keep the issued ticket. Reopen it later from your bookings, and cancel a booking when it is still applicable.

Winter-metro · Public transport, rendered as software
Search a route, compare journeys and fares, and hold a valid ticket at the station. A metro booking tool built like transit signage — coded, ordered, unmistakable.
A verified account is required to confirm a booking, pay a fare and hold an issued ticket. Search and compare journeys without one; enroll or verify here when you are ready to commit.
winter-metro moves you from one station to another with certainty — search, compare, book, pay, and travel on a valid ticket.
Enter your origin and destination stations and pick a travel date. The search is a ruled table, not a card, so origin and destination stay aligned in a strict column and a single control on the rule swaps them.
Available journeys read as a departure board: line code, departure, arrival, duration, changes and fare on ruled rows, sorted by departure, so you can weigh certainty against cost at a glance.
Confirm the traveller details, pay for the booking and keep the issued ticket. Reopen it later from your bookings, and cancel a booking when it is still applicable.
No comments yet. Be the first!