// Seat selection screen — 3D tilted cabin map with cinematic detail const ROW_COUNT = 28; const SEAT_LETTERS = ["A","B","C","D","E","F"]; // 3-3 layout const EMERGENCY_ROWS = [12, 13]; const PREMIUM_ROWS = [3, 4, 5, 6, 7]; const BLOCKED_SEATS = new Set([ "1A","1B","1C","2D","2E","2F","8C","9D","11A","14F","15B","16E","18A","19F","20C","21D","22A","23F","24B","25E","26C","27D","28A" ]); function seatPrice(row, col) { if (PREMIUM_ROWS.includes(row)) return 88; if (EMERGENCY_ROWS.includes(row)) return 38; if (col === "A" || col === "F") return 22; // window if (col === "C" || col === "D") return 12; // aisle return 0; // middle, free } function seatTier(row, col) { if (PREMIUM_ROWS.includes(row)) return "premium"; if (EMERGENCY_ROWS.includes(row)) return "emergency"; if (col === "A" || col === "F") return "window"; if (col === "C" || col === "D") return "aisle"; return "standard"; } function seatColor(tier, taken, sel) { if (taken) return "rgba(11,26,43,.18)"; if (sel) return "var(--sun)"; if (tier === "premium") return "#1f3a5a"; if (tier === "emergency") return "#b54a1d"; return "white"; } const ScreenSeats = ({ flight, query, selectedSeat, setSelectedSeat, onContinue, onBack }) => { const [tilt, setTilt] = useState(true); const [hovered, setHovered] = useState(null); return (
{/* Title row */}
Step 02 — Pick your perch

Choose where you sit.

{flight.carrier.name} {flight.id} · {flight.aircraft} · {fmtDuration(flight.durationMin)} from {query.origin.city} to {query.dest.city}.
{/* Cabin + side rail */}
{/* Cabin stage */}
{/* Decorative grid */} {/* Compass / labels */}
Cabin schematic · {flight.aircraft}
Direction of flight ↑
{/* The plane */}
{/* nose */} {/* rows */}
{/* row letters */}
{SEAT_LETTERS.slice(0,3).map(l => {l})} {SEAT_LETTERS.slice(3,6).map(l => {l})}
{Array.from({ length: ROW_COUNT }).map((_, idx) => { const row = idx + 1; const isExit = EMERGENCY_ROWS.includes(row); return (
{row} {SEAT_LETTERS.slice(0,3).map(c => )} {isExit ? "EXIT" : ""} {SEAT_LETTERS.slice(3,6).map(c => )} {row} {/* exit lights */} {isExit && <> } {/* premium divider */} {row === 7 &&
↑ PREMIUM ECONOMY
}
); })}
{/* Tail */}
{/* Floor shadow */}
{/* Right rail */}
Flight + seat
{flight.carrier.name} {flight.id} · {selectedSeat ? `Seat ${selectedSeat.row}${selectedSeat.col}` : "no seat yet"}
} right={
Subtotal
{fmtMoney(flight.price + (selectedSeat ? seatPrice(selectedSeat.row, selectedSeat.col) : 0))}
} secondary="Back" onSecondary={onBack} primary="Add passenger" onPrimary={onContinue} primaryDisabled={!selectedSeat} />
); }; // ----- Cabin parts ----- function Fuselage({ children }) { return (
{children}
); } function Nose() { return (
FIRST · BUSINESS
); } function Tail() { return (
GALLEY · LAVATORY
); } function Seat({ row, col, sel, setSel, hovered, setHovered }) { const id = `${row}${col}`; const taken = BLOCKED_SEATS.has(id); const isSel = sel && sel.row === row && sel.col === col; const tier = seatTier(row, col); const fill = seatColor(tier, taken, isSel); const border = taken ? "var(--line)" : tier === "premium" ? "#1f3a5a" : tier === "emergency" ? "#b54a1d" : "var(--ink-3)"; return ( ); } function Legend({ swatch, label, border, dashed }) { return (
{label}
); } window.ScreenSeats = ScreenSeats; window.seatPrice = seatPrice;