Business Hotel Landing
A crisp, grid-driven single-page landing for a business and conference hotel featuring room tiers, meeting room specs, business amenities, and an interactive reservation widget with room-type switching, nights calculation, and toast feedback.
MCP
Code
/* ── Theme: Meridian Business Hotel — navy + steel + white ── */
:root {
--navy: #0f2044;
--navy-2: #1a3060;
--navy-3: #253d7a;
--steel: #4a6080;
--steel-2: #6b82a0;
--steel-3: #94a8be;
--white: #ffffff;
--off-white: #f6f8fb;
--ink: #0a1628;
--ink-2: #1e2e48;
--muted: #5a6b84;
--line: rgba(15, 32, 68, 0.1);
--line-strong: rgba(15, 32, 68, 0.2);
--accent: #2563eb;
--accent-light: #dbeafe;
--success: #16a34a;
--danger: #dc2626;
--font-display: "Manrope", system-ui, sans-serif;
--font-body: "Inter", system-ui, sans-serif;
--r-sm: 4px;
--r-md: 8px;
--r-lg: 12px;
--shadow-1: 0 1px 3px rgba(15, 32, 68, 0.06), 0 2px 8px rgba(15, 32, 68, 0.07);
--shadow-2: 0 10px 40px rgba(15, 32, 68, 0.18);
--shadow-3: 0 20px 60px rgba(15, 32, 68, 0.25);
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: var(--font-body);
background: var(--off-white);
color: var(--ink);
-webkit-font-smoothing: antialiased;
}
a {
text-decoration: none;
}
/* ── Nav ── */
.nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
display: flex;
align-items: center;
gap: 20px;
padding: 0 40px;
height: 64px;
background: transparent;
transition: background 0.25s, box-shadow 0.25s;
}
.nav.scrolled {
background: var(--navy);
box-shadow: 0 2px 16px rgba(0, 0, 0, 0.25);
}
.brand {
display: flex;
align-items: center;
gap: 10px;
color: var(--white);
}
.brand-mark {
width: 36px;
height: 36px;
display: grid;
place-items: center;
border-radius: var(--r-md);
background: var(--accent);
color: var(--white);
font-family: var(--font-display);
font-weight: 800;
font-size: 1.1rem;
}
.brand-name {
font-family: var(--font-display);
font-weight: 800;
font-size: 1.05rem;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--white);
}
.nav-links {
display: flex;
gap: 24px;
margin-left: auto;
}
.nav-links a {
color: rgba(255, 255, 255, 0.75);
font-size: 0.86rem;
font-weight: 500;
letter-spacing: 0.03em;
transition: color 0.15s;
}
.nav-links a:hover {
color: var(--white);
}
.nav-actions {
display: flex;
align-items: center;
gap: 20px;
}
.nav-phone {
color: rgba(255, 255, 255, 0.6);
font-size: 0.82rem;
font-weight: 500;
letter-spacing: 0.04em;
}
.nav-cta {
background: var(--accent);
color: var(--white);
font-family: var(--font-display);
font-weight: 700;
font-size: 0.84rem;
padding: 9px 18px;
border-radius: var(--r-sm);
letter-spacing: 0.04em;
text-transform: uppercase;
transition: background 0.15s;
}
.nav-cta:hover {
background: #1d4ed8;
}
/* ── Hero ── */
.hero {
position: relative;
min-height: 100vh;
padding: 80px 40px 60px;
display: flex;
align-items: center;
background: var(--navy);
overflow: hidden;
}
.hero-bg {
position: absolute;
inset: 0;
background: linear-gradient(135deg, var(--navy) 0%, var(--navy-2) 50%, var(--navy-3) 100%);
pointer-events: none;
}
/* Grid pattern overlay */
.hero-bg::before {
content: "";
position: absolute;
inset: 0;
background-image: linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
background-size: 60px 60px;
}
.hero-bg::after {
content: "";
position: absolute;
inset: 0;
background: radial-gradient(ellipse 60% 70% at 100% 50%, rgba(37, 99, 235, 0.25), transparent 60%),
radial-gradient(ellipse 50% 50% at 0% 100%, rgba(15, 32, 68, 0.8), transparent 50%);
}
.hero-inner {
position: relative;
z-index: 2;
width: 100%;
max-width: 1100px;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr 420px;
gap: 60px;
align-items: center;
}
.hero-copy {
color: var(--white);
}
.label {
font-size: 0.72rem;
text-transform: uppercase;
letter-spacing: 0.25em;
color: rgba(255, 255, 255, 0.5);
font-weight: 600;
margin-bottom: 18px;
}
.hero-copy h1 {
font-family: var(--font-display);
font-weight: 800;
font-size: clamp(2.6rem, 5.5vw, 4.4rem);
line-height: 1.05;
letter-spacing: -0.02em;
color: var(--white);
margin-bottom: 20px;
}
.lede {
font-size: 1.05rem;
line-height: 1.65;
color: rgba(255, 255, 255, 0.7);
max-width: 500px;
margin-bottom: 36px;
}
.trust-bar {
display: flex;
align-items: center;
gap: 0;
flex-wrap: wrap;
}
.trust-item {
display: flex;
flex-direction: column;
gap: 2px;
padding: 0 28px 0 0;
}
.trust-item strong {
font-family: var(--font-display);
font-size: 1.5rem;
font-weight: 800;
color: var(--white);
line-height: 1;
}
.trust-item span {
font-size: 0.74rem;
color: rgba(255, 255, 255, 0.5);
font-weight: 500;
letter-spacing: 0.06em;
text-transform: uppercase;
}
.trust-sep {
width: 1px;
height: 36px;
background: rgba(255, 255, 255, 0.18);
margin: 0 28px 0 0;
}
/* ── Booking widget ── */
.bwidget {
background: var(--white);
border-radius: var(--r-lg);
padding: 28px;
box-shadow: var(--shadow-3);
}
.bwidget-header {
margin-bottom: 20px;
padding-bottom: 16px;
border-bottom: 1px solid var(--line);
}
.bwidget-title {
display: block;
font-family: var(--font-display);
font-weight: 800;
font-size: 1.1rem;
color: var(--navy);
text-transform: uppercase;
letter-spacing: 0.06em;
margin-bottom: 3px;
}
.bwidget-sub {
font-size: 0.76rem;
color: var(--muted);
font-weight: 500;
}
.bfield-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
margin-bottom: 12px;
}
.bfield {
display: flex;
flex-direction: column;
gap: 5px;
margin-bottom: 12px;
}
.bfield-row .bfield {
margin-bottom: 0;
}
.bfield label {
font-size: 0.66rem;
text-transform: uppercase;
letter-spacing: 0.15em;
font-weight: 700;
color: var(--steel);
}
.bfield input[type="date"],
.bfield select {
font-family: var(--font-body);
font-size: 0.9rem;
font-weight: 600;
color: var(--navy);
background: var(--off-white);
border: 1.5px solid var(--line-strong);
border-radius: var(--r-sm);
padding: 9px 10px;
outline: none;
width: 100%;
transition: border-color 0.15s;
}
.bfield input[type="date"]:focus,
.bfield select:focus {
border-color: var(--accent);
background: var(--white);
}
.spin-row {
display: flex;
align-items: center;
gap: 10px;
background: var(--off-white);
border: 1.5px solid var(--line-strong);
border-radius: var(--r-sm);
padding: 7px 10px;
}
.spin-row span {
font-weight: 700;
font-size: 1rem;
min-width: 20px;
text-align: center;
color: var(--navy);
}
.spin-btn {
width: 26px;
height: 26px;
border-radius: var(--r-sm);
border: 1.5px solid var(--line-strong);
background: var(--white);
color: var(--navy);
font-size: 1.1rem;
line-height: 1;
cursor: pointer;
display: grid;
place-items: center;
transition: background 0.12s, border-color 0.12s;
}
.spin-btn:hover:not(:disabled) {
background: var(--accent);
border-color: var(--accent);
color: var(--white);
}
.spin-btn:disabled {
opacity: 0.3;
cursor: default;
}
.nights-big {
font-family: var(--font-display);
font-weight: 800;
font-size: 2rem;
color: var(--accent);
line-height: 1;
padding-top: 2px;
display: block;
}
.bwidget-total {
background: var(--off-white);
border: 1px solid var(--line-strong);
border-radius: var(--r-sm);
padding: 10px 14px;
font-size: 0.88rem;
font-weight: 600;
color: var(--muted);
margin-bottom: 12px;
min-height: 40px;
display: flex;
align-items: center;
transition: border-color 0.15s;
}
.bwidget-total strong {
color: var(--navy);
}
.bwidget-total.error {
background: #fef2f2;
border-color: rgba(220, 38, 38, 0.3);
color: var(--danger);
}
.corp-toggle {
display: flex;
align-items: center;
gap: 10px;
font-size: 0.84rem;
font-weight: 600;
color: var(--ink-2);
cursor: pointer;
margin-bottom: 16px;
user-select: none;
}
.corp-toggle input {
display: none;
}
.toggle-track {
width: 38px;
height: 22px;
border-radius: 999px;
background: var(--steel-3);
position: relative;
flex-shrink: 0;
transition: background 0.2s;
}
.toggle-track::after {
content: "";
position: absolute;
width: 16px;
height: 16px;
border-radius: 999px;
background: var(--white);
top: 3px;
left: 3px;
transition: transform 0.2s;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.corp-toggle input:checked ~ .toggle-track {
background: var(--accent);
}
.corp-toggle input:checked ~ .toggle-track::after {
transform: translateX(16px);
}
.bwidget-cta {
width: 100%;
background: var(--navy);
color: var(--white);
border: none;
font-family: var(--font-display);
font-weight: 800;
font-size: 0.92rem;
padding: 14px;
border-radius: var(--r-md);
cursor: pointer;
letter-spacing: 0.06em;
text-transform: uppercase;
transition: background 0.15s;
}
.bwidget-cta:hover {
background: var(--navy-3);
}
/* ── Section heading ── */
.section-hd {
text-align: center;
margin-bottom: 44px;
}
.section-hd--left {
text-align: left;
}
.section-hd h2 {
font-family: var(--font-display);
font-weight: 800;
font-size: clamp(2rem, 3.5vw, 2.8rem);
color: var(--navy);
letter-spacing: -0.02em;
margin-top: 8px;
}
.section-hd--left h2 {
color: var(--white);
}
.section-lede {
margin-top: 10px;
font-size: 0.96rem;
color: rgba(255, 255, 255, 0.65);
max-width: 400px;
line-height: 1.6;
}
.eyebrow {
font-size: 0.68rem;
text-transform: uppercase;
letter-spacing: 0.22em;
font-weight: 700;
color: var(--steel);
}
/* ── Rooms ── */
.rooms {
max-width: 1100px;
margin: 80px auto;
padding: 0 40px;
}
.room-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.rc {
background: var(--white);
border: 1.5px solid var(--line);
border-radius: var(--r-lg);
overflow: hidden;
box-shadow: var(--shadow-1);
position: relative;
transition: transform 0.2s, box-shadow 0.2s;
}
.rc:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-2);
}
.rc--featured {
border-color: var(--accent);
box-shadow: 0 0 0 1px var(--accent), var(--shadow-1);
}
.rc-badge {
position: absolute;
top: 12px;
right: 12px;
background: var(--accent);
color: var(--white);
font-size: 0.68rem;
font-weight: 700;
padding: 4px 10px;
border-radius: var(--r-sm);
text-transform: uppercase;
letter-spacing: 0.08em;
z-index: 2;
}
.rc-img {
height: 170px;
}
.rc-img--standard {
background: linear-gradient(135deg, #253d7a 0%, #0f2044 100%);
}
.rc-img--superior {
background: linear-gradient(135deg, #1a5276 0%, #0a2e4a 100%);
}
.rc-img--exec {
background: linear-gradient(135deg, #2e4057 0%, #1a2840 100%);
}
.rc-img::after {
content: "";
display: block;
height: 100%;
background: radial-gradient(circle at 70% 30%, rgba(255, 255, 255, 0.1), transparent 55%);
}
.rc-body {
padding: 20px;
}
.rc-body h3 {
font-family: var(--font-display);
font-weight: 800;
font-size: 1.15rem;
color: var(--navy);
margin-bottom: 3px;
}
.rc-sub {
font-size: 0.76rem;
color: var(--muted);
font-weight: 500;
margin-bottom: 10px;
}
.rc-perks {
list-style: none;
margin-bottom: 14px;
}
.rc-perks li {
font-size: 0.82rem;
color: var(--ink-2);
line-height: 1.55;
padding-left: 12px;
position: relative;
}
.rc-perks li::before {
content: "·";
position: absolute;
left: 0;
color: var(--accent);
font-weight: 700;
}
.rc-rate {
font-size: 0.84rem;
color: var(--muted);
font-weight: 600;
border-top: 1px solid var(--line);
padding-top: 12px;
margin-top: 4px;
}
.rc-rate strong {
font-family: var(--font-display);
font-size: 1.4rem;
color: var(--navy);
font-weight: 800;
}
/* ── Conference ── */
.conference {
background: var(--navy);
padding: 80px 40px;
}
.conf-inner {
max-width: 1100px;
margin: 0 auto;
}
.conf-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 18px;
margin-bottom: 28px;
}
.conf-card {
background: rgba(255, 255, 255, 0.06);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: var(--r-lg);
overflow: hidden;
transition: background 0.2s;
}
.conf-card:hover {
background: rgba(255, 255, 255, 0.1);
}
.conf-img {
height: 130px;
}
.conf-img--boardroom {
background: linear-gradient(135deg, #1e3a5f, #0f2044);
}
.conf-img--seminar {
background: linear-gradient(135deg, #1a4065, #0d2a4a);
}
.conf-img--ballroom {
background: linear-gradient(135deg, #1f2d5a, #0f1e40);
}
.conf-img::after {
content: "";
display: block;
height: 100%;
background: radial-gradient(circle at 60% 40%, rgba(37, 99, 235, 0.3), transparent 60%);
}
.conf-body {
padding: 16px 18px 20px;
}
.conf-name {
font-family: var(--font-display);
font-weight: 800;
font-size: 1rem;
color: var(--white);
margin-bottom: 4px;
}
.conf-meta {
font-size: 0.76rem;
color: rgba(255, 255, 255, 0.55);
margin-bottom: 6px;
font-weight: 500;
}
.conf-features {
font-size: 0.78rem;
color: rgba(255, 255, 255, 0.45);
margin-bottom: 12px;
line-height: 1.4;
}
.conf-rate {
font-size: 0.82rem;
color: rgba(255, 255, 255, 0.55);
font-weight: 600;
border-top: 1px solid rgba(255, 255, 255, 0.1);
padding-top: 10px;
}
.conf-rate strong {
color: var(--white);
font-family: var(--font-display);
font-size: 1.2rem;
}
.conf-cta-line {
text-align: center;
}
.text-cta {
display: inline-flex;
align-items: center;
gap: 6px;
color: rgba(255, 255, 255, 0.7);
font-size: 0.9rem;
font-weight: 600;
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
padding-bottom: 2px;
transition: color 0.15s, border-color 0.15s;
}
.text-cta:hover {
color: var(--white);
border-color: var(--white);
}
/* ── Amenities ── */
.amenities {
max-width: 1100px;
margin: 80px auto;
padding: 0 40px;
}
.amenity-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 18px;
}
.am-card {
background: var(--white);
border: 1.5px solid var(--line);
border-radius: var(--r-lg);
padding: 24px;
box-shadow: var(--shadow-1);
}
.am-icon {
font-size: 1.6rem;
display: block;
margin-bottom: 12px;
}
.am-card strong {
display: block;
font-family: var(--font-display);
font-weight: 800;
font-size: 0.96rem;
color: var(--navy);
margin-bottom: 7px;
}
.am-card p {
font-size: 0.84rem;
color: var(--muted);
line-height: 1.55;
}
/* ── About ── */
.about {
background: var(--off-white);
padding: 90px 40px;
border-top: 1px solid var(--line);
}
.about-inner {
max-width: 1100px;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 64px;
align-items: center;
}
.about-img {
height: 440px;
border-radius: var(--r-lg);
background: linear-gradient(145deg, var(--navy-3) 0%, var(--navy) 100%);
position: relative;
overflow: hidden;
box-shadow: var(--shadow-2);
}
.about-img::before {
content: "";
position: absolute;
inset: 0;
background-image: linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px);
background-size: 48px 48px;
}
.about-img::after {
content: "Frankfurt · 2008 – today";
position: absolute;
bottom: 24px;
left: 24px;
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
color: rgba(255, 255, 255, 0.85);
font-size: 0.78rem;
font-weight: 600;
padding: 8px 16px;
border-radius: var(--r-sm);
letter-spacing: 0.08em;
text-transform: uppercase;
}
.about-copy .eyebrow {
color: var(--accent);
margin-bottom: 12px;
display: block;
}
.about-copy h2 {
font-family: var(--font-display);
font-weight: 800;
font-size: clamp(1.8rem, 3vw, 2.5rem);
color: var(--navy);
letter-spacing: -0.02em;
margin-bottom: 18px;
line-height: 1.15;
}
.about-copy p {
font-size: 0.95rem;
color: var(--muted);
line-height: 1.7;
margin-bottom: 14px;
}
.about-copy p strong {
color: var(--navy);
}
.about-kpi {
display: flex;
gap: 32px;
padding-top: 24px;
margin-top: 24px;
border-top: 1px solid var(--line);
}
.kpi strong {
display: block;
font-family: var(--font-display);
font-weight: 800;
font-size: 1.8rem;
color: var(--accent);
line-height: 1;
}
.kpi span {
font-size: 0.74rem;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--muted);
font-weight: 600;
margin-top: 4px;
display: block;
}
/* ── Location ── */
.location {
background: var(--navy);
padding: 80px 40px;
}
.loc-inner {
max-width: 1100px;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr 1.4fr;
gap: 56px;
align-items: center;
}
.loc-info .eyebrow {
color: rgba(255, 255, 255, 0.45);
margin-bottom: 8px;
display: block;
}
.loc-info h2 {
font-family: var(--font-display);
font-weight: 800;
font-size: 2rem;
color: var(--white);
letter-spacing: -0.02em;
margin-bottom: 24px;
}
.loc-hours {
list-style: none;
margin-bottom: 24px;
}
.loc-hours li {
display: flex;
justify-content: space-between;
padding: 9px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.07);
font-size: 0.88rem;
}
.loc-hours li span {
color: rgba(255, 255, 255, 0.5);
}
.loc-hours li strong {
color: var(--white);
font-weight: 600;
}
.loc-addr {
padding: 16px;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: var(--r-md);
color: rgba(255, 255, 255, 0.65);
font-size: 0.86rem;
line-height: 1.7;
}
.loc-name {
font-weight: 700;
color: var(--white);
margin-bottom: 2px;
}
.map-box {
height: 320px;
border-radius: var(--r-lg);
background: #0a1e38;
position: relative;
overflow: hidden;
box-shadow: var(--shadow-2);
}
.map-lines {
position: absolute;
inset: 0;
background-image: linear-gradient(rgba(37, 99, 235, 0.08) 1px, transparent 1px),
linear-gradient(90deg, rgba(37, 99, 235, 0.08) 1px, transparent 1px);
background-size: 48px 48px;
}
.map-roads {
position: absolute;
inset: 0;
background: linear-gradient(rgba(37, 99, 235, 0.12) 2px, transparent 2px),
linear-gradient(90deg, rgba(37, 99, 235, 0.12) 2px, transparent 2px);
background-size: 192px 192px;
}
.map-pin-wrap {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.map-dot {
width: 14px;
height: 14px;
background: var(--accent);
border-radius: 50%;
border: 2px solid var(--white);
position: relative;
z-index: 2;
}
.map-ripple {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 40px;
height: 40px;
border-radius: 50%;
border: 2px solid rgba(37, 99, 235, 0.5);
animation: ripple 2s infinite;
}
@keyframes ripple {
0% {
width: 20px;
height: 20px;
opacity: 0.9;
}
100% {
width: 70px;
height: 70px;
opacity: 0;
}
}
.map-tag {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: var(--white);
color: var(--navy);
font-size: 0.78rem;
font-weight: 700;
padding: 8px 16px;
border-radius: var(--r-sm);
white-space: nowrap;
text-align: center;
box-shadow: var(--shadow-1);
}
/* ── Reserve footer ── */
.reserve {
background: var(--accent);
padding: 72px 40px;
}
.reserve-inner {
max-width: 1000px;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr 1.1fr;
gap: 56px;
align-items: center;
}
.reserve-copy h2 {
font-family: var(--font-display);
font-weight: 800;
font-size: 2.4rem;
color: var(--white);
letter-spacing: -0.02em;
margin-bottom: 12px;
}
.reserve-copy p {
font-size: 0.92rem;
color: rgba(255, 255, 255, 0.8);
line-height: 1.6;
}
.reserve-form {
display: flex;
flex-direction: column;
gap: 10px;
}
.reserve-form input {
font-family: var(--font-body);
font-size: 0.92rem;
font-weight: 500;
color: var(--navy);
background: rgba(255, 255, 255, 0.9);
border: 1.5px solid transparent;
border-radius: var(--r-sm);
padding: 12px 14px;
outline: none;
transition: background 0.15s, border-color 0.15s;
}
.reserve-form input:focus {
background: var(--white);
border-color: var(--navy);
}
.reserve-form button {
background: var(--navy);
color: var(--white);
border: none;
font-family: var(--font-display);
font-weight: 800;
font-size: 0.9rem;
padding: 13px;
border-radius: var(--r-sm);
cursor: pointer;
letter-spacing: 0.06em;
text-transform: uppercase;
transition: background 0.15s;
}
.reserve-form button:hover {
background: var(--navy-2);
}
/* ── Toast ── */
.toast {
position: fixed;
bottom: 24px;
left: 50%;
transform: translateX(-50%);
background: var(--navy);
color: var(--white);
padding: 12px 24px;
border-radius: var(--r-sm);
font-size: 0.86rem;
font-weight: 600;
box-shadow: var(--shadow-2);
z-index: 200;
border-left: 3px solid var(--accent);
white-space: nowrap;
letter-spacing: 0.02em;
}
/* ── Responsive ── */
@media (max-width: 960px) {
.hero-inner {
grid-template-columns: 1fr;
}
.bwidget {
max-width: 480px;
}
.room-grid,
.conf-grid,
.amenity-grid {
grid-template-columns: 1fr;
max-width: 480px;
margin-left: auto;
margin-right: auto;
}
.about-inner {
grid-template-columns: 1fr;
}
.about-img {
height: 260px;
}
.loc-inner {
grid-template-columns: 1fr;
}
.reserve-inner {
grid-template-columns: 1fr;
}
}
@media (max-width: 560px) {
.nav {
padding: 0 20px;
}
.nav-links,
.nav-phone {
display: none;
}
.hero {
padding: 72px 20px 48px;
}
.rooms,
.amenities,
.about {
padding-left: 20px;
padding-right: 20px;
}
.conference,
.location,
.reserve {
padding-left: 20px;
padding-right: 20px;
}
.bfield-row {
grid-template-columns: 1fr;
}
.trust-bar {
gap: 16px;
}
.trust-sep {
display: none;
}
.about-kpi {
flex-direction: column;
gap: 16px;
}
}// ── Toast helper ─────────────────────────────────────────────────────────────
const toast = document.getElementById("toast");
function showToast(msg) {
toast.textContent = msg;
toast.hidden = false;
clearTimeout(showToast._t);
showToast._t = setTimeout(() => (toast.hidden = true), 2200);
}
// ── Sticky nav on scroll ──────────────────────────────────────────────────────
const nav = document.getElementById("nav");
window.addEventListener(
"scroll",
() => {
nav.classList.toggle("scrolled", window.scrollY > 60);
},
{ passive: true }
);
// ── Date helpers ──────────────────────────────────────────────────────────────
function iso(d) {
return d.toISOString().slice(0, 10);
}
function addDays(date, n) {
const d = new Date(date);
d.setDate(d.getDate() + n);
return d;
}
function fmt(isoStr) {
return new Date(isoStr + "T00:00").toLocaleDateString("en-GB", {
day: "numeric",
month: "short",
year: "numeric",
});
}
// ── Booking widget ────────────────────────────────────────────────────────────
const bciEl = document.getElementById("bci");
const bcoEl = document.getElementById("bco");
const broomEl = document.getElementById("broom");
const bgValEl = document.getElementById("bgVal");
const bgMinus = document.getElementById("bgMinus");
const bgPlus = document.getElementById("bgPlus");
const bNightsEl = document.getElementById("bNights");
const bTotalEl = document.getElementById("bTotal");
const corpEl = document.getElementById("corpRate");
// Room rates
const RATES = { standard: 149, superior: 189, executive: 279 };
const CORP_DISCOUNT = 0.12;
// Defaults: check-in Jun 9, check-out Jun 11
const today = new Date("2026-06-08");
const defIn = new Date("2026-06-09");
const defOut = new Date("2026-06-11");
bciEl.value = iso(defIn);
bcoEl.value = iso(defOut);
bciEl.min = iso(today);
bcoEl.min = iso(addDays(today, 1));
let bgCount = 1;
function calcNights() {
if (!bciEl.value || !bcoEl.value) return 0;
const ms = new Date(bcoEl.value) - new Date(bciEl.value);
return Math.round(ms / 86400000);
}
function renderWidget() {
const n = calcNights();
const rate = RATES[broomEl.value] ?? 189;
const corp = corpEl.checked;
const final = corp ? rate * (1 - CORP_DISCOUNT) : rate;
const total = Math.round(final * n * bgCount);
if (n <= 0) {
bNightsEl.textContent = "—";
bTotalEl.classList.add("error");
bTotalEl.textContent = "⚠ Check-out must be after check-in";
return;
}
bNightsEl.textContent = n;
bTotalEl.classList.remove("error");
const corpNote = corp ? ` <em style="color:var(--success);">−12% corp</em>` : "";
bTotalEl.innerHTML =
`<strong>€${total}</strong> total · ${n} night${n === 1 ? "" : "s"} ` +
`· ${bgCount} guest${bgCount === 1 ? "" : "s"} · €${Math.round(final)}/night${corpNote}`;
}
// Guest stepper
function syncGuests() {
bgValEl.textContent = bgCount;
bgMinus.disabled = bgCount <= 1;
bgPlus.disabled = bgCount >= 6;
}
bgMinus.addEventListener("click", () => {
if (bgCount > 1) {
bgCount--;
syncGuests();
renderWidget();
}
});
bgPlus.addEventListener("click", () => {
if (bgCount < 6) {
bgCount++;
syncGuests();
renderWidget();
}
});
bciEl.addEventListener("change", () => {
const inD = new Date(bciEl.value);
const minOut = iso(addDays(inD, 1));
bcoEl.min = minOut;
if (new Date(bcoEl.value) <= inD) bcoEl.value = minOut;
renderWidget();
});
bcoEl.addEventListener("change", renderWidget);
broomEl.addEventListener("change", renderWidget);
corpEl.addEventListener("change", renderWidget);
// Widget submit
document.getElementById("bookForm").addEventListener("submit", (e) => {
e.preventDefault();
const n = calcNights();
if (n <= 0) {
renderWidget();
return;
}
const room = broomEl.options[broomEl.selectedIndex].text.split(" —")[0];
const rate = RATES[broomEl.value] ?? 189;
const corp = corpEl.checked;
const final = corp ? rate * (1 - CORP_DISCOUNT) : rate;
const total = Math.round(final * n * bgCount);
showToast(
`Checking availability: ${room} · ${fmt(bciEl.value)} – ${fmt(bcoEl.value)} · €${total}`
);
});
syncGuests();
renderWidget();
// ── Reserve footer form ───────────────────────────────────────────────────────
document.getElementById("reserveFooterForm").addEventListener("submit", (e) => {
e.preventDefault();
const name = document.getElementById("rfName").value.trim();
const email = document.getElementById("rfEmail").value.trim();
const company = document.getElementById("rfCompany").value.trim();
if (!name) {
showToast("Please enter your full name.");
return;
}
if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
showToast("Please enter a valid work email.");
return;
}
const co = company ? ` (${company})` : "";
showToast(`Reservation request sent for ${name}${co}. We'll confirm within 1 hour.`);
e.target.reset();
});<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Inter:wght@400;500;600;700&display=swap"
/>
<link rel="stylesheet" href="style.css" />
<title>Meridian Business Hotel · Frankfurt</title>
</head>
<body>
<!-- ── Sticky nav ── -->
<header class="nav" id="nav">
<a class="brand" href="#">
<span class="brand-mark">M</span>
<span class="brand-name">Meridian</span>
</a>
<nav class="nav-links">
<a href="#rooms">Rooms</a>
<a href="#conference">Conference</a>
<a href="#amenities">Amenities</a>
<a href="#about">About</a>
<a href="#location">Location</a>
</nav>
<div class="nav-actions">
<span class="nav-phone">+49 69 000 4400</span>
<a class="nav-cta" href="#reserve">Reserve</a>
</div>
</header>
<!-- ── Hero ── -->
<section class="hero" id="top">
<div class="hero-bg"></div>
<div class="hero-inner">
<div class="hero-copy">
<p class="label">Frankfurt · Innenstadt · Est. 2008</p>
<h1>Where business<br />gets done.</h1>
<p class="lede">
Meridian Business Hotel sits 4 minutes from the Messe. Fast Wi-Fi in every room,
6 meeting suites, a 24/7 business centre, and checkout that works around your schedule.
</p>
<div class="trust-bar">
<div class="trust-item"><strong>★ 4.8</strong><span>Google Reviews</span></div>
<div class="trust-sep"></div>
<div class="trust-item"><strong>15k+</strong><span>corporate stays</span></div>
<div class="trust-sep"></div>
<div class="trust-item"><strong>4 min</strong><span>to Messe Frankfurt</span></div>
</div>
</div>
<!-- Booking widget -->
<form class="bwidget" id="bookForm" autocomplete="off">
<div class="bwidget-header">
<span class="bwidget-title">Book your stay</span>
<span class="bwidget-sub">Corporate rates available</span>
</div>
<div class="bfield-row">
<div class="bfield">
<label for="bci">Check-in</label>
<input type="date" id="bci" name="bci" />
</div>
<div class="bfield">
<label for="bco">Check-out</label>
<input type="date" id="bco" name="bco" />
</div>
</div>
<div class="bfield">
<label for="broom">Room type</label>
<select id="broom" name="broom">
<option value="standard">Standard King — €149/night</option>
<option value="superior" selected>Superior King — €189/night</option>
<option value="executive">Executive Suite — €279/night</option>
</select>
</div>
<div class="bfield-row">
<div class="bfield">
<label for="bguests">Guests</label>
<div class="spin-row">
<button type="button" class="spin-btn" id="bgMinus" aria-label="Fewer guests">−</button>
<span id="bgVal">1</span>
<button type="button" class="spin-btn" id="bgPlus" aria-label="More guests">+</button>
</div>
</div>
<div class="bfield">
<label>Nights</label>
<span class="nights-big" id="bNights">—</span>
</div>
</div>
<div class="bwidget-total" id="bTotal">Select dates to calculate total</div>
<label class="corp-toggle">
<input type="checkbox" id="corpRate" />
<span class="toggle-track"></span>
Apply corporate rate (−12%)
</label>
<button type="submit" class="bwidget-cta">Check availability →</button>
</form>
</div>
</section>
<!-- ── Rooms ── -->
<section class="rooms" id="rooms">
<div class="section-hd">
<p class="eyebrow">Guest rooms</p>
<h2>Built for productivity</h2>
</div>
<div class="room-grid">
<article class="rc">
<div class="rc-img rc-img--standard"></div>
<div class="rc-body">
<h3>Standard King</h3>
<p class="rc-sub">22 m² · City view · Ground–4F</p>
<ul class="rc-perks">
<li>King bed · Desk · 43" TV</li>
<li>1 Gbps Wi-Fi · USB-C hub</li>
<li>Nespresso · Rain shower</li>
</ul>
<div class="rc-rate">from <strong>€149</strong> / night</div>
</div>
</article>
<article class="rc rc--featured">
<div class="rc-badge">Most booked</div>
<div class="rc-img rc-img--superior"></div>
<div class="rc-body">
<h3>Superior King</h3>
<p class="rc-sub">30 m² · Skyline view · 5F–12F</p>
<ul class="rc-perks">
<li>King bed · Standing desk · 55" TV</li>
<li>1 Gbps Wi-Fi · Dual monitors on request</li>
<li>Nespresso · Bathtub + shower</li>
</ul>
<div class="rc-rate">from <strong>€189</strong> / night</div>
</div>
</article>
<article class="rc">
<div class="rc-img rc-img--exec"></div>
<div class="rc-body">
<h3>Executive Suite</h3>
<p class="rc-sub">48 m² · Panoramic view · 13F</p>
<ul class="rc-perks">
<li>King bed · Private lounge area</li>
<li>1 Gbps Wi-Fi · Printer · Scanner</li>
<li>Club floor access · Minibar</li>
</ul>
<div class="rc-rate">from <strong>€279</strong> / night</div>
</div>
</article>
</div>
</section>
<!-- ── Conference rooms ── -->
<section class="conference" id="conference">
<div class="conf-inner">
<div class="section-hd section-hd--left">
<p class="eyebrow">Meeting & events</p>
<h2>Six suites.<br />One city.</h2>
<p class="section-lede">From intimate boardrooms to full-day conference setups, every suite comes with AV, fast fibre, and a dedicated coordinator.</p>
</div>
<div class="conf-grid">
<article class="conf-card">
<div class="conf-img conf-img--boardroom"></div>
<div class="conf-body">
<div class="conf-name">Boardroom A</div>
<div class="conf-meta">Up to 12 pax · U-shape · Daylight</div>
<div class="conf-features">4K screen · Video call bar · Whiteboard</div>
<div class="conf-rate">from <strong>€380</strong> / half-day</div>
</div>
</article>
<article class="conf-card">
<div class="conf-img conf-img--seminar"></div>
<div class="conf-body">
<div class="conf-name">Seminar Hall B</div>
<div class="conf-meta">Up to 60 pax · Theatre / classroom</div>
<div class="conf-features">Projector · Stage mic · Breakout area</div>
<div class="conf-rate">from <strong>€760</strong> / half-day</div>
</div>
</article>
<article class="conf-card">
<div class="conf-img conf-img--ballroom"></div>
<div class="conf-body">
<div class="conf-name">Meridian Hall</div>
<div class="conf-meta">Up to 200 pax · Banquet / theatre</div>
<div class="conf-features">Rigged lighting · Full AV · Catering</div>
<div class="conf-rate">from <strong>€2 400</strong> / full-day</div>
</div>
</article>
</div>
<p class="conf-cta-line">
<a href="#reserve" class="text-cta">Request a conference quote →</a>
</p>
</div>
</section>
<!-- ── Business amenities ── -->
<section class="amenities" id="amenities">
<div class="section-hd">
<p class="eyebrow">On-property</p>
<h2>Everything you need</h2>
</div>
<div class="amenity-grid">
<div class="am-card">
<span class="am-icon">🖨️</span>
<strong>24/7 Business Centre</strong>
<p>Print, scan, fax, and ship. Open round the clock for late-night deck finishing.</p>
</div>
<div class="am-card">
<span class="am-icon">⚡</span>
<strong>1 Gbps Wi-Fi</strong>
<p>Dedicated bandwidth in every room and meeting suite. No shared pool, ever.</p>
</div>
<div class="am-card">
<span class="am-icon">🍳</span>
<strong>Executive Breakfast</strong>
<p>Hot buffet 06:00–10:30. Packed bags available from 05:30 for early flights.</p>
</div>
<div class="am-card">
<span class="am-icon">🏋️</span>
<strong>Fitness Centre</strong>
<p>Open 05:00–23:00. Full Technogym rig, steam room, and dry sauna.</p>
</div>
<div class="am-card">
<span class="am-icon">🚗</span>
<strong>Valet & Garage</strong>
<p>Underground parking with EV charging. Airport taxi on 30-min call.</p>
</div>
<div class="am-card">
<span class="am-icon">🍽️</span>
<strong>Restaurant & Bar</strong>
<p>Bistro menu 06:00–23:00. Private dining room for client dinners up to 18.</p>
</div>
</div>
</section>
<!-- ── About ── -->
<section class="about" id="about">
<div class="about-inner">
<div class="about-img"></div>
<div class="about-copy">
<p class="eyebrow">About Meridian</p>
<h2>Efficiency is the luxury.</h2>
<p>
Opened in 2008, Meridian was designed for the professional who needs everything to work —
reliably, quickly, and without friction. No over-the-top lobby chandeliers. Clean lines,
fast internet, and a team that anticipates your needs before you ask.
</p>
<p>
We partner with DAX 40 companies and international event organisers who need a hotel
that keeps pace with them. Over <strong>15,000 corporate stays</strong> later, our
repeat rate speaks for itself: <strong>74% of guests return</strong> within the year.
</p>
<div class="about-kpi">
<div class="kpi"><strong>74%</strong><span>repeat guests</span></div>
<div class="kpi"><strong>98%</strong><span>on-time check-in</span></div>
<div class="kpi"><strong>4.8★</strong><span>Google rating</span></div>
</div>
</div>
</div>
</section>
<!-- ── Location ── -->
<section class="location" id="location">
<div class="loc-inner">
<div class="loc-info">
<p class="eyebrow">Find us</p>
<h2>Hours & directions</h2>
<ul class="loc-hours">
<li><span>Check-in</span><strong>15:00 onwards</strong></li>
<li><span>Check-out</span><strong>until 12:00</strong></li>
<li><span>Reception</span><strong>24 hours</strong></li>
<li><span>Restaurant</span><strong>06:00 – 23:00</strong></li>
<li><span>Business centre</span><strong>24 hours</strong></li>
</ul>
<div class="loc-addr">
<p class="loc-name">Meridian Business Hotel Frankfurt</p>
<p>Ludwig-Erhard-Anlage 14</p>
<p>60327 Frankfurt am Main</p>
<p>+49 69 000 4400</p>
</div>
</div>
<div class="map-box">
<div class="map-lines"></div>
<div class="map-roads"></div>
<div class="map-pin-wrap">
<div class="map-dot"></div>
<div class="map-ripple"></div>
</div>
<div class="map-tag">Meridian Hotel<br />4 min to Messe</div>
</div>
</div>
</section>
<!-- ── Reserve CTA footer ── -->
<section class="reserve" id="reserve">
<div class="reserve-inner">
<div class="reserve-copy">
<h2>Ready to book?</h2>
<p>Direct bookings include complimentary breakfast and flexible cancellation up to 24 hours before arrival. No booking fee.</p>
</div>
<form class="reserve-form" id="reserveFooterForm">
<input type="text" id="rfName" placeholder="Full name" autocomplete="name" />
<input type="email" id="rfEmail" placeholder="Work email" autocomplete="email" />
<input type="text" id="rfCompany" placeholder="Company (optional)" autocomplete="organization" />
<button type="submit">Request reservation →</button>
</form>
</div>
</section>
<div class="toast" id="toast" hidden role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>Business Hotel Landing
A clean, corporate single-page landing for Meridian Business Hotel — an efficient city-centre property built for professionals. The page presents a structured navy-and-steel hero with an inline booking widget, three guest room cards, a conference and meeting rooms section with capacity specs, a business amenities grid, a story/about block, and a location + hours strip with a CSS map. The booking widget calculates stay totals live, validates dates, and fires a toast on submit. A sticky nav transitions from transparent to solid on scroll. Layout collapses responsively at 960 px and 560 px.