/* Full font (580 KB) is only downloaded when a page uses a character outside the subset below.
   Browsers try same-family faces last-declared first, so the small subset wins for normal text. */
@font-face {
  font-family: "Fixedsys Excelsior";
  src: url("fonts/FSEX302.ttf") format("truetype");
  font-display: swap;
}
/* Subset: Latin, Latin-1/Extended-A, punctuation, arrows, math, box drawing, blocks, shapes (~12 KB). */
@font-face {
  font-family: "Fixedsys Excelsior";
  src: url("fonts/FSEX302-latin.woff2") format("woff2");
  font-display: swap;
  unicode-range: U+0020-007E, U+00A0-017F, U+2010-205E, U+20AC, U+2122, U+2190-21FF, U+2200-22FF, U+2500-25FF, U+FFFD;
}

/* Defaults. The theme in site.json overrides these at runtime. */
:root {
  --bg: #0b0b0b;
  --fg: #e4e4e4;
  --muted: #8a8a8a;
  --accent: #ffffff;
  --link: #a9c7d6;
  --border: #2a2a2a;
  --code-bg: #131313;
  --font: "Fixedsys Excelsior", ui-monospace, Consolas, monospace;
  --size: 16px;
  --width: 820px;
  --lh: 1.5;
  color-scheme: dark;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html { background: var(--bg); }
body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  font-size: var(--size);
  line-height: var(--lh);
  -webkit-font-smoothing: none;
  font-smooth: never;
  text-rendering: optimizeSpeed;
}
::selection { background: var(--fg); color: var(--bg); }
a { color: var(--link); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }
.muted { color: var(--muted); }
hr { border: 0; border-top: 1px solid var(--border); margin: 2em 0; }

.wrap { max-width: var(--width); margin: 0 auto; padding: 24px 16px 48px; }

/* top bar */
.topbar {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 8px 24px; padding: 10px 16px; border: 1px solid var(--border); margin-bottom: 40px;
}
.brand { color: var(--accent); }
.brand::before { content: "[ "; color: var(--muted); }
.brand::after { content: " ]"; color: var(--muted); }
.brand:hover { text-decoration: none; }
.cursor { display: none; }
.show-cursor .cursor { display: inline; animation: blink 1.2s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .show-cursor .cursor { animation: none; } }
#nav { display: flex; flex-wrap: wrap; gap: 4px 20px; }
#nav a { color: var(--fg); text-transform: lowercase; }
#nav a.active { color: var(--accent); }
#nav a.active::before { content: "> "; color: var(--muted); }

/* home */
.home { text-align: center; }
.home .md { text-align: center; }
.home .md ul, .home .md ol { display: inline-block; text-align: left; }
.home h2.sub { margin-top: 2.5em; font-weight: normal; font-size: 1em; }
.recent { display: inline-block; text-align: left; margin: 0 auto; }
.friends { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin-top: 1em; }
.friends a { position: relative; display: block; width: 88px; height: 31px; overflow: hidden; border: 1px solid var(--border); }
/* Images are stretched to 88x31 on purpose. They sit blurred and dimmed under the name; hover/focus shows them sharp. */
.friends img {
  position: absolute; inset: 0; width: 100%; height: 100%; image-rendering: pixelated;
  filter: blur(2px) brightness(0.45) saturate(0.8); transform: scale(1.12);
}
.friends .txt {
  position: relative; display: flex; align-items: center; justify-content: center; height: 100%; padding: 0 4px;
  color: var(--fg); font-size: 16px; line-height: 1; white-space: nowrap; overflow: hidden;
}
.friends .txt.long { justify-content: flex-start; mask-image: linear-gradient(90deg, transparent, #000 4px, #000 calc(100% - 4px), transparent); }
.friends .txt.long .t { overflow: hidden; text-overflow: ellipsis; }
.motion .friends .txt.long .t { overflow: visible; animation: name-pan 7s ease-in-out infinite alternate; }
@keyframes name-pan { 0%, 20% { transform: translateX(0); } 80%, 100% { transform: translateX(var(--over)); } }
.friends .has-img .txt { color: #fff; text-shadow: 0 0 3px #000, 0 0 1px #000; }
.friends a:hover, .friends a:focus-visible { border-color: var(--muted); }
.friends .has-img:hover img, .friends .has-img:focus-visible img { filter: none; transform: none; }
.friends .has-img:hover .txt, .friends .has-img:focus-visible .txt { opacity: 0; }
.motion .friends img { transition: filter 0.25s, transform 0.25s; }
.motion .friends .txt { transition: opacity 0.2s; }
@media (prefers-reduced-motion: reduce) {
  .motion .friends img, .motion .friends .txt { transition: none; }
  .motion .friends .txt.long .t { overflow: hidden; animation: none; }
}

/* lists */
ul.list { list-style: none; padding: 0; margin: 0.5em 0; }
ul.list li { margin: 2px 0; }
ul.list li::before { content: "=> "; color: var(--muted); }
.date { color: var(--muted); }
.tag { color: var(--muted); }
.tag:hover { color: var(--fg); }
.section-desc { color: var(--muted); margin-top: -0.5em; }
.filter {
  width: 100%; background: transparent; color: var(--fg); border: 1px solid var(--border);
  font: inherit; padding: 6px 10px; margin-bottom: 1em; outline: none;
}
.filter:focus { border-color: var(--muted); }

/* article */
.post-head h1 { margin-bottom: 0.2em; }
.post-head .meta { color: var(--muted); margin-bottom: 1.5em; }
details.toc { border-left: 1px solid var(--border); padding-left: 12px; margin-bottom: 2em; }
details summary { cursor: pointer; list-style: none; color: var(--link); }
details summary::-webkit-details-marker { display: none; }
details summary::before { content: "[+] "; }
details[open] summary::before { content: "[-] "; }
details.toc ol { margin: 0.4em 0; padding-left: 1.5em; }
details.toc .h3 { margin-left: 1.5em; list-style: circle; }
.post-nav { display: flex; justify-content: space-between; gap: 16px; border-top: 1px solid var(--border); margin-top: 3em; padding-top: 1em; }

/* markdown body (shared with editor preview) */
.md h1, .md h2, .md h3, .md h4 { color: var(--accent); font-weight: normal; line-height: 1.25; margin: 1.6em 0 0.5em; }
.md h1 { font-size: 2em; }
.md h2 { font-size: 1.5em; }
.md h3 { font-size: 1.2em; }
.md h4 { font-size: 1em; }
.md h2::before { content: "# "; color: var(--muted); }
.md h3::before { content: "## "; color: var(--muted); }
.md > :first-child { margin-top: 0; }
.md img, .md video { max-width: 100%; height: auto; }
.md blockquote { margin: 1em 0; padding: 0 0 0 14px; border-left: 1px solid var(--muted); color: var(--muted); }
.md code { background: var(--code-bg); padding: 0 4px; font-family: inherit; }
.md pre { font-family: inherit; position: relative; background: var(--code-bg); border: 1px solid var(--border); padding: 12px 14px; overflow-x: auto; }
.md pre code { background: none; padding: 0; }
.md .copy {
  position: absolute; top: 4px; right: 6px; background: none; border: 0; color: var(--muted);
  font: inherit; cursor: pointer; opacity: 0;
}
.md pre:hover .copy, .md .copy:focus { opacity: 1; }
.md table { border-collapse: collapse; display: block; overflow-x: auto; margin: 1em 0; }
.md th, .md td { border: 1px solid var(--border); padding: 4px 12px; text-align: left; }
.md th { color: var(--accent); font-weight: normal; }
.md hr { border-top: 1px dashed var(--border); }
.md li { margin: 2px 0; }
.md kbd { border: 1px solid var(--border); padding: 0 4px; font-family: inherit; }
.md .anchor { color: var(--muted); margin-left: 0.4em; opacity: 0; font-size: 0.8em; }
.md :is(h1, h2, h3, h4):hover .anchor { opacity: 1; }

.foot { margin-top: 64px; color: var(--muted); text-align: center; font-size: 0.9em; }
.foot a { color: var(--muted); }

/* status colours (theme: ok / warn / fail) */
:root { --ok: #8fbf8f; --warn: #d6b56f; --fail: #d67a7a; }
.status { white-space: pre; }
.status-ok { color: var(--ok); }
.status-warn { color: var(--warn); }
.status-fail { color: var(--fail); }
.status-info { color: var(--link); }

/* callouts: > [!NOTE] */
.md blockquote.callout { color: var(--fg); border-left-color: var(--link); }
.md .callout-title { color: var(--link); }
.md .callout-tip { border-left-color: var(--ok); }
.md .callout-tip .callout-title { color: var(--ok); }
.md .callout-important, .md .callout-warning { border-left-color: var(--warn); }
.md :is(.callout-important, .callout-warning) .callout-title { color: var(--warn); }
.md .callout-caution { border-left-color: var(--fail); }
.md .callout-caution .callout-title { color: var(--fail); }

/* syntax highlighting (highlight.js classes, driven by theme vars) */
.hljs-comment, .hljs-quote, .hljs-meta, .hljs-doctag { color: var(--muted); }
.hljs-keyword, .hljs-selector-tag, .hljs-section, .hljs-name { color: var(--accent); }
.hljs-string, .hljs-regexp, .hljs-addition, .hljs-template-tag { color: var(--ok); }
.hljs-number, .hljs-literal, .hljs-symbol, .hljs-bullet, .hljs-variable.constant_ { color: var(--warn); }
.hljs-title, .hljs-built_in, .hljs-type, .hljs-attr, .hljs-attribute, .hljs-params { color: var(--link); }
.hljs-deletion { color: var(--fail); }

/* search snippets */
.snippet { color: var(--muted); margin: 0 0 6px 3ch; font-size: 0.9em; }
.snippet mark { background: none; color: var(--fg); text-decoration: underline; }

/* series box */
details.series { border: 1px solid var(--border); padding: 6px 12px; margin-bottom: 1.5em; }
details.series ol { margin: 0.4em 0; padding-left: 2em; }
details.series .here { color: var(--accent); }

/* optional sticky contents on wide screens (theme: sideToc) */
@media (min-width: 1300px) {
  .side-toc details.toc {
    position: fixed; top: 120px; left: calc(50% + var(--width) / 2 + 24px);
    width: calc(50% - var(--width) / 2 - 48px); max-width: 260px; max-height: calc(100vh - 160px); overflow-y: auto;
    font-size: 0.9em; margin: 0;
  }
}

/* webring */
.webring { margin-top: 2em; }
.webring a { margin: 0 6px; }

/* ---- motion (theme: motion; always off with prefers-reduced-motion) ---- */
.motion #main.enter { animation: enter 0.22s ease-out; }
@keyframes enter { from { opacity: 0; transform: translateY(4px); } }
.motion a, .motion button { transition: color 0.15s, background-color 0.15s, border-color 0.15s; }
.motion ul.list li { transition: transform 0.15s; }
.motion ul.list li:hover { transform: translateX(4px); }
@media (prefers-reduced-motion: reduce) {
  .motion #main.enter { animation: none; }
  .motion ul.list li:hover { transform: none; }
}

/* reading progress on posts */
#progress {
  position: fixed; top: 0; left: 0; right: 0; height: 2px; background: var(--muted);
  transform-origin: 0 50%; transform: scaleX(0); z-index: 10; pointer-events: none;
}

/* image zoom */
.md img { cursor: zoom-in; }
#lightbox {
  position: fixed; inset: 0; z-index: 30; display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--bg) 92%, transparent); cursor: zoom-out; padding: 24px;
}
#lightbox img { max-width: 100%; max-height: 100%; border: 1px solid var(--border); }
.motion #lightbox:not([hidden]) { animation: enter 0.15s ease-out; }

/* ---- terminal (press :) ---- */
.term-hint {
  background: none; border: 0; color: var(--muted); font: inherit; cursor: pointer; margin-top: 6px; padding: 0;
}
.term-hint:hover { color: var(--fg); }
#term {
  position: fixed; left: 50%; bottom: 16px; transform: translateX(-50%); z-index: 20;
  width: min(var(--width), calc(100% - 32px)); background: var(--bg); border: 1px solid var(--muted);
  padding: 8px 12px; box-shadow: 0 0 0 100vmax color-mix(in srgb, var(--bg) 40%, transparent);
}
.motion #term:not([hidden]) { animation: enter 0.15s ease-out; }
#term-out { max-height: 40vh; overflow-y: auto; white-space: normal; }
#term-out:not(:empty) { margin-bottom: 6px; }
.term-line { display: flex; gap: 0; align-items: baseline; }
#ps1 { color: var(--ok); white-space: pre; }
#term-in {
  flex: 1; min-width: 0; background: transparent; border: 0; outline: none; color: var(--fg);
  font: inherit; padding: 0; caret-color: var(--fg);
}

/* ---- widgets (```notepad, ```checklist, ```terminal, ```typewriter) ---- */
.widget { border: 1px solid var(--border); margin: 1em 0; }
.widget-bar {
  display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: center; padding: 2px 10px;
  border-bottom: 1px solid var(--border); color: var(--muted); font-size: 0.9em;
}
.widget-name::before { content: "# "; }
.widget-hint { color: var(--muted); }
.widget-bar .spacer { flex: 1; }
.widget-bar button { background: none; border: 0; color: var(--link); font: inherit; cursor: pointer; padding: 0; }
.widget-bar button:hover { color: var(--fg); }
.widget-notepad textarea {
  display: block; width: 100%; resize: vertical; border: 0; outline: none; background: var(--code-bg);
  color: var(--fg); font: inherit; line-height: var(--lh); padding: 10px 12px;
}
.widget-checklist ul { list-style: none; margin: 0; padding: 8px 12px; }
.widget-checklist label { display: flex; gap: 10px; align-items: baseline; cursor: pointer; }
.widget-checklist input { accent-color: var(--fg); }
.widget-checklist input:checked + span { color: var(--muted); text-decoration: line-through; }
.md .widget-terminal pre.term { margin: 0; border: 0; }
.term-cmd { color: var(--fg); }
.term-out { color: var(--muted); }
.typewriter { white-space: pre-wrap; }
.type-cursor { animation: blink 1s steps(1) infinite; }

/* ---- 404 cat (cat.js) ---- */
.cat { margin: 1.5em 0; }
.cat-say { height: 1.5em; color: var(--accent); padding-left: 11ch; }
.md .cat-art, .cat-art { display: inline-block; margin: 0; padding: 0; background: none; border: 0; color: var(--fg); cursor: pointer; user-select: none; line-height: 1.15; }
.md .cat-art:focus-visible { outline: 1px dashed var(--muted); outline-offset: 4px; }
.cat-note { font-size: 0.9em; margin-top: 0.5em; }

/* ---- seasons (seasons.js): canvas sits behind the page ---- */
#season { position: fixed; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; }
.wrap { position: relative; z-index: 1; }

/* ---- announcements (site.json "announcements") ---- */
#announce:empty { display: none; }
#announce { display: flex; flex-direction: column; gap: 6px; margin: 12px 0 28px; }
.announce { display: flex; gap: 1ch; align-items: baseline; border: 1px solid var(--border); border-left: 2px solid var(--ann); padding: 6px 10px; background: var(--bg); }
.announce-info { --ann: var(--link); }
.announce-warn { --ann: var(--warn); }
.announce-alert { --ann: var(--fail); }
.announce-tag { color: var(--ann); white-space: nowrap; }
.announce-text { flex: 1; min-width: 0; }
.announce-text p { margin: 0; }
.announce-x { color: var(--muted); background: none; border: 0; padding: 0; font: inherit; cursor: pointer; }
.announce-x:hover, .announce-x:focus-visible { color: var(--fg); }
.motion .announce { animation: enter 0.3s ease-out; }
@media (prefers-reduced-motion: reduce) { .motion .announce { animation: none; } }

/* ---- pinout widget ---- */
.pinout { overflow-x: auto; padding: 10px 12px 0; }
.pin { display: inline-flex; flex-direction: column; align-items: center; gap: 4px; min-width: 5ch; padding: 0 2px; background: none; border: 0; color: var(--fg); font: inherit; cursor: pointer; }
.pin-num { display: inline-block; min-width: 3ch; padding: 2px 4px; border: 1px solid var(--pin, var(--border)); color: var(--pin, var(--fg)); text-align: center; }
.pin-name { color: var(--pin, var(--fg)); font-size: 0.9em; white-space: nowrap; }
.pin-pwr { --pin: var(--fail); }
.pin-gnd { --pin: var(--muted); }
.pin-sig { --pin: var(--link); }
.pin-nc { --pin: var(--border); }
.pin.on .pin-num, .pin:focus-visible .pin-num { background: var(--pin, var(--fg)); color: var(--bg); }
.pin:focus-visible { outline: none; }
.pin-row { display: flex; gap: 6px; }
.pinout-dual .pin-row + .pin-row { margin-top: 6px; }
.pinout-dual .pin.top { flex-direction: column-reverse; }
.pinout-dip { display: inline-grid; grid-template-columns: auto 10ch auto; align-items: center; }
.dip-row { display: contents; }
.dip-row .pin { flex-direction: row; padding: 3px 0; }
.dip-row .pin.left { flex-direction: row-reverse; justify-self: end; }
.dip-row .pin.right { justify-self: start; }
.dip-body { align-self: stretch; border-left: 1px solid var(--muted); border-right: 1px solid var(--muted); min-height: 2em; color: var(--muted); padding: 0 6px; }
.dip-row:first-child .dip-body { border-top: 1px solid var(--muted); }
.dip-row:last-child .dip-body { border-bottom: 1px solid var(--muted); }
.pin-info { min-height: 1.5em; font-size: 0.9em; padding: 4px 12px 8px; }

/* ---- hexdump widget ---- */
.md pre.hexdump { margin: 0; border: 0; line-height: 1.35; }
.hx-off { color: var(--muted); }
.hx-asc { color: var(--muted); }
.hx-pad { white-space: pre; }
.hx { cursor: default; }
.hx.on { background: var(--fg); color: var(--bg); }
.mk0 { background: color-mix(in srgb, var(--link) 30%, transparent); }
.mk1 { background: color-mix(in srgb, var(--warn) 30%, transparent); }
.mk2 { background: color-mix(in srgb, var(--ok) 30%, transparent); }
.mk3 { background: color-mix(in srgb, var(--fail) 30%, transparent); }
.hx-legend { font-size: 0.9em; padding: 6px 12px 0; line-height: 1.8; }
.hx-legend span { padding: 0 4px; }

/* ---- footnotes / side notes ---- */
.fn-ref { font-size: 0.75em; line-height: 0; }
.fn-ref a::before { content: "["; }
.fn-ref a::after { content: "]"; }
.sidenote { display: none; }
.footnotes { margin-top: 3em; padding-top: 1em; border-top: 1px solid var(--border); color: var(--muted); font-size: 0.9em; }
.footnotes ol { padding-left: 2em; }
.fn-back { text-decoration: none; }
.flash { animation: flash 1.2s ease-out; }
@keyframes flash { from { background: color-mix(in srgb, var(--accent) 25%, transparent); } to { background: transparent; } }
/* Wide screens (and no sticky contents in the margin): notes sit beside the paragraph instead of at the end. */
@media (min-width: 1400px) {
  body:not(.side-toc) .md .sidenote {
    display: block; float: right; clear: right; position: relative; width: 230px; margin: 0.2em -260px 0.6em 0;
    color: var(--muted); font-size: 0.85em; line-height: 1.4; text-indent: 0;
  }
  body:not(.side-toc) .md .footnotes { display: none; }
}
@media (prefers-reduced-motion: reduce) { .flash { animation: none; } }
