Airline — Legacy Flag Carrier Landing
A prestigious national flag-carrier landing page rendered in navy, gold, and serif type. It pairs a flight-search widget with a filterable route network, a four-cabin showcase, an interactive Crown Club loyalty programme with a live membership card, a heritage timeline, and an app section with a boarding-pass mockup. Includes mobile navigation, region filtering, tier switching, a swap control, toasts, and scroll-reveal animations — all in self-contained vanilla JavaScript.
MCP
Code
:root {
--navy: #0b2545;
--navy-2: #11315c;
--navy-d: #071a33;
--navy-50: #eef2f8;
--gold: #c8a24b;
--gold-d: #a8842f;
--gold-50: #faf4e6;
--white: #ffffff;
--ink: #0b2545;
--ink-2: #33455f;
--muted: #6b7991;
--bg: #f6f8fb;
--surface: #ffffff;
--line: rgba(11, 37, 69, 0.1);
--line-2: rgba(11, 37, 69, 0.18);
--ok: #1f9d62;
--warn: #d59024;
--danger: #d4493e;
--r-sm: 8px;
--r-md: 14px;
--r-lg: 22px;
--serif: "Playfair Display", Georgia, "Times New Roman", serif;
--sans: "Inter", system-ui, -apple-system, sans-serif;
--shadow-sm: 0 1px 2px rgba(11, 37, 69, 0.06), 0 4px 12px rgba(11, 37, 69, 0.06);
--shadow-md: 0 8px 30px rgba(11, 37, 69, 0.12);
--shadow-lg: 0 24px 60px rgba(11, 37, 69, 0.18);
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
font-family: var(--sans);
color: var(--ink);
background: var(--bg);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-variant-numeric: tabular-nums;
}
h1, h2, h3, h4, h5 { margin: 0; line-height: 1.15; }
p { margin: 0; }
a { color: inherit; text-decoration: none; }
img, svg { display: block; }
button { font-family: inherit; cursor: pointer; }
.wrap { width: min(1180px, 92vw); margin-inline: auto; }
.tnum { font-variant-numeric: tabular-nums; }
.skip {
position: absolute; left: -999px; top: 0; z-index: 200;
background: var(--navy); color: #fff; padding: 10px 16px; border-radius: 0 0 var(--r-sm) 0;
}
.skip:focus { left: 0; }
/* ===== Buttons ===== */
.btn {
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
border: 1px solid transparent; border-radius: 999px;
padding: 12px 22px; font-weight: 600; font-size: 15px;
transition: transform .15s ease, box-shadow .2s ease, background .2s ease, color .2s ease;
}
.btn:active { transform: translateY(1px); }
.btn--gold { background: linear-gradient(180deg, var(--gold), var(--gold-d)); color: var(--navy-d); box-shadow: 0 6px 18px rgba(200,162,75,.4); }
.btn--gold:hover { box-shadow: 0 10px 26px rgba(200,162,75,.55); transform: translateY(-2px); }
.btn--ghost { background: transparent; border-color: var(--line-2); color: var(--navy); }
.btn--ghost:hover { background: var(--navy-50); }
.btn--block { width: 100%; margin-top: 8px; }
/* ===== Top bar ===== */
.topbar { background: var(--navy-d); color: #cdd7e6; font-size: 13px; }
.topbar__row { display: flex; align-items: center; justify-content: space-between; height: 38px; }
.topbar__item { letter-spacing: .04em; }
.topbar__links { display: flex; align-items: center; gap: 18px; }
.topbar__links a:hover { color: var(--gold); }
.lang { background: none; border: 0; color: #cdd7e6; font-size: 13px; }
.lang:hover { color: var(--gold); }
@media (max-width: 620px) { .topbar__item { display: none; } }
/* ===== Nav ===== */
.nav {
position: sticky; top: 0; z-index: 100;
background: rgba(255,255,255,.86); backdrop-filter: blur(12px);
border-bottom: 1px solid var(--line);
transition: box-shadow .25s ease;
}
.nav.is-scrolled { box-shadow: var(--shadow-sm); }
.nav__row { display: flex; align-items: center; gap: 28px; height: 70px; }
.brand { display: flex; align-items: center; gap: 10px; }
.brand__mark svg { fill: var(--gold); }
.brand__name { font-family: var(--serif); font-weight: 700; font-size: 21px; color: var(--navy); letter-spacing: .01em; }
.brand__name em { font-style: italic; color: var(--gold-d); font-weight: 600; }
.nav__menu { display: flex; gap: 26px; margin-left: 8px; }
.nav__menu a { font-weight: 500; color: var(--ink-2); font-size: 15px; position: relative; padding: 6px 0; }
.nav__menu a::after { content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: 0; background: var(--gold); transition: width .22s ease; }
.nav__menu a:hover { color: var(--navy); }
.nav__menu a:hover::after { width: 100%; }
.nav__cta { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.burger { display: none; flex-direction: column; gap: 5px; background: none; border: 0; padding: 8px; }
.burger span { width: 24px; height: 2px; background: var(--navy); border-radius: 2px; transition: transform .25s, opacity .2s; }
@media (max-width: 920px) {
.nav__menu {
position: fixed; inset: 70px 0 auto 0;
flex-direction: column; gap: 0;
background: var(--white); border-bottom: 1px solid var(--line);
padding: 8px 6vw 18px; transform: translateY(-130%); transition: transform .3s ease;
box-shadow: var(--shadow-md); margin: 0;
}
.nav__menu.is-open { transform: translateY(0); }
.nav__menu a { padding: 14px 4px; border-bottom: 1px solid var(--line); font-size: 17px; }
.nav__menu a::after { display: none; }
.nav__cta .btn--ghost { display: none; }
.burger { display: flex; }
.burger.is-open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.burger.is-open span:nth-child(2) { opacity: 0; }
.burger.is-open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
}
/* ===== Hero ===== */
.hero { position: relative; overflow: hidden; color: #fff; }
.hero__bg {
position: absolute; inset: 0;
background:
radial-gradient(1100px 500px at 80% -10%, rgba(200,162,75,.28), transparent 60%),
radial-gradient(900px 600px at 0% 110%, rgba(17,49,92,.9), transparent 60%),
linear-gradient(150deg, var(--navy) 0%, var(--navy-2) 55%, var(--navy-d) 100%);
}
.hero__bg::after {
content: ""; position: absolute; inset: 0;
background-image: radial-gradient(rgba(255,255,255,.05) 1px, transparent 1px);
background-size: 22px 22px; opacity: .5;
}
.hero__inner {
position: relative; display: grid; grid-template-columns: 1.05fr .95fr; gap: 48px;
align-items: center; padding: 72px 0 96px;
}
.eyebrow {
display: inline-block; font-size: 12.5px; letter-spacing: .16em; text-transform: uppercase;
color: var(--gold); border: 1px solid rgba(200,162,75,.5); border-radius: 999px;
padding: 6px 14px; margin-bottom: 22px;
}
.hero h1 { font-family: var(--serif); font-size: clamp(38px, 5.4vw, 60px); font-weight: 700; letter-spacing: -.01em; }
.hero__copy p { margin-top: 18px; color: #d3deee; font-size: 18px; max-width: 30ch; }
.hero__stats { display: flex; gap: 34px; margin-top: 34px; }
.hero__stats div { display: flex; flex-direction: column; }
.hero__stats strong { font-family: var(--serif); font-size: 28px; color: var(--gold); }
.hero__stats span { font-size: 13px; color: #aebcd1; letter-spacing: .03em; }
/* ===== Search widget ===== */
.search {
background: var(--surface); color: var(--ink);
border-radius: var(--r-lg); padding: 22px; box-shadow: var(--shadow-lg);
border-top: 4px solid var(--gold);
}
.search__trips { display: flex; gap: 6px; background: var(--navy-50); padding: 4px; border-radius: 999px; margin-bottom: 18px; }
.trip {
flex: 1; border: 0; background: transparent; padding: 9px 10px; border-radius: 999px;
font-weight: 600; font-size: 14px; color: var(--ink-2); transition: all .2s;
}
.trip.is-active { background: var(--navy); color: #fff; box-shadow: var(--shadow-sm); }
.search__grid { display: grid; grid-template-columns: 1fr auto 1fr; gap: 12px; align-items: end; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field span { font-size: 12px; font-weight: 600; color: var(--muted); letter-spacing: .04em; text-transform: uppercase; }
.field input, .field select {
font-family: inherit; font-size: 15px; color: var(--ink); font-weight: 500;
border: 1px solid var(--line-2); border-radius: var(--r-sm);
padding: 12px 12px; background: #fff; width: 100%;
transition: border-color .2s, box-shadow .2s;
}
.field input:focus, .field select:focus, .footer__field input:focus {
outline: none; border-color: var(--gold); box-shadow: 0 0 0 3px rgba(200,162,75,.22);
}
.field--sm { grid-column: span 1; }
.search__grid > .field:nth-of-type(1) { grid-column: 1; }
.search__grid > .field:nth-of-type(2) { grid-column: 3; }
.search__grid > .field:nth-of-type(3),
.search__grid > .field:nth-of-type(4) { grid-column: span 1; }
#departInput { grid-column: 1; }
#returnField { grid-column: 3; }
.search__grid .field--sm:nth-of-type(5) { grid-column: 1; }
.search__grid .field--sm:nth-of-type(6) { grid-column: 3; }
.swap {
grid-column: 2; grid-row: 1; align-self: end;
width: 40px; height: 44px; border-radius: var(--r-sm);
border: 1px solid var(--line-2); background: var(--navy-50); color: var(--navy);
font-size: 17px; transition: transform .25s, background .2s;
}
.swap:hover { background: var(--gold-50); color: var(--gold-d); }
.swap.is-spun { transform: rotate(180deg); }
.search__note { margin-top: 14px; font-size: 13.5px; color: var(--muted); text-align: center; }
.search__note strong { color: var(--navy); }
/* ===== Sections ===== */
.section { padding: 84px 0; }
.section--alt { background: var(--navy-50); }
.section__head { max-width: 640px; margin-bottom: 38px; }
.kicker { display: inline-block; font-size: 12.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--gold-d); font-weight: 700; margin-bottom: 12px; }
.kicker--gold { color: var(--gold); }
.section h2 { font-family: var(--serif); font-size: clamp(28px, 3.6vw, 40px); font-weight: 700; color: var(--navy); }
.section__head p { margin-top: 14px; color: var(--ink-2); font-size: 17px; }
.section__head--light h2 { color: #fff; }
/* ===== Chips / routes ===== */
.chips { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 28px; }
.chip {
border: 1px solid var(--line-2); background: #fff; color: var(--ink-2);
padding: 9px 18px; border-radius: 999px; font-weight: 600; font-size: 14px; transition: all .2s;
}
.chip:hover { border-color: var(--gold); color: var(--navy); }
.chip.is-active { background: var(--navy); border-color: var(--navy); color: #fff; }
.routes { display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); gap: 18px; }
.route {
background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md);
padding: 20px; box-shadow: var(--shadow-sm); transition: transform .22s, box-shadow .22s, border-color .22s;
animation: pop .35s ease both;
}
.route:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: var(--line-2); }
.route__top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.route__codes { display: flex; align-items: center; gap: 10px; font-family: var(--serif); font-weight: 700; font-size: 22px; color: var(--navy); }
.route__codes span.arr { color: var(--gold); font-size: 16px; }
.route__city { font-size: 13px; color: var(--muted); margin-top: 2px; }
.route__flag { font-size: 24px; }
.route__row { display: flex; align-items: center; justify-content: space-between; border-top: 1px dashed var(--line-2); padding-top: 14px; margin-top: 6px; }
.route__price { font-weight: 700; color: var(--navy); font-size: 17px; }
.route__price small { font-weight: 500; color: var(--muted); font-size: 12px; }
.route__meta { font-size: 13px; color: var(--ink-2); }
.pill { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 700; letter-spacing: .04em; padding: 4px 10px; border-radius: 999px; text-transform: uppercase; }
.pill--ok { background: rgba(31,157,98,.14); color: var(--ok); }
.pill--direct { background: var(--gold-50); color: var(--gold-d); }
.pill--warn { background: rgba(213,144,36,.16); color: var(--warn); }
/* ===== Cabins ===== */
.cabins { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; }
.cabin {
background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md);
padding: 26px 22px; box-shadow: var(--shadow-sm); display: flex; flex-direction: column;
transition: transform .22s, box-shadow .22s;
}
.cabin:hover { transform: translateY(-5px); box-shadow: var(--shadow-md); }
.cabin--feature { border: 1px solid var(--gold); box-shadow: 0 10px 30px rgba(200,162,75,.18); position: relative; }
.cabin__tag { align-self: flex-start; font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--navy); background: var(--navy-50); padding: 5px 12px; border-radius: 999px; margin-bottom: 16px; }
.cabin__tag--gold { background: linear-gradient(180deg, var(--gold), var(--gold-d)); color: var(--navy-d); }
.cabin h3 { font-family: var(--serif); font-size: 21px; color: var(--navy); margin-bottom: 8px; }
.cabin p { color: var(--ink-2); font-size: 14.5px; }
.cabin ul { list-style: none; padding: 0; margin: 16px 0; display: flex; flex-direction: column; gap: 8px; }
.cabin li { position: relative; padding-left: 22px; font-size: 14px; color: var(--ink-2); }
.cabin li::before { content: "✦"; position: absolute; left: 0; color: var(--gold); }
.cabin__price { margin-top: auto; font-family: var(--serif); font-weight: 700; font-size: 18px; color: var(--navy); padding-top: 14px; border-top: 1px solid var(--line); }
/* ===== Loyalty ===== */
.loyalty__grid { display: grid; grid-template-columns: 1.1fr .9fr; gap: 56px; align-items: center; }
.loyalty p { color: var(--ink-2); font-size: 17px; margin-top: 6px; }
.tiers { display: flex; gap: 8px; margin: 24px 0 18px; flex-wrap: wrap; }
.tier { border: 1px solid var(--line-2); background: #fff; color: var(--ink-2); padding: 9px 18px; border-radius: 999px; font-weight: 600; font-size: 14px; transition: all .2s; }
.tier:hover { border-color: var(--gold); }
.tier.is-active { background: var(--navy); color: #fff; border-color: var(--navy); }
.tier__perks { list-style: none; padding: 0; margin: 0 0 26px; display: grid; gap: 10px; }
.tier__perks li { position: relative; padding-left: 26px; color: var(--ink-2); font-size: 15px; }
.tier__perks li::before { content: "✓"; position: absolute; left: 0; color: var(--gold-d); font-weight: 800; }
.card-loyalty { perspective: 1200px; }
.card-loyalty__inner {
position: relative; aspect-ratio: 1.586; border-radius: var(--r-md); padding: 24px;
color: #fff; box-shadow: var(--shadow-lg); overflow: hidden;
background: linear-gradient(135deg, var(--navy-2), var(--navy-d));
transition: transform .5s ease, background .5s ease;
transform-style: preserve-3d;
}
.card-loyalty__inner::before {
content: ""; position: absolute; inset: 0;
background: radial-gradient(600px 300px at 110% -20%, rgba(200,162,75,.4), transparent 55%);
}
.card-loyalty__inner.tier-gold, .card-loyalty__inner.tier-crown { background: linear-gradient(135deg, #1a2c46, #0b2545); }
.card-loyalty__top { position: relative; display: flex; justify-content: space-between; align-items: center; }
.card-loyalty__brand { font-size: 12px; letter-spacing: .12em; color: var(--gold); font-weight: 700; }
.card-loyalty__tier { font-family: var(--serif); font-weight: 700; font-size: 16px; letter-spacing: .08em; color: #fff; }
.card-loyalty__chip { position: relative; width: 46px; height: 34px; border-radius: 6px; margin: 22px 0 18px; background: linear-gradient(135deg, #e8cf86, var(--gold-d)); box-shadow: inset 0 0 0 1px rgba(0,0,0,.15); }
.card-loyalty__no { position: relative; font-size: 19px; letter-spacing: .08em; font-weight: 600; font-variant-numeric: tabular-nums; }
.card-loyalty__row { position: relative; display: flex; justify-content: space-between; margin-top: 18px; }
.card-loyalty__row small { display: block; font-size: 10.5px; letter-spacing: .08em; color: #aebcd1; text-transform: uppercase; }
.card-loyalty__row strong { font-size: 15px; letter-spacing: .04em; }
/* ===== Heritage ===== */
.section--navy { background: linear-gradient(160deg, var(--navy) 0%, var(--navy-d) 100%); color: #fff; position: relative; }
.section--navy::after { content: ""; position: absolute; inset: 0; background-image: radial-gradient(rgba(255,255,255,.05) 1px, transparent 1px); background-size: 24px 24px; opacity: .4; pointer-events: none; }
.timeline { position: relative; display: grid; grid-template-columns: repeat(4, 1fr); gap: 22px; margin-top: 18px; }
.tl { position: relative; padding-top: 26px; }
.tl::before { content: ""; position: absolute; top: 6px; left: 0; right: 0; height: 2px; background: rgba(200,162,75,.3); }
.tl::after { content: ""; position: absolute; top: 0; left: 0; width: 14px; height: 14px; border-radius: 50%; background: var(--gold); box-shadow: 0 0 0 4px rgba(200,162,75,.2); }
.tl__year { font-family: var(--serif); font-size: 24px; font-weight: 700; color: var(--gold); }
.tl h4 { margin: 8px 0 8px; font-size: 17px; }
.tl p { color: #c5d2e4; font-size: 14px; }
/* ===== App ===== */
.app__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 56px; align-items: center; }
.app p { color: var(--ink-2); font-size: 17px; margin-top: 6px; }
.app__badges { display: flex; gap: 12px; margin-top: 26px; flex-wrap: wrap; }
.storebtn { background: var(--navy); color: #fff; border: 0; border-radius: var(--r-sm); padding: 13px 22px; font-weight: 600; font-size: 15px; transition: transform .15s, background .2s; }
.storebtn:hover { background: var(--navy-2); transform: translateY(-2px); }
.app__phone { display: flex; justify-content: center; }
.phone {
position: relative; width: 290px; padding: 14px; border-radius: 38px;
background: linear-gradient(160deg, #16294a, #0b2545); box-shadow: var(--shadow-lg);
border: 1px solid rgba(255,255,255,.08);
}
.phone__notch { position: absolute; top: 14px; left: 50%; transform: translateX(-50%); width: 110px; height: 22px; background: #0b2545; border-radius: 0 0 14px 14px; z-index: 2; }
.boarding { background: #fff; border-radius: 26px; padding: 26px 20px 22px; color: var(--ink); }
.boarding__head { display: flex; justify-content: space-between; align-items: center; font-size: 11px; letter-spacing: .12em; color: var(--muted); font-weight: 700; }
.boarding__route { display: flex; align-items: center; justify-content: space-between; margin: 20px 0; }
.boarding__route strong { font-family: var(--serif); font-size: 30px; color: var(--navy); display: block; }
.boarding__route small { font-size: 12px; color: var(--muted); }
.boarding__plane { color: var(--gold); font-size: 22px; }
.boarding__perf { border-top: 2px dashed var(--line-2); margin: 6px -20px; position: relative; }
.boarding__perf::before, .boarding__perf::after { content: ""; position: absolute; top: -10px; width: 20px; height: 20px; border-radius: 50%; background: #fff; box-shadow: inset 0 0 0 1px var(--line); }
.boarding__perf::before { left: -10px; }
.boarding__perf::after { right: -10px; }
.boarding__meta { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 16px; }
.boarding__meta small { display: block; font-size: 10px; color: var(--muted); letter-spacing: .06em; text-transform: uppercase; }
.boarding__meta b { font-size: 15px; color: var(--navy); }
/* ===== Footer ===== */
.footer { background: var(--navy-d); color: #c5d2e4; padding-top: 60px; }
.footer__grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr 1.6fr; gap: 30px; padding-bottom: 40px; }
.brand--footer .brand__name { color: #fff; }
.footer__brand p { margin-top: 14px; font-size: 14px; max-width: 26ch; color: #9fb0c7; }
.footer__col h5, .footer__news h5 { font-size: 13px; letter-spacing: .08em; text-transform: uppercase; color: var(--gold); margin-bottom: 14px; }
.footer__col a { display: block; padding: 6px 0; font-size: 14.5px; color: #c5d2e4; transition: color .2s; }
.footer__col a:hover { color: #fff; }
.footer__news p { font-size: 14px; color: #9fb0c7; margin-bottom: 14px; }
.footer__field { display: flex; gap: 8px; }
.footer__field input { flex: 1; min-width: 0; border: 1px solid rgba(255,255,255,.16); background: rgba(255,255,255,.06); color: #fff; border-radius: var(--r-sm); padding: 11px 12px; font-family: inherit; }
.footer__field input::placeholder { color: #8094ad; }
.footer__bar { display: flex; align-items: center; justify-content: space-between; padding: 20px 0; border-top: 1px solid rgba(255,255,255,.1); font-size: 13px; color: #8094ad; }
.footer__bar nav { display: flex; gap: 18px; }
.footer__bar a:hover { color: var(--gold); }
/* ===== Toast ===== */
.toast {
position: fixed; left: 50%; bottom: 28px; transform: translate(-50%, 140%);
background: var(--navy); color: #fff; padding: 13px 22px; border-radius: 999px;
font-size: 14.5px; font-weight: 500; box-shadow: var(--shadow-lg); z-index: 300;
border: 1px solid rgba(200,162,75,.4); transition: transform .35s cubic-bezier(.2,.8,.2,1);
display: flex; align-items: center; gap: 8px; max-width: 90vw;
}
.toast.is-show { transform: translate(-50%, 0); }
.toast::before { content: "✦"; color: var(--gold); }
/* ===== Reveal ===== */
.reveal { opacity: 0; transform: translateY(22px); transition: opacity .6s ease, transform .6s ease; }
.reveal.is-in { opacity: 1; transform: none; }
@keyframes pop { from { opacity: 0; transform: translateY(10px) scale(.98); } to { opacity: 1; transform: none; } }
/* ===== Responsive ===== */
@media (max-width: 980px) {
.hero__inner { grid-template-columns: 1fr; gap: 36px; padding: 56px 0 70px; }
.hero__copy p { max-width: none; }
.cabins { grid-template-columns: repeat(2, 1fr); }
.loyalty__grid, .app__grid { grid-template-columns: 1fr; gap: 38px; }
.card-loyalty { max-width: 420px; }
.timeline { grid-template-columns: repeat(2, 1fr); gap: 30px; }
.footer__grid { grid-template-columns: 1fr 1fr; }
.footer__news { grid-column: 1 / -1; }
}
@media (max-width: 520px) {
.section { padding: 60px 0; }
.search { padding: 18px; }
.search__grid { grid-template-columns: 1fr; }
.search__grid > .field,
.search__grid > .field--sm,
#departInput, #returnField,
.search__grid .field--sm:nth-of-type(5),
.search__grid .field--sm:nth-of-type(6) { grid-column: 1 !important; }
.swap { grid-column: 1 !important; justify-self: center; width: 100%; transform: rotate(90deg); }
.swap.is-spun { transform: rotate(270deg); }
.cabins { grid-template-columns: 1fr; }
.timeline { grid-template-columns: 1fr; }
.footer__grid { grid-template-columns: 1fr; }
.footer__bar { flex-direction: column; gap: 12px; text-align: center; }
.hero__stats { gap: 22px; }
.topbar__links { gap: 12px; }
}(function () {
"use strict";
/* ---------- Toast helper ---------- */
var toastEl = document.getElementById("toast");
var toastTimer;
function toast(msg) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.classList.add("is-show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("is-show");
}, 3200);
}
/* ---------- Sticky nav shadow ---------- */
var nav = document.getElementById("nav");
var onScroll = function () {
if (nav) nav.classList.toggle("is-scrolled", window.scrollY > 8);
};
window.addEventListener("scroll", onScroll, { passive: true });
onScroll();
/* ---------- Mobile nav ---------- */
var burger = document.getElementById("burger");
var navMenu = document.getElementById("navMenu");
if (burger && navMenu) {
burger.addEventListener("click", function () {
var open = navMenu.classList.toggle("is-open");
burger.classList.toggle("is-open", open);
burger.setAttribute("aria-expanded", String(open));
});
navMenu.addEventListener("click", function (e) {
if (e.target.closest("a")) {
navMenu.classList.remove("is-open");
burger.classList.remove("is-open");
burger.setAttribute("aria-expanded", "false");
}
});
}
/* ---------- Language toggle ---------- */
var langBtn = document.getElementById("langBtn");
var langs = ["EN · GBP ▾", "FR · EUR ▾", "JP · JPY ▾", "AE · USD ▾"];
var langI = 0;
if (langBtn) {
langBtn.addEventListener("click", function () {
langI = (langI + 1) % langs.length;
langBtn.textContent = langs[langI];
toast("Region set to " + langs[langI].replace(" ▾", ""));
});
}
/* ---------- Trip type tabs ---------- */
var trips = document.querySelectorAll(".trip");
var returnField = document.getElementById("returnField");
trips.forEach(function (t) {
t.addEventListener("click", function () {
trips.forEach(function (x) {
x.classList.remove("is-active");
x.setAttribute("aria-selected", "false");
});
t.classList.add("is-active");
t.setAttribute("aria-selected", "true");
if (returnField) {
returnField.style.visibility = t.dataset.trip === "oneway" ? "hidden" : "visible";
}
});
});
/* ---------- Default dates ---------- */
function fmt(d) {
return d.toISOString().slice(0, 10);
}
var depart = document.getElementById("departInput");
var ret = document.getElementById("returnInput");
var now = new Date();
var d1 = new Date(now.getTime() + 14 * 864e5);
var d2 = new Date(now.getTime() + 21 * 864e5);
if (depart) depart.value = fmt(d1);
if (ret) ret.value = fmt(d2);
/* ---------- Swap origin/destination ---------- */
var swapBtn = document.getElementById("swapBtn");
var fromI = document.getElementById("fromInput");
var toI = document.getElementById("toInput");
if (swapBtn && fromI && toI) {
swapBtn.addEventListener("click", function () {
var tmp = fromI.value;
fromI.value = toI.value;
toI.value = tmp;
swapBtn.classList.toggle("is-spun");
toast("Route reversed");
});
}
/* ---------- Search submit ---------- */
var form = document.getElementById("searchForm");
var cabin = document.getElementById("cabinSelect");
var hint = document.getElementById("searchHint");
if (form) {
form.addEventListener("submit", function (e) {
e.preventDefault();
var c = cabin ? cabin.value : "Economy";
var price = { Economy: "£210", Premium: "£980", "Crown Business": "£2,140", First: "£6,490" }[c] || "£210";
if (hint) {
hint.innerHTML =
"Searching <strong>" + (fromI ? fromI.value : "") + "</strong> → <strong>" +
(toI ? toI.value : "") + "</strong> · " + c + " from <strong>" + price + "</strong>.";
}
toast("Found 6 fares · " + c + " from " + price);
});
}
/* ---------- Route network ---------- */
var ROUTES = [
{ c: "JFK", city: "New York", flag: "🇺🇸", region: "americas", price: "2,140", flight: "MA 0107", status: "direct" },
{ c: "DXB", city: "Dubai", flag: "🇦🇪", region: "africa", price: "1,690", flight: "MA 0421", status: "direct" },
{ c: "HND", city: "Tokyo", flag: "🇯🇵", region: "asia", price: "2,980", flight: "MA 0915", status: "direct" },
{ c: "CDG", city: "Paris", flag: "🇫🇷", region: "europe", price: "180", flight: "MA 0233", status: "ok" },
{ c: "SIN", city: "Singapore", flag: "🇸🇬", region: "asia", price: "3,210", flight: "MA 0807", status: "direct" },
{ c: "JNB", city: "Johannesburg", flag: "🇿🇦", region: "africa", price: "1,420", flight: "MA 0552", status: "ok" },
{ c: "GRU", city: "São Paulo", flag: "🇧🇷", region: "americas", price: "2,760", flight: "MA 0188", status: "ok" },
{ c: "FCO", city: "Rome", flag: "🇮🇹", region: "europe", price: "210", flight: "MA 0349", status: "direct" },
{ c: "SYD", city: "Sydney", flag: "🇦🇺", region: "asia", price: "3,640", flight: "MA 0011", status: "ok" }
];
var grid = document.getElementById("routeGrid");
function statusPill(s) {
if (s === "direct") return '<span class="pill pill--direct">Direct daily</span>';
if (s === "warn") return '<span class="pill pill--warn">Seasonal</span>';
return '<span class="pill pill--ok">Available</span>';
}
function renderRoutes(region) {
if (!grid) return;
var list = ROUTES.filter(function (r) { return region === "all" || r.region === region; });
grid.innerHTML = list.map(function (r) {
return (
'<article class="route">' +
'<div class="route__top">' +
'<div>' +
'<div class="route__codes">LHR <span class="arr">✈</span> ' + r.c + '</div>' +
'<div class="route__city">London → ' + r.city + '</div>' +
'</div>' +
'<span class="route__flag">' + r.flag + '</span>' +
'</div>' +
'<div class="route__row">' +
'<div class="route__price">£' + r.price + ' <small>return · ' + r.flight + '</small></div>' +
statusPill(r.status) +
'</div>' +
'</article>'
);
}).join("");
if (!list.length) grid.innerHTML = '<p style="color:var(--muted)">No destinations in this region.</p>';
}
renderRoutes("all");
var chips = document.querySelectorAll(".chip");
chips.forEach(function (chip) {
chip.addEventListener("click", function () {
chips.forEach(function (x) { x.classList.remove("is-active"); x.setAttribute("aria-selected", "false"); });
chip.classList.add("is-active");
chip.setAttribute("aria-selected", "true");
renderRoutes(chip.dataset.region);
});
});
/* ---------- Loyalty tiers ---------- */
var TIERS = {
blue: { label: "BLUE", miles: "14,280", perks: ["Earn 1 Crown Mile per £1 spent", "Member-only seasonal fares", "Standard reward seat access"] },
silver: { label: "SILVER", miles: "38,900", perks: ["25% bonus miles on every flight", "Priority check-in & boarding", "One complimentary upgrade voucher"] },
gold: { label: "GOLD", miles: "76,540", perks: ["50% bonus miles & Crown Lounge access", "Guaranteed economy reward seats", "Extra baggage allowance worldwide"] },
crown: { label: "CROWN", miles: "152,300", perks: ["Double miles & dedicated concierge", "First-class lounge for two", "Suite upgrades & private check-in"] }
};
var tierBtns = document.querySelectorAll(".tier");
var tierPerks = document.getElementById("tierPerks");
var cardTier = document.getElementById("cardTier");
var cardMiles = document.getElementById("cardMiles");
var loyaltyCard = document.getElementById("loyaltyCard");
function setTier(key) {
var t = TIERS[key];
if (!t) return;
if (tierPerks) tierPerks.innerHTML = t.perks.map(function (p) { return "<li>" + p + "</li>"; }).join("");
if (cardTier) cardTier.textContent = t.label;
if (cardMiles) cardMiles.textContent = t.miles;
if (loyaltyCard) {
loyaltyCard.className = "card-loyalty__inner tier-" + key;
loyaltyCard.animate(
[{ transform: "rotateY(-8deg) scale(.98)" }, { transform: "rotateY(0) scale(1)" }],
{ duration: 500, easing: "ease" }
);
}
}
tierBtns.forEach(function (b) {
b.addEventListener("click", function () {
tierBtns.forEach(function (x) { x.classList.remove("is-active"); });
b.classList.add("is-active");
setTier(b.dataset.tier);
});
});
setTier("blue");
/* ---------- App store badges ---------- */
document.querySelectorAll(".storebtn").forEach(function (b) {
b.addEventListener("click", function () { toast("Opening the " + b.dataset.store + "…"); });
});
/* ---------- Newsletter ---------- */
var newsForm = document.getElementById("newsForm");
if (newsForm) {
newsForm.addEventListener("submit", function (e) {
e.preventDefault();
var email = document.getElementById("newsEmail");
toast("Welcome aboard — fare alerts on their way to " + (email ? email.value : "you") + ".");
newsForm.reset();
});
}
/* ---------- Scroll reveal ---------- */
var revealEls = document.querySelectorAll(".reveal");
if ("IntersectionObserver" in window) {
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (en) {
if (en.isIntersecting) {
en.target.classList.add("is-in");
io.unobserve(en.target);
}
});
}, { threshold: 0.12, rootMargin: "0px 0px -40px 0px" });
revealEls.forEach(function (el) { io.observe(el); });
} else {
revealEls.forEach(function (el) { el.classList.add("is-in"); });
}
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Meridian Airways — National Flag Carrier</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Playfair+Display:wght@500;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<a class="skip" href="#main">Skip to content</a>
<!-- ===== Top bar ===== -->
<div class="topbar">
<div class="wrap topbar__row">
<span class="topbar__item">Est. 1947 · Royal National Carrier</span>
<nav class="topbar__links" aria-label="Utility">
<a href="#">Manage booking</a>
<a href="#">Flight status</a>
<button class="lang" id="langBtn" aria-haspopup="true">EN · GBP ▾</button>
</nav>
</div>
</div>
<!-- ===== Header ===== -->
<header class="nav" id="nav">
<div class="wrap nav__row">
<a class="brand" href="#" aria-label="Meridian Airways home">
<span class="brand__mark" aria-hidden="true">
<svg viewBox="0 0 32 32" width="34" height="34"><path d="M16 2l3.4 9.5L29 14l-9.6 2.5L16 30l-3.4-13.5L3 14l9.6-2.5z"/></svg>
</span>
<span class="brand__name">Meridian<em>Airways</em></span>
</a>
<nav class="nav__menu" id="navMenu" aria-label="Primary">
<a href="#search">Book</a>
<a href="#network">Destinations</a>
<a href="#cabins">Cabins</a>
<a href="#loyalty">Crown Club</a>
<a href="#heritage">Heritage</a>
</nav>
<div class="nav__cta">
<a href="#loyalty" class="btn btn--ghost">Sign in</a>
<a href="#search" class="btn btn--gold">Book a flight</a>
<button class="burger" id="burger" aria-label="Open menu" aria-expanded="false" aria-controls="navMenu">
<span></span><span></span><span></span>
</button>
</div>
</div>
</header>
<main id="main">
<!-- ===== Hero + search ===== -->
<section class="hero">
<div class="hero__bg" aria-hidden="true"></div>
<div class="wrap hero__inner">
<div class="hero__copy reveal">
<span class="eyebrow">The nation's airline · 78 years aloft</span>
<h1>Where prestige takes flight.</h1>
<p>From London to ninety destinations across six continents, Meridian Airways carries you with the grace of a flag carrier and the care of a family. Fly with the crown.</p>
<div class="hero__stats">
<div><strong>90+</strong><span>Destinations</span></div>
<div><strong>142</strong><span>Aircraft</span></div>
<div><strong>4.9★</strong><span>Cabin rating</span></div>
</div>
</div>
<!-- Search widget -->
<form class="search reveal" id="searchForm" aria-label="Flight search">
<div class="search__trips" role="tablist" aria-label="Trip type">
<button type="button" class="trip is-active" data-trip="return" role="tab" aria-selected="true">Return</button>
<button type="button" class="trip" data-trip="oneway" role="tab" aria-selected="false">One way</button>
<button type="button" class="trip" data-trip="multi" role="tab" aria-selected="false">Multi-city</button>
</div>
<div class="search__grid">
<label class="field">
<span>From</span>
<input id="fromInput" type="text" value="London Heathrow (LHR)" autocomplete="off" aria-describedby="fromHint" />
</label>
<button type="button" class="swap" id="swapBtn" aria-label="Swap origin and destination">⇄</button>
<label class="field">
<span>To</span>
<input id="toInput" type="text" value="New York JFK (JFK)" autocomplete="off" />
</label>
<label class="field">
<span>Depart</span>
<input id="departInput" type="date" />
</label>
<label class="field" id="returnField">
<span>Return</span>
<input id="returnInput" type="date" />
</label>
<label class="field field--sm">
<span>Cabin</span>
<select id="cabinSelect">
<option>Economy</option>
<option>Premium</option>
<option selected>Crown Business</option>
<option>First</option>
</select>
</label>
<label class="field field--sm">
<span>Travellers</span>
<select id="paxSelect">
<option>1 adult</option>
<option selected>2 adults</option>
<option>2 adults · 1 child</option>
<option>Family · 4</option>
</select>
</label>
</div>
<button type="submit" class="btn btn--gold btn--block">Search flights</button>
<p class="search__note" id="searchHint" aria-live="polite">Direct daily service · Crown Business from <strong>£2,140</strong> return.</p>
</form>
</div>
</section>
<!-- ===== Network / destinations ===== -->
<section class="section" id="network">
<div class="wrap">
<header class="section__head reveal">
<span class="kicker">Our network</span>
<h2>Ninety destinations, one standard of excellence</h2>
<p>Filter the route map by region and explore signature services from our London hub.</p>
</header>
<div class="chips reveal" role="tablist" aria-label="Region filter">
<button class="chip is-active" data-region="all" role="tab" aria-selected="true">All regions</button>
<button class="chip" data-region="europe" role="tab" aria-selected="false">Europe</button>
<button class="chip" data-region="americas" role="tab" aria-selected="false">Americas</button>
<button class="chip" data-region="asia" role="tab" aria-selected="false">Asia & Pacific</button>
<button class="chip" data-region="africa" role="tab" aria-selected="false">Africa & Gulf</button>
</div>
<div class="routes" id="routeGrid"></div>
</div>
</section>
<!-- ===== Cabins ===== -->
<section class="section section--alt" id="cabins">
<div class="wrap">
<header class="section__head reveal">
<span class="kicker">Travel in style</span>
<h2>Four cabins, crafted for every journey</h2>
</header>
<div class="cabins">
<article class="cabin reveal">
<div class="cabin__tag">First</div>
<h3>The Sovereign Suite</h3>
<p>Private suites with closing doors, a fully-flat bed dressed in fine linen, and bespoke dining on demand.</p>
<ul>
<li>Closing-door private suite</li>
<li>À la carte fine dining</li>
<li>Chauffeur & private check-in</li>
</ul>
<span class="cabin__price">from £6,490</span>
</article>
<article class="cabin cabin--feature reveal">
<div class="cabin__tag cabin__tag--gold">Crown Business</div>
<h3>The Crown Cabin</h3>
<p>Our signature lie-flat seat with direct aisle access, a generous dining table, and lounge access worldwide.</p>
<ul>
<li>1-2-1 lie-flat with aisle access</li>
<li>Fast-track & Crown Lounge</li>
<li>Curated regional menus</li>
</ul>
<span class="cabin__price">from £2,140</span>
</article>
<article class="cabin reveal">
<div class="cabin__tag">Premium</div>
<h3>Premium Voyager</h3>
<p>Wider seats, extra recline, and an elevated menu — the considered choice for the discerning traveller.</p>
<ul>
<li>+18cm seat pitch</li>
<li>Enhanced dining & amenity kit</li>
<li>Priority boarding</li>
</ul>
<span class="cabin__price">from £980</span>
</article>
<article class="cabin reveal">
<div class="cabin__tag">Economy</div>
<h3>National Economy</h3>
<p>Warm hospitality, complimentary meals, and the same flag-carrier care at every altitude.</p>
<ul>
<li>Complimentary meals & bar</li>
<li>Seatback entertainment</li>
<li>Generous baggage allowance</li>
</ul>
<span class="cabin__price">from £210</span>
</article>
</div>
</div>
</section>
<!-- ===== Loyalty ===== -->
<section class="section loyalty" id="loyalty">
<div class="wrap loyalty__grid">
<div class="loyalty__copy reveal">
<span class="kicker">Crown Club</span>
<h2>A loyalty programme worthy of the crown</h2>
<p>Earn Crown Miles on every flight and redeem them for upgrades, reward seats, and partner stays across our global alliance. Status that travels with you.</p>
<div class="tiers">
<button class="tier is-active" data-tier="blue">Blue</button>
<button class="tier" data-tier="silver">Silver</button>
<button class="tier" data-tier="gold">Gold</button>
<button class="tier" data-tier="crown">Crown</button>
</div>
<ul class="tier__perks" id="tierPerks"></ul>
<a href="#search" class="btn btn--gold">Join Crown Club</a>
</div>
<aside class="card-loyalty reveal" aria-hidden="false">
<div class="card-loyalty__inner" id="loyaltyCard">
<div class="card-loyalty__top">
<span class="card-loyalty__brand">MERIDIAN · CROWN CLUB</span>
<span class="card-loyalty__tier" id="cardTier">BLUE</span>
</div>
<div class="card-loyalty__chip" aria-hidden="true"></div>
<div class="card-loyalty__no">4921 ·· 7740 ·· 1183</div>
<div class="card-loyalty__row">
<div><small>Member</small><strong>E. WHITMORE</strong></div>
<div><small>Miles</small><strong id="cardMiles">14,280</strong></div>
</div>
</div>
</aside>
</div>
</section>
<!-- ===== Heritage ===== -->
<section class="section section--navy heritage" id="heritage">
<div class="wrap">
<header class="section__head section__head--light reveal">
<span class="kicker kicker--gold">Since 1947</span>
<h2>Seventy-eight years carrying a nation</h2>
</header>
<div class="timeline">
<div class="tl reveal"><span class="tl__year">1947</span><h4>First flight</h4><p>Our maiden service departs the capital aboard a propliner, christened by royal charter.</p></div>
<div class="tl reveal"><span class="tl__year">1969</span><h4>The jet age</h4><p>We enter the jet era, connecting the nation to the world in hours, not days.</p></div>
<div class="tl reveal"><span class="tl__year">1994</span><h4>Crown Cabin</h4><p>The first fully-flat business seat in the skies redefines premium travel.</p></div>
<div class="tl reveal"><span class="tl__year">2025</span><h4>Carbon pledge</h4><p>A modern fleet and sustainable fuel chart our course to net-zero by 2050.</p></div>
</div>
</div>
</section>
<!-- ===== App ===== -->
<section class="section app" id="app">
<div class="wrap app__grid">
<div class="app__copy reveal">
<span class="kicker">On the move</span>
<h2>The whole journey, in your pocket</h2>
<p>Board with a tap, track your bags in real time, and unlock mobile-only fares. The Meridian app puts the flag carrier in your hand.</p>
<div class="app__badges">
<button class="storebtn" data-store="App Store">▲ App Store</button>
<button class="storebtn" data-store="Google Play">▶ Google Play</button>
</div>
</div>
<div class="app__phone reveal" aria-hidden="true">
<div class="phone">
<div class="phone__notch"></div>
<div class="boarding">
<div class="boarding__head"><span>BOARDING PASS</span><span class="pill pill--ok">Boarding</span></div>
<div class="boarding__route">
<div><strong>LHR</strong><small>London</small></div>
<div class="boarding__plane">✈</div>
<div><strong>JFK</strong><small>New York</small></div>
</div>
<div class="boarding__perf"></div>
<div class="boarding__meta">
<div><small>Flight</small><b>MA 0107</b></div>
<div><small>Gate</small><b>A12</b></div>
<div><small>Seat</small><b>2A</b></div>
<div><small>Boards</small><b>14:25</b></div>
</div>
</div>
</div>
</div>
</div>
</section>
</main>
<!-- ===== Footer ===== -->
<footer class="footer">
<div class="wrap footer__grid">
<div class="footer__brand">
<span class="brand brand--footer">
<span class="brand__mark" aria-hidden="true"><svg viewBox="0 0 32 32" width="28" height="28"><path d="M16 2l3.4 9.5L29 14l-9.6 2.5L16 30l-3.4-13.5L3 14l9.6-2.5z"/></svg></span>
<span class="brand__name">Meridian<em>Airways</em></span>
</span>
<p>The national flag carrier. Carrying the nation since 1947.</p>
</div>
<div class="footer__col"><h5>Book</h5><a href="#">Flights</a><a href="#">Holidays</a><a href="#">Cabins</a><a href="#">Group travel</a></div>
<div class="footer__col"><h5>Experience</h5><a href="#">Crown Lounges</a><a href="#">Dining</a><a href="#">Fleet</a><a href="#">Crown Club</a></div>
<div class="footer__col"><h5>Help</h5><a href="#">Manage booking</a><a href="#">Flight status</a><a href="#">Baggage</a><a href="#">Contact</a></div>
<form class="footer__news" id="newsForm">
<h5>Fare alerts</h5>
<p>Be first to know about reward seats and seasonal fares.</p>
<div class="footer__field">
<input type="email" id="newsEmail" placeholder="[email protected]" aria-label="Email" required />
<button class="btn btn--gold" type="submit">Join</button>
</div>
</form>
</div>
<div class="wrap footer__bar">
<span>© 1947–2026 Meridian Airways plc · Fictional flag carrier</span>
<nav><a href="#">Privacy</a><a href="#">Conditions of carriage</a><a href="#">Cookies</a></nav>
</div>
</footer>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>Legacy Flag Carrier Landing
A full marketing landing page for Meridian Airways, a fictional national flag carrier styled with a navy-and-gold palette and a Playfair Display serif paired with Inter. The prestige hero leads with an inline flight-search widget — trip-type tabs, a swap control that reverses origin and destination, cabin and traveller selectors, and a live fare hint that updates on submit. Tabular figures keep flight numbers, times, and prices precisely aligned.
Below the hero, the route network renders nine signature destinations from the London hub as cards with airport codes, status pills, and prices; region chips filter the grid in place. A four-cabin showcase highlights First, Crown Business, Premium, and Economy, with the business cabin given a gold-accented feature treatment. The Crown Club section switches between four loyalty tiers, swapping perks and animating a 3D membership card with updated tier and mile balance.
A heritage timeline, an app section with a dashed-perforation boarding-pass mockup, and a full footer complete the page. Interactions are progressive and accessible: a sticky header, a slide-down mobile menu, keyboard-usable buttons and inputs, a reusable toast() helper, and IntersectionObserver scroll reveals — all in dependency-free vanilla JavaScript.
Illustrative UI only — fictional airline, not a real booking or flight system.