/* Console stylesheet. Colours come only from tokens.css; no literals here. */

/* Fonts (self-hosted, generated by scripts/fonts.mjs) */
@font-face { font-family: "Geist"; font-weight: 400 600; src: url(/fonts/geist-var.woff2) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; font-display: swap; }
@font-face { font-family: "Geist Mono"; font-weight: 400 600; src: url(/fonts/geist-mono-var.woff2) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; font-display: swap; }

/* Base */
*, *::before, *::after { box-sizing: border-box; }

/* The canvas takes the theme colour too, so nothing flashes between pages. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; background: var(--color-surface); }

body {
  margin: 0;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  color: var(--color-text);
  font: var(--type-size-md)/var(--type-leading-body) var(--font-sans);
}

::selection { background: var(--color-selection); color: var(--color-text); }

:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

a {
  color: var(--color-link);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}
a:hover { text-decoration-thickness: 2px; }

h1, h2, h3, h4 { line-height: var(--type-leading-tight); font-weight: 600; margin: var(--space-6) 0 var(--space-3); }
h1 { font-size: var(--type-size-2xl); margin-top: var(--space-3); }
h2 { font-size: var(--type-size-xl); }
h3 { font-size: var(--type-size-lg); }
h4 { font-size: var(--type-size-md); }

p, ul, ol, blockquote, figure { margin: 0 0 var(--space-4); }
ul, ol { padding-inline-start: var(--space-5); }
blockquote { margin-inline: 0; padding-inline-start: var(--space-4); color: var(--color-text-muted); }
hr { height: 1px; border: 0; background: var(--color-line); margin: var(--space-6) 0; }

.prompt, time, .tags, .flag, .kind, .filters, .status, code, pre { font-family: var(--font-mono); }

/* Responsive guards */
pre, .diff, .code { max-width: 100%; overflow-x: auto; }
code, a, .t { overflow-wrap: anywhere; }
img, .yt iframe { max-width: 100%; height: auto; }
img { display: block; }

/* Skip link */
.skip {
  position: absolute;
  inset-inline-start: var(--space-4);
  top: var(--space-2);
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.skip:focus {
  width: auto;
  height: auto;
  overflow: visible;
  clip-path: none;
  padding: var(--space-1) var(--space-3);
  background: var(--color-surface-raised);
  color: var(--color-text);
  z-index: 1;
}

/* Centred column. Header, footer and status bar span the viewport; their
   .inner wrappers and main share one 64rem column, centred, with the text
   left-aligned inside it. Body text keeps to the measure within it. */
main, .inner {
  width: 100%;
  max-width: 64rem;
  margin-inline: auto;
  padding-inline:
    max(var(--space-4), env(safe-area-inset-left))
    max(var(--space-4), env(safe-area-inset-right));
}

/* Reserve the collapsed picker's box so the header does not shift when it
   upgrades: 12.25rem x 2.25rem is the measured toggle with the longest name
   (Monokai Pro); the shadow CSS fixes #toggle at exactly that size. Only when scripts run, like
   the page-mode rule below: without JS the element stays empty and must not leave a gap. */
@media (scripting: enabled) { theme-picker:not([mode]) { display: inline-block; min-width: 12.25rem; min-height: 2.25rem; } }

/* Reserve the page-mode panel (/tokens/, /lab/) so the content below does not shift when it
   upgrades. Heights measured in Chrome (Task 16) with the inspector loaded; each tier is the
   shortest panel in its width band, so the reservation never adds space. Only when scripts
   run: without JS the element stays empty and must not leave a gap. */
@media (scripting: enabled) {
  theme-picker[mode="page"] { display: block; min-height: 75.5rem; }
  @media (min-width: 364px) { theme-picker[mode="page"] { min-height: 73.9rem; } }
  @media (min-width: 466px) { theme-picker[mode="page"] { min-height: 66.5rem; } }
  @media (min-width: 624px) { theme-picker[mode="page"] { min-height: 62.8rem; } }
  @media (min-width: 694px) { theme-picker[mode="page"] { min-height: 61.25rem; } }
}

/* Header: the mark alone on the left, lowercase mono nav on the right,
   theme picker at the far end. */
header { padding-block: var(--space-4); }
header > .inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-5);
}
.brand {
  display: flex;
  flex: none;
  align-items: center;
  color: var(--color-text);
  text-decoration: none;
}
.mark { display: block; }
.site-nav { margin-inline-start: auto; }
.site-nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
  font-family: var(--font-mono);
}
.site-nav a { color: var(--color-text-muted); text-decoration: none; }
.site-nav a:hover, .site-nav a[aria-current] { color: var(--color-text); }

header [aria-current]::before {
  content: "> ";
  color: var(--section-tint);
}

/* Main column (width and centring above) */
main {
  flex: 1 0 auto;
  padding-block: var(--space-4) var(--space-7);
}
main > :not(.log, .talks-year, theme-picker) { max-width: var(--type-measure); }

/* Prompt */
.prompt {
  margin: 0 0 var(--space-3);
  font-size: var(--type-size-base);
  color: var(--color-text-muted);
  overflow-wrap: anywhere;
}
.prompt a {
  text-decoration: underline;
  text-decoration-color: var(--color-line);
  text-decoration-thickness: 1px;
  text-underline-offset: .2em;
}
.prompt a:hover, .prompt a:focus-visible { text-decoration-color: currentColor; text-decoration-thickness: 2px; }
.prompt-user { color: var(--prompt-user); }
.prompt-path { color: var(--prompt-path); }
.prompt-path :where(a) { color: inherit; } /* before .prompt-section so the tint wins */
.prompt-section { color: var(--section-tint); }

.headline {
  font-size: clamp(28px, 4.2vw, 46px);
  font-weight: 500;
  line-height: 1.08;
  letter-spacing: -0.03em;
  text-wrap: balance;
  margin: var(--space-2) 0 var(--space-4);
}
main > .headline { max-width: 22ch; }
.typed { display: inline; }

/* typed.js: ghost (invisible, full text) reserves the final layout; the live
   span types into the same cell, so lines fill one at a time. Greedy wrapping
   keeps the ghost and the partial text breaking at the same words. */
.headline.is-typing { display: grid; text-wrap: wrap; }
.headline.is-typing > * { grid-area: 1 / 1; }
.typed-ghost { visibility: hidden; }

.cursor {
  display: inline-block;
  width: .5em;
  height: .95em;
  margin-inline-start: .08em;
  background: var(--section-tint);
  vertical-align: -.08em;
  animation: blink 1.1s steps(1) infinite;
}
@keyframes blink { 50% { opacity: 0; } }

.lede {
  font-size: var(--type-size-lg);
  color: var(--color-text-muted);
  margin-bottom: var(--space-6);
}

/* Post log */
.log {
  list-style: none;
  margin: 0 0 var(--space-5);
  padding: 0;
}
.log li { border-bottom: 1px solid var(--color-line); }
.log li:first-child { border-top: 1px solid var(--color-line); }
.log li > a {
  display: grid;
  grid-template-columns: 11ch 1fr auto;
  gap: var(--space-4);
  align-items: baseline;
  padding: var(--space-2) var(--space-1);
  color: var(--color-text);
  text-decoration: none;
}
.log li > a:hover { background: var(--post-list-hover-bg); }
.log li > a:hover .t { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.2em; }
.log time { color: var(--post-list-date); font-size: var(--type-size-sm); }
.log .t { min-width: 0; }
.tags { color: var(--post-list-tag); font-size: var(--type-size-sm); white-space: nowrap; }

/* Tag flags: a stable hue per tag (render.mjs hueFor), muted "--" prefix */
.flag::before { content: "--"; color: var(--color-text-muted); }
.flag[data-hue="green"] { color: var(--hue-green); }
.flag[data-hue="yellow"] { color: var(--hue-yellow); }
.flag[data-hue="blue"] { color: var(--hue-blue); }
.flag[data-hue="orange"] { color: var(--hue-orange); }
.flag[data-hue="pink"] { color: var(--hue-pink); }

/* Writing index filters and post flags */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
  margin: 0 0 var(--space-5);
  font-size: var(--type-size-sm);
}
.filters a { color: var(--color-text-muted); text-decoration: none; }
.filters a:hover, .filters a[aria-current] { color: var(--color-text); }

.flag {
  color: var(--post-list-tag);
  font-size: var(--type-size-sm);
  text-decoration: none;
}
.flag:hover { text-decoration: underline; }

/* Article */
article h1 { margin-bottom: var(--space-2); }
.meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  color: var(--color-text-muted);
  font-size: var(--type-size-sm);
  margin-bottom: var(--space-5);
}
.written { color: var(--color-text-muted); font-size: var(--type-size-sm); }

.series {
  font-size: var(--type-size-sm);
  color: var(--color-text-muted);
  margin: 0 0 var(--space-5);
}
.series p { margin-bottom: var(--space-1); font-family: var(--font-mono); }
.series ol { margin: 0; }
.series [aria-current] { color: var(--color-text); }

.prevnext {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: var(--space-6);
}
.prevnext .next { margin-inline-start: auto; text-align: end; }

/* Code */
:not(pre) > code {
  font-size: 0.9em;
  padding: 0.1em 0.3em;
  border-radius: var(--radius-sm);
  background: var(--code-bg);
  color: var(--code-fg);
}
pre {
  margin: 0 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  font-size: var(--type-size-base);
  line-height: 1.5;
  background: var(--code-bg);
  color: var(--code-fg);
  border-radius: var(--radius-sm);
}
.code, .diff { border: 1px solid var(--color-line); }
pre code { font-size: inherit; }

.diff-add { color: var(--diff-add); }
.diff-remove { color: var(--diff-remove); }
.diff-hunk { color: var(--hue-blue); }
.diff-ctx { color: var(--color-text-muted); }

/* Box: a titled pane */
.box {
  border: 1px solid var(--color-line);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-5);
}
.box > :last-child { margin-bottom: 0; }
.box-title {
  margin: 0 0 var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--type-size-sm);
  font-weight: 500;
  color: var(--color-text-muted);
}
/* Corner ticks drawn with borders (the font subset has no box-drawing glyphs) */
.box-title::before, .box-title::after {
  content: "";
  display: inline-block;
  width: 1em;
  height: .45em;
  border-top: 1px solid var(--color-line);
}
.box-title::before { border-inline-start: 1px solid var(--color-line); margin-inline-end: .5em; }
.box-title::after { border-inline-end: 1px solid var(--color-line); margin-inline-start: .5em; }

/* YouTube embed */
.yt { margin: 0 0 var(--space-5); }
.yt iframe {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 0;
  border-radius: var(--radius-sm);
}
.yt figcaption { margin-top: var(--space-2); font-size: var(--type-size-sm); color: var(--color-text-muted); }

/* Figures: Markdown images (markdown.mjs) and Talks photos */
.fig { margin: 0 0 var(--space-5); }
.fig img { width: 100%; border-radius: var(--radius-sm); }
.fig.portrait img { width: min(100%, 20rem); }
.fig figcaption { margin-top: var(--space-2); font-size: var(--type-size-sm); color: var(--color-text-muted); }
.credit { display: block; font-size: var(--type-size-xs); }

/* About: man page */
.man h2 {
  font-family: var(--font-mono);
  font-size: var(--type-size-base);
  letter-spacing: 0.04em;
  margin: var(--space-5) 0 var(--space-2);
}
.man > :not(h2) { padding-inline-start: var(--space-6); }
/* The NAME photos (portrait, then stage) sit small and side by side, each image 12rem.
   min-content keeps each caption to its image's width; the inline blocks wrap to a
   left-aligned stack at the same width when two do not fit (360px). */
.man > #name ~ .fig {
  display: inline-block;
  vertical-align: top;
  width: min-content;
}
.man > #name ~ .fig img { width: 12rem; max-width: none; }

/* Talks: one log per year, rows styled like the post log */
.talks-year h2 {
  font-family: var(--font-mono);
  font-size: var(--type-size-base);
  letter-spacing: 0.04em;
  color: var(--color-text);
  margin: var(--space-5) 0 var(--space-2);
}
.talks {
  list-style: none;
  margin: 0 0 var(--space-5);
  padding: 0;
}
.talks li {
  display: grid;
  grid-template-columns: 11ch 11ch 1fr;
  column-gap: var(--space-4);
  align-items: baseline;
  padding: var(--space-2) var(--space-1);
  border-bottom: 1px solid var(--color-line);
}
.talks li:first-child { border-top: 1px solid var(--color-line); }
.talks time { color: var(--post-list-date); font-size: var(--type-size-sm); }
.talks .kind { color: var(--post-list-tag); font-size: var(--type-size-sm); }
.talks .t { min-width: 0; }
.talks .where {
  grid-column: 3;
  min-width: 0;
  color: var(--color-text-muted);
  font-size: var(--type-size-sm);
}
/* Photos follow their year's rows at the full column width; two across on
   wider screens, a lone photo or panorama (.wide) spans the row. */
.talks-photos {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
  margin: 0 0 var(--space-5);
}
.talks-photos .fig { margin: 0; }
.talks-photos .wide { grid-column: 1 / -1; }

/* Lab */
.showcase { margin-block: var(--space-6); }
.showcase h2 {
  font-family: var(--font-mono);
  font-size: var(--type-size-base);
  letter-spacing: 0.04em;
  margin: 0 0 var(--space-2);
}
.status-sample .inner { padding-inline: 0; }
.writeups { padding-inline-start: var(--space-5); }

/* Footer links */
.foot {
  padding-block: var(--space-4);
  font-size: var(--type-size-sm);
}
.foot > .inner {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
}
.foot a { color: var(--color-text-muted); text-decoration: none; }
.foot a:hover { color: var(--color-text); text-decoration: underline; }

/* Status bar: tmux-style line at the foot of the page */
.status {
  font-size: var(--type-size-xs);
  line-height: 1.8;
  background: var(--status-bar-bg);
  color: var(--status-bar-fg);
  border-top: 1px solid var(--color-line);
  padding-bottom: env(safe-area-inset-bottom);
}
.status > .inner {
  display: flex;
  flex-wrap: wrap;
}
.status > .inner > * { padding-inline: var(--space-3); }
.status-active {
  background: var(--section-tint);
  color: var(--color-surface);
  font-weight: 600;
}
.status a { margin-inline-start: auto; color: var(--status-bar-fg); }

/* Narrow screens */
@media (max-width: 600px) {
  .site-nav { flex-basis: 100%; margin-inline-start: 0; order: 1; }
  header theme-picker { margin-inline-start: auto; }
  .log li > a { grid-template-columns: 1fr; gap: 0; }
  .log .tags { display: none; }
  .talks li { grid-template-columns: 11ch 1fr; }
  .talks .t, .talks .where { grid-column: 1 / -1; }
  .man > :not(h2) { padding-inline-start: var(--space-4); }
  /* Status bar keeps five cells in the DOM; post count and reading time hide. */
  .status > .inner > :nth-child(2), .status > .inner > :nth-child(3) { display: none; }
  .talks-photos { grid-template-columns: minmax(0, 1fr); }
}


@media (prefers-reduced-motion: reduce) {
  /* No blink. (typed.js does not run at all under reduced motion.) */
  .cursor { animation: none; }
}
