Vet — Emergency Info
An emergency-info panel for a veterinary practice with a prominent call-now banner and phone CTA, a live open or closed indicator driven by mocked weekly hours, an animal poison-control number, a numbered what-to-do quick list, and a nearest emergency hospital address card with directions.
MCP
Code
:root {
--teal: #179c8e;
--teal-d: #0f7f73;
--teal-50: #e6f5f2;
--coral: #ff8a5c;
--ink: #173a36;
--muted: #6b827e;
--bg: #f2f8f6;
--white: #ffffff;
--green: #1f9d6b;
--red: #d9534f;
--radius: 22px;
--radius-sm: 14px;
--shadow: 0 18px 40px -22px rgba(15, 127, 115, 0.45);
--ring: 0 0 0 3px rgba(23, 156, 142, 0.35);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: "Inter", system-ui, -apple-system, sans-serif;
background: var(--bg);
color: var(--ink);
-webkit-font-smoothing: antialiased;
line-height: 1.5;
}
.wrap {
max-width: 720px;
margin: 0 auto;
padding: 32px 20px 56px;
}
.emergency {
background: var(--white);
border-radius: var(--radius);
padding: 22px;
box-shadow: var(--shadow);
display: flex;
flex-direction: column;
gap: 18px;
}
/* Header */
.emergency__top {
display: flex;
align-items: center;
gap: 14px;
}
.paw {
font-size: 28px;
background: var(--teal-50);
border-radius: 16px;
width: 52px;
height: 52px;
display: grid;
place-items: center;
flex-shrink: 0;
}
.kicker {
margin: 0;
font-size: 12px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--teal-d);
}
h1 {
margin: 2px 0 0;
font-size: 21px;
font-weight: 800;
letter-spacing: -0.01em;
}
.status {
margin-left: auto;
display: inline-flex;
align-items: center;
gap: 7px;
padding: 7px 13px;
border-radius: 999px;
font-size: 12.5px;
font-weight: 700;
white-space: nowrap;
}
.status__dot {
width: 9px;
height: 9px;
border-radius: 50%;
background: currentColor;
box-shadow: 0 0 0 4px color-mix(in srgb, currentColor 22%, transparent);
}
.status[data-state="open"] {
background: #e7f6ee;
color: var(--green);
}
.status[data-state="closed"] {
background: #fdeceb;
color: var(--red);
}
.status[data-state="loading"] {
background: var(--teal-50);
color: var(--teal-d);
}
/* Banner */
.banner {
background: linear-gradient(135deg, var(--coral), #ff7345);
color: var(--white);
border-radius: var(--radius-sm);
padding: 18px 20px;
display: flex;
align-items: center;
gap: 16px;
flex-wrap: wrap;
}
.banner__eyebrow {
margin: 0;
font-size: 18px;
font-weight: 800;
letter-spacing: -0.01em;
}
.banner__sub {
margin: 3px 0 0;
font-size: 13.5px;
opacity: 0.95;
}
.banner__cta {
margin-left: auto;
display: inline-flex;
align-items: center;
gap: 10px;
background: var(--white);
color: #d4502a;
text-decoration: none;
font-weight: 800;
font-size: 17px;
padding: 12px 18px;
border-radius: 999px;
transition: transform 0.15s ease, box-shadow 0.15s ease;
box-shadow: 0 8px 18px -8px rgba(0, 0, 0, 0.4);
}
.banner__cta:hover {
transform: translateY(-2px);
}
.banner__icon {
font-size: 18px;
animation: ring 2.4s ease-in-out infinite;
}
@keyframes ring {
0%, 88%, 100% { transform: rotate(0); }
90%, 94% { transform: rotate(-12deg); }
92%, 96% { transform: rotate(12deg); }
}
/* Grid of cards */
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
}
.card {
background: var(--bg);
border: 1px solid color-mix(in srgb, var(--teal) 12%, transparent);
border-radius: var(--radius-sm);
padding: 16px 17px;
display: flex;
flex-direction: column;
gap: 10px;
}
.card--poison {
background: #fff4ef;
border-color: color-mix(in srgb, var(--coral) 30%, transparent);
}
.card--er {
background: var(--teal-50);
border-color: color-mix(in srgb, var(--teal) 22%, transparent);
}
.card__head {
display: flex;
align-items: center;
gap: 9px;
flex-wrap: wrap;
}
.card__head h2 {
margin: 0;
font-size: 15.5px;
font-weight: 700;
}
.card__badge {
font-size: 11px;
font-weight: 700;
padding: 4px 9px;
border-radius: 999px;
text-transform: uppercase;
letter-spacing: 0.03em;
}
.badge--coral {
background: var(--coral);
color: var(--white);
}
.badge--teal {
background: var(--teal);
color: var(--white);
}
.card__desc {
margin: 0;
font-size: 13.5px;
color: var(--muted);
}
.card__note {
margin: 0;
font-size: 12px;
color: var(--muted);
}
/* Phone row */
.phone-row {
display: flex;
align-items: center;
gap: 10px;
background: var(--white);
border-radius: 12px;
padding: 11px 14px;
text-decoration: none;
color: var(--ink);
font-weight: 700;
transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.phone-row:hover {
transform: translateY(-1px);
box-shadow: 0 8px 16px -10px rgba(217, 83, 79, 0.5);
}
.phone-row__num {
font-size: 16px;
}
.phone-row__hint {
margin-left: auto;
font-size: 11px;
font-weight: 600;
color: var(--coral);
text-transform: uppercase;
letter-spacing: 0.04em;
}
/* Steps */
.steps {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 9px;
}
.steps li {
display: flex;
align-items: flex-start;
gap: 10px;
font-size: 13.5px;
}
.steps__n {
flex-shrink: 0;
width: 22px;
height: 22px;
border-radius: 7px;
background: var(--teal);
color: var(--white);
font-size: 12px;
font-weight: 700;
display: grid;
place-items: center;
margin-top: 1px;
}
/* ER card */
.er__addr {
font-style: normal;
font-size: 15px;
font-weight: 600;
}
.er__meta {
margin: 0;
font-size: 13px;
color: var(--teal-d);
font-weight: 600;
}
.er__actions {
display: flex;
flex-wrap: wrap;
gap: 9px;
margin-top: 2px;
}
.btn {
font-family: inherit;
font-size: 13.5px;
font-weight: 700;
border-radius: 999px;
padding: 10px 16px;
border: 1px solid transparent;
cursor: pointer;
text-decoration: none;
transition: transform 0.15s ease, background 0.15s ease;
}
.btn:hover {
transform: translateY(-1px);
}
.btn--primary {
background: var(--teal);
color: var(--white);
}
.btn--primary:hover {
background: var(--teal-d);
}
.btn--ghost {
background: var(--white);
color: var(--teal-d);
border-color: color-mix(in srgb, var(--teal) 30%, transparent);
}
.copied {
margin: 0;
font-size: 13px;
font-weight: 700;
color: var(--green);
}
/* Focus styles */
a:focus-visible,
button:focus-visible {
outline: none;
box-shadow: var(--ring);
}
/* Responsive */
@media (max-width: 520px) {
.wrap {
padding: 18px 14px 40px;
}
.emergency {
padding: 16px;
}
.emergency__top {
flex-wrap: wrap;
}
.status {
margin-left: 0;
order: 3;
width: 100%;
justify-content: center;
}
.banner__cta {
margin-left: 0;
width: 100%;
justify-content: center;
}
.grid {
grid-template-columns: 1fr;
}
}// Vet — Emergency Info: live open/closed indicator + copy-address.
(function () {
"use strict";
// Mocked weekly general (non-emergency) hours, 24h clock.
// Index 0 = Sunday … 6 = Saturday. null = closed that day.
var HOURS = {
0: null, // Sun
1: { open: 8, close: 19 }, // Mon
2: { open: 8, close: 19 }, // Tue
3: { open: 8, close: 19 }, // Wed
4: { open: 8, close: 20 }, // Thu
5: { open: 8, close: 18 }, // Fri
6: { open: 9, close: 14 }, // Sat
};
var DAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
function fmt(hour) {
var h = ((hour + 11) % 12) + 1;
var ampm = hour < 12 || hour === 24 ? "AM" : "PM";
return h + " " + ampm;
}
function nextOpen(now) {
// Find the next day (including future) that has hours.
for (var i = 1; i <= 7; i++) {
var d = (now.getDay() + i) % 7;
if (HOURS[d]) {
var label = i === 1 ? "tomorrow" : DAYS[d];
return label + " at " + fmt(HOURS[d].open);
}
}
return "soon";
}
function computeStatus() {
var now = new Date();
var today = HOURS[now.getDay()];
var hour = now.getHours() + now.getMinutes() / 60;
if (today && hour >= today.open && hour < today.close) {
return {
state: "open",
text: "Open now",
detail:
"General hours: open until " +
fmt(today.close) +
" today. Emergency line is staffed 24/7.",
};
}
// Closed: see if we open later today.
if (today && hour < today.open) {
return {
state: "closed",
text: "Closed",
detail:
"General clinic opens at " +
fmt(today.open) +
" today. For emergencies, call now — we answer 24/7.",
};
}
return {
state: "closed",
text: "Closed",
detail:
"General clinic reopens " +
nextOpen(now) +
". For emergencies, call now — we answer 24/7.",
};
}
function render() {
var pill = document.getElementById("status");
var text = document.getElementById("status-text");
var detail = document.getElementById("status-detail");
if (!pill || !text) return;
var s = computeStatus();
pill.setAttribute("data-state", s.state);
text.textContent = s.text;
if (detail) detail.textContent = s.detail;
}
// Copy address
var copyBtn = document.getElementById("copy-addr");
if (copyBtn) {
copyBtn.addEventListener("click", function () {
var addrEl = document.getElementById("er-address");
var copied = document.getElementById("copied");
var addr = addrEl ? addrEl.textContent.trim().replace(/\s+/g, " ") : "";
var done = function () {
if (!copied) return;
copied.hidden = false;
clearTimeout(copyBtn._t);
copyBtn._t = setTimeout(function () {
copied.hidden = true;
}, 2200);
};
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(addr).then(done, done);
} else {
var ta = document.createElement("textarea");
ta.value = addr;
ta.setAttribute("readonly", "");
ta.style.position = "absolute";
ta.style.left = "-9999px";
document.body.appendChild(ta);
ta.select();
try {
document.execCommand("copy");
} catch (e) {}
document.body.removeChild(ta);
done();
}
});
}
render();
// Re-check status every minute so it flips at opening/closing time.
setInterval(render, 60 * 1000);
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Vet — Emergency Info</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<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>
<main class="wrap">
<section class="emergency" aria-labelledby="emg-heading">
<header class="emergency__top">
<span class="paw" aria-hidden="true">🐾</span>
<div>
<p class="kicker">Brookside Animal Care</p>
<h1 id="emg-heading">Emergency & urgent help</h1>
</div>
<span class="status" id="status" data-state="loading" role="status" aria-live="polite">
<span class="status__dot" aria-hidden="true"></span>
<span class="status__text" id="status-text">Checking hours…</span>
</span>
</header>
<!-- Call-now banner -->
<div class="banner" role="group" aria-label="Emergency phone">
<div class="banner__copy">
<p class="banner__eyebrow">Emergency? Call now</p>
<p class="banner__sub" id="status-detail">We answer 24/7 for life-threatening cases.</p>
</div>
<a class="banner__cta" href="tel:+15035550199">
<span class="banner__icon" aria-hidden="true">📞</span>
<span class="banner__num">(503) 555-0199</span>
</a>
</div>
<div class="grid">
<!-- Poison control -->
<article class="card card--poison" aria-labelledby="poison-h">
<div class="card__head">
<span class="card__badge badge--coral">24/7</span>
<h2 id="poison-h">Animal poison control</h2>
</div>
<p class="card__desc">
Pet ate something toxic? Call the Animal Poison Hotline before inducing anything.
</p>
<a class="phone-row" href="tel:+18884264435">
<span class="phone-row__icon" aria-hidden="true">☎️</span>
<span class="phone-row__num">(888) 426-4435</span>
<span class="phone-row__hint">tap to call</span>
</a>
<p class="card__note">A consultation fee may apply.</p>
</article>
<!-- What to do -->
<article class="card" aria-labelledby="todo-h">
<div class="card__head">
<span class="card__badge badge--teal">Steps</span>
<h2 id="todo-h">What to do right now</h2>
</div>
<ol class="steps">
<li><span class="steps__n">1</span> Stay calm and keep your pet warm and still.</li>
<li><span class="steps__n">2</span> Call us first — do not give food, water or medication yet.</li>
<li><span class="steps__n">3</span> Note the time symptoms started and any substance involved.</li>
<li><span class="steps__n">4</span> Bring the packaging or a photo if poisoning is suspected.</li>
</ol>
</article>
</div>
<!-- Nearest ER -->
<article class="card card--er" aria-labelledby="er-h">
<div class="card__head">
<span class="card__badge badge--teal">Nearest 24/7 ER</span>
<h2 id="er-h">Riverbend Emergency Animal Hospital</h2>
</div>
<address class="er__addr" id="er-address">
2480 Willamette Blvd, Portland, OR 97217
</address>
<p class="er__meta">
<span class="er__chip" aria-hidden="true">🚗</span> 7 min away · Open now · Walk-ins accepted
</p>
<div class="er__actions">
<a
class="btn btn--primary"
href="https://www.google.com/maps/dir/?api=1&destination=2480+Willamette+Blvd+Portland+OR+97217"
target="_blank"
rel="noopener"
>
Get directions
</a>
<button class="btn btn--ghost" id="copy-addr" type="button">Copy address</button>
<a class="btn btn--ghost" href="tel:+15035550148">Call ER</a>
</div>
<p class="copied" id="copied" role="status" aria-live="polite" hidden>Address copied ✓</p>
</article>
</section>
</main>
<script src="script.js"></script>
</body>
</html>Emergency Info
A warm, reassuring panel for when a pet owner needs help fast. It leads with a coral Emergency? Call now banner and a tap-to-call phone CTA, then shows an open / closed pill computed live from a mocked weekly schedule — including the next time the clinic opens or closes.
Below the banner sits the animal poison control hotline, a numbered what to do right now quick list, and a nearest 24/7 hospital card with a copy-address action and a directions link. The open/closed status recalculates on load and on a one-minute tick, all in vanilla JS.
Illustrative UI only — not for real veterinary use. In a real emergency, call your vet or an emergency animal hospital immediately.