Pages Medium
Status Page
A system status page with service health indicators, uptime bars, incident timeline, and overall status banner. No external libraries.
Open in Lab
MCP
vanilla-js css
Targets: JS HTML
Code
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background: #f9fafb;
color: #1f2937;
line-height: 1.6;
min-height: 100vh;
}
.status-container {
max-width: 800px;
margin: 0 auto;
padding: 32px 20px 64px;
}
/* โโ Header โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */
.status-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
}
.header-brand {
display: flex;
align-items: center;
gap: 10px;
}
.brand-logo {
width: 36px;
height: 36px;
background: #6366f1;
color: #fff;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
font-size: 14px;
}
.brand-name {
font-size: 18px;
font-weight: 700;
color: #111827;
}
.btn-subscribe {
padding: 8px 18px;
font-size: 13px;
font-weight: 600;
color: #6366f1;
background: #eef2ff;
border: 1px solid #c7d2fe;
border-radius: 8px;
cursor: pointer;
transition: all 0.15s;
}
.btn-subscribe:hover {
background: #6366f1;
color: #fff;
border-color: #6366f1;
}
/* โโ Status Banner โโโโโโโโโโโโโโโโโโโโโโโโโโโโ */
.status-banner {
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
padding: 20px;
border-radius: 12px;
margin-bottom: 16px;
}
.banner-operational {
background: #22c55e;
color: #fff;
}
.banner-degraded {
background: #eab308;
color: #fff;
}
.banner-outage {
background: #ef4444;
color: #fff;
}
.banner-text {
font-size: 18px;
font-weight: 600;
}
/* โโ Refresh Indicator โโโโโโโโโโโโโโโโโโโโโโโโ */
.refresh-indicator {
display: flex;
align-items: center;
gap: 6px;
justify-content: flex-end;
margin-bottom: 24px;
}
.refresh-dot {
width: 6px;
height: 6px;
background: #22c55e;
border-radius: 50%;
animation: pulse-dot 2s infinite;
}
@keyframes pulse-dot {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.4;
}
}
.refresh-text {
font-size: 12px;
color: #9ca3af;
}
/* โโ Services Section โโโโโโโโโโโโโโโโโโโโโโโโโ */
.services-section {
background: #fff;
border-radius: 12px;
padding: 4px 0;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
margin-bottom: 32px;
}
.service-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 24px;
border-bottom: 1px solid #f3f4f6;
}
.service-row:last-of-type {
border-bottom: none;
}
.service-info {
display: flex;
flex-direction: column;
gap: 2px;
min-width: 160px;
}
.service-name {
font-size: 15px;
font-weight: 600;
color: #111827;
}
.service-status-text {
font-size: 12px;
font-weight: 500;
}
.status-text-operational {
color: #16a34a;
}
.status-text-degraded {
color: #d97706;
}
.status-text-outage {
color: #dc2626;
}
.service-right {
display: flex;
align-items: center;
gap: 12px;
flex: 1;
justify-content: flex-end;
}
/* โโ Uptime Bars โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */
.uptime-bar {
display: flex;
gap: 1px;
height: 24px;
align-items: stretch;
flex: 1;
max-width: 360px;
}
.uptime-bar .day-segment {
flex: 1;
min-width: 2px;
border-radius: 1px;
cursor: pointer;
transition: opacity 0.1s;
}
.uptime-bar .day-segment:hover {
opacity: 0.7;
}
.day-operational {
background: #22c55e;
}
.day-degraded {
background: #eab308;
}
.day-outage {
background: #ef4444;
}
.uptime-pct {
font-size: 13px;
font-weight: 600;
color: #374151;
font-family: "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
min-width: 52px;
text-align: right;
}
/* โโ Status Dots โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */
.status-dot {
width: 10px;
height: 10px;
border-radius: 50%;
flex-shrink: 0;
}
.dot-operational {
background: #22c55e;
}
.dot-degraded {
background: #eab308;
}
.dot-outage {
background: #ef4444;
}
/* โโ Uptime Legend โโโโโโโโโโโโโโโโโโโโโโโโโโโโ */
.uptime-legend {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
border-top: 1px solid #f3f4f6;
}
.legend-label {
font-size: 11px;
color: #9ca3af;
}
.legend-center {
font-size: 12px;
color: #6b7280;
}
.legend-center strong {
color: #111827;
}
/* โโ Incidents Section โโโโโโโโโโโโโโโโโโโโโโโโ */
.incidents-section {
margin-bottom: 32px;
}
.section-title {
font-size: 20px;
font-weight: 700;
color: #111827;
margin-bottom: 16px;
}
.incident {
background: #fff;
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
margin-bottom: 12px;
overflow: hidden;
}
.incident-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 20px;
cursor: pointer;
user-select: none;
transition: background 0.1s;
}
.incident-header:hover {
background: #f9fafb;
}
.incident-header-left {
display: flex;
align-items: center;
gap: 12px;
}
.incident-header-right {
display: flex;
align-items: center;
gap: 12px;
}
.incident-severity {
font-size: 11px;
font-weight: 600;
padding: 3px 10px;
border-radius: 8px;
text-transform: uppercase;
letter-spacing: 0.3px;
white-space: nowrap;
}
.severity-minor {
background: #fef3c7;
color: #d97706;
}
.severity-major {
background: #fee2e2;
color: #dc2626;
}
.severity-maintenance {
background: #dbeafe;
color: #2563eb;
}
.incident-title {
font-size: 15px;
font-weight: 600;
color: #111827;
}
.incident-date {
font-size: 13px;
color: #9ca3af;
}
.incident-chevron {
font-size: 12px;
color: #9ca3af;
transition: transform 0.2s;
}
.incident[data-expanded="true"] .incident-chevron {
transform: rotate(180deg);
}
/* โโ Incident Timeline โโโโโโโโโโโโโโโโโโโโโโโโ */
.incident-body {
padding: 0 20px 20px;
}
.incident-timeline {
border-left: 2px solid #e5e7eb;
margin-left: 12px;
padding-left: 20px;
}
.timeline-entry {
position: relative;
padding-bottom: 20px;
}
.timeline-entry:last-child {
padding-bottom: 0;
}
.timeline-entry::before {
content: "";
position: absolute;
left: -27px;
top: 6px;
width: 10px;
height: 10px;
background: #e5e7eb;
border-radius: 50%;
border: 2px solid #fff;
}
.timeline-badge {
display: inline-block;
font-size: 11px;
font-weight: 600;
padding: 2px 8px;
border-radius: 6px;
margin-bottom: 6px;
text-transform: uppercase;
letter-spacing: 0.3px;
}
.badge-investigating {
background: #fef3c7;
color: #d97706;
}
.badge-identified {
background: #fce7f3;
color: #db2777;
}
.badge-monitoring {
background: #dbeafe;
color: #2563eb;
}
.badge-resolved {
background: #dcfce7;
color: #16a34a;
}
.timeline-text {
font-size: 14px;
color: #374151;
margin-bottom: 4px;
}
.timeline-time {
font-size: 12px;
color: #9ca3af;
}
/* โโ Subscribe Modal โโโโโโโโโโโโโโโโโโโโโโโโโโ */
.modal-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
opacity: 0;
visibility: hidden;
transition: opacity 0.2s, visibility 0.2s;
padding: 20px;
}
.modal-overlay.open {
opacity: 1;
visibility: visible;
}
.subscribe-modal {
background: #fff;
border-radius: 16px;
padding: 36px;
max-width: 420px;
width: 100%;
position: relative;
transform: translateY(20px);
transition: transform 0.2s;
}
.modal-overlay.open .subscribe-modal {
transform: translateY(0);
}
.modal-close {
position: absolute;
top: 14px;
right: 14px;
width: 32px;
height: 32px;
border: none;
background: #f3f4f6;
color: #6b7280;
border-radius: 8px;
font-size: 20px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.15s;
}
.modal-close:hover {
background: #e5e7eb;
color: #111827;
}
.subscribe-title {
font-size: 20px;
font-weight: 700;
color: #111827;
margin-bottom: 6px;
}
.subscribe-desc {
font-size: 14px;
color: #6b7280;
margin-bottom: 20px;
}
.subscribe-form {
display: flex;
gap: 8px;
margin-bottom: 12px;
}
.subscribe-input {
flex: 1;
padding: 10px 14px;
font-size: 14px;
border: 1px solid #d1d5db;
border-radius: 8px;
background: #fff;
color: #1f2937;
}
.subscribe-input:focus {
outline: none;
border-color: #6366f1;
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.15);
}
.subscribe-input.error {
border-color: #ef4444;
box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.15);
}
.subscribe-btn {
padding: 10px 22px;
font-size: 14px;
font-weight: 600;
color: #fff;
background: #6366f1;
border: none;
border-radius: 8px;
cursor: pointer;
transition: background 0.15s;
white-space: nowrap;
}
.subscribe-btn:hover {
background: #4f46e5;
}
.subscribe-note {
font-size: 12px;
color: #9ca3af;
}
/* โโ Uptime Tooltip โโโโโโโโโโโโโโโโโโโโโโโโโโโ */
.uptime-tooltip {
position: fixed;
background: #1f2937;
color: #fff;
padding: 6px 12px;
border-radius: 8px;
font-size: 12px;
pointer-events: none;
opacity: 0;
transition: opacity 0.15s;
z-index: 2000;
white-space: nowrap;
}
.uptime-tooltip.visible {
opacity: 1;
}
/* โโ Toast โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */
.toast {
position: fixed;
bottom: 30px;
left: 50%;
transform: translateX(-50%) translateY(80px);
background: #1f2937;
color: #fff;
padding: 12px 24px;
border-radius: 10px;
font-size: 14px;
font-weight: 500;
opacity: 0;
transition: transform 0.3s, opacity 0.3s;
pointer-events: none;
z-index: 2000;
white-space: nowrap;
}
.toast.show {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
/* โโ Responsive โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */
@media (max-width: 640px) {
.status-header {
flex-direction: column;
gap: 12px;
align-items: flex-start;
}
.service-row {
flex-direction: column;
align-items: flex-start;
gap: 10px;
padding: 14px 16px;
}
.service-right {
width: 100%;
justify-content: flex-start;
}
.uptime-bar {
max-width: none;
overflow: hidden;
}
.uptime-bar .day-segment {
min-width: 1px;
}
.uptime-legend {
padding: 12px 16px;
}
.legend-center {
display: none;
}
.incident-header {
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
.incident-header-right {
width: 100%;
justify-content: space-between;
}
.subscribe-form {
flex-direction: column;
}
}(function () {
var tooltip = document.getElementById("uptimeTooltip");
var subscribeOverlay = document.getElementById("subscribeOverlay");
var subscribeClose = document.getElementById("subscribeClose");
var subscribeOpen = document.getElementById("subscribeOpen");
var subscribeForm = document.getElementById("subscribeForm");
var subscribeEmail = document.getElementById("subscribeEmail");
var lastCheckedEl = document.getElementById("lastChecked");
var toast = document.getElementById("toast");
var toastTimer = null;
function showToast(msg) {
toast.textContent = msg;
toast.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toast.classList.remove("show");
}, 2500);
}
// โโ Generate 90-day uptime bars โโโโโโโโโโโโโโ
// Use a seeded pseudo-random so the bars look consistent per service
function seededRandom(seed) {
var x = Math.sin(seed) * 10000;
return x - Math.floor(x);
}
var serviceSeeds = {
website: 42,
api: 137,
dashboard: 256,
database: 789,
cdn: 55,
email: 321,
auth: 999,
};
// Known incident days (days ago) that should be degraded/outage
var knownIncidents = {
database: { 1: "degraded", 2: "degraded" },
api: { 8: "outage" },
};
var uptimeBars = document.querySelectorAll(".uptime-bar");
uptimeBars.forEach(function (bar) {
var service = bar.dataset.service;
var seed = serviceSeeds[service] || 100;
var incidents = knownIncidents[service] || {};
for (var i = 89; i >= 0; i--) {
var dayEl = document.createElement("div");
dayEl.className = "day-segment";
var date = new Date();
date.setDate(date.getDate() - i);
var dateStr = date.toLocaleDateString("en-US", {
month: "short",
day: "numeric",
year: "numeric",
});
var status;
if (incidents[i]) {
status = incidents[i];
} else {
var rand = seededRandom(seed + i);
if (rand < 0.02) {
status = "outage";
} else if (rand < 0.06) {
status = "degraded";
} else {
status = "operational";
}
}
dayEl.classList.add("day-" + status);
dayEl.dataset.date = dateStr;
var statusLabel =
status === "operational"
? "No issues"
: status === "degraded"
? "Degraded performance"
: "Major outage";
dayEl.dataset.status = statusLabel;
bar.appendChild(dayEl);
}
});
// โโ Tooltip on hover โโโโโโโโโโโโโโโโโโโโโโโโโ
document.addEventListener("mouseover", function (e) {
var seg = e.target.closest(".day-segment");
if (!seg) return;
tooltip.textContent = seg.dataset.date + " \u2014 " + seg.dataset.status;
tooltip.classList.add("visible");
});
document.addEventListener("mousemove", function (e) {
if (tooltip.classList.contains("visible")) {
tooltip.style.left = e.clientX + 12 + "px";
tooltip.style.top = e.clientY - 36 + "px";
}
});
document.addEventListener("mouseout", function (e) {
var seg = e.target.closest(".day-segment");
if (seg) {
tooltip.classList.remove("visible");
}
});
// โโ Incident expand/collapse โโโโโโโโโโโโโโโโโ
var incidents = document.querySelectorAll(".incident");
incidents.forEach(function (incident) {
var header = incident.querySelector(".incident-header");
var body = incident.querySelector(".incident-body");
header.addEventListener("click", function () {
var expanded = incident.dataset.expanded === "true";
incident.dataset.expanded = expanded ? "false" : "true";
body.style.display = expanded ? "none" : "block";
});
header.addEventListener("keydown", function (e) {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
header.click();
}
});
});
// โโ Subscribe modal โโโโโโโโโโโโโโโโโโโโโโโโโโ
subscribeOpen.addEventListener("click", function () {
subscribeOverlay.classList.add("open");
document.body.style.overflow = "hidden";
subscribeEmail.focus();
});
function closeSubscribe() {
subscribeOverlay.classList.remove("open");
document.body.style.overflow = "";
subscribeEmail.value = "";
subscribeEmail.classList.remove("error");
}
subscribeClose.addEventListener("click", closeSubscribe);
subscribeOverlay.addEventListener("click", function (e) {
if (e.target === subscribeOverlay) closeSubscribe();
});
document.addEventListener("keydown", function (e) {
if (e.key === "Escape") closeSubscribe();
});
subscribeForm.addEventListener("submit", function (e) {
e.preventDefault();
var email = subscribeEmail.value.trim();
if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
subscribeEmail.classList.add("error");
return;
}
subscribeEmail.classList.remove("error");
closeSubscribe();
showToast("Subscribed! You'll receive status updates at " + email);
});
subscribeEmail.addEventListener("input", function () {
subscribeEmail.classList.remove("error");
});
// โโ Auto-refresh indicator โโโโโโโโโโโโโโโโโโโ
var refreshCounter = 0;
function updateLastChecked() {
refreshCounter += 30;
if (refreshCounter < 60) {
lastCheckedEl.textContent = refreshCounter + "s ago";
} else {
var mins = Math.floor(refreshCounter / 60);
lastCheckedEl.textContent = mins + "m ago";
}
}
setInterval(updateLastChecked, 30000);
})();<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>System Status</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="status-container">
<!-- Header -->
<header class="status-header">
<div class="header-brand">
<div class="brand-logo">ST</div>
<span class="brand-name">StealThis Status</span>
</div>
<button class="btn-subscribe" id="subscribeOpen">Subscribe to Updates</button>
</header>
<!-- Overall Status Banner -->
<div class="status-banner banner-operational" id="statusBanner">
<svg class="banner-icon" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
<polyline points="20 6 9 17 4 12"/>
</svg>
<span class="banner-text" id="bannerText">All Systems Operational</span>
</div>
<!-- Auto-refresh indicator -->
<div class="refresh-indicator">
<span class="refresh-dot"></span>
<span class="refresh-text">Last checked: <span id="lastChecked">just now</span></span>
</div>
<!-- Service List -->
<section class="services-section">
<div class="service-row" data-service="website" data-status="operational" data-uptime="99.99">
<div class="service-info">
<span class="service-name">Website</span>
<span class="service-status-text status-text-operational">Operational</span>
</div>
<div class="service-right">
<div class="uptime-bar" data-service="website"></div>
<span class="uptime-pct">99.99%</span>
<span class="status-dot dot-operational"></span>
</div>
</div>
<div class="service-row" data-service="api" data-status="operational" data-uptime="99.95">
<div class="service-info">
<span class="service-name">API</span>
<span class="service-status-text status-text-operational">Operational</span>
</div>
<div class="service-right">
<div class="uptime-bar" data-service="api"></div>
<span class="uptime-pct">99.95%</span>
<span class="status-dot dot-operational"></span>
</div>
</div>
<div class="service-row" data-service="dashboard" data-status="operational" data-uptime="99.98">
<div class="service-info">
<span class="service-name">Dashboard</span>
<span class="service-status-text status-text-operational">Operational</span>
</div>
<div class="service-right">
<div class="uptime-bar" data-service="dashboard"></div>
<span class="uptime-pct">99.98%</span>
<span class="status-dot dot-operational"></span>
</div>
</div>
<div class="service-row" data-service="database" data-status="degraded" data-uptime="99.87">
<div class="service-info">
<span class="service-name">Database</span>
<span class="service-status-text status-text-degraded">Degraded Performance</span>
</div>
<div class="service-right">
<div class="uptime-bar" data-service="database"></div>
<span class="uptime-pct">99.87%</span>
<span class="status-dot dot-degraded"></span>
</div>
</div>
<div class="service-row" data-service="cdn" data-status="operational" data-uptime="99.99">
<div class="service-info">
<span class="service-name">CDN</span>
<span class="service-status-text status-text-operational">Operational</span>
</div>
<div class="service-right">
<div class="uptime-bar" data-service="cdn"></div>
<span class="uptime-pct">99.99%</span>
<span class="status-dot dot-operational"></span>
</div>
</div>
<div class="service-row" data-service="email" data-status="operational" data-uptime="99.92">
<div class="service-info">
<span class="service-name">Email Service</span>
<span class="service-status-text status-text-operational">Operational</span>
</div>
<div class="service-right">
<div class="uptime-bar" data-service="email"></div>
<span class="uptime-pct">99.92%</span>
<span class="status-dot dot-operational"></span>
</div>
</div>
<div class="service-row" data-service="auth" data-status="operational" data-uptime="99.97">
<div class="service-info">
<span class="service-name">Authentication</span>
<span class="service-status-text status-text-operational">Operational</span>
</div>
<div class="service-right">
<div class="uptime-bar" data-service="auth"></div>
<span class="uptime-pct">99.97%</span>
<span class="status-dot dot-operational"></span>
</div>
</div>
<div class="uptime-legend">
<span class="legend-label">90 days ago</span>
<span class="legend-center">Uptime over the past 90 days · <strong>99.95%</strong> average</span>
<span class="legend-label">Today</span>
</div>
</section>
<!-- Incident History -->
<section class="incidents-section">
<h2 class="section-title">Incident History</h2>
<div class="incident" data-expanded="true">
<div class="incident-header" role="button" tabindex="0">
<div class="incident-header-left">
<span class="incident-severity severity-minor">Minor</span>
<h3 class="incident-title">Database Performance Degradation</h3>
</div>
<div class="incident-header-right">
<span class="incident-date">March 19, 2026</span>
<span class="incident-chevron">▾</span>
</div>
</div>
<div class="incident-body">
<div class="incident-timeline">
<div class="timeline-entry">
<span class="timeline-badge badge-resolved">Resolved</span>
<div class="timeline-content">
<p class="timeline-text">Performance has returned to normal levels. We will continue monitoring over the next 24 hours.</p>
<span class="timeline-time">Mar 19, 18:42 UTC</span>
</div>
</div>
<div class="timeline-entry">
<span class="timeline-badge badge-monitoring">Monitoring</span>
<div class="timeline-content">
<p class="timeline-text">A fix has been deployed to optimize the affected database queries. Response times are improving.</p>
<span class="timeline-time">Mar 19, 16:20 UTC</span>
</div>
</div>
<div class="timeline-entry">
<span class="timeline-badge badge-identified">Identified</span>
<div class="timeline-content">
<p class="timeline-text">The root cause has been identified as a sudden increase in write operations from a scheduled job. The team is working on a fix.</p>
<span class="timeline-time">Mar 19, 15:05 UTC</span>
</div>
</div>
<div class="timeline-entry">
<span class="timeline-badge badge-investigating">Investigating</span>
<div class="timeline-content">
<p class="timeline-text">We are investigating reports of elevated latency on database-dependent services. Some users may experience slower load times.</p>
<span class="timeline-time">Mar 19, 14:30 UTC</span>
</div>
</div>
</div>
</div>
</div>
<div class="incident" data-expanded="false">
<div class="incident-header" role="button" tabindex="0">
<div class="incident-header-left">
<span class="incident-severity severity-major">Major</span>
<h3 class="incident-title">API Elevated Error Rates</h3>
</div>
<div class="incident-header-right">
<span class="incident-date">March 12, 2026</span>
<span class="incident-chevron">▾</span>
</div>
</div>
<div class="incident-body" style="display: none;">
<div class="incident-timeline">
<div class="timeline-entry">
<span class="timeline-badge badge-resolved">Resolved</span>
<div class="timeline-content">
<p class="timeline-text">The issue has been fully resolved. API error rates have returned to baseline. A post-mortem will be published within 48 hours.</p>
<span class="timeline-time">Mar 12, 11:15 UTC</span>
</div>
</div>
<div class="timeline-entry">
<span class="timeline-badge badge-investigating">Investigating</span>
<div class="timeline-content">
<p class="timeline-text">We are seeing increased 5xx error rates on the API. The engineering team is investigating the cause.</p>
<span class="timeline-time">Mar 12, 09:48 UTC</span>
</div>
</div>
</div>
</div>
</div>
<div class="incident" data-expanded="false">
<div class="incident-header" role="button" tabindex="0">
<div class="incident-header-left">
<span class="incident-severity severity-maintenance">Maintenance</span>
<h3 class="incident-title">Scheduled Maintenance</h3>
</div>
<div class="incident-header-right">
<span class="incident-date">March 5, 2026</span>
<span class="incident-chevron">▾</span>
</div>
</div>
<div class="incident-body" style="display: none;">
<div class="incident-timeline">
<div class="timeline-entry">
<span class="timeline-badge badge-resolved">Completed</span>
<div class="timeline-content">
<p class="timeline-text">Maintenance has been completed successfully. All services are back online and operating normally.</p>
<span class="timeline-time">Mar 5, 06:30 UTC</span>
</div>
</div>
<div class="timeline-entry">
<span class="timeline-badge badge-monitoring">In Progress</span>
<div class="timeline-content">
<p class="timeline-text">Scheduled maintenance is underway. Some services may be briefly unavailable during this window (04:00 - 06:00 UTC).</p>
<span class="timeline-time">Mar 5, 04:00 UTC</span>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
<!-- Subscribe Modal -->
<div class="modal-overlay" id="subscribeOverlay">
<div class="subscribe-modal">
<button class="modal-close" id="subscribeClose">×</button>
<h2 class="subscribe-title">Subscribe to Updates</h2>
<p class="subscribe-desc">Get notified when there are changes to service status.</p>
<form class="subscribe-form" id="subscribeForm">
<input type="email" class="subscribe-input" id="subscribeEmail" placeholder="you@example.com" required />
<button type="submit" class="subscribe-btn">Subscribe</button>
</form>
<p class="subscribe-note">We'll only send status-related emails. Unsubscribe anytime.</p>
</div>
</div>
<!-- Uptime tooltip -->
<div class="uptime-tooltip" id="uptimeTooltip"></div>
<div class="toast" id="toast"></div>
<script src="script.js"></script>
</body>
</html>Status Page
A public-facing system status page showing service health, uptime history, and incident reports. Inspired by Statuspage.io and Instatus.
Features
- Overall status banner โ All Systems Operational (green) or degraded/outage states
- Service list โ each service with name, status indicator (operational/degraded/outage), uptime %
- Uptime bars โ 90-day history bars showing daily status (green/yellow/red)
- Incident timeline โ recent incidents with severity, description, updates, timestamps
- Subscribe โ email subscribe for status updates
- Auto-refresh โ simulated live status updates
When to use it
- Public status page for SaaS products
- API health monitoring dashboard
- Infrastructure status display