diff --git a/src/app/transit-board/page.test.tsx b/src/app/transit-board/page.test.tsx
new file mode 100644
index 0000000..bcafe65
--- /dev/null
+++ b/src/app/transit-board/page.test.tsx
@@ -0,0 +1,99 @@
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it } from "vitest";
+
+import TransitBoardPage from "./page";
+
+describe("TransitBoardPage", () => {
+ it("renders the page heading and description", () => {
+ render(
);
+
+ expect(
+ screen.getByRole("heading", {
+ level: 1,
+ name: /corridor movements, schedules, and delay tracking at a glance/i,
+ }),
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText(/monitor active corridors/i),
+ ).toBeInTheDocument();
+ });
+
+ it("renders all corridor summary cards", () => {
+ render(
);
+
+ expect(screen.getAllByText("North Arterial").length).toBeGreaterThan(0);
+ expect(screen.getAllByText("East Connector").length).toBeGreaterThan(0);
+ expect(screen.getAllByText("South Bypass").length).toBeGreaterThan(0);
+ expect(screen.getAllByText("West Loop").length).toBeGreaterThan(0);
+ expect(screen.getAllByText("Central Trunk").length).toBeGreaterThan(0);
+ });
+
+ it("displays corridor status and metrics", () => {
+ render(
);
+
+ expect(screen.getByText(/Flowing · Northbound/)).toBeInTheDocument();
+ expect(screen.getByText(/Congested · Eastbound/)).toBeInTheDocument();
+ expect(screen.getByText(/Blocked · Westbound/)).toBeInTheDocument();
+ expect(screen.getByText(/97% on-time/)).toBeInTheDocument();
+ });
+
+ it("renders summary bar with correct counts", () => {
+ render(
);
+
+ expect(screen.getByText("5")).toBeInTheDocument();
+ expect(screen.getByText("3/5")).toBeInTheDocument();
+ });
+
+ it("renders all movement cards with status badges", () => {
+ render(
);
+
+ expect(screen.getAllByText("MV-1001").length).toBeGreaterThan(0);
+ expect(screen.getByText("Express Freight Alpha")).toBeInTheDocument();
+ expect(screen.getAllByText("MV-1004").length).toBeGreaterThan(0);
+ expect(screen.getByText("Relief Convoy Delta")).toBeInTheDocument();
+ expect(screen.getByText(/Depot A → Terminal 7/)).toBeInTheDocument();
+ });
+
+ it("renders movement origin-destination and cargo info", () => {
+ render(
);
+
+ expect(screen.getByText(/Yard 3 → Hub East · Bulk materials/)).toBeInTheDocument();
+ expect(screen.getByText(/Base West → Junction 9 · Emergency supplies/)).toBeInTheDocument();
+ });
+
+ it("renders delay highlights with severity and delay duration", () => {
+ render(
);
+
+ expect(screen.getByText("+32 min")).toBeInTheDocument();
+ expect(screen.getByText("+67 min")).toBeInTheDocument();
+ expect(screen.getByText("+8 min")).toBeInTheDocument();
+ expect(screen.getByText("+14 min")).toBeInTheDocument();
+ });
+
+ it("renders delay reasons", () => {
+ render(
);
+
+ expect(
+ screen.getByText(/signal failure at junction EC-4/i),
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText(/track obstruction reported between WL-2 and WL-3/i),
+ ).toBeInTheDocument();
+ });
+
+ it("shows the tracked movements count", () => {
+ render(
);
+
+ expect(
+ screen.getByText(/6 tracked movements across all corridors/),
+ ).toBeInTheDocument();
+ });
+
+ it("shows the active delay reports count", () => {
+ render(
);
+
+ expect(
+ screen.getByText(/4 active delay reports/),
+ ).toBeInTheDocument();
+ });
+});
diff --git a/src/app/transit-board/page.tsx b/src/app/transit-board/page.tsx
new file mode 100644
index 0000000..543da06
--- /dev/null
+++ b/src/app/transit-board/page.tsx
@@ -0,0 +1,219 @@
+import type { Metadata } from "next";
+import Link from "next/link";
+
+export const metadata: Metadata = {
+ title: "Transit Board",
+ description:
+ "Corridor summaries, movement cards, and delay highlights for transit operations.",
+};
+
+interface Corridor {
+ id: string;
+ name: string;
+ direction: string;
+ status: "flowing" | "congested" | "blocked";
+ activeMovements: number;
+ avgTransitMin: number;
+ onTimeRate: string;
+}
+
+interface Movement {
+ id: string;
+ label: string;
+ corridor: string;
+ origin: string;
+ destination: string;
+ status: "in-transit" | "arrived" | "delayed" | "scheduled";
+ departedAt: string;
+ eta: string;
+ cargoType: string;
+}
+
+interface DelayHighlight {
+ id: string;
+ movementId: string;
+ corridor: string;
+ reason: string;
+ delayMin: number;
+ severity: "low" | "moderate" | "high";
+ reportedAt: string;
+}
+
+const corridors: Corridor[] = [
+ { id: "COR-N1", name: "North Arterial", direction: "Northbound", status: "flowing", activeMovements: 12, avgTransitMin: 34, onTimeRate: "94%" },
+ { id: "COR-E2", name: "East Connector", direction: "Eastbound", status: "congested", activeMovements: 8, avgTransitMin: 52, onTimeRate: "78%" },
+ { id: "COR-S3", name: "South Bypass", direction: "Southbound", status: "flowing", activeMovements: 15, avgTransitMin: 28, onTimeRate: "91%" },
+ { id: "COR-W4", name: "West Loop", direction: "Westbound", status: "blocked", activeMovements: 3, avgTransitMin: 87, onTimeRate: "42%" },
+ { id: "COR-C5", name: "Central Trunk", direction: "Bidirectional", status: "flowing", activeMovements: 20, avgTransitMin: 19, onTimeRate: "97%" },
+];
+
+const movements: Movement[] = [
+ { id: "MV-1001", label: "Express Freight Alpha", corridor: "North Arterial", origin: "Depot A", destination: "Terminal 7", status: "in-transit", departedAt: "2026-04-25T06:15:00Z", eta: "2026-04-25T06:49:00Z", cargoType: "Priority parcels" },
+ { id: "MV-1002", label: "Bulk Transfer Bravo", corridor: "East Connector", origin: "Yard 3", destination: "Hub East", status: "delayed", departedAt: "2026-04-25T05:40:00Z", eta: "2026-04-25T07:12:00Z", cargoType: "Bulk materials" },
+ { id: "MV-1003", label: "Shuttle Run Charlie", corridor: "South Bypass", origin: "Station 12", destination: "Depot C", status: "arrived", departedAt: "2026-04-25T04:50:00Z", eta: "2026-04-25T05:18:00Z", cargoType: "Equipment" },
+ { id: "MV-1004", label: "Relief Convoy Delta", corridor: "West Loop", origin: "Base West", destination: "Junction 9", status: "delayed", departedAt: "2026-04-25T05:00:00Z", eta: "2026-04-25T07:47:00Z", cargoType: "Emergency supplies" },
+ { id: "MV-1005", label: "Commuter Link Echo", corridor: "Central Trunk", origin: "Central Hub", destination: "Terminal 2", status: "in-transit", departedAt: "2026-04-25T06:30:00Z", eta: "2026-04-25T06:49:00Z", cargoType: "Passenger transfer" },
+ { id: "MV-1006", label: "Night Haul Foxtrot", corridor: "North Arterial", origin: "Depot A", destination: "Warehouse N", status: "scheduled", departedAt: "2026-04-25T22:00:00Z", eta: "2026-04-25T22:38:00Z", cargoType: "Refrigerated goods" },
+];
+
+const delayHighlights: DelayHighlight[] = [
+ { id: "DH-01", movementId: "MV-1002", corridor: "East Connector", reason: "Signal failure at junction EC-4 causing single-track operation", delayMin: 32, severity: "high", reportedAt: "2026-04-25T06:05:00Z" },
+ { id: "DH-02", movementId: "MV-1004", corridor: "West Loop", reason: "Track obstruction reported between WL-2 and WL-3 segments", delayMin: 67, severity: "high", reportedAt: "2026-04-25T05:30:00Z" },
+ { id: "DH-03", movementId: "MV-1001", corridor: "North Arterial", reason: "Minor schedule adjustment due to platform congestion at Terminal 7", delayMin: 8, severity: "low", reportedAt: "2026-04-25T06:40:00Z" },
+ { id: "DH-04", movementId: "MV-1005", corridor: "Central Trunk", reason: "Holding pattern for cross-traffic clearance at Central Hub", delayMin: 14, severity: "moderate", reportedAt: "2026-04-25T06:35:00Z" },
+];
+
+const corridorStatusColor: Record
= {
+ flowing: "bg-emerald-500",
+ congested: "bg-amber-500",
+ blocked: "bg-red-500",
+};
+
+const corridorStatusLabel: Record = {
+ flowing: "Flowing",
+ congested: "Congested",
+ blocked: "Blocked",
+};
+
+const movementStatusStyle: Record = {
+ "in-transit": "border-sky-200 bg-sky-50 text-sky-700",
+ arrived: "border-emerald-200 bg-emerald-50 text-emerald-700",
+ delayed: "border-red-200 bg-red-50 text-red-700",
+ scheduled: "border-slate-200 bg-slate-50 text-slate-600",
+};
+
+const delaySeverityStyle: Record = {
+ low: "border-slate-200 bg-slate-50 text-slate-600",
+ moderate: "border-amber-200 bg-amber-50 text-amber-700",
+ high: "border-red-200 bg-red-50 text-red-700",
+};
+
+export default function TransitBoardPage() {
+ const totalMovements = movements.length;
+ const inTransit = movements.filter((m) => m.status === "in-transit").length;
+ const delayed = movements.filter((m) => m.status === "delayed").length;
+ const flowingCorridors = corridors.filter((c) => c.status === "flowing").length;
+
+ return (
+
+
+
+
+ Transit Board
+
+
+ Back to overview
+
+
+
+ Corridor movements, schedules, and delay tracking at a glance.
+
+
+ Monitor active corridors, track individual movements across the
+ network, and review delay highlights for operational triage.
+
+
+
+ {/* Summary bar */}
+
+
+
Corridors
+
{corridors.length}
+
+
+
Flowing
+
{flowingCorridors}/{corridors.length}
+
+
+
In Transit
+
{inTransit}
+
+
+
+
+ {/* Corridor summaries */}
+
+ Corridor Summaries
+
+ {corridors.map((cor) => (
+
+
+
+
{cor.name}
+
+ {corridorStatusLabel[cor.status]} · {cor.direction}
+
+
+ {cor.activeMovements} active · avg {cor.avgTransitMin}m · {cor.onTimeRate} on-time
+
+
+
+ ))}
+
+
+
+ {/* Movement cards */}
+
+ Movements
+ {totalMovements} tracked movements across all corridors
+
+
+
+ {/* Delay highlights */}
+
+ Delay Highlights
+ {delayHighlights.length} active delay reports
+
+ {delayHighlights.map((dh) => (
+
+
+ {dh.movementId}
+
+ {dh.severity}
+
+ +{dh.delayMin} min
+
+ {dh.reason}
+
+ {dh.corridor} · Reported {dh.reportedAt.slice(11, 16)} UTC
+
+
+ ))}
+
+
+
+ );
+}