/* cengil.co: dark, dotted, terminal. one stylesheet, no web fonts. */

:root {
  /* Dark by default; the toggle sets html[data-theme="light"]. */
  color-scheme: dark;

  --bg: light-dark(#f4f3ee, #0a0a0b);
  --bg-elev: light-dark(#ecebe4, #111113);
  --text: light-dark(#1f1f1c, #d6d6cf);
  --text-muted: light-dark(#53534d, #a1a19a);
  --dim-base: light-dark(#686861, #7a7a73);
  --heading: light-dark(#0d0d0c, #f3f3ee);
  /* Accent palette. Picked with the swatch menu (html[data-accent]); default is mono. */
  --acc-mono: light-dark(#0d0d0c, #f3f3ee);
  --acc-amber: light-dark(#8a5200, #f5b544);
  --acc-green: light-dark(#1a6b2c, #7ee08a);
  --acc-blue: light-dark(#0b57b0, #7cb8ff);
  --acc-rose: light-dark(#a3123f, #ff8fa8);
  --acc-violet: light-dark(#6a32c9, #c4a5ff);
  --accent: var(--acc-mono);

  /* Everything quiet is tinted by the accent, so picking one recolors the
     whole page: dim text, rules, background dots, glow, ascii art. Mixing
     toward the accent only moves dim text away from the background, so
     contrast stays at or above the neutral tone. */
  --text-dim: color-mix(in srgb, var(--accent) 22%, var(--dim-base));
  --border: color-mix(in srgb, var(--accent) 13%, var(--bg));
  --dot: light-dark(color-mix(in srgb, var(--accent) 16%, transparent), color-mix(in srgb, var(--accent) 11%, transparent));
  --glow: color-mix(in srgb, var(--accent) 10%, transparent);
  --art: color-mix(in srgb, var(--accent) 45%, var(--dim-base));

  /* Vertical gap between page blocks (header, sections, footer). */
  --block: clamp(2.25rem, 1.75rem + 2vw, 3rem);
  --gutter: 1.25rem;

  --fs-xs: 0.75rem;
  --fs-sm: 0.875rem;
  --fs-base: 1rem;
  --fs-lg: 1.25rem;
  --fs-xl: 1.6rem;
  --fs-hero: clamp(1.9rem, 1.4rem + 1.8vw, 2.6rem);

  --mono: ui-monospace, "SF Mono", SFMono-Regular, "JetBrains Mono", "Cascadia Mono", Menlo, Consolas, "Liberation Mono", monospace;

  /* One arrow cursor. Over links and buttons it gains a terminal block caret,
     so hover reads clearly without switching to a different cursor. These
     neutral fallbacks (white, dark outline) show on both themes; theme.js
     swaps in versions drawn in the current accent. */
  --cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28'%3E%3Cpath d='M3 2v17l4.5-4.2 3 6.7 3-1.3-3-6.6H16z' fill='%23fff' stroke='%23000' stroke-width='1.5' stroke-linejoin='round'/%3E%3C/svg%3E") 3 2, auto;
  --cursor-link: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28'%3E%3Cpath d='M3 2v17l4.5-4.2 3 6.7 3-1.3-3-6.6H16z' fill='%23fff' stroke='%23000' stroke-width='1.5' stroke-linejoin='round'/%3E%3Crect x='17.5' y='14.5' width='7' height='11' fill='%23fff' stroke='%23000' stroke-width='1.5'/%3E%3C/svg%3E") 3 2, pointer;
}

:root[data-theme="light"] { color-scheme: light; }

:root[data-accent="amber"] { --accent: var(--acc-amber); }
:root[data-accent="green"] { --accent: var(--acc-green); }
:root[data-accent="blue"] { --accent: var(--acc-blue); }
:root[data-accent="rose"] { --accent: var(--acc-rose); }
:root[data-accent="violet"] { --accent: var(--acc-violet); }

* { box-sizing: border-box; margin: 0; padding: 0; }

/* Cross-page navigation: a quick crossfade, with the top bar held in place
   so it doesn't flash. Browsers without support just navigate normally. */
@view-transition { navigation: auto; }

.topbar { view-transition-name: topbar; }

::view-transition-old(root),
::view-transition-new(root) { animation-duration: 160ms; }

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}

/* Type scales from 14.5px on phones to 16px on large screens. */
html {
  font-size: clamp(14.5px, 13.5px + 0.15vw, 16px);
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Reserve the scrollbar's space on short pages too, so the centered
     column (and the top bar) doesn't jump between pages. */
  scrollbar-gutter: stable;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--mono);
  font-size: var(--fs-base);
  line-height: 1.7;
  padding:
    max(1.25rem, env(safe-area-inset-top))
    max(clamp(1.1rem, 5vw, 2rem), env(safe-area-inset-right))
    max(1.25rem, env(safe-area-inset-bottom))
    max(clamp(1.1rem, 5vw, 2rem), env(safe-area-inset-left));
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  overflow-wrap: break-word;
}

::selection {
  background: var(--accent);
  color: var(--bg);
}

@media (pointer: fine) {
  html { cursor: var(--cursor); }
  a, button, summary, label { cursor: var(--cursor-link); }
}

/* ---------- background: dot grid + one faint glow ---------- */

body::before,
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

body::before {
  background-image: radial-gradient(var(--dot) 1px, transparent 1.2px);
  background-size: 18px 18px;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, rgba(0, 0, 0, 0.55) 60%, rgba(0, 0, 0, 0.3) 100%);
          mask-image: linear-gradient(to bottom, #000 0%, rgba(0, 0, 0, 0.55) 60%, rgba(0, 0, 0, 0.3) 100%);
}

body::after {
  background: radial-gradient(48rem 30rem at 12% -8%, var(--glow), transparent 70%);
}

/* ---------- layout ---------- */

main {
  flex: 1;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 46rem;
  margin: 0 auto;
}

/* Text for screen readers only. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Keyboard users can jump past the top bar. */
.skip-link {
  position: absolute;
  top: -10rem;
  left: 1rem;
  z-index: 30;
  padding: 0.3rem 0.6rem;
  background: var(--accent);
  color: var(--bg);
  text-decoration: none;
}

.skip-link:focus { top: 1rem; }

/* ---------- top bar ---------- */

.topbar {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.4rem 1.5rem;
  padding-bottom: 0.9rem;
  margin-bottom: var(--block);
  border-bottom: 1px dashed var(--border);
  font-size: var(--fs-sm);
}

.topbar ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.1rem;
  list-style: none;
}

.topbar a { color: var(--text-muted); }

.topbar ul a[aria-current="page"] { color: var(--heading); }
.topbar a:hover { color: var(--accent); text-decoration: none; }
.topbar ul a[aria-current="page"]:hover { text-decoration: underline solid var(--accent); }

/* Current page: color and an accent underline only, so no item changes
   width and the bar never shifts between pages. */
.topbar ul a[aria-current="page"] {
  text-decoration: underline solid var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 6px;
}

/* Theme and accent controls need JS. html.js is set by the inline head
   script before first paint, so they render in place instead of popping in. */
.js-only { display: none; }
.js .js-only { display: block; }

.theme-toggle::before { content: "◐"; }
:root[data-theme="light"] .theme-toggle::before { content: "◑"; }

.topbar .brand {
  color: var(--accent);
  font-weight: 700;
}

.theme-toggle,
.accent-toggle,
.accent-menu button {
  font: inherit;
  color: var(--text-muted);
  background: none;
  border: 0;
  padding: 0 0.125rem;
  line-height: 1;
}

/* Keep the small icon buttons at a 24px touch target. */
.theme-toggle,
.accent-toggle,
.accent-menu button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  min-height: 24px;
}

.theme-toggle:hover { color: var(--accent); }

/* Accent picker: a swatch that opens a row of swatches. */
.accent-picker { position: relative; }

.swatch {
  display: inline-block;
  width: 0.7rem;
  height: 0.7rem;
  vertical-align: -0.05rem;
  background: var(--accent);
  outline: 1px solid var(--border);
  outline-offset: 1px;
}

.topbar .accent-menu {
  position: absolute;
  flex-wrap: nowrap;
  width: max-content;
  top: calc(100% + 0.6rem);
  right: 0;
  z-index: 10;
  display: flex;
  gap: 0.6rem;
  padding: 0.6rem 0.7rem;
  list-style: none;
  background: var(--bg);
  border: 1px dashed var(--border);
}

.topbar .accent-menu[hidden] { display: none; }

.accent-menu button[aria-pressed="true"] .swatch { outline-color: var(--heading); }

.accent-menu [data-accent-value="mono"] .swatch { background: var(--acc-mono); }
.accent-menu [data-accent-value="amber"] .swatch { background: var(--acc-amber); }
.accent-menu [data-accent-value="green"] .swatch { background: var(--acc-green); }
.accent-menu [data-accent-value="blue"] .swatch { background: var(--acc-blue); }
.accent-menu [data-accent-value="rose"] .swatch { background: var(--acc-rose); }
.accent-menu [data-accent-value="violet"] .swatch { background: var(--acc-violet); }

/* ---------- headings ---------- */

header { margin-bottom: var(--block); }

h1 {
  font-size: var(--fs-xl);
  font-weight: 700;
  line-height: 1.2;
  color: var(--heading);
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.page-head h1::before {
  content: "~/";
  color: var(--accent);
  font-weight: 400;
}

.page-head p {
  margin-top: 0.5rem;
  color: var(--text-muted);
}

h2 {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.875rem;
  font-size: var(--fs-sm);
  font-weight: 700;
  line-height: 1.4;
  color: var(--heading);
}

h2 .path-root,
h2 .path-parent { color: var(--accent); font-weight: 400; }
h2 .path-leaf { color: var(--heading); }
h2 .path-heading a:hover { color: var(--accent); text-decoration: underline solid var(--accent); text-underline-offset: 3px; }

section[id],
article[id] { scroll-margin-top: 1.5rem; }

section:target .path-leaf { color: var(--accent); }

h3 { font: inherit; }

/* ---------- hero (home) ---------- */

.hero h1 {
  font-size: var(--fs-hero);
  line-height: 1.1;
  letter-spacing: -0.03em;
}

.hero .tagline {
  margin-top: 0.75rem;
  color: var(--text-muted);
}

/* ---------- text ---------- */

section { margin-bottom: var(--block); }

/* Flex items don't collapse margins, so trailing child margins would
   stack on top of the block gap. */
header > :last-child,
section > :last-child,
.post > :last-child { margin-bottom: 0; }

p {
  margin-bottom: 0.9rem;
  text-wrap: pretty;
}

/* Keep prose to a readable line length. */
section > p,
.page-head p,
.post > p,
.post > ul,
.post > ol,
.post > blockquote,
.project-desc,
.post-summary { max-width: 70ch; }

a {
  color: var(--accent);
  text-decoration: underline dotted var(--text-dim);
  text-underline-offset: 3px;
}

a:hover { text-decoration: underline solid var(--accent); }

/* Navigation-like links carry no underline; their position says "link". */
.topbar a,
h2 a,
h3 a,
footer a,
.brand { text-decoration: none; }

a:focus-visible,
button:focus-visible {
  outline: 1px dashed var(--accent);
  outline-offset: 3px;
}

strong { color: var(--heading); }

code {
  font-family: inherit;
  color: var(--heading);
}

/* Content not written yet, visibly marked so nothing reads as a real claim. */
.placeholder {
  color: var(--text-dim);
  font-size: var(--fs-sm);
  border: 1px dashed var(--border);
  padding: 0.75rem 1rem;
}

.status {
  font-size: var(--fs-sm);
  color: var(--text-dim);
}

.status::before { content: "// "; color: var(--accent); }

/* ---------- lists: posts, publications, repos ---------- */

.post-list,
.project-list,
.simple { list-style: none; }

.post-item,
.project-item {
  padding: 0.75rem 0;
  border-top: 1px dashed var(--border);
}

.post-item:first-child,
.project-item:first-child { border-top: 0; padding-top: 0; }

.post-item {
  display: grid;
  /* Title on the left where reading starts, date right-aligned like repo stars. */
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 0.125rem var(--gutter);
}

.post-date {
  text-align: right;
  white-space: nowrap;
  font-size: var(--fs-sm);
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.post-title,
.project-title {
  color: var(--heading);
  font-weight: 700;
}

.post-title:hover,
.project-title:hover { color: var(--accent); }

.post-summary,
.project-desc {
  margin-top: 0.125rem;
  font-size: var(--fs-sm);
  color: var(--text-muted);
  line-height: 1.6;
}

.project-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
}

.project-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0 0.75rem;
  flex-shrink: 0;
  font-size: var(--fs-xs);
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.star { color: var(--accent); }

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0 0.9rem;
  margin-top: 0.25rem;
  list-style: none;
}

.tag {
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

.tag::before { content: "#"; color: var(--accent); }

.pub-authors {
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.pub-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.125rem 0.9rem;
  margin-top: 0.125rem;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.pub-meta a { font-size: var(--fs-xs); }
.pub-meta a::before { content: "["; }
.pub-meta a::after { content: "]"; }

.simple li {
  position: relative;
  padding-left: 1.5rem;
  margin-bottom: 0.5rem;
}

.simple li::before {
  content: ">";
  position: absolute;
  left: 0;
  color: var(--accent);
}

.simple li.placeholder { padding-left: 1rem; }
.simple li.placeholder::before { content: none; }

/* Label / value pairs (contact). */
.pairs {
  display: grid;
  grid-template-columns: 7rem 1fr;
  gap: 0.5rem var(--gutter);
}

.pairs dt { color: var(--text-dim); }
.pairs dt::after { content: ":"; color: var(--accent); }
.js .email-reveal { display: inline-flex; align-items: baseline; gap: 0.7rem; padding: 0; border: 0; background: none; font: inherit; text-align: left; }
.email-reveal .masked-address { color: var(--text-muted); }
.email-reveal .reveal-hint { color: var(--accent); font-size: var(--fs-xs); }
.email-reveal:hover .masked-address { color: var(--accent); }
.email-reveal:hover .reveal-hint { text-decoration: underline solid var(--accent); text-underline-offset: 3px; }
#toolbox .pairs { grid-template-columns: max-content minmax(0, 1fr); }

/* Loading rows */
.skeleton {
  height: 3.5rem;
  border-top: 1px dashed var(--border);
}

.skeleton:first-child { border-top: 0; }

.skeleton::after {
  content: "loading_";
  font-size: var(--fs-sm);
  color: var(--text-dim);
  animation: blink 1s steps(1) infinite;
}

@keyframes blink { 50% { opacity: 0.3; } }

/* ---------- about ---------- */

.about-grid {
  display: grid;
  grid-template-columns: 11rem 1fr;
  gap: var(--gutter) 1.75rem;
  align-items: start;
}

/* Square portrait slot: an <img> or the ascii placeholder. */
.portrait {
  aspect-ratio: 1;
  width: 100%;
  border: 1px solid var(--border);
  background: var(--bg-elev);
  overflow: hidden;
}

.portrait img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) contrast(1.05);
}

.portrait pre {
  display: grid;
  place-content: center;
  height: 100%;
  font-size: 7.5px;
  line-height: 1;
  color: var(--art);
  user-select: none;
}

/* ---------- blog post ---------- */

.post { margin-bottom: var(--block); }

.post-head { margin-bottom: 2rem; }
.post-head h1 { margin-bottom: 0.5rem; }

.post-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 0.5ch;
  font-size: var(--fs-sm);
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.post-meta .tag { margin-right: 0.75ch; }

/* Table of contents (posts with three or more headings). */
.toc {
  margin-bottom: 2.25rem;
  padding: 0.75rem 1rem;
  border: 1px dashed var(--border);
  font-size: var(--fs-sm);
}

.toc-title {
  margin-bottom: 0.25rem;
  color: var(--text-dim);
}

.toc ol {
  list-style: none;
  counter-reset: toc;
}

.toc li { counter-increment: toc; }
.toc li::before { content: counters(toc, ".") ". "; color: var(--accent); }
.toc ol ol { padding-left: 2.5ch; }
.toc a {
  display: inline-block;
  padding: 0.15rem 0;
  text-decoration: none;
  color: var(--text-muted);
}
.toc a:hover { color: var(--accent); }

.post-body h2,
.post-body h3 {
  display: block;
  margin: 2.25rem 0 0.75rem;
  scroll-margin-top: 1.5rem;
}

.post-body h2 { font-size: var(--fs-lg); }
.post-body h3 { font-size: var(--fs-base); }

/* Heading permalinks ("#") come from the Markdown toc extension. */
.post-body .anchor {
  margin-right: 0.75ch;
  color: var(--accent);
  font-weight: 400;
  text-decoration: none;
}

.post-body h3 .anchor::after { content: "#"; }

.post-body p,
.post-body ul,
.post-body ol,
.post-body pre,
.post-body table,
.post-body figure,
.post-body blockquote,
.post-body .hl,
.post-body .math { margin-bottom: 1.1rem; }

.post-body ul,
.post-body ol { padding-left: 1.5rem; }

.post-body li { margin-bottom: 0.35rem; }

.post-body img,
.post-body video,
.post-body canvas,
.post-body svg {
  display: block;
  max-width: 100%;
  height: auto;
}

.post-body figcaption {
  margin-top: 0.4rem;
  font-size: var(--fs-sm);
  color: var(--text-dim);
}

.post-body blockquote {
  padding-left: 1rem;
  border-left: 2px solid var(--accent);
  color: var(--text-muted);
}

.post-body hr {
  margin: 2rem 0;
  border: 0;
  border-top: 1px dashed var(--border);
}

.post-body :not(pre) > code {
  padding: 0 0.3ch;
  background: var(--bg-elev);
  border: 1px solid var(--border);
}

/* Tables */
.post-body table {
  display: block;
  overflow-x: auto;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}

.post-body th,
.post-body td {
  padding: 0.35rem 0.9rem 0.35rem 0;
  border-bottom: 1px dashed var(--border);
  text-align: left;
  vertical-align: top;
}

.post-body th { color: var(--heading); }
.post-body .align-right { text-align: right; }
.post-body .align-center { text-align: center; }

/* Math: LaTeX rendered to MathML at build time. */
.post-body math { font-size: 1.1em; }

.post-body .math {
  overflow-x: auto;
  padding: 0.25rem 0;
}

/* Footnotes */
.post-body .footnote {
  margin-top: 2.5rem;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.post-body .footnote hr { margin: 0 0 1rem; }
.post-body .footnote-ref a { text-decoration: none; }

/* Code blocks. Colors come from the theme, so highlighting follows the accent. */
.post-body .hl {
  position: relative;
  background: var(--bg-elev);
  border: 1px solid var(--border);
}

.post-body .hl pre,
.post-body > pre {
  overflow-x: auto;
  margin: 0;
  padding: 0.9rem 1rem;
  font-size: var(--fs-sm);
  line-height: 1.55;
  tab-size: 2;
}

.post-body > pre {
  background: var(--bg-elev);
  border: 1px solid var(--border);
}

.hl .c, .hl .c1, .hl .cm, .hl .cs, .hl .ch, .hl .cp, .hl .cpf { color: var(--text-dim); font-style: italic; }
.hl .k, .hl .kd, .hl .kn, .hl .kr, .hl .kc, .hl .kt, .hl .ow, .hl .nt { color: var(--accent); }
.hl .s, .hl .s1, .hl .s2, .hl .sb, .hl .sc, .hl .sd, .hl .se, .hl .sh, .hl .si, .hl .sx, .hl .sr, .hl .ss, .hl .dl {
  color: color-mix(in srgb, var(--accent) 55%, var(--text));
}
.hl .m, .hl .mi, .hl .mf, .hl .mh, .hl .mo, .hl .il { color: color-mix(in srgb, var(--accent) 75%, var(--heading)); }
.hl .nf, .hl .fm, .hl .nc, .hl .nn, .hl .nd, .hl .na { color: var(--heading); }
.hl .nb, .hl .bp, .hl .vc, .hl .vg, .hl .vi { color: color-mix(in srgb, var(--accent) 40%, var(--text)); }
.hl .o, .hl .p { color: var(--text-muted); }
.hl .gd { color: var(--text-dim); }
.hl .gi { color: var(--accent); }
.hl .err { color: inherit; }

.copy {
  position: absolute;
  top: 0.4rem;
  right: 0.4rem;
  padding: 0 0.5ch;
  font: inherit;
  font-size: var(--fs-xs);
  color: var(--text-dim);
  background: var(--bg);
  border: 1px solid var(--border);
  opacity: 0;
  transition: opacity 0.15s ease;
}

.hl:hover .copy,
.copy:focus-visible { opacity: 1; }
.copy:hover { color: var(--accent); }

@media (hover: none) {
  .copy { opacity: 1; }
}

/* Older / newer post links. */
.post-nav {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gutter);
  margin-bottom: var(--block);
  padding-top: 1rem;
  border-top: 1px dashed var(--border);
  font-size: var(--fs-sm);
}

.post-nav a {
  color: var(--heading);
  text-decoration: none;
}

.post-nav a:hover { color: var(--accent); }

.post-nav span {
  display: block;
  color: var(--text-dim);
  font-size: var(--fs-xs);
}

.post-nav-older span::before { content: "← "; }
.post-nav-newer { text-align: right; }
.post-nav-newer span::after { content: " →"; }

.cite {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  padding-left: 1rem;
  border-left: 2px solid var(--accent);
}

/* ---------- 404 ---------- */

.notfound {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(1.5rem, 5vw, 2.5rem);
  padding: 3rem 0;
  text-align: center;
}

.notfound-art {
  font: inherit;
  /* 39 columns of art; scales down so it never overflows a phone. */
  font-size: clamp(8px, 3.4vw, 20px);
  line-height: 1.15;
  letter-spacing: 0;
  color: var(--heading);
  white-space: pre;
  text-align: left;
  user-select: none;
}

/* Shadow layer and decode noise. */
.notfound-art i {
  color: var(--art);
  font-style: normal;
}

/* Sweep highlight and pointer scramble. */
.notfound-art b {
  color: var(--accent);
  font-weight: inherit;
}

/* Fake shell session under the art. */
.term {
  width: min(100%, 34rem);
  padding: 0.9rem 1rem;
  border: 1px dashed var(--border);
  background: color-mix(in srgb, var(--bg-elev) 80%, transparent);
  font-size: var(--fs-sm);
  line-height: 1.7;
  text-align: left;
  overflow-wrap: anywhere;
}

.term p { margin: 0; }
.term .prompt { color: var(--accent); }
.term-err { color: var(--text-muted); }

.term-ls {
  display: flex;
  flex-wrap: wrap;
  gap: 0 1.25ch;
}

.term-caret {
  display: inline-block;
  width: 0.6em;
  height: 1.1em;
  vertical-align: -0.2em;
  background: var(--accent);
  animation: blink 1.1s steps(1) infinite;
}

@media (prefers-reduced-motion: reduce) {
  .term-caret { animation: none; }
}

/* ---------- footer ---------- */

footer {
  margin-top: auto;
  padding-top: 1rem;
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

.footer-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
  padding-top: 1rem;
  border-top: 1px dashed var(--border);
}

.footer-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1rem;
  list-style: none;
}

footer a { color: var(--text-muted); }

/* Links inside footer text (not the footer nav) keep an underline so they
   don't rely on color alone. */
.footer-row > span a { text-decoration: underline dotted var(--text-dim); text-underline-offset: 3px; }
footer a:hover { color: var(--accent); }

.sep { margin: 0 0.5ch; }

/* ---------- local dev ---------- */

/* Shown only when blog.js / publications.js loaded mock data (localhost). */
html.mock::after {
  content: "mock data · local only";
  position: fixed;
  right: 0.75rem;
  bottom: 0.75rem;
  z-index: 20;
  padding: 0.2rem 0.5rem;
  font: var(--fs-xs) / 1.4 var(--mono);
  color: var(--bg);
  background: var(--accent);
  pointer-events: none;
}

/* ---------- small screens ---------- */

/* Keep the top bar on one line down to ~360px. */
@media (max-width: 440px) {
  .topbar { gap: 0.4rem 0.9rem; }
  .topbar ul { gap: 0.25rem 0.7rem; }
}

@media (max-width: 560px) {
  .pairs { grid-template-columns: 1fr; }
  #toolbox .pairs { grid-template-columns: 1fr; }
  .post-item { column-gap: 0.75rem; }

  .pairs { row-gap: 0; }
  .pairs dd { margin-bottom: 0.75rem; }
  .pairs dd:last-child { margin-bottom: 0; }

  .project-header { flex-direction: column; gap: 0.125rem; }

  /* Portrait stays a left-aligned square above the text. */
  .about-grid { grid-template-columns: 1fr; }
  .portrait { width: 8.5rem; }
}
