This page lists files in the current directory. You can view content, get download/execute commands for Wget, Curl, or PowerShell, or filter the list using wildcards (e.g., `*.sh`).
wget 'https://lists2.roe3.org/mdrone/world-clock/index.html'
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>World Clock Slider</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<link rel='stylesheet' href='https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap'>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="root"></div>
<script type="module" src="./script.js"></script>
</body>
</html>
wget 'https://lists2.roe3.org/mdrone/world-clock/script.js'
import React, { StrictMode, useEffect, useRef, useState } from "https://esm.sh/react";
import { createRoot } from "https://esm.sh/react-dom/client";
import { addMinutes, format, isSameDay, isTomorrow, isYesterday } from "https://esm.sh/date-fns";
import { toZonedTime } from "https://esm.sh/date-fns-tz";
createRoot(document.getElementById("root")).render(React.createElement(StrictMode, null,
React.createElement("main", null,
React.createElement(SVGSprites, null),
React.createElement(WorldClockSlider, null))));
function WorldClockSlider() {
const containerRef = useRef(null);
const [now, setNow] = useState(new Date());
const [offsetMinutes, setOffsetMinutes] = useState(0);
const [sliderX, setSliderX] = useState(null);
const [dragging, setDragging] = useState(false);
const [showTooltip, setShowTooltip] = useState(false);
const [isResetting, setIsResetting] = useState(false);
const localTime = addMinutes(now, offsetMinutes);
const timeBound = 1440; // minutes
const isRTL = document.dir === "rtl";
const cities = [
{ name: "San Francisco", timeZone: "America/Los_Angeles" },
{ name: "Chicago", timeZone: "America/Chicago" },
{ name: "Washington, D.C.", timeZone: "America/New_York" },
{ name: "London", timeZone: "Europe/London" },
{ name: "New Delhi", timeZone: "Asia/Kolkata" },
{ name: "Tokyo", timeZone: "Asia/Tokyo" }
];
function handleMouseDown(e) {
e.preventDefault();
if (isResetting)
return;
setDragging(true);
setShowTooltip(true);
}
function handleMouseMove(e) {
if (isResetting || !dragging || !containerRef.current)
return;
const clientX = "touches" in e ? e.touches[0].clientX : e.clientX;
const { left, width } = containerRef.current.getBoundingClientRect();
// clamp X to container bounds
const clampedX = Math.max(0, Math.min(clientX - left, width));
const clampedOffset = Math.max(-timeBound, Math.min(timeBound, Utils.getOffsetFromSliderX(clampedX, width, timeBound)));
setOffsetMinutes(isRTL ? -clampedOffset : clampedOffset);
setSliderX(Utils.getSliderXFromOffset(clampedOffset, width, timeBound));
}
function handleKeyDown(e) {
if (isResetting || !containerRef.current)
return;
const step = 30; // minutes
const { width } = containerRef.current.getBoundingClientRect();
const { key } = e;
const isHome = key === "Home";
const isEnd = key === "End";
const towardEnd = key === "ArrowUp" || key === "ArrowRight";
const towardStart = key === "ArrowDown" || key === "ArrowLeft";
let newOffset = offsetMinutes;
if (isHome) {
newOffset = -timeBound;
}
else if (isEnd) {
newOffset = timeBound;
}
else if (towardEnd) {
newOffset = Math.min(timeBound, offsetMinutes + step);
}
else if (towardStart) {
newOffset = Math.max(-timeBound, offsetMinutes - step);
}
else {
return;
}
e.preventDefault();
setOffsetMinutes(newOffset);
setSliderX(Utils.getSliderXFromOffset(isRTL ? -newOffset : newOffset, width, timeBound));
setShowTooltip(true);
}
function handleContainerClick(e) {
const target = e.target;
if (isResetting || target.closest("[data-close]") || !containerRef.current)
return;
const { left, width } = containerRef.current.getBoundingClientRect();
const clientX = "touches" in e ? e.touches[0].clientX : e.clientX;
const x = Math.max(0, Math.min(clientX - left, width));
const newOffset = Utils.getOffsetFromSliderX(x, width, timeBound);
const clampedOffset = Math.max(-timeBound, Math.min(timeBound, newOffset));
setOffsetMinutes(isRTL ? -clampedOffset : clampedOffset);
setSliderX(Utils.getSliderXFromOffset(clampedOffset, width, timeBound));
setShowTooltip(true);
setDragging(true);
}
function refreshSlider() {
if (!containerRef.current)
return;
const { width } = containerRef.current.getBoundingClientRect();
setSliderX(Utils.getSliderXFromOffset(offsetMinutes, width, timeBound));
}
function resetSlider() {
if (isResetting || !containerRef.current)
return;
setIsResetting(true);
const { width } = containerRef.current.getBoundingClientRect();
const fromOffset = offsetMinutes;
const fromSliderX = sliderX !== null && sliderX !== void 0 ? sliderX : Utils.getSliderXFromOffset(offsetMinutes, width, timeBound);
const targetOffset = 0;
const targetSliderX = Utils.getSliderXFromOffset(targetOffset, width, timeBound);
const duration = 300;
Utils.animateValue(fromOffset, targetOffset, duration, (val) => setOffsetMinutes(Math.round(val)), () => {
setIsResetting(false);
setOffsetMinutes(targetOffset);
setShowTooltip(false);
});
Utils.animateValue(fromSliderX, targetSliderX, duration, (val) => setSliderX(val), () => setSliderX(null) // recalculate if null is the default
);
}
// clock ticker and slider position
useEffect(() => {
let timeoutId;
const tick = () => {
setNow(new Date());
timeoutId = setTimeout(tick, 1e3);
};
tick();
refreshSlider();
return () => clearTimeout(timeoutId);
}, []);
// event listeners
useEffect(() => {
const handleMove = (e) => handleMouseMove(e);
const handleUp = () => setDragging(false);
window.addEventListener("mousemove", handleMove);
window.addEventListener("mouseup", handleUp);
window.addEventListener("touchmove", handleMove);
window.addEventListener("touchend", handleUp);
window.addEventListener("resize", refreshSlider);
return () => {
window.removeEventListener("mousemove", handleMove);
window.removeEventListener("mouseup", handleUp);
window.removeEventListener("touchmove", handleMove);
window.removeEventListener("touchend", handleUp);
window.removeEventListener("resize", refreshSlider);
};
}, [dragging]);
return (React.createElement("div", { className: "clocks", ref: containerRef, onMouseDown: handleContainerClick, onTouchStart: handleContainerClick },
React.createElement(WorldClockSliderWrapper, { x: sliderX },
React.createElement(WorldClockTooltip, { show: showTooltip, offsetMinutes: offsetMinutes, closeAction: resetSlider }),
React.createElement(WorldClockSliderLine, { value: offsetMinutes, min: -timeBound, max: timeBound, onMouseDown: handleMouseDown, onTouchStart: handleMouseDown, onKeyDown: handleKeyDown })),
cities.map((city, i) => (React.createElement(WorldClockRow, { key: i, localTime: localTime, city: city })))));
}
function WorldClockRow({ localTime, city }) {
const cityTime = toZonedTime(localTime, city.timeZone);
const { relative, full, short } = Utils.getRelativeTimestamp(localTime, cityTime);
const hour = cityTime.getHours();
const tod = Utils.getTimeOfDay(hour);
const rowClass = `clocks__row clocks__row--${tod}`;
return (React.createElement("div", { className: rowClass },
React.createElement("div", { className: "clocks__start" },
React.createElement("div", { className: "clocks__city" }, city.name),
React.createElement("div", { className: "clocks__relative clocks__relative--full" },
relative,
", ",
full),
React.createElement("div", { className: "clocks__relative clocks__relative--short" },
relative,
", ",
short)),
React.createElement("div", { className: "clocks__end" },
React.createElement("div", { className: "clocks__tod" },
React.createElement(Icon, { name: tod })),
React.createElement("div", { className: "clocks__time" },
format(cityTime, "h:mm"),
React.createElement("small", { className: "clocks__m" }, format(cityTime, "a"))))));
}
function WorldClockSliderLine({ value, min, max, onMouseDown, onTouchStart, onKeyDown }) {
return (React.createElement(React.Fragment, null,
React.createElement("div", { id: "slider-label", className: "clocks__sr-only" }, "Peek time"),
React.createElement("div", { className: "clocks__slider", tabIndex: 0, role: "slider", "aria-labelledby": "slider-label", "aria-valuemin": min, "aria-valuemax": max, "aria-valuenow": value, "aria-valuetext": Utils.formatOffset(value), onMouseDown: onMouseDown, onTouchStart: onTouchStart, onKeyDown: onKeyDown },
React.createElement("div", { className: "clocks__slider-line" }),
React.createElement("div", { className: "clocks__slider-arrow clocks__slider-arrow--left" },
React.createElement(Icon, { name: "triangle-left" })),
React.createElement("div", { className: "clocks__slider-arrow clocks__slider-arrow--right" },
React.createElement(Icon, { name: "triangle-right" })))));
}
function WorldClockSliderWrapper({ x, children }) {
const sliderStyle = {
left: x != null ? `${x}px` : "50%"
};
return (React.createElement("div", { className: "clocks__slider-wrapper", style: sliderStyle }, children));
}
function WorldClockTooltip({ show, offsetMinutes, closeAction }) {
const toolTipClass = `clocks__tooltip${show ? " clocks__tooltip--show" : ""}`;
return (React.createElement("div", { className: toolTipClass },
Utils.formatOffset(offsetMinutes),
React.createElement("button", { className: "clocks__tooltip-close", type: "button", "aria-label": "Reset", onClick: closeAction, "data-close": true },
React.createElement(Icon, { name: "close" }))));
}
function Icon({ name }) {
const href = `#${name}`;
return (React.createElement("svg", { className: "icon", width: "16px", height: "16px", "aria-hidden": "true" },
React.createElement("use", { href: href })));
}
function SVGSprites() {
return (React.createElement("svg", { width: "0", height: "0", display: "none" },
React.createElement("symbol", { id: "close", viewBox: "0 0 16 16" },
React.createElement("g", { stroke: "currentcolor", strokeLinecap: "round", strokeWidth: "2" },
React.createElement("polyline", { points: "2 2,14 14" }),
React.createElement("polyline", { points: "2 14,14 2" }))),
React.createElement("symbol", { id: "day", viewBox: "0 0 16 16" },
React.createElement("path", { fill: "currentcolor", d: "M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z" })),
React.createElement("symbol", { id: "night", viewBox: "0 0 16 16" },
React.createElement("g", { fill: "currentcolor" },
React.createElement("path", { d: "M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z" }),
React.createElement("path", { d: "M10.794 3.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387a1.734 1.734 0 0 0-1.097 1.097l-.387 1.162a.217.217 0 0 1-.412 0l-.387-1.162A1.734 1.734 0 0 0 9.31 6.593l-1.162-.387a.217.217 0 0 1 0-.412l1.162-.387a1.734 1.734 0 0 0 1.097-1.097l.387-1.162zM13.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.156 1.156 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.156 1.156 0 0 0-.732-.732l-.774-.258a.145.145 0 0 1 0-.274l.774-.258c.346-.115.617-.386.732-.732L13.863.1z" }))),
React.createElement("symbol", { id: "sunrise", viewBox: "0 0 16 16" },
React.createElement("path", { fill: "currentcolor", d: "M7.646 1.146a.5.5 0 0 1 .708 0l1.5 1.5a.5.5 0 0 1-.708.708L8.5 2.707V4.5a.5.5 0 0 1-1 0V2.707l-.646.647a.5.5 0 1 1-.708-.708l1.5-1.5zM2.343 4.343a.5.5 0 0 1 .707 0l1.414 1.414a.5.5 0 0 1-.707.707L2.343 5.05a.5.5 0 0 1 0-.707zm11.314 0a.5.5 0 0 1 0 .707l-1.414 1.414a.5.5 0 1 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zM11.709 11.5a4 4 0 1 0-7.418 0H.5a.5.5 0 0 0 0 1h15a.5.5 0 0 0 0-1h-3.79zM0 10a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2A.5.5 0 0 1 0 10zm13 0a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z" })),
React.createElement("symbol", { id: "sunset", viewBox: "0 0 16 16" },
React.createElement("path", { fill: "currentcolor", d: "M7.646 4.854a.5.5 0 0 0 .708 0l1.5-1.5a.5.5 0 0 0-.708-.708l-.646.647V1.5a.5.5 0 0 0-1 0v1.793l-.646-.647a.5.5 0 1 0-.708.708l1.5 1.5zm-5.303-.51a.5.5 0 0 1 .707 0l1.414 1.413a.5.5 0 0 1-.707.707L2.343 5.05a.5.5 0 0 1 0-.707zm11.314 0a.5.5 0 0 1 0 .706l-1.414 1.414a.5.5 0 1 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zM11.709 11.5a4 4 0 1 0-7.418 0H.5a.5.5 0 0 0 0 1h15a.5.5 0 0 0 0-1h-3.79zM0 10a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2A.5.5 0 0 1 0 10zm13 0a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z" })),
React.createElement("symbol", { id: "triangle-left", viewBox: "0 0 16 16" },
React.createElement("polygon", { fill: "currentcolor", points: "0 8,12 2,12 14" })),
React.createElement("symbol", { id: "triangle-right", viewBox: "0 0 16 16" },
React.createElement("polygon", { fill: "currentcolor", points: "16 8,4 2,4 14" }))));
}
class Utils {
static animateValue(from, to, duration, onUpdate, onComplete) {
const start = performance.now();
const frame = (now) => {
const elapsed = now - start;
const progress = Math.min(elapsed / duration, 1);
const eased = this.easeInOutSine(progress);
const currentValue = from + (to - from) * eased;
onUpdate(currentValue);
if (progress < 1) {
requestAnimationFrame(frame);
}
else {
onComplete();
}
};
requestAnimationFrame(frame);
}
static easeInOutSine(x) {
return -(Math.cos(Math.PI * x) - 1) / 2;
}
static formatOffset(mins) {
if (mins === 0)
return "Now";
const sign = mins >= 0 ? "+" : "-";
const abs = Math.abs(mins);
const hrs = Math.floor(abs / 60);
const min = abs % 60;
return `${sign}${hrs}:${String(min).padStart(2, "0")}`;
}
static formatShortDate(date) {
return new Intl.DateTimeFormat(this.LOCALE, {
month: "short",
day: "numeric",
}).format(date);
}
static getOffsetFromSliderX(x, containerWidth, maxOffset) {
const centerX = containerWidth / 2;
const deltaX = x - centerX;
const ratio = deltaX / centerX;
return Math.round(ratio * maxOffset);
}
static getRelativeTimestamp(timeA, timeB) {
const now = new Date();
let relative = this.formatShortDate(timeB);
if (isSameDay(now, timeB))
relative = "Today";
if (isTomorrow(timeB))
relative = "Tomorrow";
if (isYesterday(timeB))
relative = "Yesterday";
const diffMs = timeB.getTime() - timeA.getTime();
const diffTotalMinutes = Math.round(diffMs / (1000 * 60));
const offsetAbsMinutes = Math.abs(diffTotalMinutes);
const offsetHours = Math.floor(offsetAbsMinutes / 60);
const is1Hour = offsetHours === 1;
const hoursLabel = is1Hour ? "hour" : "hours";
const offsetMinutes = offsetAbsMinutes % 60;
const is1Minute = offsetMinutes === 1;
const minutesLabel = is1Minute ? "minute" : "minutes";
const ahead = diffTotalMinutes > 0;
const behind = diffTotalMinutes < 0;
const sign = ahead ? "+" : behind ? "-" : "±";
const parts = [];
if (offsetHours > 0)
parts.push(`${offsetHours} ${hoursLabel}`);
if (offsetMinutes > 0)
parts.push(`${offsetMinutes} ${minutesLabel}`);
if (parts.length === 0)
parts.push("same time");
let full = parts.join(" ");
if (ahead)
full += " ahead";
if (behind)
full += " behind";
const shortHours = `${sign}${offsetHours}`;
const shortMins = `${shortHours}:${offsetMinutes.toString().padStart(2, "0")}`;
const shortMins00 = `${shortHours}${is1Hour ? "HR" : "HRS"}`;
const short = offsetMinutes > 0 ? shortMins : shortMins00;
return { relative, full, short };
}
static getSliderXFromOffset(offsetMinutes, containerWidth, maxOffset) {
const centerX = containerWidth / 2;
return centerX + (offsetMinutes / maxOffset) * centerX;
}
static getTimeOfDay(hour) {
if (hour >= 6 && hour < 9)
return "sunrise";
if (hour >= 9 && hour < 18)
return "day";
if (hour >= 18 && hour < 20)
return "sunset";
return "night";
}
}
Utils.LOCALE = navigator.language;
;
;
;
;
;
wget 'https://lists2.roe3.org/mdrone/world-clock/style.css'
* {
border: 0;
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--hue: 223;
--sat: 10%;
--white: hsl(0, 0%, 100%);
--gray100: hsl(var(--hue), var(--sat), 90%);
--gray200: hsl(var(--hue), var(--sat), 80%);
--gray300: hsl(var(--hue), var(--sat), 70%);
--gray400: hsl(var(--hue), var(--sat), 60%);
--gray500: hsl(var(--hue), var(--sat), 50%);
--gray600: hsl(var(--hue), var(--sat), 40%);
--gray700: hsl(var(--hue), var(--sat), 30%);
--gray800: hsl(var(--hue), var(--sat), 20%);
--gray900: hsl(var(--hue), var(--sat), 10%);
--black: hsl(0, 0%, 0%);
--green500: hsl(82, 60%, 45%);
--green700: hsl(82, 60%, 25%);
--yellow500: hsl(58, 100%, 45%);
--yellow800: hsl(40, 100%, 45%);
--trans-dur: 0.3s;
--trans-timing: cubic-bezier(0.65, 0, 0.35, 1);
color-scheme: light dark;
font-size: clamp(1rem, 0.95rem + 0.25vw, 1.25rem);
}
body,
button {
color: light-dark(var(--gray900), var(--gray100));
font: 1em/1.5 Inter, sans-serif;
transition: background-color var(--trans-dur), color var(--trans-dur);
}
body {
background-color: light-dark(var(--gray100), var(--gray900));
display: grid;
place-items: center;
overflow-x: hidden;
height: 100vh;
}
button {
appearance: none;
-webkit-tap-highlight-color: transparent;
}
main {
padding: 1.5em 3em;
width: 100vw;
}
.icon {
display: block;
width: 1em;
height: 1em;
}
.clocks {
margin: auto;
max-width: 33em;
padding-top: 2.25em;
position: relative;
}
.clocks__row {
display: grid;
gap: 1.5em;
grid-template-columns: 1fr 7em;
align-items: center;
height: 4.5em;
transition: box-shadow var(--trans-dur);
user-select: none;
-webkit-user-select: none;
}
.clocks__row + .clocks__row {
box-shadow: 0 -1px 0 light-dark(var(--gray300), var(--gray700));
}
.clocks__start {
min-width: 0;
}
.clocks__end {
display: flex;
justify-content: space-between;
align-items: center;
}
.clocks__city, .clocks__relative {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.clocks__city {
font-size: 1.25em;
font-weight: 400;
line-height: 1.2;
}
.clocks__relative, .clocks__time, .clocks__tod {
transition: color var(--trans-dur);
}
.clocks__relative {
color: light-dark(var(--gray600), var(--gray400));
}
.clocks__relative--full {
display: none;
}
.clocks__time {
font-size: 1.5em;
font-weight: 400;
}
.clocks__m {
font-size: 0.5em;
font-weight: 600;
}
.clocks__tod {
font-size: 1.25em;
}
.clocks__row--sunrise .clocks__time {
color: light-dark(var(--gray900), var(--gray100));
}
.clocks__row--day .clocks__time {
color: light-dark(var(--green700), var(--green500));
}
.clocks__row--day .clocks__tod, .clocks__row--sunrise .clocks__tod, .clocks__row--sunset .clocks__tod {
color: light-dark(var(--yellow800), var(--yellow500));
}
.clocks__row--sunset .clocks__time, .clocks__row--night .clocks__time, .clocks__row--night .clocks__tod {
color: light-dark(var(--gray600), var(--gray400));
}
.clocks__slider {
cursor: ew-resize;
top: 2.5em;
bottom: 0;
left: 0;
width: 1.5em;
transform: translateX(-50%);
z-index: 5;
}
.clocks__slider, .clocks__slider-wrapper, .clocks__slider-line, .clocks__slider-arrow {
position: absolute;
}
.clocks__slider-wrapper {
top: 0;
bottom: 0;
}
.clocks__slider-line {
background: light-dark(var(--gray700), var(--gray300));
left: 50%;
width: 2px;
height: 100%;
transform: translateX(-50%);
transition: background-color var(--trans-dur);
}
.clocks__slider-arrow {
color: light-dark(var(--gray700), var(--gray300));
top: 50%;
transform: translateY(-50%);
transition: color var(--trans-dur);
}
.clocks__slider-arrow--left {
left: 0;
}
.clocks__slider-arrow--right {
right: 0;
}
.clocks__slider-arrow .icon {
width: 0.5em;
}
.clocks__tooltip {
border-radius: 0.25em;
box-shadow: 0 0 0 2px light-dark(var(--gray400), var(--gray600)) inset;
color: light-dark(var(--gray900), var(--gray100));
cursor: ew-resize;
font-size: 0.875em;
display: flex;
align-items: center;
gap: 0.25em;
opacity: 0;
padding: 0.25em 0.5em;
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
transition: background-color var(--trans-dur), box-shadow var(--trans-dur), color var(--trans-dur), opacity var(--trans-dur) var(--trans-timing), visibility var(--trans-dur) var(--trans-timing);
white-space: nowrap;
user-select: none;
-webkit-user-select: none;
visibility: hidden;
z-index: 1;
}
.clocks__tooltip, .clocks__tooltip:after {
background-color: light-dark(var(--gray100), var(--gray900));
}
.clocks__tooltip:after {
box-shadow: -2px -2px 0 light-dark(var(--gray400), var(--gray600)) inset;
clip-path: polygon(80% 0, 100% 0, 100% 100%, 0 100%, 0 80%);
content: "";
display: block;
position: absolute;
top: 100%;
left: 50%;
width: 1em;
height: 1em;
transform: translate(-50%, -50%) rotate(45deg);
transition: background-color var(--trans-dur), box-shadow var(--trans-dur);
}
.clocks__tooltip--show {
opacity: 1;
visibility: visible;
}
.clocks__tooltip-close {
background-color: transparent;
border-radius: 0.125em;
color: light-dark(var(--gray700), var(--gray300));
cursor: pointer;
display: grid;
place-items: center;
margin-inline-end: -0.25em;
width: 1.5em;
height: 1.5em;
}
.clocks__tooltip-close:hover {
background-color: light-dark(var(--gray200), var(--gray700));
}
.clocks__sr-only {
overflow: hidden;
position: absolute;
width: 1px;
height: 1px;
}
@media (min-width: 600px) {
.clocks__row {
grid-template-columns: 1fr 12em;
}
.clocks__relative--short {
display: none;
}
.clocks__relative--full {
display: inherit;
}
.clocks__time {
font-size: 3em;
font-weight: 200;
}
.clocks__m {
font-weight: 400;
}
}