Hotel Amenities & Services Page
A full marketing amenities page for Aurelia Hotels featuring filterable service cards, an opening-hours accordion, and a request-info contact form with validation and toast feedback.
MCP
コード
:root {
--navy: #1a2b4a;
--navy-d: #0f1d36;
--navy-2: #2d4570;
--cream: #f7f3eb;
--cream-2: #ece5d4;
--bone: #fbf8f2;
--gold: #c9a649;
--gold-light: #e0c378;
--gold-d: #a88a2e;
--ink: #161e2c;
--ink-2: #2e3a52;
--warm-gray: #6c7280;
--line: rgba(22, 30, 44, 0.1);
--line-strong: rgba(22, 30, 44, 0.18);
--success: #4a7752;
--danger: #b34232;
--warning: #d99020;
--info: #4a6da0;
--font-display: "Cormorant Garamond", Georgia, serif;
--font-body: "Inter", system-ui, sans-serif;
--font-mono: "JetBrains Mono", ui-monospace, monospace;
--r-sm: 6px;
--r-md: 10px;
--r-lg: 16px;
--shadow-1: 0 1px 2px rgba(22, 30, 44, 0.06), 0 2px 8px rgba(22, 30, 44, 0.06);
--shadow-2: 0 12px 36px rgba(15, 29, 54, 0.16);
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: var(--font-body);
background: var(--cream);
color: var(--ink);
-webkit-font-smoothing: antialiased;
}
/* ── Topbar ── */
.topbar {
position: sticky;
top: 0;
z-index: 30;
background: var(--navy-d);
color: var(--bone);
padding: 0 32px;
height: 64px;
display: flex;
align-items: center;
gap: 32px;
}
.brand {
display: flex;
align-items: center;
gap: 10px;
text-decoration: none;
color: var(--bone);
flex-shrink: 0;
}
.brand-mark {
width: 34px;
height: 34px;
display: grid;
place-items: center;
border-radius: var(--r-sm);
background: var(--gold);
color: var(--navy-d);
font-family: var(--font-display);
font-weight: 700;
font-size: 1.2rem;
}
.brand-name {
font-family: var(--font-display);
font-size: 1.15rem;
font-weight: 700;
}
.brand-name em {
font-style: normal;
color: var(--gold-light);
}
.top-nav {
display: flex;
gap: 6px;
margin-left: 24px;
}
.top-nav a {
text-decoration: none;
color: rgba(251, 248, 242, 0.65);
font-size: 0.86rem;
font-weight: 500;
padding: 6px 13px;
border-radius: var(--r-sm);
transition: color 0.15s, background 0.15s;
}
.top-nav a:hover,
.top-nav a.active {
color: var(--bone);
background: rgba(255, 255, 255, 0.08);
}
.top-nav a.active {
color: var(--gold-light);
}
.nav-cta {
margin-left: auto;
background: var(--gold);
color: var(--navy-d);
font-weight: 700;
font-size: 0.84rem;
padding: 9px 20px;
border-radius: 999px;
text-decoration: none;
transition: background 0.15s;
}
.nav-cta:hover {
background: var(--gold-light);
}
/* ── Hero strip ── */
.hero-strip {
background: linear-gradient(160deg, var(--navy-2) 0%, var(--navy-d) 55%, #070f1e 100%);
color: var(--bone);
padding: 60px 32px 48px;
text-align: center;
position: relative;
overflow: hidden;
}
.hero-strip::before {
content: "";
position: absolute;
inset: 0;
background: radial-gradient(ellipse 70% 50% at 50% 0%, rgba(201, 166, 73, 0.16), transparent 70%);
}
.breadcrumb {
position: relative;
font-size: 0.75rem;
color: var(--gold-light);
letter-spacing: 0.08em;
text-transform: uppercase;
font-weight: 600;
margin-bottom: 14px;
}
.hero-strip h1 {
position: relative;
font-family: var(--font-display);
font-weight: 700;
font-size: clamp(2.2rem, 5vw, 3.6rem);
line-height: 1.05;
}
.hero-sub {
position: relative;
margin-top: 12px;
font-size: 0.95rem;
color: rgba(251, 248, 242, 0.68);
}
/* ── Tabs bar ── */
.tabs-bar {
background: var(--bone);
border-bottom: 1px solid var(--line);
padding: 0 32px;
position: sticky;
top: 64px;
z-index: 20;
}
.tabs {
max-width: 1200px;
margin: 0 auto;
display: flex;
gap: 4px;
overflow-x: auto;
scrollbar-width: none;
padding: 10px 0;
}
.tabs::-webkit-scrollbar {
display: none;
}
.tab {
font-family: var(--font-body);
font-size: 0.86rem;
font-weight: 600;
padding: 7px 18px;
border: 1.5px solid transparent;
border-radius: 999px;
background: transparent;
color: var(--ink-2);
cursor: pointer;
white-space: nowrap;
transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.tab:hover {
border-color: var(--navy);
color: var(--navy);
}
.tab.active {
background: var(--navy);
color: var(--bone);
border-color: var(--navy);
}
/* ── Content wrap ── */
.content-wrap {
max-width: 1200px;
margin: 0 auto;
padding: 36px 32px 72px;
display: flex;
flex-direction: column;
gap: 60px;
}
/* ── Amenity grid ── */
.amenity-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: 20px;
}
.amenity-card {
background: var(--bone);
border: 1px solid var(--line);
border-radius: var(--r-lg);
padding: 28px 24px 22px;
box-shadow: var(--shadow-1);
display: flex;
flex-direction: column;
gap: 10px;
transition: box-shadow 0.18s, transform 0.18s;
}
.amenity-card:hover {
box-shadow: var(--shadow-2);
transform: translateY(-2px);
}
.amenity-icon {
width: 52px;
height: 52px;
display: grid;
place-items: center;
font-size: 1.6rem;
background: linear-gradient(135deg, var(--navy-2), var(--navy-d));
border-radius: var(--r-md);
color: var(--gold-light);
flex-shrink: 0;
}
.amenity-card h3 {
font-family: var(--font-display);
font-weight: 700;
font-size: 1.3rem;
color: var(--navy-d);
line-height: 1.15;
}
.amenity-card p {
font-size: 0.84rem;
color: var(--warm-gray);
line-height: 1.55;
}
.amenity-hours {
margin-top: auto;
padding-top: 12px;
border-top: 1px solid var(--line);
font-size: 0.76rem;
font-weight: 600;
color: var(--gold-d);
display: flex;
align-items: center;
gap: 6px;
}
/* ── Empty state ── */
.empty {
text-align: center;
padding: 60px 24px;
color: var(--warm-gray);
font-style: italic;
background: var(--bone);
border: 1px dashed var(--line-strong);
border-radius: var(--r-md);
}
/* ── Section title ── */
.section-title {
font-family: var(--font-display);
font-weight: 700;
font-size: 2rem;
color: var(--navy-d);
margin-bottom: 20px;
}
/* ── Accordion ── */
.accordion-section {
}
.accordion {
border: 1px solid var(--line);
border-radius: var(--r-lg);
overflow: hidden;
background: var(--bone);
}
.acc-item {
border-bottom: 1px solid var(--line);
}
.acc-item:last-child {
border-bottom: none;
}
.acc-trigger {
width: 100%;
background: none;
border: none;
padding: 18px 24px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
cursor: pointer;
text-align: left;
transition: background 0.15s;
}
.acc-trigger:hover {
background: var(--cream);
}
.acc-trigger-left {
display: flex;
align-items: center;
gap: 14px;
}
.acc-ico {
font-size: 1.4rem;
width: 36px;
text-align: center;
flex-shrink: 0;
}
.acc-name {
font-family: var(--font-display);
font-size: 1.2rem;
font-weight: 700;
color: var(--navy-d);
}
.acc-chevron {
font-size: 1rem;
color: var(--warm-gray);
transition: transform 0.22s;
flex-shrink: 0;
}
.acc-item.open .acc-chevron {
transform: rotate(180deg);
}
.acc-body {
max-height: 0;
overflow: hidden;
transition: max-height 0.28s ease;
}
.acc-body-inner {
padding: 0 24px 20px 74px;
}
.hours-table {
width: 100%;
border-collapse: collapse;
font-size: 0.86rem;
}
.hours-table td {
padding: 5px 0;
color: var(--ink-2);
}
.hours-table td:first-child {
width: 160px;
color: var(--warm-gray);
font-weight: 500;
}
.hours-table td:last-child {
font-family: var(--font-mono);
font-variant-numeric: tabular-nums;
font-size: 0.82rem;
}
.highlight-row td {
color: var(--gold-d) !important;
font-weight: 600;
}
/* ── Form section ── */
.form-section {
}
.form-card {
background: var(--bone);
border: 1px solid var(--line);
border-radius: var(--r-lg);
padding: 36px 40px;
max-width: 640px;
box-shadow: var(--shadow-1);
}
.form-card h2 {
font-family: var(--font-display);
font-size: 1.9rem;
font-weight: 700;
color: var(--navy-d);
margin-bottom: 6px;
}
.form-desc {
font-size: 0.86rem;
color: var(--warm-gray);
margin-bottom: 24px;
}
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
}
.field {
display: flex;
flex-direction: column;
gap: 5px;
margin-bottom: 16px;
}
.field label {
font-size: 0.78rem;
font-weight: 600;
color: var(--ink-2);
text-transform: uppercase;
letter-spacing: 0.07em;
}
.field input,
.field select,
.field textarea {
font-family: var(--font-body);
font-size: 0.9rem;
color: var(--ink);
background: var(--cream);
border: 1.5px solid var(--line-strong);
border-radius: var(--r-sm);
padding: 10px 14px;
transition: border-color 0.15s, box-shadow 0.15s;
resize: vertical;
}
.field input:focus,
.field select:focus,
.field textarea:focus {
outline: none;
border-color: var(--navy);
box-shadow: 0 0 0 3px rgba(26, 43, 74, 0.1);
}
.field input.invalid,
.field select.invalid {
border-color: var(--danger);
box-shadow: 0 0 0 3px rgba(179, 66, 50, 0.1);
}
.field-error {
font-size: 0.74rem;
color: var(--danger);
min-height: 16px;
}
.optional {
color: var(--warm-gray);
font-weight: 400;
text-transform: none;
letter-spacing: 0;
}
.submit-btn {
font-family: var(--font-body);
font-size: 0.9rem;
font-weight: 700;
background: var(--navy);
color: var(--bone);
border: none;
border-radius: var(--r-sm);
padding: 13px 28px;
cursor: pointer;
transition: background 0.15s;
width: 100%;
margin-top: 4px;
}
.submit-btn:hover {
background: var(--navy-d);
}
/* ── Toast ── */
.toast {
position: fixed;
bottom: 24px;
left: 50%;
transform: translateX(-50%);
background: var(--navy-d);
color: var(--bone);
padding: 12px 24px;
border-radius: 999px;
font-size: 0.88rem;
font-weight: 600;
box-shadow: var(--shadow-2);
z-index: 50;
white-space: nowrap;
}
/* ── Responsive ── */
@media (max-width: 960px) {
.top-nav {
display: none;
}
.content-wrap {
padding: 28px 20px 56px;
}
.amenity-grid {
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}
.form-card {
padding: 28px 24px;
}
}
@media (max-width: 560px) {
.topbar {
padding: 0 18px;
gap: 16px;
}
.hero-strip {
padding: 44px 20px 36px;
}
.tabs-bar {
padding: 0 18px;
}
.content-wrap {
padding: 24px 18px 48px;
}
.amenity-grid {
grid-template-columns: 1fr 1fr;
}
.form-row {
grid-template-columns: 1fr;
}
.acc-body-inner {
padding-left: 24px;
}
}
@media (max-width: 400px) {
.amenity-grid {
grid-template-columns: 1fr;
}
}// ── Amenity data ──────────────────────────────────────────────────────────────
const AMENITIES = [
{
id: "spa",
name: "Spa & Wellness",
cat: "wellness",
icon: "🌿",
desc: "A 1,200 m² sanctuary offering signature treatments, hammam, aromatherapy showers, and a serenity lounge overlooking the courtyard garden.",
hours: "Daily 08:00–21:00",
accHours: [
{ day: "Mon–Fri", time: "08:00–21:00" },
{ day: "Sat–Sun", time: "07:30–22:00" },
{ day: "Public holidays", time: "09:00–20:00" },
],
},
{
id: "pool",
name: "Pool & Jacuzzi",
cat: "wellness",
icon: "🏊",
desc: "A heated 25-metre indoor pool and outdoor rooftop plunge pool with panoramic city views. Heated towels, sunbeds, and complimentary water provided.",
hours: "Daily 07:00–22:00",
accHours: [
{ day: "Mon–Sun", time: "07:00–22:00" },
{ day: "Maintenance closure", time: "Tue 06:00–07:00" },
],
},
{
id: "fitness",
name: "Fitness Centre",
cat: "sport",
icon: "🏋️",
desc: "State-of-the-art Technogym equipment, free weights, TRX zones, and personal training sessions available on request (advance booking required).",
hours: "Daily 06:00–23:00",
accHours: [
{ day: "Mon–Sun", time: "06:00–23:00" },
{ day: "Personal training", time: "By appointment" },
],
},
{
id: "dining",
name: "Fine Dining",
cat: "dining",
icon: "🍽️",
desc: "Restaurante Laurel offers contemporary Iberian cuisine under Executive Chef Marcos Soto. Tasting menus of 5 and 8 courses, curated wine pairings available.",
hours: "Dinner 19:00–23:00",
accHours: [
{ day: "Breakfast", time: "07:00–10:30" },
{ day: "Lunch", time: "13:00–15:30" },
{ day: "Dinner", time: "19:00–23:00" },
{ day: "Monday", time: "Dinner only", highlight: true },
],
},
{
id: "bar",
name: "Rooftop Bar",
cat: "dining",
icon: "🥂",
desc: "Cenit Rooftop Bar on the 14th floor. Craft cocktails, a curated natural wine list, and tapas bites. Sunset sessions with resident DJ every Friday–Saturday.",
hours: "Daily 17:00–01:00",
accHours: [
{ day: "Sun–Thu", time: "17:00–00:00" },
{ day: "Fri–Sat", time: "15:00–01:00" },
{ day: "DJ nights (Fri–Sat)", time: "21:00–01:00", highlight: true },
],
},
{
id: "business",
name: "Business Centre",
cat: "business",
icon: "💼",
desc: "Four private meeting rooms (8–24 pax), executive boardroom, high-speed fibre Wi-Fi, A/V equipment, printing & secretarial services available.",
hours: "Mon–Fri 07:00–21:00",
accHours: [
{ day: "Mon–Fri", time: "07:00–21:00" },
{ day: "Sat", time: "08:00–14:00" },
{ day: "Sun", time: "On request", highlight: true },
],
},
{
id: "concierge",
name: "Concierge",
cat: "business",
icon: "🛎️",
desc: "Our dedicated concierge team handles restaurant reservations, private tours, event tickets, airport transfers, and any bespoke request around the clock.",
hours: "24 / 7",
accHours: [
{ day: "All days", time: "24 hours" },
{ day: "Reservations desk", time: "08:00–22:00" },
],
},
{
id: "parking",
name: "Valet Parking",
cat: "parking",
icon: "🚗",
desc: "Secure underground valet parking with EV charging points. Complimentary for Signature Suite guests; €28/night for all other room categories.",
hours: "24 / 7",
accHours: [
{ day: "All days", time: "24 hours" },
{ day: "EV charging", time: "On demand" },
{ day: "Rate", time: "€28 / night", highlight: true },
],
},
];
// ── State ─────────────────────────────────────────────────────────────────────
let activeCat = "all";
// ── DOM refs ──────────────────────────────────────────────────────────────────
const grid = document.getElementById("amenityGrid");
const emptyEl = document.getElementById("emptyMsg");
const accordion = document.getElementById("accordion");
const toast = document.getElementById("toast");
// ── Helpers ───────────────────────────────────────────────────────────────────
function showToast(msg) {
toast.textContent = msg;
toast.hidden = false;
clearTimeout(showToast._t);
showToast._t = setTimeout(() => (toast.hidden = true), 2200);
}
// ── Render amenity cards ──────────────────────────────────────────────────────
function renderCards() {
const visible = AMENITIES.filter((a) => activeCat === "all" || a.cat === activeCat);
emptyEl.hidden = visible.length > 0;
grid.innerHTML = visible
.map(
(a) => `
<div class="amenity-card" data-id="${a.id}">
<div class="amenity-icon">${a.icon}</div>
<h3>${a.name}</h3>
<p>${a.desc}</p>
<div class="amenity-hours">🕐 ${a.hours}</div>
</div>`
)
.join("");
}
// ── Render accordion ─────────────────────────────────────────────────────────
function renderAccordion() {
accordion.innerHTML = AMENITIES.map(
(a) => `
<div class="acc-item" data-id="${a.id}">
<button class="acc-trigger" aria-expanded="false">
<div class="acc-trigger-left">
<span class="acc-ico">${a.icon}</span>
<span class="acc-name">${a.name}</span>
</div>
<span class="acc-chevron">▾</span>
</button>
<div class="acc-body">
<div class="acc-body-inner">
<table class="hours-table">
<tbody>
${a.accHours
.map(
(h) =>
`<tr class="${h.highlight ? "highlight-row" : ""}">
<td>${h.day}</td>
<td>${h.time}</td>
</tr>`
)
.join("")}
</tbody>
</table>
</div>
</div>
</div>`
).join("");
}
// ── Accordion toggle ──────────────────────────────────────────────────────────
accordion.addEventListener("click", (e) => {
const trigger = e.target.closest(".acc-trigger");
if (!trigger) return;
const item = trigger.closest(".acc-item");
const body = item.querySelector(".acc-body");
const isOpen = item.classList.contains("open");
// Close all
document.querySelectorAll(".acc-item.open").forEach((el) => {
el.classList.remove("open");
el.querySelector(".acc-body").style.maxHeight = "0";
el.querySelector(".acc-trigger").setAttribute("aria-expanded", "false");
});
// Open clicked if it wasn't open
if (!isOpen) {
item.classList.add("open");
body.style.maxHeight = body.scrollHeight + "px";
trigger.setAttribute("aria-expanded", "true");
}
});
// ── Category tabs ─────────────────────────────────────────────────────────────
document.getElementById("tabs").addEventListener("click", (e) => {
const tab = e.target.closest(".tab");
if (!tab) return;
activeCat = tab.dataset.cat;
document.querySelectorAll(".tab").forEach((t) => {
t.classList.toggle("active", t === tab);
t.setAttribute("aria-selected", t === tab ? "true" : "false");
});
renderCards();
});
// ── Form validation & submit ──────────────────────────────────────────────────
const form = document.getElementById("infoForm");
function setErr(id, msg) {
const el = document.getElementById(id + "Err");
const inp = document.getElementById(id);
if (el) el.textContent = msg;
if (inp) inp.classList.toggle("invalid", !!msg);
}
form.addEventListener("submit", (e) => {
e.preventDefault();
let ok = true;
const fname = document.getElementById("fname").value.trim();
const lname = document.getElementById("lname").value.trim();
const email = document.getElementById("email").value.trim();
const interest = document.getElementById("interest").value;
if (!fname) {
setErr("fname", "Please enter your first name.");
ok = false;
} else setErr("fname", "");
if (!lname) {
setErr("lname", "Please enter your last name.");
ok = false;
} else setErr("lname", "");
const emailRe = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!email) {
setErr("email", "Email address is required.");
ok = false;
} else if (!emailRe.test(email)) {
setErr("email", "Please enter a valid email address.");
ok = false;
} else setErr("email", "");
if (!interest) {
setErr("interest", "Please select an area of interest.");
ok = false;
} else setErr("interest", "");
if (!ok) return;
showToast(`Request sent — our concierge will contact ${email} shortly ✓`);
form.reset();
document.querySelectorAll(".invalid").forEach((el) => el.classList.remove("invalid"));
});
// ── Init ──────────────────────────────────────────────────────────────────────
renderCards();
renderAccordion();<!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=Cormorant+Garamond:wght@600;700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@500;700&display=swap"
/>
<link rel="stylesheet" href="style.css" />
<title>Amenities & Services · Aurelia Hotels</title>
</head>
<body>
<!-- ── Nav ── -->
<header class="topbar">
<a class="brand" href="#">
<span class="brand-mark">A</span>
<span class="brand-name">Aurelia <em>Hotels</em></span>
</a>
<nav class="top-nav">
<a href="#">Overview</a>
<a href="#">Rooms</a>
<a href="#" class="active">Amenities</a>
<a href="#">Dining</a>
<a href="#">Gallery</a>
</nav>
<a class="nav-cta" href="#">Book now</a>
</header>
<!-- ── Hero strip ── -->
<section class="hero-strip">
<p class="breadcrumb">Aurelia · Madrid › Amenities & Services</p>
<h1>Amenities & Services</h1>
<p class="hero-sub">World-class facilities for a stay that exceeds every expectation</p>
</section>
<!-- ── Category tabs ── -->
<div class="tabs-bar">
<div class="tabs" id="tabs" role="tablist" aria-label="Amenity category">
<button class="tab active" data-cat="all" role="tab" aria-selected="true">All</button>
<button class="tab" data-cat="wellness" role="tab" aria-selected="false">Wellness</button>
<button class="tab" data-cat="dining" role="tab" aria-selected="false">Dining</button>
<button class="tab" data-cat="sport" role="tab" aria-selected="false">Sport</button>
<button class="tab" data-cat="business" role="tab" aria-selected="false">Business</button>
<button class="tab" data-cat="parking" role="tab" aria-selected="false">Parking</button>
</div>
</div>
<!-- ── Amenity grid ── -->
<main class="content-wrap">
<div class="amenity-grid" id="amenityGrid"></div>
<p class="empty" id="emptyMsg" hidden>No amenities in this category.</p>
<!-- ── Hours accordion ── -->
<section class="accordion-section">
<h2 class="section-title">Opening Hours</h2>
<div class="accordion" id="accordion"></div>
</section>
<!-- ── Request form ── -->
<section class="form-section">
<div class="form-card">
<h2>Request More Information</h2>
<p class="form-desc">Our concierge team will respond within 2 hours during hotel hours.</p>
<form id="infoForm" novalidate>
<div class="form-row">
<div class="field">
<label for="fname">First name</label>
<input type="text" id="fname" name="fname" placeholder="Elena" autocomplete="given-name" />
<span class="field-error" id="fnameErr"></span>
</div>
<div class="field">
<label for="lname">Last name</label>
<input type="text" id="lname" name="lname" placeholder="Vidal" autocomplete="family-name" />
<span class="field-error" id="lnameErr"></span>
</div>
</div>
<div class="field">
<label for="email">Email address</label>
<input type="email" id="email" name="email" placeholder="[email protected]" autocomplete="email" />
<span class="field-error" id="emailErr"></span>
</div>
<div class="field">
<label for="interest">Area of interest</label>
<select id="interest" name="interest">
<option value="">Select an amenity…</option>
<option>Spa & Wellness</option>
<option>Pool & Jacuzzi</option>
<option>Fitness Centre</option>
<option>Fine Dining</option>
<option>Rooftop Bar</option>
<option>Business Centre</option>
<option>Concierge Services</option>
<option>Valet Parking</option>
</select>
<span class="field-error" id="interestErr"></span>
</div>
<div class="field">
<label for="msg">Message <span class="optional">(optional)</span></label>
<textarea id="msg" name="msg" rows="3" placeholder="I'm staying 9–12 Jun 2026 and would like to pre-book the spa…"></textarea>
</div>
<button type="submit" class="submit-btn">Send request</button>
</form>
</div>
</section>
</main>
<div class="toast" id="toast" hidden role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>Amenities & Services Page
A polished marketing page showcasing the full breadth of Aurelia Hotels Madrid’s services. A sticky nav and cinematic navy-gradient hero strip open the page, followed by a pill-tab category bar that instantly filters the amenity card grid across six groups: All, Wellness, Dining, Sport, Business, and Parking. Each card carries a large Unicode icon, a service title, a short description, and operating hours. Below the grid an accordion section expands individual amenity hours with smooth animation. The page closes with a compact “Request more information” form featuring client-side validation (required fields, email format) and a success toast on submit.