/* ─────────────────────────────────────────────────────────────
   Quants & Qualia — terminal shell

   Tokens first, then layout (shell chrome), then page modes
   (index, article, static), then prose, then the interactive
   prompt and overlays (scanlines, flicker, vignette, bloom).
   Mobile rules live at the end.
   ───────────────────────────────────────────────────────────── */

/* ── Fonts ── */
/* One typeface for the whole machine: Monaspace Neon (variable). The
   single woff2 carries weights 200-800 plus a slant axis, so `font-style:
   italic` maps to oblique -11deg via the declared oblique range. Coding
   ligatures (!=, //) ship in `liga` and are killed on <body> with
   `font-variant-ligatures: no-common-ligatures`; texture healing lives in
   `calt` and stays on. */
@font-face {
  font-family: 'Monaspace Neon';
  src: url('/fonts/MonaspaceNeon-Var.woff2') format('woff2');
  font-weight: 200 800;
  font-stretch: 100% 125%;
  font-style: oblique 0deg 11deg;
  font-display: swap;
}

/* ── Tokens ── */
:root {
  --bg:         #0a0806;
  --surface:    #14110d;
  --text:       #ede4d3;
  --muted:      #a39684;
  --dim:        #6e6254;
  --warm:       #f2cc8f;
  --err:        #f87171;

  --font-mono:   'Monaspace Neon', ui-monospace, 'SF Mono', 'Menlo', monospace;

  --size-mono:        15px;
  --size-mono-sm:     13px;
  --size-mono-xs:     12px;  /* UI chrome, tags, bylines, status */
  --size-body:        16px;
  --size-body-lg:     17px;
  --size-title:       56px;
  --size-title-sm:    34px;

  --chrome-h: 40px;
  --status-h: 32px;
  --main-max: 820px;
  --shell-max: 1240px;

  --bloom: 2;
  --bloom-strength: calc(var(--bloom) * 1);
}

/* Accent palette. Each theme overrides --accent* tokens. `--accent-rgb`
   is the space-separated form used with the modern `rgb(R G B / A)` syntax
   for glows and tints, so everything follows a theme change. */
:root,
.theme-amber {
  --accent:       #fbbf24;
  --accent-2:     #f59e0b;
  --accent-dim:   #b78420;
  --accent-rgb:   251 191 36;
  --accent-2-rgb: 245 158 11;
  --bg-tint:      #241a0a;
  --rule:         rgb(var(--accent-rgb) / 0.14);
}
.theme-violet {
  --accent:       #c084fc;
  --accent-2:     #a855f7;
  --accent-dim:   #7c3aed;
  --accent-rgb:   192 132 252;
  --accent-2-rgb: 168 85 247;
  --bg-tint:      #1a1229;
  --rule:         rgb(var(--accent-rgb) / 0.14);
}
.theme-phosphor {
  --accent:       #6ee7b7;
  --accent-2:     #34d399;
  --accent-dim:   #047857;
  --accent-rgb:   110 231 183;
  --accent-2-rgb: 52 211 153;
  --bg-tint:      #0c1f1a;
  --rule:         rgb(var(--accent-rgb) / 0.14);
}
.theme-cyan {
  --accent:       #67e8f9;
  --accent-2:     #22d3ee;
  --accent-dim:   #0891b2;
  --accent-rgb:   103 232 249;
  --accent-2-rgb: 34 211 238;
  --bg-tint:      #0c1f24;
  --rule:         rgb(var(--accent-rgb) / 0.14);
}
.theme-red {
  --accent:       #f87171;
  --accent-2:     #ef4444;
  --accent-dim:   #b91c1c;
  --accent-rgb:   248 113 113;
  --accent-2-rgb: 239 68 68;
  --bg-tint:      #241014;
  --rule:         rgb(var(--accent-rgb) / 0.14);
}

/* ── Reset ── */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  scrollbar-gutter: stable;
  scrollbar-color: var(--accent-dim) transparent;
}

body {
  font-family: var(--font-mono);
  font-size: var(--size-mono);
  line-height: 1.4;
  font-variant-ligatures: no-common-ligatures;
  background:
    radial-gradient(ellipse at top, var(--bg-tint) 0%, var(--bg) 60%)
    fixed;
  color: var(--text);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-synthesis: none;
  overflow-x: hidden;
}

::selection {
  background: rgb(var(--accent-rgb) / 0.3);
  color: var(--text);
}

a { color: inherit; }

/* ─────────────────────────────────────────────────────────────
   Shell: chrome bar + status bar + inner two-column grid.
   The shell doesn't take over the whole viewport — content
   can scroll naturally and chrome stays at the top of the
   document flow.
   ───────────────────────────────────────────────────────────── */

.crt {
  max-width: var(--shell-max);
  margin: 0 auto;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  position: relative;
}

.crt__chrome {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--bg);
  border-bottom: 1px solid var(--rule);
  padding: 10px 20px;
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: var(--size-mono-xs);
  color: var(--dim);
  letter-spacing: 0.02em;
  height: var(--chrome-h);
  flex-shrink: 0;
}

.crt__path {
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}

.crt__path--link {
  text-decoration: none;
  color: var(--muted);
  transition: color 120ms ease;
}
.crt__path--link:hover,
.crt__path--link:focus-visible {
  color: var(--text);
  outline: none;
}
.crt__path--link:hover .crt__back,
.crt__path--link:focus-visible .crt__back {
  color: var(--text);
  transform: translateX(-2px);
}

.crt__back {
  color: var(--accent);
  font-size: 12px;
  transition: color 120ms ease, transform 120ms ease;
  text-shadow: 0 0 calc(4px + var(--bloom-strength) * 2px) rgb(var(--accent-rgb) / 0.5);
  display: inline-block;
}

.crt__meta {
  margin-left: auto;
  font-family: var(--font-mono);
  white-space: nowrap;
}

.crt__meta a {
  color: var(--accent);
  text-decoration: none;
  margin-left: 14px;
}
.crt__meta a:hover { color: var(--text); }

.crt__body {
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 48px;
  padding: 24px 28px 40px;
  position: relative;
  z-index: 5;
}

.crt--no-aside .crt__body {
  grid-template-columns: minmax(0, 1fr);
}

.crt__main { min-width: 0; }

.crt__aside {
  border-left: 1px dashed var(--rule);
  padding-left: 28px;
  font-family: var(--font-mono);
  font-size: var(--size-mono);
  color: var(--muted);
  align-self: start;
  position: sticky;
  top: calc(var(--chrome-h) + 20px);
}

.crt__status {
  position: sticky;
  bottom: 0;
  z-index: 20;
  background: var(--bg);
  border-top: 1px solid var(--rule);
  padding: 6px 20px;
  height: var(--status-h);
  display: flex;
  align-items: center;
  gap: 18px;
  font-size: var(--size-mono-xs);
  color: var(--dim);
  flex-shrink: 0;
}

.crt__status .status-ready { color: var(--accent); }
.crt__status .status-right { margin-left: auto; }
.crt__status .status-key { color: var(--dim); }

/* ─────────────────────────────────────────────────────────────
   Command line output blocks (used on index + static + article
   chrome). A "line" is typically prompt + text, or raw output.
   ───────────────────────────────────────────────────────────── */

.cmd {
  font-family: var(--font-mono);
  font-size: var(--size-mono);
  color: var(--text);
  white-space: pre-wrap;
  padding: 2px 0;
  line-height: 1.4;
}

.cmd__prompt {
  color: var(--accent);
  margin-right: 0.55em;
  text-shadow: 0 0 calc(4px + var(--bloom-strength) * 2px) rgb(var(--accent-rgb) / 0.5);
}

.cmd-out {
  font-family: var(--font-mono);
  font-size: var(--size-mono);
  color: var(--text);
  padding: 2px 0 10px 14px;
  white-space: pre-wrap;
  line-height: 1.4;
}

.cmd-out--dim  { color: var(--dim); }
.cmd-out--hint { color: var(--warm); }
.cmd-out--err  { color: var(--err); }

/* ── Hero (ASCII + ampersand flourish) ── */

.hero {
  padding: 20px 0 10px 14px;
  color: var(--accent);
  display: block;
  overflow-x: auto;
  transform-origin: center;
  /* Ambient breathe: slow 4s pulse on the glow radius + intensity.
     Runs indefinitely once the hero is visible. Overridden briefly by
     the power-on keyframes during boot via animation composition. */
  animation: hero-breathe 4s ease-in-out infinite;
  will-change: transform, filter, text-shadow;
}

@keyframes hero-breathe {
  0%, 100% {
    text-shadow:
      0 0 calc(6px  + var(--bloom-strength) * 3px) rgb(var(--accent-rgb) / 0.55),
      0 0 calc(18px + var(--bloom-strength) * 8px) rgb(var(--accent-2-rgb) / 0.28);
  }
  50% {
    text-shadow:
      0 0 calc(10px + var(--bloom-strength) * 5px) rgb(var(--accent-rgb) / 0.72),
      0 0 calc(28px + var(--bloom-strength) * 12px) rgb(var(--accent-2-rgb) / 0.4);
  }
}

/* Power-on: collapsed horizontal line → full height, with a brief
   hot-white flash as it snaps open. ~400ms total. Only plays during
   the boot reveal; on subsequent loads the hero is already settled. */
@keyframes hero-power-on {
  0% {
    opacity: 0;
    transform: scaleY(0);
    filter: brightness(3) saturate(1.6);
  }
  8% {
    opacity: 1;
    transform: scaleY(0.02);
    filter: brightness(3) saturate(1.6);
  }
  55% {
    transform: scaleY(1.06);
    filter: brightness(1.3) saturate(1.1);
  }
  100% {
    opacity: 1;
    transform: scaleY(1);
    filter: brightness(1) saturate(1);
  }
}

/* Hero boot container: suppress the default fade-up reveal; let the
   child .hero run its own power-on animation instead. */
.is-booting [data-boot-step="hero"] {
  opacity: 1;
  transform: none;
  transition: none;
}
.is-booting [data-boot-step="hero"]:not(.is-revealed) .hero {
  opacity: 0;
  animation: none;
}
.is-booting [data-boot-step="hero"].is-revealed .hero {
  animation:
    hero-power-on 400ms cubic-bezier(0.19, 1, 0.22, 1) both,
    hero-breathe 4s 400ms ease-in-out infinite;
}

.hero__group {
  position: relative;
  display: inline-block;
}

.hero__art {
  font-family: var(--font-mono);
  font-size: var(--size-mono-sm);
  line-height: 1.05;
  white-space: pre;
  margin: 0;
  color: inherit;
}

.hero__amp {
  position: absolute;
  right: -28px;
  bottom: 0;
  font-family: var(--font-mono);
  font-style: normal;
  font-weight: 700;
  font-size: 34px;
  line-height: 1;
  color: var(--accent);
  transform-origin: left center;
}

@keyframes amp-draw-in {
  0%   { opacity: 0; transform: scale(0.55) rotate(-12deg); }
  60%  { opacity: 1; transform: scale(1.12) rotate(3deg); }
  100% { opacity: 1; transform: scale(1) rotate(0); }
}

.is-booting [data-boot-step="hero"].is-revealed .hero__amp {
  animation: amp-draw-in 450ms 380ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

/* ─────────────────────────────────────────────────────────────
   Index: ls output. Rows are <a>s so the whole line is clickable
   + accessible. Columns align because the type is monospace.
   ───────────────────────────────────────────────────────────── */

.post-list {
  list-style: none;
  padding: 0 0 8px 14px;
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--size-mono);
}

.post-row a {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 140px 60px 80px;
  gap: 18px;
  padding: 2px 0;
  text-decoration: none;
  color: var(--text);
  transition: color 120ms ease;
  align-items: baseline;
}

.post-row__filename {
  color: var(--accent-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.post-row__date,
.post-row__size,
.post-row__time {
  color: var(--dim);
  white-space: nowrap;
}

.post-row a:hover {
  color: var(--accent);
  background: rgb(var(--accent-rgb) / 0.04);
}
.post-row a:hover .post-row__filename { color: var(--accent); }
.post-row a:hover .post-row__date,
.post-row a:hover .post-row__size,
.post-row a:hover .post-row__time { color: var(--muted); }

/* ─────────────────────────────────────────────────────────────
   Interactive prompt (the live one the shell writes to).
   Hidden until the client JS mounts, to avoid a flash.
   ───────────────────────────────────────────────────────────── */

/* Single inline line so the prompt char, value, ghost, and caret all
   share one line-box and baseline. `white-space: pre` preserves the
   single space between the char and value. No flexbox — baseline flex
   alignment drifts when the value is empty (caret becomes the baseline),
   which is what caused the `>` and caret to visually misalign. */
.prompt {
  display: none;
  font-family: var(--font-mono);
  font-size: var(--size-mono);
  line-height: 1.4;
  padding: 6px 0 20vh 0;  /* bottom padding so there's breathing room
                             below the caret when history is short, but
                             not so much that the prompt falls off-screen
                             on first load */
  position: relative;
  cursor: text;
  color: var(--text);
  white-space: pre;
  word-break: break-word;
}

.crt.js-ready .prompt { display: block; }

.prompt__char {
  color: var(--accent);
  text-shadow: 0 0 calc(4px + var(--bloom-strength) * 2px) rgb(var(--accent-rgb) / 0.5);
}

.prompt__value { color: var(--text); }
.prompt__ghost { color: var(--dim); }

.prompt__caret {
  display: inline-block;
  width: 0.55ch;
  height: 1em;
  background: var(--accent);
  vertical-align: -2px;
  box-shadow: 0 0 calc(6px + var(--bloom-strength) * 3px) rgb(var(--accent-rgb) / 0.6);
  animation: caret 1s steps(2) infinite;
}

.prompt__input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  width: 1px;
  height: 1px;
  top: 0;
  left: 0;
  border: 0;
  background: transparent;
}

@keyframes caret {
  0%, 49%  { opacity: 1; }
  50%, 100% { opacity: 0; }
}

/* ─────────────────────────────────────────────────────────────
   Article view. Masthead and body share the one monospace face;
   shell chrome is handled by layout. Headings carry a quiet
   markdown-style marker (## / ###) instead of a § flourish.
   ───────────────────────────────────────────────────────────── */

.article {
  max-width: var(--main-max);
  padding: 24px 0 48px;
}

.article__tags {
  font-family: var(--font-mono);
  font-size: var(--size-mono-xs);
  color: var(--dim);
  margin-bottom: 28px;
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
}

.article__tags .sep { color: var(--dim); }
.article__tags .piece { color: var(--muted); }

.article__title {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: clamp(30px, 6vw, var(--size-title));
  line-height: 1.08;
  letter-spacing: -0.01em;
  color: var(--text);
  text-wrap: balance;
  margin: 0 0 22px;
  text-shadow: 0 0 calc(12px + var(--bloom-strength) * 6px) rgb(var(--accent-rgb) / 0.18);
}

.article__excerpt {
  font-family: var(--font-mono);
  font-size: var(--size-body-lg);
  line-height: 1.6;
  color: var(--muted);
  max-width: 60ch;
  margin: 0 0 28px;
}

.article__byline {
  font-family: var(--font-mono);
  font-size: var(--size-mono-xs);
  color: var(--dim);
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  padding-bottom: 32px;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 40px;
}

.article__byline .author { color: var(--muted); }

.article__body {
  font-family: var(--font-mono);
  font-size: var(--size-body);
  line-height: 1.7;
  color: var(--text);
}

.article__footer {
  margin-top: 48px;
  padding-top: 16px;
  border-top: 1px dashed var(--rule);
  font-family: var(--font-mono);
  font-size: var(--size-mono-xs);
  color: var(--dim);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}

.article__footer a {
  color: var(--accent);
  text-decoration: none;
  transition: color 120ms ease;
}
.article__footer a:hover { color: var(--text); }
.article__footer .sep { color: var(--dim); margin: 0 10px; }

/* ── Prose (inside .article__body and .static-page__body) ── */

.prose h2 {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 24px;
  line-height: 1.3;
  letter-spacing: -0.01em;
  margin: 44px 0 18px;
  color: var(--text);
}

.prose h3 {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 19px;
  line-height: 1.35;
  margin: 32px 0 14px;
  color: var(--text);
}

/* Markdown-style heading markers: a quiet hash count standing in for
   the document outline, in keeping with the terminal conceit. */
.prose h2::before,
.prose h3::before {
  color: var(--accent-dim);
  margin-right: 0.6ch;
  font-weight: 600;
}
.prose h2::before { content: "##"; }
.prose h3::before { content: "###"; }

.prose p { margin-bottom: 22px; }

.prose a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid rgb(var(--accent-rgb) / 0.3);
  transition: border-color 120ms ease, color 120ms ease;
}
.prose a:hover {
  color: var(--text);
  border-bottom-color: var(--accent);
}

.prose em  { font-style: italic; color: var(--text); }
.prose strong { font-weight: 700; color: var(--text); }

.prose blockquote {
  border-left: 2px solid var(--accent);
  margin: 28px 0;
  padding: 6px 20px;
  color: var(--muted);
}
.prose blockquote p { margin-bottom: 10px; }
.prose blockquote p:last-child { margin-bottom: 0; }

.prose ul, .prose ol {
  padding-left: 1.4rem;
  margin-bottom: 22px;
}
.prose li { margin-bottom: 8px; }

.prose code {
  font-family: var(--font-mono);
  font-size: 0.86em;
  color: var(--accent);
  background: rgb(var(--accent-rgb) / 0.08);
  padding: 0.08em 0.35em;
  border-radius: 2px;
}

.prose pre {
  background: var(--surface);
  border: 1px solid var(--rule);
  padding: 16px 20px;
  margin: 22px 0;
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.55;
}
.prose pre code {
  background: transparent;
  color: var(--text);
  padding: 0;
  font-size: inherit;
}

.prose hr {
  border: none;
  border-top: 1px dashed var(--rule);
  margin: 32px 0;
}

.prose del { color: var(--dim); }

/* ─────────────────────────────────────────────────────────────
   Static pages (about, projects/*). Looks like an article but
   without prev/next, byline, or entry numbering.
   ───────────────────────────────────────────────────────────── */

.static-page {
  max-width: var(--main-max);
  padding: 24px 0 48px;
}

.static-page__title {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: clamp(28px, 5vw, 44px);
  line-height: 1.1;
  letter-spacing: -0.01em;
  margin: 0 0 8px;
  color: var(--text);
}

.static-page__path {
  font-family: var(--font-mono);
  font-size: var(--size-mono-xs);
  color: var(--dim);
  margin-bottom: 22px;
}

.static-page__body {
  font-family: var(--font-mono);
  font-size: var(--size-body);
  line-height: 1.7;
  color: var(--text);
  padding-top: 22px;
}

/* ─────────────────────────────────────────────────────────────
   Sidebar (kept as a right column, restyled).
   Blocks get a section label like `$ <header>` and hairline
   borders instead of cards. Fits the shell, not the blog.
   ───────────────────────────────────────────────────────────── */

.sidebar-block {
  margin-bottom: 28px;
  padding-bottom: 22px;
  border-bottom: 1px dashed var(--rule);
}

.sidebar-block:last-child {
  border-bottom: none;
  margin-bottom: 0;
  padding-bottom: 0;
}

.sidebar-block h3 {
  font-family: var(--font-mono);
  font-size: var(--size-mono-xs);
  font-weight: 600;
  color: var(--accent);
  margin-bottom: 12px;
}

.sidebar-block h3::before {
  content: "$ ";
  color: var(--dim);
}

.sidebar-content {
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.6;
  color: var(--muted);
}
.sidebar-content p { margin-bottom: 10px; }
.sidebar-content p:last-child { margin-bottom: 0; }
.sidebar-content strong { color: var(--text); font-weight: 600; }
.sidebar-content a { color: var(--accent); text-decoration: none; border-bottom: 1px solid rgb(var(--accent-rgb) / 0.3); }
.sidebar-content a:hover { border-bottom-color: var(--accent); color: var(--text); }

.sidebar-links {
  list-style: none;
  padding: 0;
  margin: 0;
}

.sidebar-links li {
  padding: 4px 0;
}

.sidebar-links a {
  color: var(--muted);
  text-decoration: none;
  font-family: var(--font-mono);
  transition: color 120ms ease;
}
.sidebar-links a::before {
  content: "→ ";
  color: var(--dim);
  margin-right: 4px;
}
.sidebar-links a:hover {
  color: var(--accent);
}

.sidebar-socials {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  align-items: center;
}
.sidebar-socials a {
  color: var(--muted);
  transition: color 120ms ease;
}
.sidebar-socials a:hover { color: var(--accent); }
.sidebar-socials svg { width: 18px; height: 18px; display: block; }

/* ─────────────────────────────────────────────────────────────
   404 — styled like a terminal error.
   ───────────────────────────────────────────────────────────── */

.not-found {
  padding: 48px 14px;
  font-family: var(--font-mono);
  font-size: var(--size-mono);
}

.not-found__code {
  color: var(--err);
  font-size: 64px;
  line-height: 1;
  margin-bottom: 12px;
}

.not-found__msg {
  color: var(--text);
  margin-bottom: 18px;
}

.not-found a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
}

/* ─────────────────────────────────────────────────────────────
   Overlays — scanlines, flicker, vignette.
   Fixed to viewport, above content, pointer-events:none.
   Toggleable by class on the body for future tweaks, but
   enabled by default (subtle).
   ───────────────────────────────────────────────────────────── */

.crt-scanlines,
.crt-vignette,
.crt-flicker {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 100;
}

.crt-scanlines {
  background: repeating-linear-gradient(
    to bottom,
    transparent 0,
    transparent 2px,
    rgba(255, 255, 255, 0.022) 2px,
    rgba(255, 255, 255, 0.022) 3px
  );
  mix-blend-mode: overlay;
}

.crt-flicker {
  background: rgba(255, 255, 255, 0.015);
  mix-blend-mode: overlay;
  animation: flicker 0.18s infinite steps(2, end);
}

@keyframes flicker {
  0%, 100% { opacity: 0.65; }
  20%      { opacity: 0.85; }
  45%      { opacity: 0.55; }
  70%      { opacity: 0.9; }
  85%      { opacity: 0.7; }
}

.crt-vignette {
  box-shadow:
    inset 0 0 200px rgba(0,0,0,0.7),
    inset 0 0 80px rgba(0,0,0,0.4);
}

/* ─────────────────────────────────────────────────────────────
   Boot animation states. When JS decides to replay boot, it
   adds `is-booting` to the shell; elements tagged with data-
   attributes are hidden and revealed progressively.
   ───────────────────────────────────────────────────────────── */

.is-booting [data-boot-reveal] {
  opacity: 0;
  transform: translateY(-3px);
  transition: opacity 160ms ease, transform 160ms ease;
}

.is-booting [data-boot-reveal].is-revealed {
  opacity: 1;
  transform: translateY(0);
}

/* ─────────────────────────────────────────────────────────────
   Reduced motion — kill typewriter, flicker, caret blink.
   ───────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .crt-flicker { display: none; }
  .prompt__caret { animation: none; opacity: 1; }
  .hero, .hero__amp,
  .is-booting [data-boot-step="hero"].is-revealed .hero,
  .is-booting [data-boot-step="hero"].is-revealed .hero__amp {
    animation: none !important;
  }
  .is-booting [data-boot-reveal] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* ─────────────────────────────────────────────────────────────
   Mobile. At narrower widths we drop the sidebar below the
   main column and relax paddings. The hero ASCII overflows
   horizontally with a scroll rather than breaking across lines.
   ───────────────────────────────────────────────────────────── */

@media (max-width: 960px) {
  .crt__body {
    grid-template-columns: 1fr;
    gap: 32px;
    padding: 20px 18px 32px;
  }
  .crt__aside {
    border-left: none;
    border-top: 1px dashed var(--rule);
    padding-left: 0;
    padding-top: 22px;
    position: static;
  }
  .post-row a {
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 12px;
  }
  .post-row__date  { grid-column: 1; grid-row: 2; }
  .post-row__size,
  .post-row__time  { grid-column: 2; grid-row: 2; text-align: right; }

  /* The inset vignette darkens too much of a narrow viewport. */
  .crt-vignette { display: none; }
}

@media (max-width: 560px) {
  :root { --size-mono: 16px; --size-body: 18px; }
  .crt__chrome { padding: 8px 12px; font-size: 12px; gap: 10px; }
  .crt__path { font-size: 12px; min-width: 0; flex-shrink: 1; }
  .crt__meta { flex-shrink: 0; }
  .crt__body { padding: 14px 12px 24px; }
  .crt__status { padding: 6px 12px; font-size: 12px; gap: 10px; }
  .crt__status .status-right { display: none; }
  .article__title { font-size: 40px; }
  .hero__amp { display: none; }
}
