Dental — Hero Landing
A trust-first dental practice hero section with a warm headline, smiling patient photo, dual booking and phone CTAs, animated proof badges for years in practice, patients treated and star rating, plus a hoverable services strip covering checkups, whitening, aligners and implants. Includes a lightweight availability picker, live count-up stats, a floating appointment toast and a fully responsive layout that collapses gracefully on small screens.
MCP
Code
:root {
--blue: #2563eb;
--blue-d: #1d4ed8;
--blue-50: #eff5ff;
--mint: #34d399;
--mint-50: #e8fbf3;
--ink: #0f2740;
--ink-2: #3a5169;
--muted: #6b7c90;
--bg: #f3f8ff;
--white: #fff;
--line: rgba(15, 39, 64, 0.10);
--line-2: rgba(15, 39, 64, 0.18);
--ok: #22b07d;
--warn: #d98a2b;
--danger: #e05252;
--r-sm: 8px;
--r-md: 14px;
--r-lg: 22px;
--sh-sm: 0 2px 8px rgba(15, 39, 64, 0.06);
--sh-md: 0 14px 34px rgba(15, 39, 64, 0.10);
--sh-lg: 0 30px 70px rgba(37, 99, 235, 0.16);
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
margin: 0;
font-family: "Inter", system-ui, -apple-system, sans-serif;
line-height: 1.5;
color: var(--ink);
background:
radial-gradient(1100px 620px at 85% -12%, var(--blue-50), transparent 60%),
radial-gradient(900px 520px at -8% 8%, var(--mint-50), transparent 55%),
var(--bg);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
min-height: 100vh;
}
.sr-only {
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
img { max-width: 100%; display: block; }
/* ---------- Buttons ---------- */
.btn {
display: inline-flex; align-items: center; gap: 9px;
font: inherit; font-weight: 600; font-size: 15px;
border: 1px solid transparent; border-radius: 999px;
padding: 12px 20px; cursor: pointer; text-decoration: none;
transition: transform .16s ease, box-shadow .16s ease, background .16s ease, color .16s ease, opacity .16s ease;
white-space: nowrap;
}
.btn:focus-visible { outline: 3px solid rgba(37, 99, 235, 0.45); outline-offset: 2px; }
.btn-primary {
background: linear-gradient(180deg, var(--blue), var(--blue-d));
color: var(--white); box-shadow: 0 10px 24px rgba(37, 99, 235, 0.32);
}
.btn-primary:not(:disabled):hover { transform: translateY(-2px); box-shadow: 0 16px 34px rgba(37, 99, 235, 0.40); }
.btn-primary:not(:disabled):active { transform: translateY(0); }
.btn-primary:disabled { opacity: .55; cursor: not-allowed; box-shadow: none; }
.btn-primary.is-ready { animation: pop .4s ease; }
.btn-ghost {
background: var(--white); color: var(--ink); border-color: var(--line-2);
box-shadow: var(--sh-sm);
}
.btn-ghost:hover { border-color: var(--blue); color: var(--blue-d); transform: translateY(-2px); }
/* ---------- Topbar ---------- */
.topbar {
max-width: 1180px; margin: 0 auto; padding: 20px clamp(18px, 4vw, 40px);
display: flex; align-items: center; gap: 20px;
}
.brand { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; color: var(--ink); }
.brand-mark {
display: grid; place-items: center; width: 38px; height: 38px; border-radius: 12px;
background: linear-gradient(150deg, var(--blue), var(--mint)); color: var(--white);
box-shadow: 0 8px 18px rgba(37, 99, 235, 0.30);
}
.brand-name { font-weight: 800; font-size: 19px; letter-spacing: -0.02em; }
.brand-name em { font-style: normal; color: var(--blue); font-weight: 700; }
.nav { display: flex; gap: 26px; margin-left: 14px; }
.nav a {
text-decoration: none; color: var(--ink-2); font-weight: 500; font-size: 15px;
position: relative; padding: 4px 0;
}
.nav a::after {
content: ""; position: absolute; left: 0; bottom: -2px; width: 0; height: 2px;
background: var(--blue); border-radius: 2px; transition: width .2s ease;
}
.nav a:hover { color: var(--ink); }
.nav a:hover::after { width: 100%; }
.btn-phone { margin-left: auto; font-size: 14px; padding: 9px 16px; }
/* ---------- Hero ---------- */
.hero {
max-width: 1180px; margin: 8px auto 0; padding: clamp(16px, 3vw, 34px) clamp(18px, 4vw, 40px) 30px;
display: grid; grid-template-columns: 1.05fr 0.95fr; gap: clamp(28px, 4vw, 56px);
align-items: center;
}
.eyebrow {
display: inline-flex; align-items: center; gap: 8px;
background: var(--white); border: 1px solid var(--line); color: var(--ink-2);
padding: 6px 14px 6px 10px; border-radius: 999px; font-size: 13px; font-weight: 600;
box-shadow: var(--sh-sm);
}
.eyebrow .dot {
width: 8px; height: 8px; border-radius: 50%; background: var(--mint);
box-shadow: 0 0 0 4px var(--mint-50); animation: pulse 2s infinite;
}
h1 {
margin: 18px 0 0; font-size: clamp(2.1rem, 5vw, 3.35rem); line-height: 1.06;
letter-spacing: -0.03em; font-weight: 800; color: var(--ink);
}
h1 .hl {
color: var(--blue);
background: linear-gradient(180deg, transparent 62%, rgba(52, 211, 153, 0.35) 62%);
padding: 0 2px;
}
.lede { margin: 18px 0 0; max-width: 46ch; color: var(--ink-2); font-size: clamp(1rem, 2vw, 1.12rem); }
.cta-row { margin-top: 26px; display: flex; flex-wrap: wrap; gap: 12px; }
/* ---------- Picker ---------- */
.picker {
margin-top: 26px; background: var(--white); border: 1px solid var(--line);
border-radius: var(--r-lg); padding: 16px; box-shadow: var(--sh-md); max-width: 460px;
}
.picker-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.picker-title { font-weight: 700; font-size: 15px; }
.picker-hint { font-size: 13px; color: var(--muted); transition: color .2s ease; }
.picker-hint.is-set { color: var(--ok); font-weight: 600; }
.days { display: flex; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
.chip {
font: inherit; border: 1px solid var(--line-2); background: var(--white); color: var(--ink-2);
border-radius: var(--r-md); padding: 8px 12px; cursor: pointer; font-size: 13px; font-weight: 600;
display: inline-flex; flex-direction: column; align-items: center; line-height: 1.15; min-width: 52px;
transition: all .16s ease;
}
.chip b { font-size: 16px; color: var(--ink); }
.chip:hover { border-color: var(--blue); transform: translateY(-1px); }
.chip[aria-selected="true"] {
background: var(--blue-50); border-color: var(--blue); color: var(--blue-d);
}
.chip[aria-selected="true"] b { color: var(--blue-d); }
.chip:focus-visible { outline: 3px solid rgba(37, 99, 235, 0.4); outline-offset: 2px; }
.slots { display: flex; gap: 8px; flex-wrap: wrap; }
.slot {
font: inherit; border: 1px solid var(--line-2); background: var(--white); color: var(--ink);
border-radius: 999px; padding: 8px 14px; cursor: pointer; font-size: 13px; font-weight: 600;
transition: all .16s ease;
}
.slot:hover:not(:disabled) { border-color: var(--blue); background: var(--blue-50); transform: translateY(-1px); }
.slot.is-selected { background: var(--blue); border-color: var(--blue); color: var(--white); box-shadow: 0 8px 16px rgba(37, 99, 235, 0.30); }
.slot.is-busy { opacity: .45; cursor: not-allowed; text-decoration: line-through; }
.slot:focus-visible { outline: 3px solid rgba(37, 99, 235, 0.4); outline-offset: 2px; }
/* ---------- Badges ---------- */
.badges {
margin-top: 30px; display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px;
max-width: 500px;
}
.badge {
background: var(--white); border: 1px solid var(--line); border-radius: var(--r-md);
padding: 14px 12px; text-align: center; box-shadow: var(--sh-sm);
}
.badge-num {
display: block; font-size: clamp(1.4rem, 3vw, 1.8rem); font-weight: 800; color: var(--blue-d);
letter-spacing: -0.02em; line-height: 1;
}
.badge-label { display: block; margin-top: 6px; font-size: 12px; color: var(--muted); font-weight: 500; }
.badge .stars { display: block; color: #f5b301; font-size: 12px; letter-spacing: 1px; }
/* ---------- Media ---------- */
.hero-media { display: flex; justify-content: center; }
.photo {
position: relative; width: 100%; max-width: 480px; aspect-ratio: 5 / 5.4;
border-radius: 30px; overflow: visible;
}
.photo img {
width: 100%; height: 100%; object-fit: cover; border-radius: 30px;
box-shadow: var(--sh-lg); border: 6px solid var(--white);
}
.chip-rating {
position: absolute; top: 22px; left: -18px; background: var(--white);
border-radius: var(--r-md); padding: 10px 14px; box-shadow: var(--sh-md);
display: flex; align-items: center; gap: 8px; border: 1px solid var(--line);
animation: floaty 4s ease-in-out infinite;
}
.chip-rating .stars { color: #f5b301; font-size: 13px; letter-spacing: 1px; }
.chip-rating b { font-size: 18px; color: var(--ink); }
.chip-rating .chip-sub { font-size: 12px; color: var(--muted); }
.chip-safe {
position: absolute; bottom: 20px; right: -14px; background: var(--ink); color: var(--white);
border-radius: 999px; padding: 10px 16px; box-shadow: var(--sh-md); font-size: 13px; font-weight: 600;
display: flex; align-items: center; gap: 8px; animation: floaty 4.6s ease-in-out infinite reverse;
}
.chip-safe svg { color: var(--mint); }
/* ---------- Services strip ---------- */
.services { max-width: 1180px; margin: 6px auto 60px; padding: 0 clamp(18px, 4vw, 40px); }
.service-strip {
list-style: none; margin: 0; padding: 12px; display: grid;
grid-template-columns: repeat(4, 1fr); gap: 12px;
background: var(--white); border: 1px solid var(--line); border-radius: var(--r-lg);
box-shadow: var(--sh-md);
}
.service {
display: flex; align-items: center; gap: 12px; padding: 14px; border-radius: var(--r-md);
cursor: pointer; transition: transform .16s ease, background .16s ease, box-shadow .16s ease;
border: 1px solid transparent;
}
.service:hover, .service:focus-visible {
transform: translateY(-3px); background: var(--blue-50); border-color: var(--line);
box-shadow: var(--sh-sm); outline: none;
}
.service:focus-visible { outline: 3px solid rgba(37, 99, 235, 0.4); outline-offset: 2px; }
.service-ic {
display: grid; place-items: center; width: 44px; height: 44px; flex: none;
background: var(--mint-50); border-radius: 12px; font-size: 22px;
}
.service-name { display: block; font-weight: 700; font-size: 15px; color: var(--ink); }
.service-meta { display: block; font-size: 13px; color: var(--muted); }
/* ---------- Toast ---------- */
.toast {
position: fixed; left: 50%; bottom: 26px; transform: translate(-50%, 30px);
background: var(--ink); color: var(--white); padding: 13px 20px; border-radius: 999px;
font-size: 14px; font-weight: 600; box-shadow: var(--sh-lg); opacity: 0; pointer-events: none;
transition: transform .3s cubic-bezier(.2,.9,.3,1.2), opacity .3s ease; z-index: 50;
display: flex; align-items: center; gap: 8px; max-width: min(92vw, 420px);
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
.toast::before { content: "✓"; color: var(--mint); font-weight: 800; }
/* ---------- Animations ---------- */
@keyframes pulse {
0%, 100% { box-shadow: 0 0 0 4px var(--mint-50); }
50% { box-shadow: 0 0 0 7px rgba(52, 211, 153, 0.12); }
}
@keyframes floaty { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
@keyframes pop { 0% { transform: scale(1); } 45% { transform: scale(1.04); } 100% { transform: scale(1); } }
@media (prefers-reduced-motion: reduce) {
* { animation: none !important; transition: none !important; }
}
/* ---------- Responsive ---------- */
@media (max-width: 900px) {
.hero { grid-template-columns: 1fr; }
.hero-media { order: -1; }
.photo { max-width: 420px; }
.nav { display: none; }
}
@media (max-width: 520px) {
.topbar { flex-wrap: wrap; gap: 12px; padding: 16px; }
.btn-phone { margin-left: 0; }
.hero { padding: 8px 16px 24px; gap: 24px; }
h1 { font-size: 2rem; }
.cta-row .btn { flex: 1 1 auto; justify-content: center; }
.picker { padding: 14px; }
.chip { min-width: 44px; padding: 7px 8px; }
.badges { grid-template-columns: 1fr; gap: 10px; max-width: 100%; }
.badge { display: flex; align-items: center; justify-content: space-between; text-align: left; padding: 12px 16px; }
.badge-label { margin-top: 0; }
.badge .stars { display: inline; }
.chip-rating { left: 0; top: 12px; }
.chip-safe { right: 0; bottom: 12px; }
.service-strip { grid-template-columns: 1fr; }
.services { margin-bottom: 40px; }
}(function () {
"use strict";
var toastEl = document.getElementById("toast");
var toastTimer;
function toast(msg) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("show");
}, 2600);
}
/* ---------- State ---------- */
var selectedDay = "Mon 8";
var selectedTime = null;
var bookBtn = document.getElementById("bookBtn");
var bookLabel = bookBtn ? bookBtn.querySelector(".btn-label") : null;
var hint = document.getElementById("pickerHint");
function updateBooking() {
var ready = !!selectedTime;
if (bookBtn) {
bookBtn.disabled = !ready;
if (ready) {
bookBtn.classList.add("is-ready");
if (bookLabel) bookLabel.textContent = "Book " + selectedDay + " · " + selectedTime;
} else {
bookBtn.classList.remove("is-ready");
if (bookLabel) bookLabel.textContent = "Pick a time to book";
}
}
if (hint) {
if (ready) {
hint.textContent = selectedDay + " at " + selectedTime + " selected";
hint.classList.add("is-set");
} else {
hint.textContent = "Select a day & time";
hint.classList.remove("is-set");
}
}
}
/* ---------- Day tabs ---------- */
var days = document.getElementById("days");
if (days) {
var chips = Array.prototype.slice.call(days.querySelectorAll(".chip"));
days.addEventListener("click", function (e) {
var chip = e.target.closest(".chip");
if (!chip) return;
chips.forEach(function (c) { c.setAttribute("aria-selected", "false"); });
chip.setAttribute("aria-selected", "true");
selectedDay = chip.getAttribute("data-day");
updateBooking();
});
// Keyboard arrow navigation between day tabs
days.addEventListener("keydown", function (e) {
if (e.key !== "ArrowRight" && e.key !== "ArrowLeft") return;
var i = chips.indexOf(document.activeElement);
if (i === -1) return;
e.preventDefault();
var next = e.key === "ArrowRight" ? (i + 1) % chips.length : (i - 1 + chips.length) % chips.length;
chips[next].focus();
chips[next].click();
});
}
/* ---------- Time slots ---------- */
var slots = document.getElementById("slots");
if (slots) {
var slotBtns = Array.prototype.slice.call(slots.querySelectorAll(".slot"));
slots.addEventListener("click", function (e) {
var slot = e.target.closest(".slot");
if (!slot || slot.disabled) return;
slotBtns.forEach(function (s) { s.classList.remove("is-selected"); });
slot.classList.add("is-selected");
selectedTime = slot.getAttribute("data-time");
updateBooking();
toast("Held " + selectedDay + " at " + selectedTime + " for 10 min");
});
}
/* ---------- Book button ---------- */
if (bookBtn) {
bookBtn.addEventListener("click", function () {
if (!selectedTime) return;
toast("Appointment requested — " + selectedDay + " at " + selectedTime + ". We'll call to confirm.");
});
}
/* ---------- Services ---------- */
var services = document.querySelectorAll(".service");
services.forEach(function (s) {
function pick() {
var name = s.querySelector(".service-name");
toast((name ? name.textContent : "Service") + " — added to your visit");
}
s.addEventListener("click", pick);
s.addEventListener("keydown", function (e) {
if (e.key === "Enter" || e.key === " ") { e.preventDefault(); pick(); }
});
});
/* ---------- Count-up badges ---------- */
function formatValue(v, el) {
var decimal = el.getAttribute("data-decimal");
var fmt = el.getAttribute("data-format");
if (decimal) {
// stored as integer * 10 (e.g. 49 -> 4.9)
return (v / 10).toFixed(parseInt(decimal, 10));
}
if (fmt === "k") {
if (v >= 1000) return (v / 1000).toFixed(v % 1000 === 0 ? 0 : 1) + "k";
return String(v);
}
return String(v);
}
function countUp(el) {
var target = parseInt(el.getAttribute("data-count"), 10) || 0;
var suffix = el.getAttribute("data-suffix") || "";
var start = performance.now();
var dur = 1400;
function tick(now) {
var p = Math.min((now - start) / dur, 1);
var eased = 1 - Math.pow(1 - p, 3);
var val = Math.round(target * eased);
el.textContent = formatValue(val, el) + suffix;
if (p < 1) requestAnimationFrame(tick);
else el.textContent = formatValue(target, el) + suffix;
}
requestAnimationFrame(tick);
}
var badgeNums = document.querySelectorAll(".badge-num");
var reduced = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
if (reduced) {
badgeNums.forEach(function (el) {
var target = parseInt(el.getAttribute("data-count"), 10) || 0;
el.textContent = formatValue(target, el) + (el.getAttribute("data-suffix") || "");
});
} else if ("IntersectionObserver" in window) {
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
countUp(entry.target);
io.unobserve(entry.target);
}
});
}, { threshold: 0.4 });
badgeNums.forEach(function (el) { io.observe(el); });
} else {
badgeNums.forEach(countUp);
}
updateBooking();
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Brightleaf Dental — Gentle care, brighter smiles</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<header class="topbar">
<a class="brand" href="#" aria-label="Brightleaf Dental home">
<span class="brand-mark" aria-hidden="true">
<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 5.5c2-2.2 6-2.6 7.5.4 1.6 3.2-1 7-3 9.4-1 1.2-2 2.7-2.5 4-.4 1-1.6 1-2 0-.5-1.3-1.5-2.8-2.5-4-2-2.4-4.6-6.2-3-9.4C7.9 2.9 10 3.3 12 5.5Z"/>
</svg>
</span>
<span class="brand-name">Brightleaf<em>Dental</em></span>
</a>
<nav class="nav" aria-label="Primary">
<a href="#services">Services</a>
<a href="#about">About</a>
<a href="#reviews">Reviews</a>
</nav>
<a class="btn btn-ghost btn-phone" href="tel:+15550190142">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3.1 19.5 19.5 0 0 1-6-6A19.8 19.8 0 0 1 2.1 4.2 2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7c.1 1 .4 1.9.7 2.8a2 2 0 0 1-.5 2.1L8.1 9.9a16 16 0 0 0 6 6l1.3-1.3a2 2 0 0 1 2.1-.4c.9.3 1.8.6 2.8.7a2 2 0 0 1 1.7 2Z"/></svg>
(555) 019-0142
</a>
</header>
<main>
<section class="hero" aria-labelledby="hero-title">
<div class="hero-copy">
<span class="eyebrow">
<span class="dot" aria-hidden="true"></span>
Now welcoming new patients
</span>
<h1 id="hero-title">Gentle dental care for a <span class="hl">brighter</span> smile.</h1>
<p class="lede">
Modern, judgement-free dentistry in the heart of Maplewood. Same-week
appointments, transparent pricing, and a team that actually listens.
</p>
<div class="cta-row">
<button class="btn btn-primary" id="bookBtn" type="button" disabled>
<span class="btn-label">Pick a time to book</span>
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
</button>
<a class="btn btn-ghost" href="tel:+15550190142">
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3.1 19.5 19.5 0 0 1-6-6A19.8 19.8 0 0 1 2.1 4.2 2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7c.1 1 .4 1.9.7 2.8a2 2 0 0 1-.5 2.1L8.1 9.9a16 16 0 0 0 6 6l1.3-1.3a2 2 0 0 1 2.1-.4c.9.3 1.8.6 2.8.7a2 2 0 0 1 1.7 2Z"/></svg>
Call us
</a>
</div>
<div class="picker" role="group" aria-label="Choose an appointment time">
<div class="picker-head">
<span class="picker-title">Reserve a slot</span>
<span class="picker-hint" id="pickerHint">Select a day & time</span>
</div>
<div class="days" id="days" role="tablist" aria-label="Day">
<button class="chip" role="tab" aria-selected="true" data-day="Mon 8">Mon <b>8</b></button>
<button class="chip" role="tab" aria-selected="false" data-day="Tue 9">Tue <b>9</b></button>
<button class="chip" role="tab" aria-selected="false" data-day="Wed 10">Wed <b>10</b></button>
<button class="chip" role="tab" aria-selected="false" data-day="Thu 11">Thu <b>11</b></button>
<button class="chip" role="tab" aria-selected="false" data-day="Fri 12">Fri <b>12</b></button>
</div>
<div class="slots" id="slots" aria-label="Time slot">
<button class="slot" data-time="9:00 AM">9:00 AM</button>
<button class="slot" data-time="10:30 AM">10:30 AM</button>
<button class="slot is-busy" data-time="1:00 PM" disabled>1:00 PM</button>
<button class="slot" data-time="2:30 PM">2:30 PM</button>
<button class="slot" data-time="4:00 PM">4:00 PM</button>
</div>
</div>
<div class="badges" id="badges" aria-label="Practice highlights">
<div class="badge">
<span class="badge-num" data-count="18" data-suffix="+">0</span>
<span class="badge-label">Years in practice</span>
</div>
<div class="badge">
<span class="badge-num" data-count="12400" data-suffix="+" data-format="k">0</span>
<span class="badge-label">Patients treated</span>
</div>
<div class="badge">
<span class="badge-num" data-count="49" data-decimal="1">0</span>
<span class="badge-label">
<span class="stars" aria-hidden="true">★★★★★</span>
Average rating
</span>
</div>
</div>
</div>
<div class="hero-media">
<div class="photo">
<img
src="https://images.unsplash.com/photo-1588776814546-1ffcf47267a5?auto=format&fit=crop&w=900&q=80"
alt="Smiling patient in a bright dental clinic"
loading="eager"
width="560" height="620"
/>
<div class="chip-rating" aria-label="Rated 4.9 out of 5 by patients">
<span class="stars" aria-hidden="true">★★★★★</span>
<b>4.9</b>
<span class="chip-sub">2,300+ reviews</span>
</div>
<div class="chip-safe">
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z"/><path d="m9 12 2 2 4-4"/></svg>
<span>Painless & sedation options</span>
</div>
</div>
</div>
</section>
<section class="services" id="services" aria-labelledby="services-title">
<h2 id="services-title" class="sr-only">Our services</h2>
<ul class="service-strip">
<li class="service" tabindex="0">
<span class="service-ic" aria-hidden="true">🦷</span>
<div>
<span class="service-name">Checkups & cleaning</span>
<span class="service-meta">From $79</span>
</div>
</li>
<li class="service" tabindex="0">
<span class="service-ic" aria-hidden="true">✨</span>
<div>
<span class="service-name">Teeth whitening</span>
<span class="service-meta">1-visit results</span>
</div>
</li>
<li class="service" tabindex="0">
<span class="service-ic" aria-hidden="true">😁</span>
<div>
<span class="service-name">Clear aligners</span>
<span class="service-meta">Free scan</span>
</div>
</li>
<li class="service" tabindex="0">
<span class="service-ic" aria-hidden="true">🪥</span>
<div>
<span class="service-name">Implants</span>
<span class="service-meta">0% financing</span>
</div>
</li>
</ul>
</section>
</main>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>The Dental Hero Landing is a clean, clinical landing section for a fictional practice, Brightleaf Dental. A calm blue-and-mint palette, generous white space and rounded cards set a reassuring, trust-first tone. The left column leads with a friendly headline, a short supporting line, and two prominent calls to action — a primary Book appointment button and a secondary phone CTA — while the right column frames a smiling patient photo with a floating rating chip.
Interactions are handled in vanilla JavaScript. Three proof badges (years in practice, patients treated, and average star rating) animate with a count-up when the hero enters view. A compact availability strip lets visitors pick a day and time slot; choosing one enables the booking button and confirms the choice through a floating toast. The services strip below the hero highlights checkups, whitening, clear aligners and implants, with hover lift and keyboard focus states so it stays usable by mouse and keyboard alike.
The layout is responsive down to about 360px: the two hero columns stack, badges wrap into a neat grid, and the services strip becomes a single scannable column. Focus rings, aria labels and AA-contrast text keep the section accessible without sacrificing the soft, welcoming look.
Illustrative UI only — not intended for real medical use.