Clinic — General Practice Landing
A warm, community-feel landing page for a family general practice. A sticky nav with a mobile menu sits above a friendly hero with a live same-day slot card, a services grid spanning family medicine, pediatrics, women's health, chronic care and vaccines, a teal same-day-appointments feature band with animated stats, a doctors strip, today-aware hours with a map and location CTA, a quick booking form, and reveal-on-scroll throughout.
MCP
程式碼
:root {
--teal: #129c93;
--teal-d: #0c7a73;
--teal-700: #0a655f;
--teal-50: #e7f5f3;
--coral: #ff7a66;
--coral-d: #f05e48;
--coral-soft: #ffe6df;
--ink: #16322f;
--ink-2: #3a534f;
--muted: #6b827e;
--bg: #f1f7f6;
--white: #ffffff;
--line: rgba(16, 50, 47, 0.1);
--line-2: rgba(16, 50, 47, 0.18);
--ok: #2f9e6f;
--warn: #d98a2b;
--danger: #d4503e;
--font: "Inter", system-ui, -apple-system, sans-serif;
--r-sm: 8px;
--r-md: 14px;
--r-lg: 20px;
--r-xl: 28px;
--shadow-1: 0 1px 2px rgba(16, 50, 47, 0.05), 0 4px 14px rgba(16, 50, 47, 0.06);
--shadow-2: 0 16px 40px rgba(12, 122, 115, 0.16);
--shadow-soft: 0 18px 48px rgba(16, 50, 47, 0.1);
--maxw: 1120px;
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
scroll-behavior: smooth;
scroll-padding-top: 84px;
}
body {
font-family: var(--font);
background: var(--bg);
color: var(--ink);
-webkit-font-smoothing: antialiased;
line-height: 1.5;
overflow-x: hidden;
}
img,
svg {
display: block;
}
a {
color: inherit;
text-decoration: none;
}
::selection {
background: var(--coral-soft);
color: var(--teal-700);
}
.skip-link {
position: absolute;
left: -999px;
top: 8px;
z-index: 100;
background: var(--teal-d);
color: #fff;
padding: 10px 16px;
border-radius: var(--r-sm);
font-weight: 600;
}
.skip-link:focus {
left: 12px;
}
:focus-visible {
outline: 3px solid var(--coral);
outline-offset: 2px;
border-radius: 4px;
}
/* ── Buttons ── */
.btn {
--btn-bg: var(--white);
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
border: none;
border-radius: 999px;
padding: 11px 20px;
font: inherit;
font-weight: 600;
font-size: 0.92rem;
cursor: pointer;
white-space: nowrap;
transition: transform 0.12s ease, background 0.15s, border-color 0.15s,
box-shadow 0.15s, color 0.15s;
}
.btn:active {
transform: translateY(1px);
}
.btn-sm {
padding: 9px 16px;
font-size: 0.86rem;
}
.btn-lg {
padding: 14px 26px;
font-size: 1rem;
}
.btn-block {
width: 100%;
}
.btn-primary {
background: var(--teal-d);
color: #fff;
box-shadow: 0 8px 20px rgba(12, 122, 115, 0.22);
}
.btn-primary:hover {
background: var(--teal-700);
box-shadow: 0 12px 26px rgba(12, 122, 115, 0.3);
}
.btn-coral {
background: var(--coral);
color: #5a2419;
box-shadow: 0 10px 24px rgba(255, 122, 102, 0.4);
}
.btn-coral:hover {
background: var(--coral-d);
color: #fff;
}
.btn-ghost {
background: var(--white);
border: 1px solid var(--line-2);
color: var(--ink-2);
}
.btn-ghost:hover {
border-color: var(--teal);
color: var(--teal-d);
background: var(--teal-50);
}
.btn-onband {
background: rgba(255, 255, 255, 0.16);
color: #fff;
border: 1px solid rgba(255, 255, 255, 0.42);
}
.btn-onband:hover {
background: rgba(255, 255, 255, 0.26);
}
/* ── Sticky nav ── */
.nav {
position: sticky;
top: 0;
z-index: 40;
background: rgba(241, 247, 246, 0.78);
backdrop-filter: saturate(1.4) blur(12px);
border-bottom: 1px solid transparent;
transition: border-color 0.2s, background 0.2s, box-shadow 0.2s;
}
.nav.is-stuck {
border-color: var(--line);
background: rgba(255, 255, 255, 0.86);
box-shadow: 0 4px 18px rgba(16, 50, 47, 0.05);
}
.nav-inner {
max-width: var(--maxw);
margin: 0 auto;
padding: 14px 24px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 18px;
}
.brand {
display: inline-flex;
align-items: center;
gap: 10px;
font-weight: 800;
letter-spacing: -0.01em;
color: var(--ink);
}
.brand-mark {
display: inline-grid;
place-items: center;
width: 34px;
height: 34px;
border-radius: 11px;
background: linear-gradient(150deg, var(--teal), var(--teal-700));
color: #fff;
box-shadow: 0 6px 14px rgba(12, 122, 115, 0.32);
}
.brand-name {
display: inline-flex;
flex-direction: column;
line-height: 1.05;
font-size: 1.02rem;
}
.brand-dot {
font-size: 0.66rem;
font-weight: 600;
letter-spacing: 0.05em;
text-transform: uppercase;
color: var(--teal-d);
}
.brand-name.big {
font-size: 1.4rem;
}
.nav-links {
display: flex;
align-items: center;
gap: 6px;
margin-left: auto;
}
.nav-links a {
padding: 8px 14px;
border-radius: 999px;
font-weight: 600;
font-size: 0.92rem;
color: var(--ink-2);
transition: color 0.15s, background 0.15s;
}
.nav-links a:hover {
color: var(--teal-d);
background: var(--teal-50);
}
.nav-cta {
display: flex;
align-items: center;
gap: 10px;
}
.nav-toggle {
display: none;
flex-direction: column;
gap: 5px;
background: var(--white);
border: 1px solid var(--line-2);
border-radius: 10px;
padding: 10px 9px;
cursor: pointer;
}
.nav-toggle span {
width: 20px;
height: 2px;
border-radius: 2px;
background: var(--ink);
transition: transform 0.2s, opacity 0.2s;
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) {
transform: translateY(7px) rotate(45deg);
}
.nav-toggle[aria-expanded="true"] span:nth-child(2) {
opacity: 0;
}
.nav-toggle[aria-expanded="true"] span:nth-child(3) {
transform: translateY(-7px) rotate(-45deg);
}
/* ── Sections ── */
.section {
max-width: var(--maxw);
margin: 0 auto;
padding: 88px 24px;
}
.section-head {
max-width: 640px;
margin: 0 auto 44px;
text-align: center;
}
.kicker {
display: inline-block;
font-size: 0.78rem;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--coral-d);
margin-bottom: 12px;
}
.kicker.light {
color: #ffd9cf;
}
h1,
h2,
h3 {
letter-spacing: -0.02em;
}
.section-head h2 {
font-size: clamp(1.7rem, 3.6vw, 2.3rem);
font-weight: 800;
}
.section-sub {
margin-top: 12px;
color: var(--muted);
font-size: 1.04rem;
}
.grid {
display: grid;
gap: 18px;
}
/* ── Hero ── */
.hero {
position: relative;
max-width: var(--maxw);
margin: 0 auto;
padding: 56px 24px 72px;
overflow: hidden;
}
.blob {
position: absolute;
border-radius: 50%;
filter: blur(8px);
z-index: 0;
pointer-events: none;
}
.blob-a {
width: 460px;
height: 460px;
top: -140px;
right: -120px;
background: radial-gradient(circle at 30% 30%, rgba(255, 122, 102, 0.22), transparent 62%);
}
.blob-b {
width: 420px;
height: 420px;
bottom: -180px;
left: -120px;
background: radial-gradient(circle at 60% 40%, rgba(18, 156, 147, 0.18), transparent 64%);
}
.hero-grid {
position: relative;
z-index: 1;
display: grid;
grid-template-columns: 1.15fr 0.85fr;
gap: 48px;
align-items: center;
}
.hero-copy {
max-width: 560px;
}
.eyebrow {
display: inline-flex;
align-items: center;
gap: 9px;
background: var(--coral-soft);
color: var(--coral-d);
font-size: 0.82rem;
font-weight: 700;
padding: 7px 14px;
border-radius: 999px;
margin-bottom: 20px;
}
.eyebrow .dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--coral-d);
box-shadow: 0 0 0 0 rgba(240, 94, 72, 0.5);
animation: pulse 2.2s ease-out infinite;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(240, 94, 72, 0.5);
}
70% {
box-shadow: 0 0 0 8px rgba(240, 94, 72, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(240, 94, 72, 0);
}
}
.hero h1 {
font-size: clamp(2.2rem, 5.2vw, 3.4rem);
font-weight: 800;
line-height: 1.06;
}
.hl {
position: relative;
color: var(--teal-d);
white-space: nowrap;
}
.hl::after {
content: "";
position: absolute;
left: -2px;
right: -2px;
bottom: 0.06em;
height: 0.34em;
background: var(--coral-soft);
border-radius: 4px;
z-index: -1;
}
.lede {
margin-top: 20px;
font-size: 1.1rem;
color: var(--ink-2);
max-width: 50ch;
}
.hero-actions {
margin-top: 28px;
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.hero-pills {
margin-top: 26px;
display: flex;
flex-wrap: wrap;
gap: 10px 20px;
list-style: none;
}
.hero-pills li {
display: inline-flex;
align-items: center;
gap: 8px;
font-size: 0.9rem;
font-weight: 600;
color: var(--ink-2);
}
.hero-pills li span {
display: inline-grid;
place-items: center;
width: 20px;
height: 20px;
border-radius: 50%;
background: var(--teal-50);
color: var(--teal-d);
font-size: 0.72rem;
font-weight: 800;
}
/* Hero card */
.hero-card {
background: var(--white);
border: 1px solid var(--line);
border-radius: var(--r-xl);
padding: 24px;
box-shadow: var(--shadow-soft);
position: relative;
}
.hero-card::before {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
padding: 1px;
background: linear-gradient(150deg, rgba(255, 122, 102, 0.4), rgba(18, 156, 147, 0.32));
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
}
.hc-top {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
}
.hc-tag {
font-size: 0.78rem;
font-weight: 700;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--muted);
}
.hc-time {
margin: 14px 0 16px;
display: flex;
align-items: baseline;
gap: 10px;
}
.hc-num {
font-size: 2.6rem;
font-weight: 800;
color: var(--teal-d);
line-height: 1;
letter-spacing: -0.03em;
}
.hc-unit {
font-size: 0.92rem;
font-weight: 600;
color: var(--ink-2);
}
.hc-list {
list-style: none;
display: flex;
flex-direction: column;
gap: 2px;
margin-bottom: 18px;
}
.hc-list li {
display: flex;
align-items: center;
gap: 10px;
padding: 11px 12px;
border-radius: var(--r-sm);
font-size: 0.92rem;
transition: background 0.15s;
}
.hc-list li:hover {
background: var(--teal-50);
}
.hc-list li span:nth-of-type(1) {
flex: 1;
color: var(--ink-2);
font-weight: 500;
}
.hc-list li strong {
font-weight: 700;
color: var(--ink);
font-variant-numeric: tabular-nums;
}
.hc-dot {
width: 9px;
height: 9px;
border-radius: 50%;
flex-shrink: 0;
}
.hc-dot.teal {
background: var(--teal);
}
.hc-dot.coral {
background: var(--coral);
}
.hc-foot {
margin-top: 14px;
font-size: 0.82rem;
color: var(--muted);
text-align: center;
}
/* ── Badges ── */
.badge {
display: inline-flex;
align-items: center;
font-size: 0.74rem;
font-weight: 700;
padding: 4px 11px;
border-radius: 999px;
white-space: nowrap;
}
.badge.ok {
background: rgba(47, 158, 111, 0.14);
color: var(--ok);
}
.badge.warn {
background: rgba(217, 138, 43, 0.16);
color: var(--warn);
}
.badge.closed {
background: rgba(212, 80, 62, 0.14);
color: var(--danger);
}
/* ── Services grid ── */
.services-grid {
grid-template-columns: repeat(3, 1fr);
}
.svc {
background: var(--white);
border: 1px solid var(--line);
border-radius: var(--r-lg);
padding: 26px 24px;
box-shadow: var(--shadow-1);
transition: transform 0.18s ease, box-shadow 0.18s, border-color 0.18s;
outline-offset: 4px;
}
.svc:hover,
.svc:focus-visible {
transform: translateY(-4px);
box-shadow: var(--shadow-2);
border-color: rgba(18, 156, 147, 0.4);
}
.svc-icon {
display: inline-grid;
place-items: center;
width: 50px;
height: 50px;
border-radius: 15px;
margin-bottom: 16px;
}
.svc-icon.teal {
background: var(--teal-50);
color: var(--teal-d);
}
.svc-icon.coral {
background: var(--coral-soft);
color: var(--coral-d);
}
.svc h3 {
font-size: 1.16rem;
font-weight: 700;
}
.svc p {
margin-top: 8px;
color: var(--ink-2);
font-size: 0.95rem;
}
.svc-link {
display: inline-block;
margin-top: 14px;
font-size: 0.8rem;
font-weight: 700;
color: var(--teal-d);
letter-spacing: 0.01em;
}
/* ── Same-day band ── */
.band {
position: relative;
overflow: hidden;
background: linear-gradient(135deg, var(--teal-d), var(--teal-700) 70%, #084f4a);
color: #fff;
}
.band-blob {
position: absolute;
width: 520px;
height: 520px;
border-radius: 50%;
top: -200px;
right: -120px;
background: radial-gradient(circle, rgba(255, 122, 102, 0.32), transparent 60%);
pointer-events: none;
}
.band-inner {
position: relative;
max-width: var(--maxw);
margin: 0 auto;
padding: 72px 24px;
display: grid;
grid-template-columns: 1.25fr 0.75fr;
gap: 48px;
align-items: center;
}
.band-copy h2 {
font-size: clamp(1.7rem, 3.6vw, 2.4rem);
font-weight: 800;
margin-top: 6px;
}
.band-copy p {
margin-top: 14px;
color: rgba(255, 255, 255, 0.82);
font-size: 1.06rem;
max-width: 50ch;
}
.band-actions {
margin-top: 28px;
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.band-stats {
display: grid;
gap: 14px;
}
.band-stat {
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.18);
border-radius: var(--r-md);
padding: 16px 20px;
display: flex;
align-items: baseline;
gap: 12px;
}
.band-stat .stat-num {
font-size: 1.8rem;
font-weight: 800;
letter-spacing: -0.02em;
color: #fff;
font-variant-numeric: tabular-nums;
min-width: 78px;
}
.band-stat dd {
font-size: 0.92rem;
color: rgba(255, 255, 255, 0.78);
}
/* ── Doctors ── */
.doctors-grid {
grid-template-columns: repeat(4, 1fr);
}
.doc {
background: var(--white);
border: 1px solid var(--line);
border-radius: var(--r-lg);
padding: 24px 22px;
box-shadow: var(--shadow-1);
transition: transform 0.18s, box-shadow 0.18s;
}
.doc:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-2);
}
.doc-avatar {
display: grid;
place-items: center;
width: 56px;
height: 56px;
border-radius: 50%;
font-weight: 800;
font-size: 1.1rem;
color: #fff;
margin-bottom: 14px;
background: linear-gradient(150deg, var(--teal), var(--teal-700));
}
.doc-avatar.coral-av {
background: linear-gradient(150deg, var(--coral), var(--coral-d));
color: #5a2419;
}
.doc-avatar.warm-av {
background: linear-gradient(150deg, #f6b352, #e0892c);
}
.doc-avatar.teal-av {
background: linear-gradient(150deg, #2bbcae, var(--teal-d));
}
.doc h3 {
font-size: 1.06rem;
font-weight: 700;
}
.doc-spec {
margin-top: 3px;
font-size: 0.84rem;
font-weight: 600;
color: var(--teal-d);
}
.doc-bio {
margin: 10px 0 14px;
font-size: 0.9rem;
color: var(--ink-2);
}
/* ── Hours + location ── */
.visit-grid {
display: grid;
grid-template-columns: 1fr 1.1fr;
gap: 22px;
}
.visit-card,
.map-card {
background: var(--white);
border: 1px solid var(--line);
border-radius: var(--r-lg);
box-shadow: var(--shadow-1);
}
.visit-card {
padding: 32px;
}
.visit-card h2 {
font-size: 1.5rem;
font-weight: 800;
margin-top: 6px;
}
.hours {
list-style: none;
margin: 20px 0 0;
border-top: 1px solid var(--line);
}
.hours li {
display: flex;
justify-content: space-between;
gap: 12px;
padding: 12px 4px;
border-bottom: 1px solid var(--line);
font-size: 0.95rem;
}
.hours li span:first-child {
font-weight: 600;
color: var(--ink-2);
}
.hours li span:last-child {
color: var(--ink);
font-variant-numeric: tabular-nums;
}
.hours li.is-today {
background: var(--teal-50);
border-radius: var(--r-sm);
padding-left: 12px;
padding-right: 12px;
margin: 0 -8px;
border-bottom-color: transparent;
}
.hours li.is-today span:first-child {
color: var(--teal-700);
}
.hours .closed {
color: var(--danger);
font-weight: 600;
}
.visit-note {
margin-top: 18px;
font-size: 0.92rem;
font-weight: 600;
color: var(--ink-2);
display: inline-flex;
align-items: center;
gap: 8px;
background: var(--teal-50);
border-radius: 999px;
padding: 9px 16px;
}
.visit-note.is-closed {
background: var(--coral-soft);
color: var(--coral-d);
}
.map-card {
display: flex;
flex-direction: column;
overflow: hidden;
}
.map-art {
position: relative;
height: 220px;
background: linear-gradient(160deg, #d6ece8, #c7e3df 60%, #e3f3f0);
overflow: hidden;
}
.map-road {
position: absolute;
background: rgba(255, 255, 255, 0.85);
}
.map-road.r1 {
height: 14px;
left: 0;
right: 0;
top: 58%;
transform: rotate(-4deg);
}
.map-road.r2 {
width: 14px;
top: 0;
bottom: 0;
left: 38%;
}
.map-block {
position: absolute;
border-radius: 6px;
background: rgba(18, 156, 147, 0.16);
}
.map-block.b1 {
width: 64px;
height: 48px;
left: 12%;
top: 18%;
}
.map-block.b2 {
width: 80px;
height: 60px;
right: 14%;
top: 14%;
background: rgba(255, 122, 102, 0.18);
}
.map-block.b3 {
width: 70px;
height: 50px;
right: 22%;
bottom: 12%;
}
.map-pin {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -100%);
color: var(--coral-d);
filter: drop-shadow(0 6px 8px rgba(16, 50, 47, 0.25));
animation: bob 2.4s ease-in-out infinite;
}
@keyframes bob {
0%,
100% {
transform: translate(-50%, -100%);
}
50% {
transform: translate(-50%, -116%);
}
}
.map-info {
padding: 22px 24px 24px;
}
.map-info h3 {
font-size: 1.12rem;
font-weight: 700;
}
.map-info p {
margin-top: 6px;
color: var(--ink-2);
font-size: 0.95rem;
}
.map-actions {
margin-top: 16px;
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.map-fine {
margin-top: 16px;
font-size: 0.82rem;
color: var(--muted);
}
/* ── Book CTA ── */
.book {
padding-top: 24px;
}
.book-card {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0;
background: var(--white);
border: 1px solid var(--line);
border-radius: var(--r-xl);
overflow: hidden;
box-shadow: var(--shadow-soft);
}
.book-copy {
padding: 44px;
background: linear-gradient(155deg, var(--teal-50), #dff1ee);
}
.book-copy h2 {
font-size: 1.7rem;
font-weight: 800;
margin-top: 6px;
}
.book-copy p {
margin-top: 12px;
color: var(--ink-2);
}
.book-points {
margin-top: 22px;
list-style: none;
display: flex;
flex-direction: column;
gap: 10px;
}
.book-points li {
display: flex;
align-items: center;
gap: 10px;
font-size: 0.94rem;
font-weight: 600;
color: var(--ink-2);
}
.book-points li span {
display: inline-grid;
place-items: center;
width: 22px;
height: 22px;
border-radius: 50%;
background: var(--teal-d);
color: #fff;
font-size: 0.74rem;
font-weight: 800;
}
.book-form {
padding: 44px;
display: flex;
flex-direction: column;
gap: 16px;
}
.field {
display: flex;
flex-direction: column;
gap: 7px;
}
.field > span {
font-size: 0.86rem;
font-weight: 600;
color: var(--ink-2);
}
.field-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
}
.field input,
.field select {
font: inherit;
font-size: 0.95rem;
padding: 12px 14px;
border: 1px solid var(--line-2);
border-radius: var(--r-sm);
background: var(--white);
color: var(--ink);
transition: border-color 0.15s, box-shadow 0.15s;
}
.field input:focus,
.field select:focus {
outline: none;
border-color: var(--teal);
box-shadow: 0 0 0 3px rgba(18, 156, 147, 0.16);
}
.field input.invalid {
border-color: var(--danger);
box-shadow: 0 0 0 3px rgba(212, 80, 62, 0.14);
}
.book-fine {
font-size: 0.8rem;
color: var(--muted);
text-align: center;
}
/* ── Footer ── */
.footer {
background: var(--ink);
color: rgba(255, 255, 255, 0.78);
margin-top: 40px;
}
.footer-grid {
max-width: var(--maxw);
margin: 0 auto;
padding: 56px 24px 36px;
display: grid;
grid-template-columns: 1.5fr 1fr 1fr;
gap: 36px;
}
.foot-brand .brand-name {
color: #fff;
margin-bottom: 12px;
}
.foot-brand .brand-dot {
color: var(--coral);
}
.foot-brand p {
font-size: 0.95rem;
max-width: 36ch;
}
.foot-col h4 {
color: #fff;
font-size: 0.86rem;
letter-spacing: 0.06em;
text-transform: uppercase;
margin-bottom: 14px;
}
.foot-col ul {
list-style: none;
display: flex;
flex-direction: column;
gap: 10px;
font-size: 0.94rem;
}
.foot-col li span {
display: inline-block;
min-width: 78px;
color: rgba(255, 255, 255, 0.6);
}
.foot-col a:hover {
color: var(--coral);
}
.footer-bar {
border-top: 1px solid rgba(255, 255, 255, 0.12);
max-width: var(--maxw);
margin: 0 auto;
padding: 20px 24px;
display: flex;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
font-size: 0.85rem;
}
.footer-bar a:hover {
color: var(--coral);
}
/* ── Toast ── */
.toast {
position: fixed;
left: 50%;
bottom: 26px;
transform: translateX(-50%) translateY(12px);
background: var(--ink);
color: #fff;
padding: 13px 22px;
border-radius: 999px;
font-size: 0.92rem;
font-weight: 600;
box-shadow: var(--shadow-2);
z-index: 60;
max-width: 90vw;
opacity: 0;
transition: opacity 0.22s ease, transform 0.22s ease;
}
.toast:not([hidden]) {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
.toast .toast-mark {
color: var(--coral);
margin-right: 6px;
}
/* ── Reveal on scroll ── */
.reveal {
opacity: 0;
transform: translateY(18px);
transition: opacity 0.55s ease, transform 0.55s ease;
}
.reveal.is-in {
opacity: 1;
transform: none;
}
/* ── Responsive ── */
@media (max-width: 940px) {
.hero-grid,
.band-inner,
.visit-grid,
.book-card {
grid-template-columns: 1fr;
}
.hero-card {
max-width: 460px;
}
.services-grid {
grid-template-columns: repeat(2, 1fr);
}
.doctors-grid {
grid-template-columns: repeat(2, 1fr);
}
.book-copy {
padding: 36px;
}
}
@media (max-width: 520px) {
.nav-links {
position: absolute;
top: calc(100% + 8px);
right: 16px;
left: 16px;
flex-direction: column;
align-items: stretch;
gap: 2px;
background: var(--white);
border: 1px solid var(--line);
border-radius: var(--r-md);
padding: 8px;
box-shadow: var(--shadow-soft);
opacity: 0;
transform: translateY(-8px);
pointer-events: none;
transition: opacity 0.2s, transform 0.2s;
}
.nav-links.is-open {
opacity: 1;
transform: none;
pointer-events: auto;
}
.nav-links a {
padding: 12px 14px;
}
.nav-toggle {
display: flex;
}
.nav-cta .btn-primary {
display: none;
}
.section {
padding: 60px 18px;
}
.hero {
padding: 36px 18px 56px;
}
.hero-actions {
flex-direction: column;
align-items: stretch;
}
.hero-actions .btn {
width: 100%;
}
.services-grid,
.doctors-grid {
grid-template-columns: 1fr;
}
.band-inner {
padding: 56px 18px;
}
.band-actions {
flex-direction: column;
align-items: stretch;
}
.visit-card,
.book-copy,
.book-form {
padding: 28px 22px;
}
.field-row {
grid-template-columns: 1fr;
}
.footer-grid {
grid-template-columns: 1fr;
gap: 28px;
}
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
scroll-behavior: auto !important;
}
.reveal {
opacity: 1;
transform: none;
}
}(function () {
"use strict";
/* ── Toast helper ── */
var toastEl = document.getElementById("toast");
var toastTimer = null;
function toast(msg) {
if (!toastEl) return;
toastEl.innerHTML = '<span class="toast-mark" aria-hidden="true">✓</span>' + msg;
toastEl.hidden = false;
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.hidden = true;
}, 3000);
}
/* ── Sticky nav shadow ── */
var nav = document.getElementById("nav");
function onScroll() {
if (!nav) return;
nav.classList.toggle("is-stuck", window.scrollY > 8);
}
window.addEventListener("scroll", onScroll, { passive: true });
onScroll();
/* ── Mobile nav toggle ── */
var navToggle = document.getElementById("navToggle");
var navLinks = document.getElementById("navLinks");
function closeNav() {
if (!navToggle || !navLinks) return;
navLinks.classList.remove("is-open");
navToggle.setAttribute("aria-expanded", "false");
navToggle.setAttribute("aria-label", "Open menu");
}
if (navToggle && navLinks) {
navToggle.addEventListener("click", function () {
var open = navLinks.classList.toggle("is-open");
navToggle.setAttribute("aria-expanded", open ? "true" : "false");
navToggle.setAttribute("aria-label", open ? "Close menu" : "Open menu");
});
navLinks.addEventListener("click", function (e) {
if (e.target.closest("a")) closeNav();
});
document.addEventListener("keydown", function (e) {
if (e.key === "Escape") closeNav();
});
}
/* ── Smooth-scroll for in-page links + close mobile nav ── */
document.querySelectorAll('a[data-link][href^="#"]').forEach(function (a) {
a.addEventListener("click", function (e) {
var id = a.getAttribute("href");
if (id.length < 2) return;
var target = document.querySelector(id);
if (!target) return;
e.preventDefault();
closeNav();
target.scrollIntoView({ behavior: "smooth", block: "start" });
});
});
/* ── Reveal on scroll ── */
var reveals = document.querySelectorAll(".reveal");
if ("IntersectionObserver" in window) {
var io = new IntersectionObserver(
function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
entry.target.classList.add("is-in");
io.unobserve(entry.target);
}
});
},
{ threshold: 0.12, rootMargin: "0px 0px -40px 0px" }
);
reveals.forEach(function (el) {
io.observe(el);
});
} else {
reveals.forEach(function (el) {
el.classList.add("is-in");
});
}
/* ── Animated count-up stats ── */
function animateCount(el) {
var target = parseFloat(el.getAttribute("data-count")) || 0;
var decimals = parseInt(el.getAttribute("data-decimals") || "0", 10);
var suffix = el.getAttribute("data-suffix") || "";
var start = performance.now();
var dur = 1200;
function step(now) {
var p = Math.min((now - start) / dur, 1);
var eased = 1 - Math.pow(1 - p, 3);
var val = target * eased;
el.textContent = val.toFixed(decimals) + suffix;
if (p < 1) requestAnimationFrame(step);
else el.textContent = target.toFixed(decimals) + suffix;
}
requestAnimationFrame(step);
}
var counters = document.querySelectorAll(".stat-num[data-count]");
if ("IntersectionObserver" in window) {
var cio = new IntersectionObserver(
function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
animateCount(entry.target);
cio.unobserve(entry.target);
}
});
},
{ threshold: 0.6 }
);
counters.forEach(function (el) {
cio.observe(el);
});
} else {
counters.forEach(animateCount);
}
/* ── Live same-day slot counter ── */
var slotCount = document.getElementById("slotCount");
var slotsLeft = slotCount ? parseInt(slotCount.textContent, 10) || 6 : 6;
var grabBtn = document.getElementById("grabSlot");
if (grabBtn && slotCount) {
grabBtn.addEventListener("click", function () {
if (slotsLeft <= 0) {
toast("Today is fully booked — try a next-day slot.");
return;
}
slotsLeft -= 1;
slotCount.textContent = String(slotsLeft);
// mark the matching band stat as live so it mirrors the count
var bandStat = document.querySelector('.band-stat .stat-num[data-count="6"]');
if (bandStat) {
bandStat.dataset.live = "1";
bandStat.textContent = String(slotsLeft);
}
var openBadge = document.getElementById("openBadge");
if (slotsLeft === 0 && openBadge) {
openBadge.textContent = "Fully booked";
openBadge.classList.remove("ok");
openBadge.classList.add("warn");
grabBtn.disabled = true;
grabBtn.style.opacity = "0.6";
grabBtn.style.cursor = "default";
}
toast("Slot reserved — " + slotsLeft + " left today. We'll text to confirm.");
});
}
/* ── Check availability button ── */
var checkBtn = document.getElementById("checkAvail");
if (checkBtn) {
checkBtn.addEventListener("click", function () {
if (slotsLeft > 0) {
toast(slotsLeft + " same-day slots open right now — earliest 9:20 AM.");
} else {
toast("Same-day is full today, but next-day looks wide open.");
}
// gently nudge attention to the hero card's count
if (slotCount && slotCount.animate) {
slotCount.animate(
[
{ transform: "scale(1)" },
{ transform: "scale(1.18)" },
{ transform: "scale(1)" }
],
{ duration: 420, easing: "ease-out" }
);
}
});
}
/* ── Today's hours highlight ── */
var hoursList = document.getElementById("hoursList");
var todayNote = document.getElementById("todayNote");
if (hoursList && todayNote) {
var now = new Date();
var day = now.getDay(); // 0 = Sun
var li = hoursList.querySelector('li[data-day="' + day + '"]');
if (li) li.classList.add("is-today");
// open ranges per weekday: [openHour, closeHour] or null when closed
var ranges = {
0: null,
1: [8, 19],
2: [8, 19],
3: [8, 19],
4: [8, 19],
5: [8, 18],
6: [9, 14]
};
var r = ranges[day];
var hour = now.getHours() + now.getMinutes() / 60;
if (!r) {
todayNote.textContent = "Closed today — open again Monday at 8:00 AM.";
todayNote.classList.add("is-closed");
} else if (hour < r[0]) {
todayNote.textContent = "Opening soon — front desk at " + fmtHour(r[0]) + " today.";
} else if (hour >= r[1]) {
todayNote.textContent = "Closed for the day — back tomorrow morning.";
todayNote.classList.add("is-closed");
} else {
todayNote.textContent = "Open now until " + fmtHour(r[1]) + " — walk-ins welcome.";
}
}
function fmtHour(h) {
var ampm = h >= 12 ? "PM" : "AM";
var hr = h % 12 || 12;
return hr + ":00 " + ampm;
}
/* ── Directions button (illustrative) ── */
var directionsBtn = document.getElementById("directionsBtn");
if (directionsBtn) {
directionsBtn.addEventListener("click", function (e) {
// it's a #book anchor; let the smooth-scroll run but also confirm
toast("412 Maple Grove Rd — about 6 min from Cedar Hollow center.");
});
}
/* ── Booking form ── */
var form = document.getElementById("bookForm");
if (form) {
form.addEventListener("submit", function (e) {
e.preventDefault();
var nameInput = form.querySelector('input[name="name"]');
var name = (nameInput.value || "").trim();
if (name.length < 2) {
nameInput.classList.add("invalid");
nameInput.focus();
toast("Please add a name so we know who's coming in.");
return;
}
nameInput.classList.remove("invalid");
var reason = form.querySelector('select[name="reason"]').value;
var first = name.split(" ")[0];
toast("Thanks, " + first + " — we'll text to confirm your " + reason + " visit.");
form.reset();
});
form.querySelector('input[name="name"]').addEventListener("input", function (e) {
if (e.target.value.trim().length >= 2) e.target.classList.remove("invalid");
});
}
/* ── Phone call button feedback ── */
var callBtn = document.getElementById("callBtn");
if (callBtn) {
callBtn.addEventListener("click", function () {
toast("Calling the front desk — Mon–Fri 8 AM to 7 PM.");
});
}
})();<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap"
/>
<link rel="stylesheet" href="style.css" />
<title>Family Practice · Maple Grove Family Clinic</title>
</head>
<body>
<a class="skip-link" href="#hero">Skip to content</a>
<!-- ── Sticky nav ── -->
<header class="nav" id="nav">
<div class="nav-inner">
<a class="brand" href="#hero" aria-label="Maple Grove Family Clinic home">
<span class="brand-mark" aria-hidden="true">
<svg viewBox="0 0 24 24" width="20" height="20" fill="none">
<path
d="M12 21s-7-4.35-7-10a4 4 0 0 1 7-2.65A4 4 0 0 1 19 11c0 5.65-7 10-7 10Z"
fill="currentColor"
/>
<path d="M12 8v6M9 11h6" stroke="#fff" stroke-width="1.7" stroke-linecap="round" />
</svg>
</span>
<span class="brand-name">Maple Grove<span class="brand-dot">Family Clinic</span></span>
</a>
<nav class="nav-links" id="navLinks" aria-label="Primary">
<a href="#services" data-link>Services</a>
<a href="#same-day" data-link>Same-day care</a>
<a href="#team" data-link>Our team</a>
<a href="#visit" data-link>Hours & location</a>
</nav>
<div class="nav-cta">
<a class="btn btn-primary btn-sm" href="#book" data-link>Book a visit</a>
<button
class="nav-toggle"
id="navToggle"
aria-label="Open menu"
aria-expanded="false"
aria-controls="navLinks"
>
<span></span><span></span><span></span>
</button>
</div>
</div>
</header>
<main>
<!-- ── Hero ── -->
<section class="hero" id="hero">
<span class="blob blob-a" aria-hidden="true"></span>
<span class="blob blob-b" aria-hidden="true"></span>
<div class="hero-grid">
<div class="hero-copy reveal">
<span class="eyebrow">
<span class="dot" aria-hidden="true"></span> Welcoming new families this month
</span>
<h1>
Care for the <span class="hl">whole family</span>, from first steps to golden years.
</h1>
<p class="lede">
Maple Grove is your neighborhood family practice — same-day sick visits, gentle care
for the little ones, and a team that remembers your name. No rush, no fuss, just good
medicine close to home.
</p>
<div class="hero-actions">
<a class="btn btn-primary btn-lg" href="#book" data-link>Book a visit</a>
<a class="btn btn-ghost btn-lg" href="tel:+15550172204" id="callBtn">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" aria-hidden="true">
<path
d="M5 4h3l1.5 4-2 1.5a12 12 0 0 0 5 5l1.5-2 4 1.5V18a2 2 0 0 1-2 2A15 15 0 0 1 4 6a2 2 0 0 1 2-2Z"
stroke="currentColor"
stroke-width="1.6"
stroke-linejoin="round"
/>
</svg>
(555) 017-2204
</a>
</div>
<ul class="hero-pills" aria-label="What to expect">
<li><span aria-hidden="true">✓</span> Most insurance accepted</li>
<li><span aria-hidden="true">✓</span> Walk-ins welcome</li>
<li><span aria-hidden="true">✓</span> Evening & Saturday hours</li>
</ul>
</div>
<aside class="hero-card reveal" aria-label="Same-day availability">
<div class="hc-top">
<span class="hc-tag">Today at Maple Grove</span>
<span class="badge ok" id="openBadge">Open now</span>
</div>
<p class="hc-time">
<span class="hc-num" id="slotCount">6</span>
<span class="hc-unit">same-day slots left</span>
</p>
<ul class="hc-list">
<li>
<span class="hc-dot teal" aria-hidden="true"></span>
<span>Family medicine</span>
<strong>9:20 AM</strong>
</li>
<li>
<span class="hc-dot coral" aria-hidden="true"></span>
<span>Pediatrics</span>
<strong>11:00 AM</strong>
</li>
<li>
<span class="hc-dot teal" aria-hidden="true"></span>
<span>Women's health</span>
<strong>2:40 PM</strong>
</li>
</ul>
<button class="btn btn-primary btn-block" id="grabSlot" type="button">
Grab a same-day slot
</button>
<p class="hc-foot">Dr. Lena Okafor & team · 412 Maple Grove Rd</p>
</aside>
</div>
</section>
<!-- ── Services ── -->
<section class="section" id="services">
<header class="section-head reveal">
<span class="kicker">For every age & stage</span>
<h2>Everything your family needs, under one roof</h2>
<p class="section-sub">
One familiar team for check-ups, sniffles, chronic conditions and the milestones in
between.
</p>
</header>
<div class="grid services-grid">
<article class="svc reveal" tabindex="0">
<span class="svc-icon teal" aria-hidden="true">
<svg viewBox="0 0 24 24" width="22" height="22" fill="none">
<path d="M9 3v5a3 3 0 0 0 6 0V3M6 13a6 6 0 0 0 12 0M9 19h6" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="12" cy="19" r="2" stroke="currentColor" stroke-width="1.7"/>
</svg>
</span>
<h3>Family medicine</h3>
<p>Annual physicals, screenings and everyday concerns with a doctor who knows your story.</p>
<span class="svc-link">Most popular</span>
</article>
<article class="svc reveal" tabindex="0">
<span class="svc-icon coral" aria-hidden="true">
<svg viewBox="0 0 24 24" width="22" height="22" fill="none">
<path d="M12 21s-6-3.7-6-9a4 4 0 0 1 6-3.46A4 4 0 0 1 18 12c0 5.3-6 9-6 9Z" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/>
<circle cx="9.5" cy="9.5" r=".9" fill="currentColor"/>
<circle cx="14.5" cy="9.5" r=".9" fill="currentColor"/>
</svg>
</span>
<h3>Pediatrics</h3>
<p>Gentle, reassuring visits for newborns through teens — well-checks, growth and worries big or small.</p>
<span class="svc-link">Newborn to 18</span>
</article>
<article class="svc reveal" tabindex="0">
<span class="svc-icon teal" aria-hidden="true">
<svg viewBox="0 0 24 24" width="22" height="22" fill="none">
<circle cx="12" cy="8" r="4.2" stroke="currentColor" stroke-width="1.7"/>
<path d="M12 12.5v7M9 16h6" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/>
</svg>
</span>
<h3>Women's health</h3>
<p>Wellness exams, family planning and supportive care at every life stage, on your terms.</p>
<span class="svc-link">Private & unhurried</span>
</article>
<article class="svc reveal" tabindex="0">
<span class="svc-icon coral" aria-hidden="true">
<svg viewBox="0 0 24 24" width="22" height="22" fill="none">
<path d="M4 18a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/>
<path d="M6 18V8a6 6 0 0 1 12 0v10" stroke="currentColor" stroke-width="1.7"/>
<path d="M9 11h6M9 14h6" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/>
</svg>
</span>
<h3>Chronic care</h3>
<p>Steady, coordinated management of diabetes, blood pressure and asthma — with check-ins that fit your week.</p>
<span class="svc-link">Ongoing support</span>
</article>
<article class="svc reveal" tabindex="0">
<span class="svc-icon teal" aria-hidden="true">
<svg viewBox="0 0 24 24" width="22" height="22" fill="none">
<rect x="8" y="3" width="8" height="5" rx="1.5" stroke="currentColor" stroke-width="1.7"/>
<path d="M9 8 7 14a4 4 0 0 0 4 6h2a4 4 0 0 0 4-6l-2-6" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/>
<path d="M12 13v3M10.5 14.5h3" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/>
</svg>
</span>
<h3>Vaccines & travel</h3>
<p>Flu shots, childhood immunizations and travel boosters — quick, gentle and on schedule.</p>
<span class="svc-link">Walk-ins welcome</span>
</article>
<article class="svc reveal" tabindex="0">
<span class="svc-icon coral" aria-hidden="true">
<svg viewBox="0 0 24 24" width="22" height="22" fill="none">
<path d="M21 15a2 2 0 0 1-2 2H8l-4 4V6a2 2 0 0 1 2-2h13a2 2 0 0 1 2 2Z" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/>
<path d="M8.5 10h7M8.5 13h4" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/>
</svg>
</span>
<h3>Video visits</h3>
<p>For follow-ups, refills and quick questions — care from your couch when coming in isn't easy.</p>
<span class="svc-link">From home</span>
</article>
</div>
</section>
<!-- ── Same-day feature band ── -->
<section class="band" id="same-day">
<span class="band-blob" aria-hidden="true"></span>
<div class="band-inner reveal">
<div class="band-copy">
<span class="kicker light">Feeling unwell today?</span>
<h2>Same-day appointments, every weekday</h2>
<p>
Fevers, sore throats and earaches don't wait for next week. Reserve your spot in the
morning and we'll usually have you seen the same day — in person or by video.
</p>
<div class="band-actions">
<a class="btn btn-coral btn-lg" href="#book" data-link>Reserve a same-day slot</a>
<button class="btn btn-onband btn-lg" id="checkAvail" type="button">
Check today's availability
</button>
</div>
</div>
<dl class="band-stats" aria-label="Same-day care highlights">
<div class="band-stat">
<dt class="stat-num" data-count="6" data-suffix="">0</dt>
<dd>open slots left today</dd>
</div>
<div class="band-stat">
<dt class="stat-num" data-count="22" data-suffix=" min">0</dt>
<dd>average wait time</dd>
</div>
<div class="band-stat">
<dt class="stat-num" data-count="98" data-suffix="%">0</dt>
<dd>seen the same day</dd>
</div>
</dl>
</div>
</section>
<!-- ── Doctors strip ── -->
<section class="section" id="team">
<header class="section-head reveal">
<span class="kicker">Familiar faces</span>
<h2>The team your family will get to know</h2>
<p class="section-sub">Friendly, board-certified and accepting new patients this month.</p>
</header>
<div class="grid doctors-grid">
<article class="doc reveal">
<span class="doc-avatar" data-initials="LO" aria-hidden="true">LO</span>
<h3>Dr. Lena Okafor</h3>
<p class="doc-spec">Family medicine · Lead physician</p>
<p class="doc-bio">Believes the best medicine starts with an unhurried conversation.</p>
<span class="badge ok">Accepting patients</span>
</article>
<article class="doc reveal">
<span class="doc-avatar coral-av" data-initials="RP" aria-hidden="true">RP</span>
<h3>Dr. Ravi Patel</h3>
<p class="doc-spec">Pediatrics</p>
<p class="doc-bio">Turns nervous check-ups into the easy part of a parent's week.</p>
<span class="badge ok">Accepting patients</span>
</article>
<article class="doc reveal">
<span class="doc-avatar warm-av" data-initials="MB" aria-hidden="true">MB</span>
<h3>Dr. Maya Bloom</h3>
<p class="doc-spec">Women's health</p>
<p class="doc-bio">Creates a calm, private space for the questions that matter.</p>
<span class="badge ok">Accepting patients</span>
</article>
<article class="doc reveal">
<span class="doc-avatar teal-av" data-initials="TS" aria-hidden="true">TS</span>
<h3>Theo Sandoval, NP</h3>
<p class="doc-spec">Chronic care & same-day</p>
<p class="doc-bio">Keeps long-term conditions steady with practical, kind plans.</p>
<span class="badge warn">A few slots left</span>
</article>
</div>
</section>
<!-- ── Hours + location ── -->
<section class="section" id="visit">
<div class="visit-grid">
<div class="visit-card reveal">
<span class="kicker">Stop by</span>
<h2>Open early, late & on Saturdays</h2>
<ul class="hours" id="hoursList">
<li data-day="0"><span>Sunday</span><span class="closed">Closed</span></li>
<li data-day="1"><span>Monday</span><span>8:00 AM – 7:00 PM</span></li>
<li data-day="2"><span>Tuesday</span><span>8:00 AM – 7:00 PM</span></li>
<li data-day="3"><span>Wednesday</span><span>8:00 AM – 7:00 PM</span></li>
<li data-day="4"><span>Thursday</span><span>8:00 AM – 7:00 PM</span></li>
<li data-day="5"><span>Friday</span><span>8:00 AM – 6:00 PM</span></li>
<li data-day="6"><span>Saturday</span><span>9:00 AM – 2:00 PM</span></li>
</ul>
<p class="visit-note" id="todayNote">Checking today's hours…</p>
</div>
<div class="map-card reveal" aria-label="Clinic location">
<div class="map-art" aria-hidden="true">
<span class="map-road r1"></span>
<span class="map-road r2"></span>
<span class="map-block b1"></span>
<span class="map-block b2"></span>
<span class="map-block b3"></span>
<span class="map-pin">
<svg viewBox="0 0 24 24" width="24" height="24" fill="none">
<path d="M12 22s7-6.2 7-12a7 7 0 1 0-14 0c0 5.8 7 12 7 12Z" fill="currentColor"/>
<circle cx="12" cy="10" r="2.6" fill="#fff"/>
</svg>
</span>
</div>
<div class="map-info">
<h3>Maple Grove Family Clinic</h3>
<p>412 Maple Grove Rd, Suite 2<br />Cedar Hollow, OR 97000</p>
<div class="map-actions">
<a class="btn btn-primary btn-sm" href="#book" data-link id="directionsBtn">
Get directions
</a>
<a class="btn btn-ghost btn-sm" href="tel:+15550172204">Call front desk</a>
</div>
<p class="map-fine">Free parking · Wheelchair accessible · On the No. 9 bus line</p>
</div>
</div>
</div>
</section>
<!-- ── Book CTA ── -->
<section class="section book" id="book">
<div class="book-card reveal">
<div class="book-copy">
<span class="kicker">Let's get you in</span>
<h2>Booking takes about a minute</h2>
<p>
Tell us who's coming in and what's going on. We'll confirm by text and send everything
you need before your visit.
</p>
<ul class="book-points">
<li><span aria-hidden="true">✓</span> Same-day & next-day slots</li>
<li><span aria-hidden="true">✓</span> In person or by video</li>
<li><span aria-hidden="true">✓</span> Easy text reminders</li>
</ul>
</div>
<form class="book-form" id="bookForm" novalidate>
<label class="field">
<span>Full name</span>
<input type="text" name="name" placeholder="Alex Morgan" autocomplete="name" required />
</label>
<div class="field-row">
<label class="field">
<span>Who's the visit for?</span>
<select name="who">
<option>Myself</option>
<option>My child</option>
<option>A family member</option>
</select>
</label>
<label class="field">
<span>Reason for visit</span>
<select name="reason">
<option>Family medicine</option>
<option>Pediatrics</option>
<option>Women's health</option>
<option>Chronic care</option>
<option>Vaccines & travel</option>
<option>Video visit</option>
</select>
</label>
</div>
<button class="btn btn-primary btn-block btn-lg" type="submit">Request appointment</button>
<p class="book-fine">Illustrative form — no data is sent anywhere.</p>
</form>
</div>
</section>
</main>
<!-- ── Footer ── -->
<footer class="footer" id="contact">
<div class="footer-grid">
<div class="foot-brand">
<span class="brand-name big">Maple Grove<span class="brand-dot">Family Clinic</span></span>
<p>Warm, attentive care for your whole family — in person or online, close to home.</p>
</div>
<div class="foot-col">
<h4>Visit</h4>
<ul>
<li>412 Maple Grove Rd, Suite 2</li>
<li>Cedar Hollow, OR 97000</li>
<li><span>Mon – Fri</span> 8:00 AM – 7:00 PM</li>
<li><span>Saturday</span> 9:00 AM – 2:00 PM</li>
</ul>
</div>
<div class="foot-col">
<h4>Get in touch</h4>
<ul>
<li><a href="tel:+15550172204">(555) 017-2204</a></li>
<li><a href="mailto:[email protected]">[email protected]</a></li>
<li>Nurse line: evenings & weekends</li>
</ul>
</div>
</div>
<div class="footer-bar">
<span>© 2026 Maple Grove Family Clinic — a fictional practice.</span>
<a href="#hero" data-link>Back to top ↑</a>
</div>
</footer>
<div class="toast" id="toast" hidden role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>General Practice Landing
A friendly, neighborhood-clinic landing page for Maple Grove Family Clinic, built around the calm teal palette with warmer coral accents to set it apart from the more clinical default. A sticky nav fades in a subtle shadow as you scroll and collapses into a tidy menu on small screens. The hero pairs a reassuring Care for the whole family headline with a live availability card that tracks same-day slots — grabbing one decrements the count, ripples the booking stat, and flips the badge to Fully booked when the day fills up.
Below, a six-tile services grid covers family medicine, pediatrics, women’s health, chronic care, vaccines and video visits, each with a soft hover lift. A teal same-day appointments feature band counts its stats up as it enters view, a four-person doctors strip introduces the team, and a hours-and-location section highlights the current weekday, computes whether the clinic is open right now, and offers directions and a call CTA beside a stylized map. A short booking form validates the name field and confirms with a toast. Everything is vanilla JS — reveal-on-scroll, count-ups, the live slot counter and the mobile nav all run without a single dependency.
Illustrative UI only — not intended for real medical use.