183 lines
5.8 KiB
Plaintext
183 lines
5.8 KiB
Plaintext
---
|
|
import "../styles/global.css";
|
|
import { site } from "../data/site";
|
|
import Egg from "../components/Egg.astro";
|
|
import { Icon } from "astro-icon/components";
|
|
|
|
interface Props {
|
|
title?: string;
|
|
description?: string;
|
|
nav?: boolean;
|
|
}
|
|
|
|
const {
|
|
title = `${site.name} — ${site.tagline}`,
|
|
description = site.description,
|
|
nav = true,
|
|
} = Astro.props;
|
|
|
|
const path = Astro.url.pathname;
|
|
const canonical = new URL(path, `https://${site.domain}`).href;
|
|
|
|
const KAO_DEADLINE = "2027-01-01T00:00:00";
|
|
const kaoMs = new Date(KAO_DEADLINE).getTime() - Date.now();
|
|
const kaoCount = kaoMs > 0 ? `${Math.floor(kaoMs / 86_400_000)}d` : "in effect";
|
|
---
|
|
|
|
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<title>{title}</title>
|
|
<meta name="description" content={description} />
|
|
<link rel="canonical" href={canonical} />
|
|
{path.startsWith("/admin") && <meta name="robots" content="noindex, nofollow" />}
|
|
<link rel="icon" href="/favicon.ico" sizes="32x32" />
|
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
<meta name="color-scheme" content="dark" />
|
|
<meta name="theme-color" content="#1b1a18" />
|
|
{
|
|
path === "/" && (
|
|
<>
|
|
<link rel="preconnect" href="https://assets.hardcover.app" crossorigin />
|
|
<link rel="preconnect" href="https://i.scdn.co" crossorigin />
|
|
</>
|
|
)
|
|
}
|
|
<script is:inline>
|
|
try {
|
|
if (localStorage.getItem("kao-ribbon") === "off")
|
|
document.documentElement.dataset.ribbon = "off";
|
|
} catch (e) {}
|
|
</script>
|
|
|
|
<meta property="og:type" content="website" />
|
|
<meta property="og:site_name" content={site.domain} />
|
|
<meta property="og:url" content={canonical} />
|
|
<meta property="og:title" content={title} />
|
|
<meta property="og:description" content={description} />
|
|
<meta property="og:image" content={`https://${site.domain}/og-image.png`} />
|
|
<meta name="twitter:card" content="summary_large_image" />
|
|
<meta name="twitter:title" content={title} />
|
|
<meta name="twitter:description" content={description} />
|
|
<meta name="twitter:image" content={`https://${site.domain}/og-image.png`} />
|
|
</head>
|
|
<body>
|
|
<a class="skip" href="#main">skip to content</a>
|
|
|
|
<div class="ribbon">
|
|
<a
|
|
class="ribbon__link"
|
|
href="https://keepandroidopen.org/"
|
|
target="_blank"
|
|
rel="noopener"
|
|
data-umami-event="ribbon"
|
|
data-umami-event-to="keepandroidopen"
|
|
>
|
|
<span class="ribbon__dot" aria-hidden="true"></span>
|
|
<span class="ribbon__text">keep android open</span>
|
|
<span class="ribbon__sub"
|
|
>— <span
|
|
class="ribbon__count"
|
|
data-kao-count
|
|
data-kao-deadline={KAO_DEADLINE}>{kaoCount}</span
|
|
></span
|
|
>
|
|
<span class="ribbon__arw" aria-hidden="true">↗</span>
|
|
</a>
|
|
<button
|
|
class="ribbon__x"
|
|
type="button"
|
|
data-ribbon-dismiss
|
|
aria-label="dismiss"
|
|
>✕</button>
|
|
</div>
|
|
|
|
{
|
|
nav && (
|
|
<header class="topbar">
|
|
<a class="mark" href="/">{site.wordmark}</a>
|
|
<nav class="topnav" aria-label="primary">
|
|
<a href="/projects" aria-current={path.startsWith("/projects") ? "page" : undefined}>
|
|
projects
|
|
</a>
|
|
<a href="/notes" aria-current={path.startsWith("/notes") ? "page" : undefined}>
|
|
notes
|
|
</a>
|
|
<a href="/contact" aria-current={path.startsWith("/contact") ? "page" : undefined}>
|
|
contact
|
|
</a>
|
|
</nav>
|
|
</header>
|
|
)
|
|
}
|
|
|
|
<main id="main">
|
|
<slot />
|
|
<p class="colophon">
|
|
<span class="version">{site.version}</span>
|
|
<Egg
|
|
note="third full version of the site, this ones a complete ui rebuild (still on cf workers, always)."
|
|
/>
|
|
</p>
|
|
<p class="srcline">
|
|
<a
|
|
href="https://git.zachy.cc/zach/website/"
|
|
target="_blank"
|
|
rel="noopener"
|
|
data-umami-event="src"
|
|
>
|
|
<Icon class="srcline__icon" name="ph:git-branch" aria-hidden="true" />
|
|
source ↗
|
|
</a>
|
|
</p>
|
|
</main>
|
|
|
|
<script>
|
|
const mark = document.querySelector(".mark");
|
|
const still = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
if (mark && !still.matches) {
|
|
const sweep = () => {
|
|
mark.classList.add("is-sweeping");
|
|
setTimeout(() => mark.classList.remove("is-sweeping"), 1200);
|
|
setTimeout(sweep, 9000 + Math.random() * 13000);
|
|
};
|
|
setTimeout(sweep, 4000 + Math.random() * 4000);
|
|
}
|
|
|
|
document
|
|
.querySelector("[data-ribbon-dismiss]")
|
|
?.addEventListener("click", () => {
|
|
document.querySelector(".ribbon")?.remove();
|
|
try {
|
|
localStorage.setItem("kao-ribbon", "off");
|
|
} catch (e) {}
|
|
});
|
|
|
|
const kaoEl = document.querySelector("[data-kao-count]");
|
|
if (kaoEl instanceof HTMLElement && kaoEl.dataset.kaoDeadline) {
|
|
const target = new Date(kaoEl.dataset.kaoDeadline).getTime();
|
|
const tick = () => {
|
|
const d = target - Date.now();
|
|
if (d <= 0) {
|
|
kaoEl.textContent = "in effect";
|
|
return true;
|
|
}
|
|
const days = Math.floor(d / 86400000);
|
|
const hrs = Math.floor((d % 86400000) / 3600000);
|
|
const min = Math.floor((d % 3600000) / 60000);
|
|
const sec = Math.floor((d % 60000) / 1000);
|
|
kaoEl.textContent = `${days}d ${hrs}h ${min}m ${sec}s`;
|
|
return false;
|
|
};
|
|
if (!tick()) {
|
|
const iv = setInterval(() => {
|
|
if (tick()) clearInterval(iv);
|
|
}, 1000);
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|