Real Estate — Neighborhood Guide
An editorial neighborhood guide page for the fictional Maplewood Heights, pairing a serif display hero and lifestyle vibe tags with a four-stat market snapshot covering median price, price per square foot, days-on-market trend, and sale-to-list ratio. Animated walk, transit, and bike score dials fill on scroll, a filterable amenities list groups schools, parks, dining, and shops, and three featured listing cards offer save-to-favorites with toast feedback.
MCP
Codice
:root {
--ivory: #f7f4ec;
--paper: #fffdf8;
--white: #ffffff;
--green: #1f3d34;
--green-d: #16302a;
--green-700: #26493e;
--green-50: #e8efea;
--brass: #b08d57;
--brass-d: #94733f;
--brass-50: #f3ead9;
--ink: #1c2a25;
--ink-2: #33433d;
--muted: #6b7a72;
--line: rgba(31, 61, 52, 0.12);
--line-2: rgba(31, 61, 52, 0.22);
--ok: #2f9e6f;
--warn: #c98a2b;
--danger: #c4503e;
--r-sm: 8px;
--r-md: 14px;
--r-lg: 22px;
--sh-1: 0 1px 2px rgba(28, 42, 37, 0.06), 0 2px 8px rgba(28, 42, 37, 0.05);
--sh-2: 0 6px 18px rgba(28, 42, 37, 0.08), 0 18px 40px rgba(28, 42, 37, 0.08);
}
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
margin: 0;
font-family: "Inter", system-ui, sans-serif;
line-height: 1.55;
color: var(--ink);
background: var(--ivory);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
h1,
h2,
h3 {
font-family: "Cormorant Garamond", Georgia, serif;
margin: 0;
line-height: 1.08;
letter-spacing: 0.01em;
}
p {
margin: 0;
}
a {
color: inherit;
text-decoration: none;
}
.wrap {
width: min(1140px, 92vw);
margin-inline: auto;
}
.skip-link {
position: absolute;
left: -999px;
top: 0;
background: var(--green);
color: var(--paper);
padding: 10px 16px;
border-radius: 0 0 var(--r-sm) 0;
z-index: 100;
}
.skip-link:focus {
left: 0;
}
:focus-visible {
outline: 2px solid var(--brass);
outline-offset: 2px;
border-radius: 4px;
}
.eyebrow {
font-size: 0.74rem;
letter-spacing: 0.18em;
text-transform: uppercase;
font-weight: 600;
color: var(--brass-d);
}
/* ===== Buttons ===== */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
font-family: inherit;
font-size: 0.92rem;
font-weight: 600;
padding: 11px 20px;
border-radius: 999px;
border: 1px solid transparent;
cursor: pointer;
transition: transform 0.15s ease, background 0.2s ease, box-shadow 0.2s ease,
color 0.2s ease;
}
.btn:active {
transform: translateY(1px);
}
.btn--solid {
background: var(--green);
color: var(--paper);
box-shadow: var(--sh-1);
}
.btn--solid:hover {
background: var(--green-d);
box-shadow: var(--sh-2);
}
.btn--outline {
background: transparent;
color: var(--green);
border-color: var(--line-2);
}
.btn--outline:hover {
border-color: var(--green);
background: var(--green-50);
}
.btn--ghost {
background: var(--brass-50);
color: var(--brass-d);
padding: 9px 16px;
font-size: 0.86rem;
}
.btn--ghost:hover {
background: var(--brass);
color: var(--paper);
}
/* ===== Topbar ===== */
.topbar {
position: sticky;
top: 0;
z-index: 40;
background: rgba(247, 244, 236, 0.86);
backdrop-filter: saturate(1.4) blur(10px);
border-bottom: 1px solid var(--line);
}
.topbar__inner {
display: flex;
align-items: center;
gap: 22px;
height: 66px;
}
.brand {
display: inline-flex;
align-items: center;
gap: 9px;
font-family: "Cormorant Garamond", Georgia, serif;
font-weight: 700;
font-size: 1.32rem;
color: var(--green);
}
.brand__mark {
color: var(--brass);
font-size: 0.9em;
}
.topnav {
display: flex;
gap: 26px;
margin-left: auto;
font-size: 0.9rem;
font-weight: 500;
color: var(--ink-2);
}
.topnav a {
position: relative;
padding: 4px 0;
}
.topnav a::after {
content: "";
position: absolute;
left: 0;
bottom: -2px;
width: 0;
height: 1.5px;
background: var(--brass);
transition: width 0.22s ease;
}
.topnav a:hover {
color: var(--green);
}
.topnav a:hover::after {
width: 100%;
}
/* ===== Hero ===== */
.hero {
width: min(1140px, 92vw);
margin: 28px auto 0;
display: grid;
grid-template-columns: 1.15fr 1fr;
gap: 0;
border-radius: var(--r-lg);
overflow: hidden;
background: var(--paper);
box-shadow: var(--sh-2);
border: 1px solid var(--line);
}
.hero__photo {
position: relative;
min-height: 440px;
background: linear-gradient(180deg, rgba(28, 42, 37, 0) 35%, rgba(22, 48, 42, 0.55) 100%),
radial-gradient(120% 80% at 75% 12%, #f3d9a8 0%, rgba(243, 217, 168, 0) 45%),
linear-gradient(135deg, #3c6354 0%, #244a3e 42%, #6b8a5a 78%, #a9b884 100%);
}
.hero__chip {
position: absolute;
left: 18px;
top: 18px;
background: rgba(255, 253, 248, 0.92);
color: var(--green);
font-size: 0.72rem;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
padding: 7px 12px;
border-radius: 999px;
box-shadow: var(--sh-1);
}
.hero__body {
padding: 44px 42px 40px;
display: flex;
flex-direction: column;
justify-content: center;
}
.hero__body h1 {
font-size: clamp(2.6rem, 5vw, 3.7rem);
font-weight: 700;
color: var(--green-d);
margin: 10px 0 14px;
}
.hero__vibe {
color: var(--ink-2);
font-size: 1.02rem;
max-width: 46ch;
}
.hero__tags {
list-style: none;
display: flex;
flex-wrap: wrap;
gap: 8px;
padding: 0;
margin: 22px 0 26px;
}
.hero__tags li {
font-size: 0.78rem;
font-weight: 500;
color: var(--green-700);
background: var(--green-50);
border: 1px solid var(--line);
padding: 6px 12px;
border-radius: 999px;
}
.hero__cta {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
/* ===== Sections ===== */
.section {
padding: 64px 0;
}
.section--alt {
background: linear-gradient(180deg, var(--paper), var(--ivory));
border-block: 1px solid var(--line);
}
.section__head {
max-width: 60ch;
margin-bottom: 34px;
}
.section__head h2 {
font-size: clamp(1.9rem, 3.6vw, 2.6rem);
font-weight: 600;
color: var(--green-d);
margin: 8px 0 8px;
}
.section__sub {
color: var(--muted);
font-size: 0.98rem;
}
/* ===== Stats ===== */
.stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 18px;
}
.stat {
position: relative;
background: var(--paper);
border: 1px solid var(--line);
border-radius: var(--r-md);
padding: 22px 20px 20px;
box-shadow: var(--sh-1);
transition: transform 0.18s ease, box-shadow 0.2s ease;
}
.stat::before {
content: "";
position: absolute;
left: 20px;
top: 0;
width: 34px;
height: 3px;
border-radius: 0 0 3px 3px;
background: var(--brass);
}
.stat:hover {
transform: translateY(-3px);
box-shadow: var(--sh-2);
}
.stat__label {
font-size: 0.8rem;
color: var(--muted);
font-weight: 500;
}
.stat__value {
font-family: "Cormorant Garamond", Georgia, serif;
font-size: 2.2rem;
font-weight: 700;
color: var(--green-d);
margin: 4px 0 6px;
line-height: 1;
}
.stat__delta {
font-size: 0.82rem;
font-weight: 600;
display: flex;
align-items: baseline;
gap: 6px;
}
.stat__delta span {
font-weight: 400;
color: var(--muted);
font-size: 0.74rem;
}
.stat__delta--up {
color: var(--ok);
}
.stat__delta--down {
color: var(--green-700);
}
.spark {
margin-top: 12px;
}
.spark svg {
width: 100%;
height: 30px;
display: block;
}
.spark polyline {
fill: none;
stroke: var(--brass);
stroke-width: 2.4;
stroke-linecap: round;
stroke-linejoin: round;
}
/* ===== Lifestyle dials ===== */
.dials {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 22px;
}
.dial {
margin: 0;
background: var(--paper);
border: 1px solid var(--line);
border-radius: var(--r-lg);
padding: 28px 22px 26px;
text-align: center;
box-shadow: var(--sh-1);
display: flex;
flex-direction: column;
align-items: center;
transition: transform 0.18s ease, box-shadow 0.2s ease;
}
.dial:hover {
transform: translateY(-3px);
box-shadow: var(--sh-2);
}
.dial__ring {
position: relative;
width: 142px;
height: 142px;
}
.dial__ring svg {
width: 100%;
height: 100%;
transform: rotate(-90deg);
}
.dial__track {
fill: none;
stroke: var(--green-50);
stroke-width: 12;
}
.dial__fill {
fill: none;
stroke: var(--brass);
stroke-width: 12;
stroke-linecap: round;
stroke-dasharray: 326.7;
stroke-dashoffset: 326.7;
transition: stroke-dashoffset 1.1s cubic-bezier(0.22, 1, 0.36, 1);
}
.dial__num {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
font-family: "Cormorant Garamond", Georgia, serif;
font-size: 2.5rem;
font-weight: 700;
color: var(--green-d);
}
.dial figcaption {
margin-top: 16px;
}
.dial figcaption strong {
display: block;
color: var(--green-d);
font-size: 1.02rem;
margin-bottom: 4px;
}
.dial figcaption span {
color: var(--muted);
font-size: 0.84rem;
}
/* ===== Amenities ===== */
.filters {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 26px;
}
.chip {
font-family: inherit;
font-size: 0.86rem;
font-weight: 500;
color: var(--ink-2);
background: var(--paper);
border: 1px solid var(--line-2);
padding: 8px 16px;
border-radius: 999px;
cursor: pointer;
transition: all 0.18s ease;
}
.chip:hover {
border-color: var(--green);
color: var(--green);
}
.chip.is-active {
background: var(--green);
border-color: var(--green);
color: var(--paper);
}
.amen-list {
list-style: none;
padding: 0;
margin: 0;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 14px;
}
.amen {
display: flex;
align-items: center;
gap: 14px;
background: var(--paper);
border: 1px solid var(--line);
border-radius: var(--r-md);
padding: 14px 16px;
box-shadow: var(--sh-1);
transition: transform 0.18s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.amen.is-hidden {
display: none;
}
.amen:hover {
transform: translateY(-2px);
box-shadow: var(--sh-2);
border-color: var(--line-2);
}
.amen__icon {
flex: 0 0 auto;
width: 44px;
height: 44px;
display: grid;
place-items: center;
border-radius: var(--r-sm);
font-size: 1.25rem;
background: var(--green-50);
}
.amen__icon--dining {
background: var(--brass-50);
}
.amen__icon--parks {
background: #e3efe1;
}
.amen__main {
flex: 1;
min-width: 0;
}
.amen__name {
font-weight: 600;
color: var(--ink);
}
.amen__meta {
font-size: 0.82rem;
color: var(--muted);
}
.amen__badge {
flex: 0 0 auto;
font-size: 0.76rem;
font-weight: 600;
padding: 5px 10px;
border-radius: 999px;
white-space: nowrap;
}
.badge--green {
background: var(--green-50);
color: var(--green-700);
}
.badge--brass {
background: var(--brass-50);
color: var(--brass-d);
}
.amen-empty {
color: var(--muted);
font-style: italic;
margin-top: 8px;
}
/* ===== Listing cards ===== */
.cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 22px;
}
.card {
background: var(--paper);
border: 1px solid var(--line);
border-radius: var(--r-lg);
overflow: hidden;
box-shadow: var(--sh-1);
transition: transform 0.2s ease, box-shadow 0.22s ease;
}
.card:hover {
transform: translateY(-5px);
box-shadow: var(--sh-2);
}
.card__photo {
position: relative;
aspect-ratio: 4 / 3;
}
.card__photo--1 {
background: linear-gradient(160deg, #d9c39a 0%, #b89a64 50%, #7d6a47 100%),
radial-gradient(80% 60% at 70% 20%, rgba(255, 248, 230, 0.7), transparent 60%);
background-blend-mode: overlay, normal;
}
.card__photo--2 {
background: linear-gradient(160deg, #5d7e6c 0%, #2f4f42 55%, #20382f 100%),
radial-gradient(70% 50% at 30% 18%, rgba(214, 230, 210, 0.55), transparent 60%);
background-blend-mode: screen, normal;
}
.card__photo--3 {
background: linear-gradient(160deg, #c7b3c4 0%, #8b6d80 48%, #5a4a64 100%),
radial-gradient(75% 55% at 65% 22%, rgba(255, 240, 230, 0.6), transparent 60%);
background-blend-mode: overlay, normal;
}
.card__status {
position: absolute;
left: 14px;
top: 14px;
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.04em;
padding: 5px 11px;
border-radius: 999px;
box-shadow: var(--sh-1);
}
.badge--ok {
background: var(--ok);
color: #fff;
}
.badge--warn {
background: var(--warn);
color: #fff;
}
.card__fav {
position: absolute;
right: 12px;
top: 12px;
width: 38px;
height: 38px;
border-radius: 50%;
border: none;
background: rgba(255, 253, 248, 0.92);
color: var(--danger);
font-size: 1.1rem;
cursor: pointer;
display: grid;
place-items: center;
box-shadow: var(--sh-1);
transition: transform 0.15s ease, background 0.2s ease;
}
.card__fav:hover {
transform: scale(1.08);
}
.card__fav[aria-pressed="true"] {
background: var(--danger);
color: #fff;
}
.card__body {
padding: 18px 20px 20px;
}
.card__price {
font-family: "Cormorant Garamond", Georgia, serif;
font-size: 1.7rem;
font-weight: 700;
color: var(--green-d);
line-height: 1;
}
.card__addr {
font-weight: 600;
margin: 6px 0 2px;
}
.card__specs {
font-size: 0.86rem;
color: var(--muted);
}
.card__agent {
display: flex;
align-items: center;
gap: 9px;
margin-top: 16px;
padding-top: 14px;
border-top: 1px solid var(--line);
font-size: 0.83rem;
color: var(--ink-2);
}
.avatar {
width: 30px;
height: 30px;
border-radius: 50%;
background: var(--green);
color: var(--paper);
display: grid;
place-items: center;
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.02em;
}
/* ===== Footer ===== */
.footer {
background: var(--green-d);
color: var(--green-50);
padding: 34px 0;
}
.footer__inner {
display: flex;
flex-wrap: wrap;
gap: 16px;
justify-content: space-between;
align-items: center;
}
.brand--footer {
color: var(--paper);
font-size: 1.2rem;
}
.brand--footer .brand__mark {
color: var(--brass);
}
.footer__fine {
font-size: 0.82rem;
color: rgba(232, 239, 234, 0.72);
}
/* ===== Toast ===== */
.toast {
position: fixed;
left: 50%;
bottom: 26px;
transform: translate(-50%, 24px);
background: var(--green-d);
color: var(--paper);
padding: 12px 20px;
border-radius: 999px;
font-size: 0.88rem;
font-weight: 500;
box-shadow: var(--sh-2);
opacity: 0;
pointer-events: none;
transition: opacity 0.25s ease, transform 0.25s ease;
z-index: 80;
}
.toast.is-show {
opacity: 1;
transform: translate(-50%, 0);
}
/* ===== Responsive ===== */
@media (max-width: 880px) {
.hero {
grid-template-columns: 1fr;
}
.hero__photo {
min-height: 280px;
}
.stats {
grid-template-columns: repeat(2, 1fr);
}
.dials,
.cards {
grid-template-columns: 1fr;
}
.topnav {
display: none;
}
}
@media (max-width: 520px) {
.section {
padding: 46px 0;
}
.hero__body {
padding: 30px 24px 28px;
}
.stats {
grid-template-columns: 1fr;
}
.amen-list {
grid-template-columns: 1fr;
}
.dials {
grid-template-columns: 1fr;
}
.topbar__inner {
gap: 12px;
}
.brand__name {
font-size: 0.95em;
}
.footer__inner {
flex-direction: column;
align-items: flex-start;
}
}
@media (prefers-reduced-motion: reduce) {
* {
scroll-behavior: auto !important;
transition-duration: 0.001ms !important;
}
}(function () {
"use strict";
/* ---------- Toast helper ---------- */
var toastEl = document.getElementById("toast");
var toastTimer = null;
function toast(msg) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.classList.add("is-show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("is-show");
}, 2400);
}
/* ---------- Animated lifestyle dials ---------- */
var CIRCUMFERENCE = 2 * Math.PI * 52; // r = 52
var dials = Array.prototype.slice.call(document.querySelectorAll(".dial"));
function fillDial(dial) {
if (dial.dataset.done === "1") return;
dial.dataset.done = "1";
var score = Math.max(0, Math.min(100, parseInt(dial.dataset.score, 10) || 0));
var fill = dial.querySelector(".dial__fill");
var num = dial.querySelector(".dial__num");
var offset = CIRCUMFERENCE * (1 - score / 100);
// Trigger the stroke animation on next frame.
requestAnimationFrame(function () {
fill.style.strokeDashoffset = String(offset);
});
// Count the number up in step with the ring.
var DURATION = 1100;
var start = null;
function tick(ts) {
if (start === null) start = ts;
var t = Math.min(1, (ts - start) / DURATION);
// easeOutCubic
var eased = 1 - Math.pow(1 - t, 3);
num.textContent = String(Math.round(eased * score));
if (t < 1) requestAnimationFrame(tick);
else num.textContent = String(score);
}
requestAnimationFrame(tick);
}
if ("IntersectionObserver" in window && dials.length) {
var io = new IntersectionObserver(
function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
fillDial(entry.target);
io.unobserve(entry.target);
}
});
},
{ threshold: 0.4 }
);
dials.forEach(function (d) {
io.observe(d);
});
} else {
// Fallback: just fill them.
dials.forEach(fillDial);
}
/* ---------- Amenity category filter ---------- */
var filterBar = document.getElementById("filters");
var amenities = Array.prototype.slice.call(
document.querySelectorAll(".amen")
);
var emptyMsg = document.getElementById("amenEmpty");
function applyFilter(cat) {
var visible = 0;
amenities.forEach(function (item) {
var show = cat === "all" || item.dataset.cat === cat;
item.classList.toggle("is-hidden", !show);
if (show) visible++;
});
if (emptyMsg) emptyMsg.hidden = visible !== 0;
}
if (filterBar) {
filterBar.addEventListener("click", function (e) {
var btn = e.target.closest(".chip");
if (!btn) return;
filterBar.querySelectorAll(".chip").forEach(function (c) {
c.classList.remove("is-active");
c.setAttribute("aria-selected", "false");
});
btn.classList.add("is-active");
btn.setAttribute("aria-selected", "true");
applyFilter(btn.dataset.filter);
});
}
/* ---------- Favorite (save) listings ---------- */
document.querySelectorAll(".card__fav").forEach(function (btn) {
btn.addEventListener("click", function () {
var saved = btn.getAttribute("aria-pressed") === "true";
btn.setAttribute("aria-pressed", String(!saved));
btn.textContent = saved ? "♡" : "♥";
var card = btn.closest(".card");
var addr = card
? card.querySelector(".card__addr").textContent.trim()
: "listing";
toast(saved ? "Removed " + addr : "Saved " + addr + " to favorites");
});
});
/* ---------- Save guide ---------- */
var saveGuide = document.getElementById("saveGuide");
if (saveGuide) {
saveGuide.addEventListener("click", function () {
toast("Maplewood Heights guide saved to your account");
});
}
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Maplewood Heights — Neighborhood Guide</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=Cormorant+Garamond:wght@500;600;700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<!-- ===== Top bar ===== -->
<header class="topbar">
<div class="wrap topbar__inner">
<a class="brand" href="#">
<span class="brand__mark" aria-hidden="true">◈</span>
<span class="brand__name">Hartwell & Vane</span>
</a>
<nav class="topnav" aria-label="Primary">
<a href="#snapshot">Market</a>
<a href="#lifestyle">Lifestyle</a>
<a href="#amenities">Amenities</a>
<a href="#listings">Listings</a>
</nav>
<button class="btn btn--ghost" id="saveGuide" type="button">Save guide</button>
</div>
</header>
<main id="main">
<!-- ===== Hero ===== -->
<section class="hero" aria-labelledby="hero-title">
<div class="hero__photo" role="img" aria-label="Tree-lined street in Maplewood Heights at golden hour">
<span class="hero__chip">Featured neighborhood</span>
</div>
<div class="hero__body">
<p class="eyebrow">Westbrook County · Established 1924</p>
<h1 id="hero-title">Maplewood Heights</h1>
<p class="hero__vibe">Leafy, walkable, and quietly stately — a canopy of old maples shades brick rowhouses, a Saturday farmers market, and a café-lined high street where neighbors still know your order.</p>
<ul class="hero__tags" aria-label="Neighborhood character">
<li>Historic charm</li>
<li>Family-friendly</li>
<li>Café culture</li>
<li>Green space</li>
</ul>
<div class="hero__cta">
<a class="btn btn--solid" href="#listings">Browse listings</a>
<a class="btn btn--outline" href="#snapshot">See the market</a>
</div>
</div>
</section>
<!-- ===== Market snapshot ===== -->
<section id="snapshot" class="section" aria-labelledby="snap-title">
<div class="wrap">
<div class="section__head">
<p class="eyebrow">Market snapshot</p>
<h2 id="snap-title">How Maplewood is trending</h2>
<p class="section__sub">A read on prices and pace, refreshed against the last quarter.</p>
</div>
<div class="stats">
<article class="stat">
<p class="stat__label">Median sale price</p>
<p class="stat__value">$842,000</p>
<p class="stat__delta stat__delta--up">▲ 4.2% <span>vs. last quarter</span></p>
</article>
<article class="stat">
<p class="stat__label">Price per sq ft</p>
<p class="stat__value">$486</p>
<p class="stat__delta stat__delta--up">▲ 2.8% <span>vs. last quarter</span></p>
</article>
<article class="stat">
<p class="stat__label">Median days on market</p>
<p class="stat__value">19 days</p>
<p class="stat__delta stat__delta--down">▼ 6 days <span>faster than before</span></p>
<div class="spark" aria-label="Days-on-market trend, declining">
<svg viewBox="0 0 120 36" preserveAspectRatio="none" aria-hidden="true">
<polyline points="0,8 20,12 40,10 60,18 80,22 100,28 120,30" />
</svg>
</div>
</article>
<article class="stat">
<p class="stat__label">Sale-to-list ratio</p>
<p class="stat__value">101.6%</p>
<p class="stat__delta stat__delta--up">▲ 0.9% <span>seller's market</span></p>
</article>
</div>
</div>
</section>
<!-- ===== Lifestyle dials ===== -->
<section id="lifestyle" class="section section--alt" aria-labelledby="life-title">
<div class="wrap">
<div class="section__head">
<p class="eyebrow">Lifestyle scores</p>
<h2 id="life-title">Getting around & daily life</h2>
<p class="section__sub">Scores out of 100. Dials animate when they scroll into view.</p>
</div>
<div class="dials" id="dials">
<figure class="dial" data-score="92">
<div class="dial__ring">
<svg viewBox="0 0 120 120" aria-hidden="true">
<circle class="dial__track" cx="60" cy="60" r="52" />
<circle class="dial__fill" cx="60" cy="60" r="52" />
</svg>
<span class="dial__num">0</span>
</div>
<figcaption>
<strong>Walk score</strong>
<span>Walker's paradise — errands need no car</span>
</figcaption>
</figure>
<figure class="dial" data-score="78">
<div class="dial__ring">
<svg viewBox="0 0 120 120" aria-hidden="true">
<circle class="dial__track" cx="60" cy="60" r="52" />
<circle class="dial__fill" cx="60" cy="60" r="52" />
</svg>
<span class="dial__num">0</span>
</div>
<figcaption>
<strong>Transit score</strong>
<span>Excellent — two rail lines & frequent buses</span>
</figcaption>
</figure>
<figure class="dial" data-score="85">
<div class="dial__ring">
<svg viewBox="0 0 120 120" aria-hidden="true">
<circle class="dial__track" cx="60" cy="60" r="52" />
<circle class="dial__fill" cx="60" cy="60" r="52" />
</svg>
<span class="dial__num">0</span>
</div>
<figcaption>
<strong>Bike score</strong>
<span>Very bikeable — protected lanes & greenway</span>
</figcaption>
</figure>
</div>
</div>
</section>
<!-- ===== Amenities ===== -->
<section id="amenities" class="section" aria-labelledby="amen-title">
<div class="wrap">
<div class="section__head">
<p class="eyebrow">Local amenities</p>
<h2 id="amen-title">What's around the corner</h2>
<p class="section__sub">Filter by category to explore the neighborhood's anchors.</p>
</div>
<div class="filters" role="tablist" aria-label="Amenity categories" id="filters">
<button class="chip is-active" role="tab" aria-selected="true" data-filter="all" type="button">All</button>
<button class="chip" role="tab" aria-selected="false" data-filter="schools" type="button">Schools</button>
<button class="chip" role="tab" aria-selected="false" data-filter="parks" type="button">Parks</button>
<button class="chip" role="tab" aria-selected="false" data-filter="dining" type="button">Dining</button>
<button class="chip" role="tab" aria-selected="false" data-filter="shops" type="button">Shops</button>
</div>
<ul class="amen-list" id="amenList">
<li class="amen" data-cat="schools">
<span class="amen__icon amen__icon--schools" aria-hidden="true">🎓</span>
<div class="amen__main">
<p class="amen__name">Maplewood Public Elementary</p>
<p class="amen__meta">Public · K–5 · 0.3 mi</p>
</div>
<span class="amen__badge badge--green">9/10</span>
</li>
<li class="amen" data-cat="schools">
<span class="amen__icon amen__icon--schools" aria-hidden="true">🎓</span>
<div class="amen__main">
<p class="amen__name">Vane Academy Middle School</p>
<p class="amen__meta">Public · 6–8 · 0.7 mi</p>
</div>
<span class="amen__badge badge--green">8/10</span>
</li>
<li class="amen" data-cat="parks">
<span class="amen__icon amen__icon--parks" aria-hidden="true">🌳</span>
<div class="amen__main">
<p class="amen__name">Hartwell Commons</p>
<p class="amen__meta">14-acre park · Dog run · 0.2 mi</p>
</div>
<span class="amen__badge badge--brass">Green space</span>
</li>
<li class="amen" data-cat="parks">
<span class="amen__icon amen__icon--parks" aria-hidden="true">🌳</span>
<div class="amen__main">
<p class="amen__name">Birchwater Greenway</p>
<p class="amen__meta">Riverside trail · Cycling · 0.5 mi</p>
</div>
<span class="amen__badge badge--brass">Trail</span>
</li>
<li class="amen" data-cat="dining">
<span class="amen__icon amen__icon--dining" aria-hidden="true">🍽️</span>
<div class="amen__main">
<p class="amen__name">The Copper Kettle</p>
<p class="amen__meta">Seasonal bistro · $$$ · 0.1 mi</p>
</div>
<span class="amen__badge badge--green">4.7★</span>
</li>
<li class="amen" data-cat="dining">
<span class="amen__icon amen__icon--dining" aria-hidden="true">🍽️</span>
<div class="amen__main">
<p class="amen__name">Olive & Fennel</p>
<p class="amen__meta">Wood-fired · $$ · 0.3 mi</p>
</div>
<span class="amen__badge badge--green">4.5★</span>
</li>
<li class="amen" data-cat="dining">
<span class="amen__icon amen__icon--dining" aria-hidden="true">☕</span>
<div class="amen__main">
<p class="amen__name">Driftwood Coffee Co.</p>
<p class="amen__meta">Roastery & café · $ · 0.2 mi</p>
</div>
<span class="amen__badge badge--green">4.8★</span>
</li>
<li class="amen" data-cat="shops">
<span class="amen__icon amen__icon--shops" aria-hidden="true">🛍️</span>
<div class="amen__main">
<p class="amen__name">Maplewood Mercantile</p>
<p class="amen__meta">Grocer & deli · 0.2 mi</p>
</div>
<span class="amen__badge badge--brass">Daily</span>
</li>
<li class="amen" data-cat="shops">
<span class="amen__icon amen__icon--shops" aria-hidden="true">📚</span>
<div class="amen__main">
<p class="amen__name">Foxglove Books</p>
<p class="amen__meta">Independent bookshop · 0.4 mi</p>
</div>
<span class="amen__badge badge--brass">Local</span>
</li>
</ul>
<p class="amen-empty" id="amenEmpty" hidden>No amenities in this category yet.</p>
</div>
</section>
<!-- ===== Featured listings ===== -->
<section id="listings" class="section section--alt" aria-labelledby="list-title">
<div class="wrap">
<div class="section__head">
<p class="eyebrow">On the market</p>
<h2 id="list-title">Featured Maplewood listings</h2>
<p class="section__sub">A handful of homes available in the neighborhood right now.</p>
</div>
<div class="cards">
<article class="card">
<div class="card__photo card__photo--1">
<span class="card__status badge--ok">New</span>
<button class="card__fav" type="button" aria-pressed="false" aria-label="Save 218 Birch Lane">♡</button>
</div>
<div class="card__body">
<p class="card__price">$795,000</p>
<p class="card__addr">218 Birch Lane</p>
<p class="card__specs">3 bd · 2 ba · 1,840 sq ft</p>
<div class="card__agent">
<span class="avatar" aria-hidden="true">EC</span>
<span>Listed by Elena Cho</span>
</div>
</div>
</article>
<article class="card">
<div class="card__photo card__photo--2">
<span class="card__status badge--warn">Open Sun</span>
<button class="card__fav" type="button" aria-pressed="false" aria-label="Save 47 Hartwell Row">♡</button>
</div>
<div class="card__body">
<p class="card__price">$1,120,000</p>
<p class="card__addr">47 Hartwell Row</p>
<p class="card__specs">4 bd · 3 ba · 2,610 sq ft</p>
<div class="card__agent">
<span class="avatar" aria-hidden="true">MR</span>
<span>Listed by Marcus Reyes</span>
</div>
</div>
</article>
<article class="card">
<div class="card__photo card__photo--3">
<span class="card__status badge--green">Pending</span>
<button class="card__fav" type="button" aria-pressed="false" aria-label="Save 9 Foxglove Court">♡</button>
</div>
<div class="card__body">
<p class="card__price">$668,000</p>
<p class="card__addr">9 Foxglove Court</p>
<p class="card__specs">2 bd · 2 ba · 1,310 sq ft</p>
<div class="card__agent">
<span class="avatar" aria-hidden="true">PT</span>
<span>Listed by Priya Tran</span>
</div>
</div>
</article>
</div>
</div>
</section>
<!-- ===== Footer ===== -->
<footer class="footer">
<div class="wrap footer__inner">
<div>
<p class="brand brand--footer"><span class="brand__mark" aria-hidden="true">◈</span> Hartwell & Vane</p>
<p class="footer__fine">Neighborhood guide · Maplewood Heights, Westbrook County</p>
</div>
<p class="footer__fine">Illustrative UI — all listings & data are fictional.</p>
</div>
</footer>
</main>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>Neighborhood Guide
An editorial guide page for Maplewood Heights built on the green-and-brass real-estate palette, with Cormorant Garamond display headings over an Inter body. The hero pairs a CSS-gradient “golden hour” street photo with the neighborhood name, a descriptive vibe paragraph, and character tags. Below it, a four-card market snapshot reports median sale price, price per square foot, a declining days-on-market trend (with an inline sparkline), and the sale-to-list ratio, each with an up/down delta against last quarter.
The lifestyle section renders walk, transit, and bike scores as SVG ring dials that animate from zero — the stroke sweeps and the number counts up — the first time they scroll into view, using an IntersectionObserver. The amenities section lists schools, parks, dining, and shops as refined rows with category icons and badges; the chip filter bar instantly narrows the list by category and shows an empty-state message when needed.
Finally, three featured listing cards present price, address, beds/baths/square footage, and a listing agent, each with a status badge (New, Open Sun, Pending) and a heart button that toggles a saved state and fires a toast. Everything is vanilla JS, keyboard-usable, and responsive down to roughly 360px.
Illustrative UI only — sample listings and data are fictional; not a real real-estate service.