Real Estate — Agent Profile
An editorial personal-brand page for fictional broker Marguerite Alcott of Halford and Vane. A portrait hero pairs name, title and brokerage with call, email and share actions, followed by count-up career stats, a bio with areas served, and a tabbed listings grid that switches between active and sold homes. A self-advancing reviews carousel and a validated contact form round it out, with toast feedback on tour requests and submissions.
MCP
Código
: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 10px 30px rgba(28, 42, 37, 0.10), 0 2px 6px rgba(28, 42, 37, 0.06);
--sh-3: 0 24px 60px rgba(22, 48, 42, 0.18);
--serif: "Cormorant Garamond", Georgia, serif;
--sans: "Inter", system-ui, sans-serif;
}
*,
*::before,
*::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
font-family: var(--sans);
background: var(--ivory);
color: var(--ink);
line-height: 1.55;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
h1, h2, h3 { margin: 0; font-family: var(--serif); font-weight: 600; line-height: 1.08; }
p { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
.wrap { width: min(1140px, 92vw); margin-inline: auto; }
/* ---------- shared bits ---------- */
.eyebrow,
.kicker {
font-size: 0.74rem;
letter-spacing: 0.18em;
text-transform: uppercase;
font-weight: 600;
color: var(--brass-d);
}
.kicker { display: inline-flex; align-items: center; gap: 0.55rem; }
.kicker--center { justify-content: center; }
.hair { width: 28px; height: 1px; background: var(--brass); display: inline-block; }
.h2 {
font-size: clamp(1.9rem, 1.2rem + 2vw, 2.9rem);
color: var(--green-d);
letter-spacing: 0.005em;
margin-top: 0.4rem;
}
.lede { font-size: 1.12rem; color: var(--ink-2); margin-top: 1rem; }
.body { color: var(--ink-2); margin-top: 0.9rem; }
.ic { width: 18px; height: 18px; fill: currentColor; flex: none; }
.btn {
--bg: var(--green);
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
font-family: var(--sans);
font-weight: 600;
font-size: 0.95rem;
padding: 0.72rem 1.15rem;
border-radius: 999px;
border: 1px solid transparent;
cursor: pointer;
transition: transform 0.15s ease, box-shadow 0.2s ease, background 0.2s ease, color 0.2s ease;
}
.btn:active { transform: translateY(1px); }
.btn--green { background: var(--green); color: var(--paper); box-shadow: var(--sh-1); }
.btn--green:hover { background: var(--green-d); box-shadow: var(--sh-2); }
.btn--brass { background: var(--brass); color: #2a1f0f; }
.btn--brass:hover { background: var(--brass-d); color: #fff; }
.btn--outline { background: var(--white); color: var(--green-d); border-color: var(--line-2); }
.btn--outline:hover { border-color: var(--green); box-shadow: var(--sh-1); }
.btn--ghost { background: transparent; color: var(--green-700); border-color: transparent; }
.btn--ghost:hover { background: var(--green-50); }
.btn--block { width: 100%; }
.btn:focus-visible { outline: 2px solid var(--brass); outline-offset: 3px; }
/* ---------- top bar ---------- */
.topbar {
position: sticky;
top: 0;
z-index: 40;
background: color-mix(in srgb, var(--ivory) 88%, transparent);
backdrop-filter: blur(10px);
border-bottom: 1px solid var(--line);
}
.topbar__in { display: flex; align-items: center; gap: 1.5rem; padding: 0.85rem 0; }
.brand { display: inline-flex; align-items: center; gap: 0.6rem; }
.brand__mark {
width: 34px; height: 34px;
display: grid; place-items: center;
border-radius: 9px;
background: var(--green);
color: var(--brass-50);
font-family: var(--serif);
font-weight: 700;
font-size: 1.25rem;
box-shadow: inset 0 0 0 1px rgba(176, 141, 87, 0.5);
}
.brand__name { font-family: var(--serif); font-weight: 600; font-size: 1.2rem; color: var(--green-d); letter-spacing: 0.01em; }
.topnav { display: flex; gap: 1.4rem; margin-left: auto; font-size: 0.92rem; font-weight: 500; color: var(--ink-2); }
.topnav a { padding: 0.2rem 0; border-bottom: 1.5px solid transparent; transition: color 0.15s, border-color 0.15s; }
.topnav a:hover { color: var(--green-d); border-color: var(--brass); }
.topbar__cta { padding: 0.55rem 1.05rem; }
/* ---------- hero ---------- */
.hero { padding: clamp(2.5rem, 1rem + 6vw, 5rem) 0 clamp(2rem, 4vw, 3.5rem); }
.hero__in {
display: grid;
grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
gap: clamp(1.8rem, 4vw, 3.5rem);
align-items: center;
}
.hero__portrait { margin: 0; position: relative; }
.portrait {
aspect-ratio: 4 / 5;
border-radius: var(--r-lg);
box-shadow: var(--sh-3);
position: relative;
overflow: hidden;
background:
radial-gradient(120% 80% at 70% 12%, rgba(247, 244, 236, 0.55), transparent 55%),
radial-gradient(90% 70% at 30% 95%, rgba(22, 48, 42, 0.55), transparent 60%),
linear-gradient(165deg, #5d7166 0%, #3b554b 38%, #243f37 70%, #16302a 100%);
}
.portrait::before {
content: "";
position: absolute;
left: 50%; top: 30%;
width: 46%; aspect-ratio: 1;
transform: translateX(-50%);
border-radius: 50% 50% 48% 48%;
background: radial-gradient(60% 60% at 50% 40%, #e9d8bf, #d9bd97 60%, #b89a72 100%);
box-shadow: 0 18px 40px rgba(0, 0, 0, 0.25);
}
.portrait::after {
content: "";
position: absolute;
left: 50%; bottom: 0;
width: 74%; height: 38%;
transform: translateX(-50%);
border-radius: 50% 50% 0 0;
background: linear-gradient(180deg, #f3ead9, #d9c19a 70%, #c2a878);
box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.15);
}
.portrait__badge {
position: absolute;
left: 14px; bottom: 14px;
display: inline-flex; align-items: center; gap: 0.45rem;
background: rgba(255, 253, 248, 0.94);
color: var(--green-d);
font-size: 0.78rem; font-weight: 600;
padding: 0.4rem 0.7rem;
border-radius: 999px;
box-shadow: var(--sh-1);
}
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ok); box-shadow: 0 0 0 3px rgba(47, 158, 111, 0.22); }
.hero__name {
font-size: clamp(2.6rem, 1.4rem + 4.5vw, 4.4rem);
font-weight: 700;
color: var(--green-d);
margin-top: 0.6rem;
letter-spacing: -0.005em;
}
.hero__role { font-family: var(--serif); font-size: 1.5rem; color: var(--brass-d); margin-top: 0.2rem; }
.hero__brand { color: var(--muted); font-size: 0.95rem; margin-top: 0.35rem; }
.hero__chips { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1.2rem; }
.hero__chips li {
font-size: 0.82rem; font-weight: 500;
color: var(--green-700);
background: var(--green-50);
border: 1px solid var(--line);
padding: 0.35rem 0.75rem;
border-radius: 999px;
}
.hero__actions { display: flex; flex-wrap: wrap; gap: 0.7rem; margin-top: 1.7rem; }
/* ---------- stats ---------- */
.stats { padding: 1rem 0 0.5rem; }
.stats__grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 1px;
background: var(--line);
border: 1px solid var(--line);
border-radius: var(--r-md);
overflow: hidden;
box-shadow: var(--sh-1);
}
.stat { background: var(--paper); padding: 1.4rem 1rem; text-align: center; }
.stat__num { display: block; font-family: var(--serif); font-weight: 700; font-size: clamp(1.6rem, 1rem + 1.6vw, 2.25rem); color: var(--green-d); }
.stat__small { font-size: 0.55em; color: var(--brass-d); }
.stat__label { display: block; font-size: 0.76rem; color: var(--muted); margin-top: 0.25rem; letter-spacing: 0.02em; }
/* ---------- about ---------- */
.about { padding: clamp(3rem, 5vw, 5rem) 0; }
.about__in { display: grid; grid-template-columns: 1.55fr 0.9fr; gap: clamp(1.8rem, 4vw, 3.5rem); align-items: start; }
.areas {
background: var(--paper);
border: 1px solid var(--line);
border-radius: var(--r-lg);
padding: 1.6rem 1.5rem;
box-shadow: var(--sh-1);
}
.areas__title { font-size: 1.5rem; color: var(--green-d); }
.areas__list { margin-top: 1rem; }
.areas__list li { display: flex; justify-content: space-between; align-items: baseline; padding: 0.6rem 0; border-bottom: 1px solid var(--line); }
.areas__list li:last-child { border-bottom: 0; }
.areas__list span { color: var(--ink-2); font-weight: 500; }
.areas__list b { color: var(--green-700); font-variant-numeric: tabular-nums; font-size: 0.9rem; }
.areas__note { margin-top: 1rem; font-size: 0.85rem; color: var(--muted); padding-top: 0.9rem; border-top: 1px dashed var(--line-2); }
/* ---------- section heads ---------- */
.sec-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; margin-bottom: 1.8rem; }
.sec-head--center { justify-content: center; text-align: center; }
/* ---------- tabs ---------- */
.tabs { display: inline-flex; background: var(--paper); border: 1px solid var(--line); border-radius: 999px; padding: 0.3rem; box-shadow: var(--sh-1); }
.tab {
font-family: var(--sans);
font-weight: 600; font-size: 0.92rem;
color: var(--ink-2);
background: transparent;
border: 0; cursor: pointer;
padding: 0.5rem 1.1rem;
border-radius: 999px;
display: inline-flex; align-items: center; gap: 0.45rem;
transition: background 0.18s, color 0.18s;
}
.tab__count { font-size: 0.72rem; background: var(--green-50); color: var(--green-700); padding: 0.05rem 0.45rem; border-radius: 999px; }
.tab.is-active { background: var(--green); color: var(--paper); }
.tab.is-active .tab__count { background: rgba(255, 253, 248, 0.2); color: var(--brass-50); }
.tab:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
/* ---------- listings grid ---------- */
.listings { padding: clamp(1rem, 3vw, 2rem) 0 clamp(3rem, 5vw, 5rem); }
.grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.3rem; }
.grid.is-hidden { display: none; }
.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.25s ease, border-color 0.2s ease;
animation: rise 0.4s ease both;
}
.card:hover { transform: translateY(-4px); box-shadow: var(--sh-2); border-color: var(--line-2); }
.card__photo { aspect-ratio: 4 / 3; position: relative; }
.card__body { padding: 1rem 1.1rem 1.2rem; }
.card__title { font-size: 1.35rem; color: var(--green-d); }
.card__addr { color: var(--muted); font-size: 0.86rem; margin-top: 0.15rem; }
.specs { display: flex; flex-wrap: wrap; gap: 0.4rem 0.6rem; margin-top: 0.8rem; }
.specs li {
font-size: 0.78rem; font-weight: 500; color: var(--ink-2);
background: var(--ivory);
border: 1px solid var(--line);
padding: 0.25rem 0.55rem;
border-radius: var(--r-sm);
font-variant-numeric: tabular-nums;
}
.card__cta {
margin-top: 1rem;
width: 100%;
font-family: var(--sans); font-weight: 600; font-size: 0.9rem;
color: var(--green-d);
background: var(--white);
border: 1px solid var(--line-2);
border-radius: 999px;
padding: 0.6rem;
cursor: pointer;
transition: background 0.18s, color 0.18s, border-color 0.18s;
}
.card__cta:hover { background: var(--green); color: var(--paper); border-color: var(--green); }
.card__cta:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
.sold-note { margin-top: 0.9rem; font-size: 0.83rem; font-weight: 600; color: var(--green-700); }
.card--sold .card__photo { filter: saturate(0.85); }
.badge {
position: absolute;
font-size: 0.75rem; font-weight: 600;
padding: 0.32rem 0.6rem;
border-radius: 999px;
backdrop-filter: blur(2px);
}
.badge--status { top: 12px; left: 12px; background: rgba(255, 253, 248, 0.92); color: var(--green-d); }
.badge--new { background: var(--brass); color: #2a1f0f; }
.badge--sold { top: 12px; left: 12px; background: var(--green-d); color: var(--brass-50); }
.badge--price { bottom: 12px; right: 12px; background: rgba(22, 48, 42, 0.9); color: #fff; letter-spacing: 0.01em; }
/* simulated listing photography */
.ph-1 { background: radial-gradient(120% 100% at 20% 10%, #cfe0e6, transparent 55%), linear-gradient(150deg, #93b2bd 0%, #5e8492 45%, #355661 100%); }
.ph-2 { background: radial-gradient(110% 90% at 80% 15%, #f3e7cf, transparent 55%), linear-gradient(155deg, #c9a878 0%, #9c7d54 50%, #6e5436 100%); }
.ph-3 { background: radial-gradient(120% 100% at 30% 90%, #d7e3cf, transparent 55%), linear-gradient(150deg, #9fb98a 0%, #6f8e5d 48%, #3f5b32 100%); }
.ph-4 { background: radial-gradient(110% 90% at 75% 20%, #e9dcc9, transparent 55%), linear-gradient(160deg, #d8c4a4 0%, #b49a73 45%, #7e6644 100%); }
.ph-5 { background: radial-gradient(120% 100% at 25% 12%, #d9d2e6, transparent 55%), linear-gradient(150deg, #9d93b6 0%, #6c618c 50%, #443a63 100%); }
.ph-6 { background: radial-gradient(110% 90% at 80% 18%, #f1d9cd, transparent 55%), linear-gradient(155deg, #d8a98e 0%, #b07b5d 48%, #774a32 100%); }
.ph-7 { background: radial-gradient(120% 100% at 30% 90%, #cfe2df, transparent 55%), linear-gradient(150deg, #8fc0b6 0%, #5a958a 48%, #336158 100%); }
.ph-8 { background: radial-gradient(110% 90% at 70% 15%, #e6e2d0, transparent 55%), linear-gradient(160deg, #c4bf99 0%, #9a946b 48%, #65613f 100%); }
@keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: translateY(0); } }
/* ---------- reviews ---------- */
.reviews { padding: clamp(3rem, 5vw, 5rem) 0; background: linear-gradient(180deg, var(--green) 0%, var(--green-d) 100%); color: var(--paper); }
.reviews .h2 { color: var(--paper); }
.reviews .kicker { color: var(--brass); }
.reviews .hair { background: var(--brass); }
.carousel { display: flex; align-items: center; gap: 1rem; max-width: 820px; margin: 0 auto; }
.car-viewport { overflow: hidden; flex: 1; border-radius: var(--r-lg); }
.car-track { display: flex; transition: transform 0.45s cubic-bezier(0.4, 0, 0.2, 1); }
.review { flex: 0 0 100%; padding: 0.4rem 0.6rem 0.2rem; text-align: center; }
.review__stars { color: var(--brass); letter-spacing: 0.18em; font-size: 1rem; }
.review blockquote { margin: 0.9rem 0 0; font-family: var(--serif); font-size: clamp(1.3rem, 0.9rem + 1.4vw, 1.85rem); line-height: 1.32; color: var(--ivory); }
.review figcaption { margin-top: 1.1rem; font-size: 0.9rem; color: rgba(247, 244, 236, 0.72); }
.review figcaption b { color: var(--brass-50); }
.car-btn {
flex: none;
width: 44px; height: 44px;
border-radius: 50%;
display: grid; place-items: center;
background: rgba(255, 253, 248, 0.08);
border: 1px solid rgba(247, 244, 236, 0.22);
color: var(--ivory);
cursor: pointer;
transition: background 0.18s, border-color 0.18s;
}
.car-btn:hover { background: rgba(255, 253, 248, 0.18); border-color: var(--brass); }
.car-btn svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.car-btn:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
.dots { display: flex; gap: 0.5rem; justify-content: center; margin-top: 1.8rem; }
.dots button {
width: 9px; height: 9px; padding: 0;
border-radius: 50%;
border: 0;
background: rgba(247, 244, 236, 0.3);
cursor: pointer;
transition: background 0.2s, transform 0.2s;
}
.dots button.is-active { background: var(--brass); transform: scale(1.25); }
.dots button:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
/* ---------- contact ---------- */
.contact { padding: clamp(3rem, 5vw, 5.5rem) 0; }
.contact__in { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 4vw, 4rem); align-items: start; }
.contact__meta { margin-top: 1.6rem; display: grid; gap: 0.7rem; }
.contact__meta li { font-size: 0.95rem; color: var(--ink-2); }
.contact__meta b { display: block; font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--brass-d); margin-bottom: 0.1rem; }
.form { background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg); padding: clamp(1.4rem, 3vw, 2.2rem); box-shadow: var(--sh-2); }
.field { display: flex; flex-direction: column; gap: 0.35rem; margin-bottom: 1rem; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.field label { font-size: 0.82rem; font-weight: 600; color: var(--ink-2); }
.field .opt { font-weight: 400; color: var(--muted); }
.field input,
.field select,
.field textarea {
font-family: var(--sans);
font-size: 0.95rem;
color: var(--ink);
background: var(--white);
border: 1px solid var(--line-2);
border-radius: var(--r-sm);
padding: 0.65rem 0.8rem;
transition: border-color 0.15s, box-shadow 0.15s;
}
.field textarea { resize: vertical; min-height: 90px; }
.field input:focus,
.field select:focus,
.field textarea:focus { outline: none; border-color: var(--green); box-shadow: 0 0 0 3px rgba(31, 61, 52, 0.12); }
.field input:user-invalid,
.field textarea:user-invalid { border-color: var(--danger); }
.form .btn { margin-top: 0.4rem; }
.form__fine { margin-top: 0.8rem; font-size: 0.78rem; color: var(--muted); text-align: center; }
/* ---------- footer ---------- */
.foot { border-top: 1px solid var(--line); padding: 2rem 0; }
.foot__in { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 0.4rem; }
.foot p { font-size: 0.9rem; color: var(--ink-2); }
.foot__fine { color: var(--muted); font-size: 0.82rem; }
/* ---------- toast ---------- */
.toast {
position: fixed;
left: 50%; bottom: 26px;
transform: translate(-50%, 140%);
background: var(--green-d);
color: var(--paper);
font-weight: 500; font-size: 0.92rem;
padding: 0.8rem 1.2rem;
border-radius: 999px;
box-shadow: var(--sh-3);
z-index: 80;
opacity: 0;
transition: transform 0.4s cubic-bezier(0.2, 0.9, 0.3, 1.2), opacity 0.3s;
max-width: 90vw;
}
.toast.show { transform: translate(-50%, 0); opacity: 1; }
.toast::before { content: "✓"; color: var(--brass); font-weight: 700; margin-right: 0.5rem; }
/* ---------- responsive ---------- */
@media (max-width: 960px) {
.hero__in { grid-template-columns: 1fr; }
.hero__portrait { max-width: 360px; }
.stats__grid { grid-template-columns: repeat(3, 1fr); }
.stat:nth-child(4) { border-top: 1px solid var(--line); }
.stat:nth-child(5) { border-top: 1px solid var(--line); }
.about__in { grid-template-columns: 1fr; }
.contact__in { grid-template-columns: 1fr; }
.grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 520px) {
.topnav { display: none; }
.topbar__cta { margin-left: auto; }
.stats__grid { grid-template-columns: repeat(2, 1fr); }
.stat:nth-child(3) { border-top: 1px solid var(--line); }
.stat:nth-child(5) { grid-column: 1 / -1; border-top: 1px solid var(--line); }
.hero__actions .btn { flex: 1 1 auto; }
.grid { grid-template-columns: 1fr; }
.field-row { grid-template-columns: 1fr; }
.carousel { gap: 0.4rem; }
.car-btn { width: 38px; height: 38px; }
.foot__in { justify-content: center; text-align: center; }
}
@media (prefers-reduced-motion: reduce) {
* { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; }
}
/* Visibility guard: honor the [hidden] attribute over base display */
.grid[hidden] {
display: none;
}(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("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("show");
}, 3200);
}
/* ---------- listing tab switch (active / sold) ---------- */
var tabs = Array.prototype.slice.call(document.querySelectorAll(".tab"));
var panels = {
active: document.querySelector('[data-panel="active"]'),
sold: document.querySelector('[data-panel="sold"]'),
};
function selectTab(name) {
tabs.forEach(function (tab) {
var on = tab.dataset.tab === name;
tab.classList.toggle("is-active", on);
tab.setAttribute("aria-selected", on ? "true" : "false");
tab.tabIndex = on ? 0 : -1;
});
Object.keys(panels).forEach(function (key) {
var panel = panels[key];
if (!panel) return;
var on = key === name;
panel.classList.toggle("is-hidden", !on);
if (on) {
panel.removeAttribute("hidden");
// re-trigger the rise animation on the newly shown cards
panel.querySelectorAll(".card").forEach(function (card, i) {
card.style.animation = "none";
// force reflow
void card.offsetWidth;
card.style.animation = "";
card.style.animationDelay = i * 0.05 + "s";
});
} else {
panel.setAttribute("hidden", "");
}
});
}
tabs.forEach(function (tab, idx) {
tab.addEventListener("click", function () {
selectTab(tab.dataset.tab);
});
tab.addEventListener("keydown", function (e) {
if (e.key !== "ArrowRight" && e.key !== "ArrowLeft") return;
e.preventDefault();
var next = e.key === "ArrowRight" ? (idx + 1) % tabs.length : (idx - 1 + tabs.length) % tabs.length;
tabs[next].focus();
selectTab(tabs[next].dataset.tab);
});
});
/* ---------- tour request buttons ---------- */
document.querySelectorAll("[data-tour]").forEach(function (btn) {
btn.addEventListener("click", function () {
toast("Tour requested for " + btn.dataset.tour + " — Marguerite will be in touch.");
});
});
/* ---------- share ---------- */
var shareBtn = document.getElementById("shareBtn");
if (shareBtn) {
shareBtn.addEventListener("click", function () {
var data = {
title: "Marguerite Alcott — Halford & Vane",
text: "Marguerite Alcott, Principal Broker on the Marisol coast.",
url: location.href,
};
if (navigator.share) {
navigator.share(data).catch(function () {});
} else if (navigator.clipboard) {
navigator.clipboard.writeText(location.href).then(
function () { toast("Profile link copied to clipboard."); },
function () { toast("Couldn't copy — please copy the URL manually."); }
);
} else {
toast("Sharing isn't supported in this browser.");
}
});
}
/* ---------- reviews carousel ---------- */
var track = document.getElementById("revTrack");
var prevBtn = document.getElementById("revPrev");
var nextBtn = document.getElementById("revNext");
var dotsWrap = document.getElementById("revDots");
if (track) {
var slides = Array.prototype.slice.call(track.querySelectorAll("[data-rev]"));
var index = 0;
var auto = null;
// build dots
slides.forEach(function (_, i) {
var b = document.createElement("button");
b.type = "button";
b.setAttribute("role", "tab");
b.setAttribute("aria-label", "Review " + (i + 1));
b.addEventListener("click", function () { go(i, true); });
dotsWrap.appendChild(b);
});
var dots = Array.prototype.slice.call(dotsWrap.children);
function render() {
track.style.transform = "translateX(" + -index * 100 + "%)";
dots.forEach(function (d, i) {
d.classList.toggle("is-active", i === index);
d.setAttribute("aria-selected", i === index ? "true" : "false");
});
}
function go(i, userInitiated) {
index = (i + slides.length) % slides.length;
render();
if (userInitiated) restartAuto();
}
function startAuto() {
auto = setInterval(function () { go(index + 1, false); }, 6000);
}
function restartAuto() {
clearInterval(auto);
startAuto();
}
if (nextBtn) nextBtn.addEventListener("click", function () { go(index + 1, true); });
if (prevBtn) prevBtn.addEventListener("click", function () { go(index - 1, true); });
// pause on hover / focus
var carousel = track.closest(".reviews");
if (carousel) {
carousel.addEventListener("mouseenter", function () { clearInterval(auto); });
carousel.addEventListener("mouseleave", startAuto);
carousel.addEventListener("focusin", function () { clearInterval(auto); });
carousel.addEventListener("focusout", startAuto);
}
// keyboard
track.parentElement.addEventListener("keydown", function (e) {
if (e.key === "ArrowRight") { e.preventDefault(); go(index + 1, true); }
if (e.key === "ArrowLeft") { e.preventDefault(); go(index - 1, true); }
});
render();
startAuto();
}
/* ---------- count-up stats ---------- */
var counters = Array.prototype.slice.call(document.querySelectorAll("[data-count]"));
if (counters.length && "IntersectionObserver" in window) {
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (!entry.isIntersecting) return;
animateCount(entry.target);
io.unobserve(entry.target);
});
}, { threshold: 0.6 });
counters.forEach(function (el) { io.observe(el); });
}
function animateCount(el) {
var target = parseInt(el.dataset.count, 10) || 0;
var dur = 1100;
var start = performance.now();
function tick(now) {
var p = Math.min((now - start) / dur, 1);
var eased = 1 - Math.pow(1 - p, 3);
el.textContent = Math.round(target * eased).toString();
if (p < 1) requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
}
/* ---------- contact form ---------- */
var form = document.getElementById("contactForm");
if (form) {
form.addEventListener("submit", function (e) {
e.preventDefault();
if (!form.checkValidity()) {
var firstInvalid = form.querySelector(":invalid");
if (firstInvalid) firstInvalid.focus();
toast("Please complete the highlighted fields.");
return;
}
var name = (form.elements.name.value || "").trim().split(" ")[0] || "there";
form.reset();
toast("Thanks, " + name + " — your message is on its way to Marguerite.");
});
}
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Marguerite Alcott — Real Estate Agent</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>
<!-- ===== Top bar ===== -->
<header class="topbar">
<div class="wrap topbar__in">
<a class="brand" href="#" aria-label="Halford & Vane Real Estate, home">
<span class="brand__mark" aria-hidden="true">H</span>
<span class="brand__name">Halford & Vane</span>
</a>
<nav class="topnav" aria-label="Primary">
<a href="#listings">Listings</a>
<a href="#about">About</a>
<a href="#reviews">Reviews</a>
<a href="#contact">Contact</a>
</nav>
<a class="btn btn--brass topbar__cta" href="#contact">Book a call</a>
</div>
</header>
<main>
<!-- ===== Hero ===== -->
<section class="hero">
<div class="wrap hero__in">
<figure class="hero__portrait" aria-label="Portrait of Marguerite Alcott">
<div class="portrait" role="img" aria-label="Studio portrait of agent Marguerite Alcott"></div>
<figcaption class="portrait__badge">
<span class="dot" aria-hidden="true"></span> Available this week
</figcaption>
</figure>
<div class="hero__copy">
<p class="eyebrow">Luxury Residential · Greater Marisol Bay</p>
<h1 class="hero__name">Marguerite Alcott</h1>
<p class="hero__role">Principal Broker & Founding Partner</p>
<p class="hero__brand">Halford & Vane · License #RE-0288417</p>
<ul class="hero__chips" aria-label="Highlights">
<li>Coastal & Hillside Specialist</li>
<li>Top 1% Producer 2025</li>
<li>Bilingual EN / ES</li>
</ul>
<div class="hero__actions">
<a class="btn btn--green" href="#contact">
<svg viewBox="0 0 24 24" aria-hidden="true" class="ic"><path d="M6.6 10.8a15.5 15.5 0 0 0 6.6 6.6l2.2-2.2a1 1 0 0 1 1-.24 11 11 0 0 0 3.5.56 1 1 0 0 1 1 1V20a1 1 0 0 1-1 1A17 17 0 0 1 3 4a1 1 0 0 1 1-1h3.5a1 1 0 0 1 1 1 11 11 0 0 0 .56 3.5 1 1 0 0 1-.24 1Z"/></svg>
Call (305) 555‑0148
</a>
<a class="btn btn--outline" href="#contact">
<svg viewBox="0 0 24 24" aria-hidden="true" class="ic"><path d="M4 5h16a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1Zm.6 2L12 12l7.4-5Z"/></svg>
Email Marguerite
</a>
<button class="btn btn--ghost" type="button" id="shareBtn">
<svg viewBox="0 0 24 24" aria-hidden="true" class="ic"><path d="M14 9V5l7 7-7 7v-4.1c-5 0-8.5 1.6-11 5 1-5 4-10 11-10.9Z"/></svg>
Share profile
</button>
</div>
</div>
</div>
</section>
<!-- ===== Stats ===== -->
<section class="stats" aria-label="Career statistics">
<div class="wrap stats__grid">
<div class="stat">
<span class="stat__num" data-count="312">312</span>
<span class="stat__label">Homes sold</span>
</div>
<div class="stat">
<span class="stat__num">$486M</span>
<span class="stat__label">Lifetime volume</span>
</div>
<div class="stat">
<span class="stat__num" data-count="19">19</span>
<span class="stat__label">Avg. days on market</span>
</div>
<div class="stat">
<span class="stat__num">102%</span>
<span class="stat__label">Avg. list‑to‑sale</span>
</div>
<div class="stat">
<span class="stat__num">4.97<span class="stat__small">/5</span></span>
<span class="stat__label">Client rating</span>
</div>
</div>
</section>
<!-- ===== About + areas ===== -->
<section class="about" id="about">
<div class="wrap about__in">
<div class="about__main">
<p class="kicker"><span class="hair" aria-hidden="true"></span> About</p>
<h2 class="h2">Quietly relentless, endlessly local.</h2>
<p class="lede">
For seventeen years I have helped families buy and sell along the
Marisol coastline — from cliff‑edge moderns to restored bungalows
three streets back from the water. My practice is small by design:
fewer clients, deeper attention, sharper results.
</p>
<p class="body">
I read a neighbourhood the way most people read a room. That means
pricing that holds up under scrutiny, staging that photographs
beautifully, and negotiation that protects your number without
burning the relationship. Whether it is your first home or your
fifth, you will always work directly with me — never a handoff.
</p>
</div>
<aside class="areas" aria-label="Areas served">
<h3 class="areas__title">Areas served</h3>
<ul class="areas__list">
<li><span>Marisol Bay</span><b>118 sales</b></li>
<li><span>Heron Cliffs</span><b>74 sales</b></li>
<li><span>Old Town Verde</span><b>61 sales</b></li>
<li><span>Saltmeadow</span><b>39 sales</b></li>
<li><span>Ridgeline Park</span><b>20 sales</b></li>
</ul>
<p class="areas__note">Currently representing 9 active listings.</p>
</aside>
</div>
</section>
<!-- ===== Listings ===== -->
<section class="listings" id="listings">
<div class="wrap">
<div class="sec-head">
<div>
<p class="kicker"><span class="hair" aria-hidden="true"></span> Portfolio</p>
<h2 class="h2">Listings</h2>
</div>
<div class="tabs" role="tablist" aria-label="Listing status">
<button class="tab is-active" role="tab" id="tab-active" aria-selected="true" aria-controls="panel-active" data-tab="active">
Active <span class="tab__count">4</span>
</button>
<button class="tab" role="tab" id="tab-sold" aria-selected="false" aria-controls="panel-sold" tabindex="-1" data-tab="sold">
Sold <span class="tab__count">4</span>
</button>
</div>
</div>
<!-- Active -->
<div class="grid" role="tabpanel" id="panel-active" aria-labelledby="tab-active" data-panel="active">
<article class="card">
<div class="card__photo ph-1">
<span class="badge badge--status">For sale</span>
<span class="badge badge--price">$3,250,000</span>
</div>
<div class="card__body">
<h3 class="card__title">28 Cliffwater Terrace</h3>
<p class="card__addr">Heron Cliffs · Marisol Bay</p>
<ul class="specs">
<li>4 bd</li><li>5 ba</li><li>4,120 sqft</li><li>0.6 ac</li>
</ul>
<button class="card__cta" type="button" data-tour="28 Cliffwater Terrace">Request a tour</button>
</div>
</article>
<article class="card">
<div class="card__photo ph-2">
<span class="badge badge--status">For sale</span>
<span class="badge badge--price">$1,495,000</span>
</div>
<div class="card__body">
<h3 class="card__title">9 Saltmeadow Lane</h3>
<p class="card__addr">Saltmeadow · Marisol Bay</p>
<ul class="specs">
<li>3 bd</li><li>2 ba</li><li>2,260 sqft</li><li>0.2 ac</li>
</ul>
<button class="card__cta" type="button" data-tour="9 Saltmeadow Lane">Request a tour</button>
</div>
</article>
<article class="card">
<div class="card__photo ph-3">
<span class="badge badge--status badge--new">New</span>
<span class="badge badge--price">$2,140,000</span>
</div>
<div class="card__body">
<h3 class="card__title">412 Old Town Verde</h3>
<p class="card__addr">Old Town Verde · Marisol Bay</p>
<ul class="specs">
<li>5 bd</li><li>4 ba</li><li>3,540 sqft</li><li>0.3 ac</li>
</ul>
<button class="card__cta" type="button" data-tour="412 Old Town Verde">Request a tour</button>
</div>
</article>
<article class="card">
<div class="card__photo ph-4">
<span class="badge badge--status">For sale</span>
<span class="badge badge--price">$985,000</span>
</div>
<div class="card__body">
<h3 class="card__title">7 Ridgeline Court</h3>
<p class="card__addr">Ridgeline Park · Marisol Bay</p>
<ul class="specs">
<li>3 bd</li><li>2 ba</li><li>1,840 sqft</li><li>0.15 ac</li>
</ul>
<button class="card__cta" type="button" data-tour="7 Ridgeline Court">Request a tour</button>
</div>
</article>
</div>
<!-- Sold -->
<div class="grid is-hidden" role="tabpanel" id="panel-sold" aria-labelledby="tab-sold" data-panel="sold" hidden>
<article class="card card--sold">
<div class="card__photo ph-5">
<span class="badge badge--sold">Sold</span>
<span class="badge badge--price">$4,100,000</span>
</div>
<div class="card__body">
<h3 class="card__title">1 Headland Mews</h3>
<p class="card__addr">Heron Cliffs · Marisol Bay</p>
<ul class="specs">
<li>5 bd</li><li>6 ba</li><li>5,300 sqft</li><li>14 days</li>
</ul>
<p class="sold-note">Closed 4% over ask · Mar 2026</p>
</div>
</article>
<article class="card card--sold">
<div class="card__photo ph-6">
<span class="badge badge--sold">Sold</span>
<span class="badge badge--price">$1,725,000</span>
</div>
<div class="card__body">
<h3 class="card__title">34 Verde Walk</h3>
<p class="card__addr">Old Town Verde · Marisol Bay</p>
<ul class="specs">
<li>4 bd</li><li>3 ba</li><li>2,910 sqft</li><li>11 days</li>
</ul>
<p class="sold-note">Multiple offers · Feb 2026</p>
</div>
</article>
<article class="card card--sold">
<div class="card__photo ph-7">
<span class="badge badge--sold">Sold</span>
<span class="badge badge--price">$1,260,000</span>
</div>
<div class="card__body">
<h3 class="card__title">18 Meadow Crescent</h3>
<p class="card__addr">Saltmeadow · Marisol Bay</p>
<ul class="specs">
<li>3 bd</li><li>2 ba</li><li>2,050 sqft</li><li>9 days</li>
</ul>
<p class="sold-note">Closed 6% over ask · Jan 2026</p>
</div>
</article>
<article class="card card--sold">
<div class="card__photo ph-8">
<span class="badge badge--sold">Sold</span>
<span class="badge badge--price">$820,000</span>
</div>
<div class="card__body">
<h3 class="card__title">5 Lantern Row</h3>
<p class="card__addr">Ridgeline Park · Marisol Bay</p>
<ul class="specs">
<li>2 bd</li><li>2 ba</li><li>1,460 sqft</li><li>22 days</li>
</ul>
<p class="sold-note">At asking · Dec 2025</p>
</div>
</article>
</div>
</div>
</section>
<!-- ===== Reviews ===== -->
<section class="reviews" id="reviews">
<div class="wrap">
<div class="sec-head sec-head--center">
<div>
<p class="kicker kicker--center"><span class="hair" aria-hidden="true"></span> Testimonials</p>
<h2 class="h2">What clients say</h2>
</div>
</div>
<div class="carousel" aria-roledescription="carousel" aria-label="Client reviews">
<button class="car-btn car-btn--prev" type="button" id="revPrev" aria-label="Previous review">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M15 5l-7 7 7 7"/></svg>
</button>
<div class="car-viewport">
<ul class="car-track" id="revTrack">
<li class="review" data-rev>
<div class="review__stars" aria-label="5 out of 5 stars">★★★★★</div>
<blockquote>Marguerite sold our Heron Cliffs home in under two weeks, four percent over asking. She is the calmest negotiator we have ever met — and the most prepared.</blockquote>
<figcaption><b>Dana & Priya R.</b> · Sellers, Heron Cliffs</figcaption>
</li>
<li class="review" data-rev>
<div class="review__stars" aria-label="5 out of 5 stars">★★★★★</div>
<blockquote>We were first‑time buyers and terrified. She walked us through every clause, every inspection, and never once made us feel rushed. We got the house.</blockquote>
<figcaption><b>Theo M.</b> · Buyer, Saltmeadow</figcaption>
</li>
<li class="review" data-rev>
<div class="review__stars" aria-label="5 out of 5 stars">★★★★★</div>
<blockquote>Her pricing was uncannily accurate. Three offers in a weekend on a street everyone said was slow. I would not list with anyone else on the coast.</blockquote>
<figcaption><b>Lucia V.</b> · Seller, Old Town Verde</figcaption>
</li>
<li class="review" data-rev>
<div class="review__stars" aria-label="5 out of 5 stars">★★★★★</div>
<blockquote>Responsive at midnight, gracious under pressure, and genuinely kind. Marguerite turned a stressful relocation into something we actually enjoyed.</blockquote>
<figcaption><b>The Okonkwo Family</b> · Buyers, Ridgeline Park</figcaption>
</li>
</ul>
</div>
<button class="car-btn car-btn--next" type="button" id="revNext" aria-label="Next review">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9 5l7 7-7 7"/></svg>
</button>
</div>
<div class="dots" id="revDots" role="tablist" aria-label="Choose review"></div>
</div>
</section>
<!-- ===== Contact ===== -->
<section class="contact" id="contact">
<div class="wrap contact__in">
<div class="contact__copy">
<p class="kicker"><span class="hair" aria-hidden="true"></span> Let's talk</p>
<h2 class="h2">Thinking about your next move?</h2>
<p class="body">
Tell me a little about what you are after — a free, no‑pressure
consultation, a valuation on your current home, or a question about
the market. I reply to every message myself, usually within a day.
</p>
<ul class="contact__meta">
<li><b>Office</b> 14 Harbourfront Walk, Marisol Bay</li>
<li><b>Direct</b> (305) 555‑0148</li>
<li><b>Email</b> [email protected]</li>
</ul>
</div>
<form class="form" id="contactForm" novalidate>
<div class="field">
<label for="f-name">Full name</label>
<input id="f-name" name="name" type="text" autocomplete="name" required placeholder="Jordan Avery" />
</div>
<div class="field-row">
<div class="field">
<label for="f-email">Email</label>
<input id="f-email" name="email" type="email" autocomplete="email" required placeholder="[email protected]" />
</div>
<div class="field">
<label for="f-phone">Phone <span class="opt">(optional)</span></label>
<input id="f-phone" name="phone" type="tel" autocomplete="tel" placeholder="(305) 555‑0000" />
</div>
</div>
<div class="field">
<label for="f-intent">I'm interested in</label>
<select id="f-intent" name="intent">
<option>Buying a home</option>
<option>Selling a home</option>
<option>A home valuation</option>
<option>Just exploring the market</option>
</select>
</div>
<div class="field">
<label for="f-msg">Message</label>
<textarea id="f-msg" name="message" rows="4" required placeholder="A few words about what you're looking for…"></textarea>
</div>
<button class="btn btn--green btn--block" type="submit">Send message</button>
<p class="form__fine">By sending, you agree to be contacted about your enquiry.</p>
</form>
</div>
</section>
</main>
<footer class="foot">
<div class="wrap foot__in">
<p>Marguerite Alcott · Halford & Vane Real Estate</p>
<p class="foot__fine">Illustrative demo — listings, prices and people are fictional.</p>
</div>
</footer>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>Agent Profile
A polished personal-brand page for fictional luxury broker Marguerite Alcott of Halford & Vane on the Marisol coast. A serif-led hero pairs a gradient “portrait” with her name, role, license and a row of highlight chips, plus call, email and share buttons — the share control uses the Web Share API and falls back to copying the URL. A five-cell stat band animates its numbers upward as it scrolls into view, and a bio section sits beside a card listing the neighbourhoods she covers.
The Listings block is tab-switched: an Active / Sold toggle (clickable and arrow-key navigable) swaps between two card grids, re-running the entrance animation each time. Active cards carry status, price, beds, baths and area badges plus a “Request a tour” button that fires a toast; sold cards show closing notes instead. Below, a reviews carousel advances automatically, pauses on hover or focus, and is driven by prev/next buttons and dot controls.
The closing contact form validates inline, surfaces the first invalid field, and confirms submission with a personalised toast. The whole page uses the editorial ivory-and-green palette, brass hairline accents, simulated CSS listing photography, and is responsive down to ~360px.
Illustrative UI only — sample listings and data are fictional; not a real real-estate service.