JIT
Grid - Untitled
Create HTML/CSS of an analog clock showing ${time}. Include numbers (or numerals) if you wish, and have a CSS animated second hand
<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Analog Clock</title> <style> :root{ --bg: #0e1116; --bg2: #151a22; --face: #f7f7fa; --face-shadow: rgba(0,0,0,0.25); --accent: #e63946; --mark: #2b2f3a; --mark-strong: #0e1116; --hand: #0e1116; --glass: rgba(255,255,255,0.35); } @media (prefers-color-scheme: light) { :root{ --bg: #f0f2f7; --bg2: #e8ebf3; --face: #ffffff; --face-shadow: rgba(0,0,0,0.15); --accent: #d82739; --mark: #c9ceda; --mark-strong: #2b2f3a; --hand: #1b1e27; --glass: rgba(255,255,255,0.5); } }

html, body { height: 100%; } body { margin: 0; background: radial-gradient(120vmax 120vmax at 70% 20%, var(--bg2), var(--bg)); display: flex; align-items: center; justify-content: center; font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji"; color: #151826; }

.wrap { width: min(92vw, 92vh); max-width: 1024px; display: grid; grid-template-rows: 1fr auto; gap: 2.8vh; align-items: center; justify-items: center; padding: clamp(12px, 3vmin, 28px); box-sizing: border-box; }

.clock { width: min(86vmin, 90vw); aspect-ratio: 1 / 1; position: relative; border-radius: 50%; background: radial-gradient(circle at 50% 38%, rgba(0,0,0,0.06), transparent 42%), radial-gradient(circle at 50% 50%, var(--face), var(--face)); box-shadow: 0 1.2vmin 3vmin -1vmin var(--face-shadow), inset 0 0 0.8vmin #fff, inset 0 0 0 1.2vmin rgba(0,0,0,0.04); display: grid; place-items: center; overflow: hidden; --hour-rot: 0deg; --minute-rot: 0deg; --second-rot: 0deg; }

.bezel { position: absolute; inset: 0; border-radius: 50%; box-shadow: inset 0 0 0 0.9vmin rgba(0,0,0,0.06), inset 0 0 0 1.6vmin rgba(255,255,255,0.9), 0 0.6vmin 1.6vmin rgba(0,0,0,0.06); pointer-events: none; }

.ticks, .numbers, .hands { position: absolute; inset: 0; }

.tick { position: absolute; left: 50%; top: 2.2%; transform-origin: 50% calc(100% - 0%); translate: -50% 0; background: var(--mark); border-radius: 999px; opacity: 0.9; } .tick.major { background: var(--mark-strong); opacity: 1; }

.numbers { pointer-events: none; } .num { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) rotate(var(--a)) translateY(-42%) rotate(calc(-1 * var(--a))); font-weight: 700; letter-spacing: 0.02em; color: var(--mark-strong); text-shadow: 0 1px 0 rgba(255,255,255,0.6); font-size: clamp(14px, 3.8vmin, 28px); user-select: none; }

.hands { pointer-events: none; }

.hand { position: absolute; inset: 0; transform: rotate(0deg); display: block; } .hand.hour { transform: rotate(var(--hour-rot)); } .hand.minute { transform: rotate(var(--minute-rot)); } .hand.second { transform: rotate(var(--second-rot)); }

.hand .shaft { position: absolute; left: 50%; bottom: 50%; transform-origin: 50% 100%; transform: translateX(-50%); background: var(--hand); border-radius: 999px; box-shadow: 0 1px 0 rgba(255,255,255,0.6); }

.hand.hour .shaft { width: 1.8%; height: 29%; animation: sweep 43200s linear infinite; } .hand.minute .shaft { width: 1.2%; height: 39%; animation: sweep 3600s linear infinite; } .hand.second .shaft { width: 0.7%; height: 43%; background: var(--accent); box-shadow: 0 0 0.6vmin rgba(230,57,70,0.35); animation: sweep 60s linear infinite; }

.cap-outer, .cap-inner { position: absolute; left: 50%; top: 50%; translate: -50% -50%; border-radius: 50%; } .cap-outer { width: 6.4%; aspect-ratio: 1; background: linear-gradient(180deg, #d9dbe3, #b9bcc9); box-shadow: 0 0.5vmin 1vmin rgba(0,0,0,0.15), inset 0 0 0 0.4vmin rgba(255,255,255,0.75); z-index: 3; } .cap-inner { width: 3.6%; aspect-ratio: 1; background: var(--hand); z-index: 4; box-shadow: inset 0 0 0 0.2vmin rgba(255,255,255,0.25); }

.brand { position: absolute; left: 50%; top: 58%; translate: -50% -50%; font-weight: 600; font-size: clamp(10px, 1.8vmin, 14px); color: rgba(0,0,0,0.45); letter-spacing: 0.12em; text-transform: uppercase; pointer-events: none; }

.glass { position: absolute; inset: 0; border-radius: 50%; background: radial-gradient(120% 100% at 20% 0%, var(--glass), transparent 55%); mix-blend-mode: screen; opacity: 0.55; pointer-events: none; }

.caption { text-align: center; color: rgba(255,255,255,0.85); font-size: clamp(14px, 2.2vmin, 18px); letter-spacing: 0.02em; max-width: 90vw; }

@keyframes sweep { from { transform: translateX(-50%) rotate(0deg); } to { transform: translateX(-50%) rotate(360deg); } }

@media (max-width: 600px) { .wrap { gap: 2vh; } .brand { top: 60%; } }

@media (prefers-reduced-motion: reduce) { .hand .shaft { animation-duration: 0.001s; } } </style>

</head> <body> <div class="wrap"> <div class="clock" id="clock" aria-label="Analog clock"> <div class="bezel"></div> <div class="ticks" id="ticks"></div> <div class="numbers" id="numbers"></div>
<div class="hands">
  <div class="hand hour"><div class="shaft"></div></div>
  <div class="hand minute"><div class="shaft"></div></div>
  <div class="hand second"><div class="shaft"></div></div>
</div>

<div class="cap-outer"></div>
<div class="cap-inner"></div>
<div class="brand">Chrono</div>
<div class="glass"></div>
</div> <div id="caption" class="caption"></div> </div> <script> (function(){ var INIT_TIME = "${time}"; function getQueryTime(){ var p = new URLSearchParams(location.search); return p.get("time") || p.get("t") || ""; } function parseTimeString(str){ var now = new Date(); if (!str) return now; var s = String(str).trim(); if (!s || s.includes("${")) return now; if (/^now$/i.test(s)) return now; var d = new Date(s); if (!Number.isNaN(d.getTime())) return d; var m = s.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?\s*(am|pm)?$/i); if (m){ var h = parseInt(m[1],10); var min = parseInt(m[2],10); var sec = m[3] ? parseInt(m[3],10) : 0; var ap = m[4] ? m[4].toLowerCase() : ""; if (ap === "pm" && h !== 12) h += 12; if (ap === "am" && h === 12) h = 0; var dd = new Date(); dd.setHours(h, min, sec, 0); return dd; } var m2 = s.match(/^(\d{1,2})\s*(am|pm)$/i); if (m2){ var hh = parseInt(m2[1],10); var ap2 = m2[2].toLowerCase(); if (ap2 === "pm" && hh !== 12) hh += 12; if (ap2 === "am" && hh === 12) hh = 0; var d2 = new Date(); d2.setHours(hh, 0, 0, 0); return d2; } var m3 = s.match(/^(\d{1,2})$/); if (m3){ var h3 = parseInt(m3[1],10) % 24; var d3 = new Date(); d3.setHours(h3, 0, 0, 0); return d3; } return now; } function pad(n){ return n < 10 ? "0"+n : ""+n; } function formatDisplayTime(d){ var h = d.getHours(); var m = d.getMinutes(); var s = d.getSeconds(); var ampm = h >= 12 ? "PM" : "AM"; var h12 = h % 12 || 12; return h12 + ":" + pad(m) + ":" + pad(s) + " " + ampm; } function setInitialAngles(clock, date){ var h = date.getHours(); var m = date.getMinutes(); var s = date.getSeconds(); var ms = date.getMilliseconds() || 0; var seconds = s + ms/1000; var minutes = m + seconds/60; var hours = (h % 12) + minutes/60; var secDeg = seconds * 6; // 360/60 var minDeg = minutes * 6; // 360/60 var hourDeg = hours * 30; // 360/12 clock.style.setProperty("--second-rot", secDeg.toFixed(4) + "deg"); clock.style.setProperty("--minute-rot", minDeg.toFixed(4) + "deg"); clock.style.setProperty("--hour-rot", hourDeg.toFixed(4) + "deg"); } function buildTicks(container){ container.innerHTML = ""; for (var i = 0; i < 60; i++){ var t = document.createElement("div"); var isMajor = i % 5 === 0; t.className = "tick" + (isMajor ? " major" : ""); t.style.height = (isMajor ? 10 : 6.4) + "%"; t.style.width = isMajor ? "0.9%" : "0.35%"; t.style.transform = "translateX(-50%) rotate(" + (i * 6) + "deg)"; t.style.borderRadius = "999px"; container.appendChild(t); } } function buildNumbers(container){ container.innerHTML = ""; for (var n = 1; n <= 12; n++){ var el = document.createElement("div"); el.className = "num"; var angle = n * 30; el.style.setProperty("--a", angle + "deg"); el.textContent = String(n); container.appendChild(el); } } var clockEl = document.getElementById("clock"); var ticksEl = document.getElementById("ticks"); var numbersEl = document.getElementById("numbers"); var captionEl = document.getElementById("caption"); buildTicks(ticksEl); buildNumbers(numbersEl); var inputTime = getQueryTime() || INIT_TIME; var initDate = parseTimeString(inputTime); setInitialAngles(clockEl, initDate); var info; if (!inputTime || (String(inputTime).includes("${"))){ info = "Running from your current local time: " + formatDisplayTime(initDate); } else { info = "Initialized to: " + (decodeURIComponent(inputTime)) + " → " + formatDisplayTime(initDate); } captionEl.textContent = info; window.addEventListener("resize", function(){ /* layout is responsive via CSS; no action needed */ }); })(); </script> </body> </html>
Updated files
v1