@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Newsreader:ital,opsz,wght@0,6..72,400;0,6..72,500;0,6..72,600;1,6..72,400;1,6..72,500&family=Pirata+One&family=JetBrains+Mono:wght@400;500&display=swap');

/* ============================================================================
   The Paper Edition: design tokens
   Ported from the portfolio at thekrishna.in (app/globals.css) so the blog and
   the front site read as one publication. A newspaper-inspired system: paper
   stock, ink text, hairline rules, condensed serif display type, one
   vermilion accent for tags. Hierarchy comes from type scale and rule weight,
   never from colour.

   Type, rules and the dark edition track the portfolio. The light edition
   deliberately departs from it: the owner wants paper white rather than grey
   newsprint, with depth carried by a ladder of fills instead of shadows.
   Style with the variables, never with hardcoded values.

   Light-edition depth ladder, darkest to lightest. Each step is a distinct,
   visible fill so stacked components separate by tone alone:
     --chip-bg       badges and tags, the densest ink-tinted stock
     --button-bg     buttons, pagination, tab strips
     --surface-strong image wells inside cards and figures
     --section-alt   recessed bands that cards sit on
     --bg            the page: warm paper white
     --card          the raised sheet, lighter than the page
     --card-hover    the same sheet, lit on hover
   ============================================================================ */
:root {
  color-scheme: light;
  --bg: #f7f5f0; /* paper white */
  --section-alt: #efece4; /* a recessed band, one step under the page */
  --surface: transparent;
  --surface-strong: #e8e4da; /* image wells */
  --ink: #1d1d1b;
  --text-primary: #1d1d1b;
  --text-secondary: #3b3a36;
  --text-muted: #605e57;
  --text-subtle: #7c7970;
  --rule: rgba(29, 29, 27, 0.28); /* hairline */
  --rule-strong: rgba(29, 29, 27, 0.6); /* raised / active */
  --card-edge: rgba(29, 29, 27, 0.72); /* ticket card outer border, a step under full ink */
  --rule-subtle: rgba(29, 29, 27, 0.16);
  --accent: #c2412a; /* vermilion tag, the single accent */
  --accent-ink: #fbf9f5; /* text printed on an accent tag */
  --plate: #1d1d1b;
  --plate-text: #f7f5f0;
  --nav-bg: rgba(247, 245, 240, 0.94);
  --button-primary-bg: #1d1d1b;
  --button-primary-text: #f7f5f0;
  --button-primary-hover: #3b3a36;
  --button-outline-text: #1d1d1b;
  --button-bg: #ebe7de; /* filled outline buttons */
  --button-hover: #e2ddd2;
  --chip-bg: #e3ded2; /* badges: a step denser than buttons */
  --chip-hover: #d9d3c5;
  --code-bg: #e8e3d8; /* inline code: between the button and band tones */
  --quote-bg: #efebe3; /* blockquote panel, one step under the page */
  --ghost-text: #605e57;
  --ghost-hover-text: #1d1d1b;
  --ghost-hover-bg: rgba(29, 29, 27, 0.06);
  --ring: #1d1d1b;
  --selection-bg: rgba(29, 29, 27, 0.85);
  --selection-text: #f7f5f0;
  /* Paper texture, modelled on Papersrc (github.com/Umer-Hamaaz/Papersrc): a
     mid-grey noise sheet at a few percent opacity. Five octaves give point
     grain plus a softer fibre mottle at the 4 to 16px scale; the transfer
     centres it on mid grey so it darkens light stock and lightens dark stock
     by the same amount. Strength lives in the alpha slope (Papersrc default is
     0.06; the portfolio uses 0.052; the owner asked for 30% less grain on
     the blog, so 0.0364). It is a background-image layer, so each sheet,
     band and card carries its own grain and it scrolls with them. */
  --paper-texture: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='320' height='320'%3E%3Cfilter id='n' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.35' numOctaves='5' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix values='1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1'/%3E%3CfeComponentTransfer%3E%3CfeFuncR type='linear' slope='1' intercept='-0.25'/%3E%3CfeFuncG type='linear' slope='1' intercept='-0.25'/%3E%3CfeFuncB type='linear' slope='1' intercept='-0.25'/%3E%3CfeFuncA type='linear' slope='0.0364'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  --live: #2f7d4f; /* reserved for current status */
  /* Card stock: the raised sheet, lighter than the page */
  --card: #fdfcf9;
  --card-hover: #ffffff;
  --card-shadow: 0 1px 0 rgba(29, 29, 27, 0.18), 0 10px 24px -14px rgba(29, 29, 27, 0.45);
  --card-shadow-raised: 0 1px 0 rgba(29, 29, 27, 0.25), 0 16px 32px -14px rgba(29, 29, 27, 0.55);

  /* Instrument Serif ships at 400 only. Headlines and titles gain newsprint
     heft from a stroke on the glyphs; a synthetic bold would just smear them.
     With paint-order stroke-first, only the outer half of the stroke shows,
     so these are twice the visible thickening. The owner asked for a heavier
     broadsheet headline than the portfolio's 0.019/0.013.
     Applies to headings and titles ONLY, never to labels, chips or metadata. */
  --headline-ink: 0.036em;
  --title-ink: 0.03em;

  /* Headline leading. Every title that can wrap uses one of these so wrapped
     lines read as a set, as on a newspaper page. Instrument Serif has tall
     ascenders and the ink stroke thickens it further, so the display value
     sits above the usual 1.0 to 1.1. Single-line marks (masthead, the 404
     numeral) keep line-height 1. */
  --lh-display: 1.18; /* nameplate, article and section heads */
  --lh-title: 1.34; /* card titles, subheads, prev/next titles */

  /* Reading leading. Newsreader sets a little tight at 1.5, so body copy
     runs at 1.75 and the shorter measures (cards, decks, captions) at 1.6. */
  --lh-body: 1.75;
  --lh-copy: 1.6;

  /* Type */
  --font-display: 'Instrument Serif', 'Times New Roman', serif;
  --font-body: 'Newsreader', Georgia, 'Times New Roman', serif;
  --font-masthead: 'Pirata One', 'Instrument Serif', serif;
  --font-mono: 'JetBrains Mono', ui-monospace, monospace;

  /* Shape: a softened corner on cards and tiles, sharp on chips */
  --r-card: 0.375rem;
  --r-tile: 0.25rem;
  --r-chip: 0;

  /* Measure. The side margin scales gently with the viewport (24px on a
     phone, about 50px on a laptop, capped at 64px) so wide screens put more
     of their width into content without the page running into the edges.
     Past --page the frame stops growing and the margins take the rest. */
  --page: 96rem;
  --column: 44rem; /* the reading column of an article */
  --gutter: clamp(1.5rem, 4vw, 4rem);
}

html[data-theme='dark'] {
  color-scheme: dark;
  /* The ink edition's depth ladder, darkest to lightest. The steps are wider
     than a naive inversion of the light ladder: near black, equal steps in
     hex are nearly invisible, so each rung is a clear jump in rendered
     contrast (1.1x to 1.2x its neighbour, measured; the paper edition's
     rungs sit at 1.05x to 1.08x). */
  --bg: #121210;            /* page */
  --section-alt: #1b1b18;   /* recessed bands under the cards */
  --surface-strong: #2c2c27; /* image wells */
  --card: #262621;          /* the raised sheet */
  --card-hover: #2f2f29;
  --button-bg: #32322c;     /* controls sit above the sheet */
  --button-hover: #3d3d36;
  --chip-bg: #3c3c35;       /* badges, the highest rung */
  --chip-hover: #484840;
  --code-bg: #32322c;
  --quote-bg: #1b1b18;
  --ink: #e3dfd6;
  --text-primary: #e3dfd6;
  --text-secondary: #c4c0b6;
  --text-muted: #9c988e;
  --text-subtle: #7f7b72;
  --rule: rgba(227, 223, 214, 0.28);
  --rule-strong: rgba(227, 223, 214, 0.62);
  --card-edge: rgba(227, 223, 214, 0.55);
  --rule-subtle: rgba(227, 223, 214, 0.14);
  --accent: #e4603f;
  --accent-ink: #121210;
  --plate: #e3dfd6;
  --plate-text: #121210;
  --nav-bg: rgba(18, 18, 16, 0.94);
  --button-primary-bg: #e3dfd6;
  --button-primary-text: #121210;
  --button-primary-hover: #c4c0b6;
  --button-outline-text: #e3dfd6;
  --ghost-text: #9c988e;
  --ghost-hover-text: #e3dfd6;
  --ghost-hover-bg: rgba(227, 223, 214, 0.08);
  --ring: #e3dfd6;
  --selection-bg: rgba(227, 223, 214, 0.88);
  --selection-text: #121210;
  --live: #6fbf8c;
  --card-shadow: 0 1px 0 rgba(0, 0, 0, 0.6), 0 10px 24px -14px rgba(0, 0, 0, 0.9);
  --card-shadow-raised: 0 1px 0 rgba(0, 0, 0, 0.7), 0 16px 32px -14px rgba(0, 0, 0, 0.95);
}

/* ---------------------------------------------------------------------------
   Reset and base
   --------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: var(--lh-copy);
  background: var(--paper-texture) var(--bg);
  color: var(--text-primary);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: 'kern', 'liga', 'onum';
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: 400;
  margin: 0;
}

p {
  margin: 0;
}

img {
  max-width: 100%;
  height: auto;
}

a {
  color: inherit;
  text-decoration-style: dotted;
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1.5px;
}

button {
  font: inherit;
  color: inherit;
}

:is(a, button, summary):focus-visible {
  outline: 1.5px solid var(--ring);
  outline-offset: 3px;
}

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

::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--rule-strong); }

/* The no-JS banner from baseof. Ink on paper, like everything else. */
.danger-enable-js {
  position: fixed;
  z-index: 60;
  top: 4.5rem;
  left: 0;
  right: 0;
  padding: 0.5rem 1rem;
  text-align: center;
  font-family: var(--font-display);
  background: var(--accent);
  color: var(--accent-ink);
}

/* ---------------------------------------------------------------------------
   Layout: page frame, bands, rules
   --------------------------------------------------------------------------- */
.page-frame {
  width: min(100% - 2 * var(--gutter), var(--page));
  margin-inline: auto;
}

/* The reading measure for an article body. */
.column-frame {
  width: min(100% - 2 * var(--gutter), var(--column));
  margin-inline: auto;
}

.site-content {
  /* Clears the fixed masthead. */
  padding-top: 4.5rem;
  min-height: 60vh;
}

/* Bands separate by tone alone. No edge rules: the stock change is the
   boundary, and stacking a hairline on it just doubles the seam. */
.band {
  background: var(--paper-texture) var(--bg);
}

/* Alternate bands carry a faint dot grid so cards read as lifted sheets. */
.band--alt {
  background-color: var(--section-alt);
  background-image: var(--paper-texture), radial-gradient(var(--rule-subtle) 1px, transparent 1.5px);
  background-size: auto, 22px 22px;
}

.band-inner {
  padding-block: 3rem;
}

/* ---------------------------------------------------------------------------
   Type scale
   --------------------------------------------------------------------------- */
.section-title {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 4.6vw, 3.75rem);
  line-height: var(--lh-display);
  letter-spacing: -0.01em;
  text-align: center;
  text-wrap: balance;
  -webkit-text-stroke: var(--headline-ink) currentColor;
  paint-order: stroke fill;
}

/* An italic deck under the heading. */
.deck {
  font-family: var(--font-body);
  font-style: italic;
  font-size: clamp(1.125rem, 1.6vw, 1.375rem);
  line-height: 1.45;
  color: var(--text-secondary);
  text-align: center;
  text-wrap: balance;
  margin: 0;
}

.section-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 2.5rem;
}

.section-head::after {
  content: none;
}

/* Small caption for metadata (dates, reading time, sources). */
.caption {
  font-family: var(--font-body);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--text-muted);
  font-variant-numeric: oldstyle-nums;
}

/* The vermilion tag: the single accent in the system. */
.tag {
  display: inline-flex;
  align-items: center;
  height: 1.15rem;
  padding: 0 0.32rem;
  font-family: var(--font-display);
  font-size: 0.8rem;
  line-height: 1;
  letter-spacing: 0.02em;
  color: var(--accent-ink);
  background: var(--accent);
  border-radius: var(--r-chip);
  white-space: nowrap;
}

/* A metadata row: items in one caption voice, separated by a small dot. */
.meta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 1rem;
}

.meta-row > span {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  white-space: nowrap;
}

.meta-row svg {
  width: 0.9rem;
  height: 0.9rem;
  flex: 0 0 auto;
  color: var(--text-subtle);
}

.meta-row > span + span::before {
  content: '';
  width: 3px;
  height: 3px;
  margin-right: 0.35rem;
  background: var(--text-subtle);
}

@media (max-width: 639px) {
  .meta-row > span + span::before {
    content: none;
  }
}

/* ---------------------------------------------------------------------------
   Buttons and links
   --------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 2.75rem;
  padding: 0.5rem 1.25rem;
  font-family: var(--font-display);
  font-size: 1.0625rem;
  letter-spacing: 0.01em;
  line-height: 1;
  border: 1px solid var(--ink);
  border-radius: var(--r-tile);
  color: var(--button-outline-text);
  background: var(--button-bg);
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.2s ease, color 0.2s ease;
}

.btn:hover {
  background: var(--button-hover);
}

.btn--primary {
  background: var(--button-primary-bg);
  color: var(--button-primary-text);
}

.btn--primary:hover {
  background: var(--button-primary-hover);
}

.btn svg {
  width: 1rem;
  height: 1rem;
}

.icon-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  color: var(--ghost-text);
  transition: color 0.2s ease;
}

button.icon-link {
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}

.icon-link:hover {
  color: var(--ghost-hover-text);
}

.icon-link svg {
  width: 1.15rem;
  height: 1.15rem;
}

/* ---------------------------------------------------------------------------
   Masthead
   --------------------------------------------------------------------------- */
.masthead {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  background: var(--nav-bg);
  border-bottom: 1px solid var(--rule);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

.masthead-row {
  display: grid;
  /* Equal outer tracks keep the title on the page's true centre line. */
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  min-height: 4.5rem;
  gap: 1rem;
}

.masthead-left {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  min-width: 0;
  overflow: hidden;
}

.masthead-links {
  display: none;
  align-items: center;
  gap: 1.1rem;
}

.masthead-links a {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-family: var(--font-display);
  font-size: 1.0625rem;
  letter-spacing: 0.01em;
  color: var(--text-secondary);
  text-decoration: none;
  transition: color 0.2s ease;
}

.masthead-links a:hover,
.masthead-links a[aria-current='page'] {
  color: var(--text-primary);
}

.masthead-links svg {
  width: 0.95rem;
  height: 0.95rem;
  color: var(--text-muted);
}

.masthead-title {
  font-family: var(--font-masthead);
  font-size: clamp(1.35rem, 2.2vw, 1.75rem);
  line-height: 1;
  color: var(--text-primary);
  white-space: nowrap;
  text-align: center;
  text-decoration: none;
}

.masthead-right {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.25rem;
}

.masthead-menu,
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 0;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  transition: color 0.2s ease;
}

.masthead-menu:hover,
.theme-toggle:hover {
  color: var(--text-primary);
}

.masthead-menu svg,
.theme-toggle svg {
  width: 1.25rem;
  height: 1.25rem;
}

/* The toggle prints the edition you would switch *to*. */
.theme-toggle .icon-moon { display: block; }
.theme-toggle .icon-sun { display: none; }
html[data-theme='dark'] .theme-toggle .icon-moon { display: none; }
html[data-theme='dark'] .theme-toggle .icon-sun { display: block; }

.masthead-drawer {
  border-top: 1px solid var(--rule);
  padding: 1rem 0 1.25rem;
  display: flex;
  flex-direction: column;
}

.masthead-drawer[hidden] {
  display: none;
}

.masthead-drawer a {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-display);
  font-size: 1.5rem;
  line-height: 1;
  padding: 0.7rem 0;
  border-bottom: 1px dashed var(--rule);
  color: var(--text-primary);
  text-decoration: none;
}

.masthead-drawer a:last-child {
  border-bottom: 0;
}

.masthead-drawer svg {
  width: 1.25rem;
  height: 1.25rem;
  color: var(--text-muted);
}

@media (min-width: 1024px) {
  .masthead-links { display: flex; }
  .masthead-menu { display: none; }
  .masthead-drawer { display: none !important; }
}

/* ---------------------------------------------------------------------------
   Front page of the blog: the nameplate
   --------------------------------------------------------------------------- */
.nameplate {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  padding-block: 3rem 2.5rem;
  text-align: center;
}

.nameplate-title {
  font-family: var(--font-masthead);
  font-size: clamp(2.75rem, 7vw, 5rem);
  line-height: var(--lh-display);
  color: var(--text-primary);
  text-wrap: balance;
}

.nameplate-deck {
  font-family: var(--font-body);
  font-style: italic;
  font-size: clamp(1.0625rem, 1.8vw, 1.375rem);
  color: var(--text-secondary);
  max-width: 48ch;
  text-wrap: balance;
}

/* The dateline rule under the nameplate, as on a broadsheet: a hairline with
   the edition details set into it. */
.dateline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.35rem 1rem;
  width: 100%;
  margin-top: 0.5rem;
  padding-block: 0.85rem 0;
  border-top: 1px solid var(--rule);
  font-family: var(--font-display);
  font-size: 0.9375rem;
  letter-spacing: 0.02em;
  color: var(--text-muted);
}

.dateline > span {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.dateline svg {
  width: 0.9rem;
  height: 0.9rem;
}

.nameplate-portrait {
  width: 5.5rem;
  height: 5.5rem;
  object-fit: cover;
  border: 1px solid var(--ink);
  border-radius: var(--r-tile);
  background: var(--surface-strong);
}

/* ---------------------------------------------------------------------------
   Post cards: the ticket treatment shared across the system. A solid outer
   border a step under full ink, a dashed inner rule inset from it, the lighter
   card stock, and a press shadow. This is the only shadow in the system.
   --------------------------------------------------------------------------- */
.post-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}

@media (min-width: 640px) {
  .post-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
  .post-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Wide desktops: a fourth column rather than three oversized cards. */
@media (min-width: 1600px) {
  .post-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.post-card {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--paper-texture) var(--card);
  border: 1.5px solid var(--card-edge);
  border-radius: var(--r-card);
  box-shadow: var(--card-shadow);
  transition: box-shadow 0.25s ease, transform 0.25s ease;
}

.post-card::before {
  content: '';
  position: absolute;
  inset: 5px;
  border: 1px dashed var(--rule-strong);
  border-radius: calc(var(--r-card) - 3px);
  pointer-events: none;
  z-index: 1;
}

.post-card:is(:hover, :focus-within) {
  box-shadow: var(--card-shadow-raised);
  transform: translateY(-3px);
}

.post-card-media {
  position: relative;
  margin: 12px 12px 0;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border: 1px solid var(--rule);
  border-radius: calc(var(--r-card) - 4px);
  background: var(--surface-strong);
  filter: saturate(0.85) contrast(0.95);
  transition: filter 0.3s ease;
}

.post-card:is(:hover, :focus-within) .post-card-media {
  filter: none;
}

.post-card-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

/* No cover art: set the first letter of the headline as a printer's block. */
.post-card-fallback {
  display: grid;
  place-items: center;
  height: 100%;
  font-family: var(--font-display);
  font-size: 5rem;
  color: var(--text-subtle);
}

/* The headline takes only the lines it needs, so the hairline always sits
   the same distance under its last line and the summary the same distance
   under the hairline, whether the headline runs one line or two. The byline
   is pinned to the bottom edge; any slack from a shorter headline collects
   above it, never around the rule. */
.post-card-body {
  --card-rule-gap: 1.05rem;
  display: grid;
  grid-template-rows: auto auto 1fr auto;
  flex: 1 1 auto;
  padding: 1.6rem 1.75rem 1.75rem;
}

.post-card-title {
  font-family: var(--font-display);
  font-size: 1.5rem;
  line-height: var(--lh-title);
  -webkit-text-stroke: var(--title-ink) currentColor;
  paint-order: stroke fill;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  margin-bottom: var(--card-rule-gap);
}

.post-card-title a {
  color: inherit;
  text-decoration: none;
}

.post-card-title a:hover {
  text-decoration: underline dotted;
  text-decoration-thickness: 0.06em;
}

/* A hairline under the headline keeps every summary starting on the same rule. */
.post-card-rule {
  height: 1px;
  background: var(--rule-strong);
}

.post-card-summary {
  align-self: start;
  margin-top: var(--card-rule-gap);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  overflow: hidden;
  font-size: 1rem;
  line-height: var(--lh-copy);
  color: var(--text-secondary);
}

.post-card-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 0.75rem;
  align-self: end;
  margin-top: 1.75rem;
  padding-top: 1rem;
  border-top: 1px dashed var(--rule);
}

.post-card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* ---------------------------------------------------------------------------
   Chips: tags, categories. Sharp-cornered card stock with an ink outline.
   --------------------------------------------------------------------------- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.2rem 0.55rem;
  font-family: var(--font-body);
  font-size: 0.8125rem;
  line-height: 1.3;
  color: var(--text-primary);
  background: var(--paper-texture) var(--chip-bg);
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-tile);
  text-decoration: none;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}

.chip:hover {
  background-color: var(--chip-hover);
  border-color: var(--ink);
}

.chip svg {
  width: 0.75rem;
  height: 0.75rem;
  color: var(--text-subtle);
}

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.chip-row--center {
  justify-content: center;
}

/* ---------------------------------------------------------------------------
   Article: the headline block, cover plate and reading column
   --------------------------------------------------------------------------- */
/* The story head, set as a broadsheet opens a piece: slug and dateline, the
   headline, a deck, then one double rule with the byline beneath it. Nothing
   is boxed; the double rule is the only ornament, and it does the work the
   three hairlines used to do. */
.article-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  width: min(100%, 60rem);
  margin-inline: auto;
  padding-block: 2.75rem 0;
  text-align: center;
}

/* Section slug and dateline on one line, the section in the display face. */
.article-slug {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 0.5rem 0.65rem;
  font-family: var(--font-body);
  font-size: 0.9375rem;
  letter-spacing: 0.02em;
  color: var(--text-muted);
  font-variant-numeric: oldstyle-nums;
}

.article-section {
  font-family: var(--font-display);
  font-size: 1.0625rem;
  letter-spacing: 0.04em;
  color: var(--text-primary);
  text-transform: capitalize;
}

.article-section::after {
  content: '';
  display: inline-block;
  width: 3px;
  height: 3px;
  margin-left: 0.65rem;
  vertical-align: 0.25em;
  background: var(--text-subtle);
}

/* The front-page headline. Heavier and a touch more open than the section
   heads: the stroke thickens every glyph outward, so the letter and word
   spacing open up by about the same amount to keep counters clear. */
.article-title {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 5.4vw, 4.5rem);
  line-height: var(--lh-display);
  letter-spacing: 0.012em;
  word-spacing: 0.05em;
  text-wrap: balance;
  -webkit-text-stroke: 0.042em currentColor;
  paint-order: stroke fill;
}

/* The deck: the standfirst under the headline, italic in the reading face. */
.article-deck {
  max-width: 44rem;
  font-family: var(--font-body);
  font-style: italic;
  font-size: clamp(1.125rem, 1.7vw, 1.4375rem);
  line-height: 1.5;
  color: var(--text-secondary);
  text-wrap: pretty;
}

/* One double rule closes the head. The byline sits under it, unboxed. */
.article-byline {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 0.35rem 1.25rem;
  width: 100%;
  margin-top: 0.75rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--rule);
}

.byline-by {
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--text-muted);
}

.byline-name {
  font-family: var(--font-display);
  font-size: 1.1875rem;
  letter-spacing: 0.01em;
  color: var(--text-primary);
}

/* The story's art: cut to the column, no frame, a caption line beneath in
   the caption voice, then a hairline to hand over to the body. */
.article-cover {
  max-width: 48rem;
  margin: 2.25rem auto 0;
}

.article-cover img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--r-tile);
  background: var(--surface-strong);
}

.article-cover figcaption {
  margin-top: 0.6rem;
  text-align: center;
}

.article-cover + .article-layout {
  margin-top: 2.25rem;
}

/* Without a cover, the body starts a rule's width under the byline. */
.article-head + * .article-layout:first-child {
  margin-top: 2.5rem;
}

.article-body {
  padding-bottom: 3rem;
}

/* The article foot: tags, then the previous/next rule. */
.article-foot {
  margin-top: 3rem;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.page-nav {
  display: grid;
  gap: 0.75rem;
}

@media (min-width: 640px) {
  .page-nav { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.page-nav a {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 0.9rem 1.1rem;
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-tile);
  background: var(--paper-texture) var(--card);
  text-decoration: none;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}

.page-nav a:hover {
  border-color: var(--ink);
  background-color: var(--card-hover);
}

.page-nav-label {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-family: var(--font-display);
  font-size: 0.875rem;
  color: var(--text-muted);
}

.page-nav-label svg {
  width: 0.85rem;
  height: 0.85rem;
}

.page-nav-title {
  font-family: var(--font-display);
  font-size: 1.125rem;
  line-height: var(--lh-title);
  color: var(--text-primary);
  -webkit-text-stroke: var(--title-ink) currentColor;
  paint-order: stroke fill;
}

.page-nav a.page-nav--next {
  text-align: right;
  grid-column: 2;
}

.page-nav a.page-nav--next .page-nav-label {
  align-self: flex-end;
}

/* ---------------------------------------------------------------------------
   The share rail: a column of ink glyphs beside the article on wide screens,
   a row above it on narrow ones.
   --------------------------------------------------------------------------- */
.article-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1.5rem;
}

@media (min-width: 1100px) {
  .article-layout {
    grid-template-columns: 3.5rem minmax(0, 1fr) 3.5rem;
    align-items: start;
  }
}

.share-rail {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.25rem;
  padding-bottom: 0.5rem;
}

.share-rail-label {
  font-family: var(--font-display);
  font-size: 0.875rem;
  color: var(--text-muted);
  margin-right: 0.35rem;
}

@media (min-width: 1100px) {
  .share-rail {
    position: sticky;
    top: 6rem;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    padding-bottom: 0;
    padding-right: 0.5rem;
  }

  .share-rail-label {
    margin-right: 0;
    margin-bottom: 0.25rem;
  }
}

/* ---------------------------------------------------------------------------
   Pagination: a "continued" rule, as a broadsheet marks a story that runs on.
   --------------------------------------------------------------------------- */
.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 2.5rem;
}

.pagination a,
.pagination span {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-height: 2.5rem;
  padding: 0.35rem 0.9rem;
  font-family: var(--font-display);
  font-size: 1rem;
  letter-spacing: 0.01em;
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-tile);
  background: var(--button-bg);
  text-decoration: none;
  color: var(--text-primary);
  transition: border-color 0.2s ease, background-color 0.2s ease;
}

.pagination a:hover {
  border-color: var(--ink);
  background: var(--button-hover);
}

.pagination .is-current {
  background: var(--button-primary-bg);
  color: var(--button-primary-text);
  border-color: var(--ink);
}

.pagination .is-disabled {
  opacity: 0.35;
}

.pagination svg {
  width: 0.9rem;
  height: 0.9rem;
}

/* ---------------------------------------------------------------------------
   Footer (the colophon)
   --------------------------------------------------------------------------- */
/* The colophon sits on the recessed band stock, one rung under the page,
   closed off by a strong rule so the back page reads as its own sheet.
   Plain stock, no dot grid: the owner wants the footer unpatterned. */
.colophon {
  background: var(--paper-texture) var(--section-alt);
  padding-block: 2.25rem;
}

.colophon-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.9375rem;
  color: var(--text-muted);
  text-align: center;
}

.colophon-imprint {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 0.35rem 0.75rem;
}

.colophon-mark {
  font-family: var(--font-masthead);
  font-size: 1.375rem;
  line-height: 1;
  color: var(--text-primary);
}

.colophon-note {
  font-family: var(--font-body);
  font-style: italic;
  color: var(--text-muted);
}

@media (min-width: 640px) {
  .colophon-row {
    flex-direction: row;
    text-align: left;
  }
}

.colophon-social {
  display: flex;
  align-items: center;
  gap: 0.1rem;
}

/* ---------------------------------------------------------------------------
   Back to top
   --------------------------------------------------------------------------- */
.to-top {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 40;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid var(--ink);
  border-radius: var(--r-tile);
  background: var(--paper-texture) var(--button-bg);
  color: var(--text-primary);
  box-shadow: var(--card-shadow);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.25s ease, visibility 0.25s ease, box-shadow 0.2s ease, transform 0.2s ease;
}

.to-top[data-visible] {
  opacity: 1;
  visibility: visible;
}

.to-top:hover {
  box-shadow: var(--card-shadow-raised);
  transform: translateY(-1px);
}

.to-top svg {
  width: 1.1rem;
  height: 1.1rem;
}

/* ---------------------------------------------------------------------------
   Prose: the article body. Ink on paper, one accent, hairline rules.
   --------------------------------------------------------------------------- */
.prose {
  font-size: 1.1875rem;
  line-height: var(--lh-body);
  color: var(--text-secondary);
}

/* The article column widens with the screen, and the body steps up a size
   at each stop so a line shows more of the page without running past a
   comfortable measure (about 80 to 90 characters). --column includes the
   share rail and its mirror track (10rem in all), so the text itself is
   --column minus 10rem once the rail moves to the side. */
@media (min-width: 1100px) {
  :root { --column: 54rem; } /* text 44rem */
}

@media (min-width: 1440px) {
  :root { --column: 62rem; } /* text 52rem */
  .prose { font-size: 1.3125rem; }
}

@media (min-width: 1800px) {
  :root { --column: 68rem; } /* text 58rem */
  .prose { font-size: 1.375rem; }
}

.prose {
  /* The gap between paragraphs, and the larger gap that sets framed blocks
     (code, tables, figures, quotes, chart tabs) apart from the copy on
     either side so they don't crowd the sentences that introduce them. */
  --flow: 1.3rem;
  --flow-block: 2rem;
}

.prose > * + * {
  margin-top: var(--flow);
}

/* Framed blocks take the wider gap above and below. The wrappers are Hugo's
   `.highlight` around fenced code, plus the inline-HTML wrappers old posts use
   (some arrive wrapped in a <p>, hence the :has). The gap is a margin on both
   sides of the block, so it collapses with its neighbours' margins: the
   result is always the larger of the two, and hidden leftovers in between
   (below) don't break it. */
.prose > :is(.highlight, pre, table, .tg-wrap, figure, blockquote, .row, .tab, .tabcontent, center, img, hr, p:has(> center:only-child)) {
  margin-block: var(--flow-block);
}

.prose > :first-child {
  margin-top: 0;
}

/* Leftovers from the old theme that faked spacing: a post's inline <style>
   (sometimes wrapped in a <p>) and bare <br>s between blocks. The flow gaps
   above do that job now. (`&nbsp;` spacer paragraphs are stripped in
   single.html, since CSS can't match on text.) */
.prose > :is(style, script, br),
.prose > p:has(> :is(style, script):only-child) {
  display: none;
}

/* The chart tabs and their panels are one unit: no gap between them. */
.prose > .tab {
  margin-bottom: 0;
}

.prose > .tab ~ .tabcontent {
  margin-top: 0;
}

/* Code nested in a list item still gets breathing room from its text. */
.prose li > :is(.highlight, pre) {
  margin-block: 1rem;
}

.prose p {
  margin: 0;
}

/* Article subheads, set as broadsheet heads: sized in em off the body so
   they keep their proportion as the body steps up on wide screens, with the
   ink stroke and the letter spacing both stepping down by level. The stroke
   swells each glyph outward, so each level's tracking roughly matches its
   stroke to keep the condensed face from closing up. Same face throughout;
   weight comes only from the stroke. */
.prose :is(h1, h2, h3, h4, h5, h6) {
  --head-ink: var(--title-ink);
  color: var(--text-primary);
  line-height: var(--lh-title);
  margin-top: 2.5em;
  margin-bottom: 0.6em;
  word-spacing: 0.04em;
  -webkit-text-stroke: var(--head-ink) currentColor;
  paint-order: stroke fill;
  scroll-margin-top: 6rem;
}

.prose h1 { font-size: 2.15em;  --head-ink: 0.042em; letter-spacing: 0.014em; line-height: var(--lh-display); margin-top: 1.4em; }
.prose h2 { font-size: 1.8em;   --head-ink: 0.04em;  letter-spacing: 0.014em; line-height: var(--lh-display); margin-top: 1.5em; }
.prose h3 { font-size: 1.42em;  --head-ink: 0.036em; letter-spacing: 0.016em; margin-top: 1.6em; }
.prose h4 { font-size: 1.2em;   --head-ink: 0.032em; letter-spacing: 0.018em; margin-top: 1.7em; }
.prose h5,
.prose h6 { font-size: 1.06em;  --head-ink: 0.03em;  letter-spacing: 0.02em;  margin-top: 1.7em; }

/* Broadsheet rules: the top level sits over a double ink rule like the
   section heads, the next over a strong hairline, the third over a light one. */
/* One rule style for subheads, on the top two levels only. */
.prose :is(h1, h2) {
  padding-bottom: 0.28em;
  border-bottom: 1px solid var(--rule);
}

.prose strong,
.prose b {
  font-weight: 600;
  color: var(--text-primary);
}

.prose em { font-style: italic; }

.prose a {
  color: var(--text-primary);
  text-decoration: underline dotted;
  text-decoration-color: var(--rule-strong);
  text-decoration-thickness: 1.5px;
  transition: text-decoration-color 0.2s ease;
}

.prose a:hover {
  text-decoration-color: var(--ink);
}

.prose :is(ul, ol) {
  margin: 0;
  padding-left: 0;
}

.prose li {
  margin: 0.55rem 0;
}

.prose li > ul,
.prose li > ol {
  margin-top: 0.4rem;
}

/* Square ink bullets rather than the browser's discs. */
.prose ul {
  list-style: none;
  padding-left: 0.25rem;
}

.prose ul > li {
  position: relative;
  padding-left: 1.25rem;
}

.prose ul > li::before {
  content: '';
  position: absolute;
  left: 0.15rem;
  top: 0.72em;
  width: 5px;
  height: 5px;
  background: var(--ink);
}

.prose ol {
  list-style: decimal;
  padding-left: 1.6rem;
}

.prose ol > li::marker {
  color: var(--text-muted);
  font-variant-numeric: oldstyle-nums;
}

.prose blockquote {
  margin: 0;
  padding: 1.1rem 1.4rem 1.1rem 1.35rem;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--ink);
  border-radius: 0 var(--r-card) var(--r-card) 0;
  background: var(--paper-texture) var(--quote-bg);
  color: var(--text-primary);
  font-size: 1em;
  line-height: var(--lh-body);
}

.prose blockquote p + p {
  margin-top: 0.8rem;
}

.prose hr {
  border: none;
  border-top: 1px solid var(--rule);
  margin-block: 2rem;
}

.prose img {
  display: block;
  margin-inline: auto;
  border: 1px solid var(--rule);
  border-radius: var(--r-tile);
  background: var(--surface-strong);
}

.prose figure {
  margin: 0;
}

.prose figcaption,
.prose center > em {
  display: block;
  margin-top: 0.5rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
  text-align: center;
}

/* Inline code and code blocks: the one place the mono face appears. */
.prose code {
  font-family: var(--font-mono);
  font-size: 0.88em;
  padding: 0.1em 0.38em;
  border: 1px solid var(--rule);
  border-radius: var(--r-tile);
  color: var(--text-primary);
  background: var(--code-bg);
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

.prose pre {
  margin: 0;
  padding: 1rem 1.15rem;
  overflow-x: auto;
  border: 1px solid var(--card-edge);
  border-radius: var(--r-card);
  background: var(--paper-texture) var(--card);
  box-shadow: var(--card-shadow);
  font-size: 0.9375rem;
  line-height: 1.7;
  tab-size: 4;
}

/* Inside a block, code takes the highlighter's own colours from the <pre>
   rather than the inline-code ink, which is unreadable on its dark ground. */
.prose pre code {
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font-size: inherit;
}

/* Tables, including the `.tg` tables pasted into older posts. */
.prose table,
.prose .tg {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9375rem;
  font-variant-numeric: oldstyle-nums;
}

.prose :is(th, td) {
  border: 1px solid var(--rule);
  padding: 0.45rem 0.6rem;
  text-align: left;
  vertical-align: top;
}

.prose th {
  font-family: var(--font-display);
  font-weight: 400;
  letter-spacing: 0.01em;
  color: var(--text-primary);
  background: var(--button-bg);
}

.prose tbody tr:nth-child(even) :is(td, th) {
  background: var(--rule-subtle);
}

/* The Nginx post pastes `.tg` tables with inline white fills and #333 text.
   These selectors outrank that inline <style> so the table sits on the paper. */
.prose .tg :is(td, th),
.prose .tg :is(.tg-baqh, .tg-dzk6) {
  color: inherit;
  font-size: inherit;
  font-weight: 400;
  border-color: var(--rule);
  background-color: transparent;
  padding: 0.5rem 0.6rem;
  text-align: center;
}

.prose .tg th,
.prose .tg th:is(.tg-baqh, .tg-dzk6) {
  color: var(--text-primary);
  background-color: var(--button-bg);
}

.prose .tg tbody tr:nth-child(even) :is(td, th) {
  background-color: var(--rule-subtle);
}

/* Wide data tables from older posts scroll rather than break the column. */
.prose .tg-wrap {
  overflow-x: auto;
  border: 1px solid var(--rule-subtle);
  border-radius: var(--r-tile);
}

.prose .tg-wrap table {
  min-width: 40rem;
}

/* --- Classes used by the posts' own inline HTML ---------------------------- */

/* Older posts wrap figures in <center>. */
.prose center {
  display: block;
  text-align: center;
}

/* A framed screenshot. The system has one shadow, so it is the card press. */
.prose .img-shadow {
  border: 1px solid var(--card-edge);
  border-radius: var(--r-card);
  box-shadow: var(--card-shadow);
}

/* The two-column figure/copy split used in the Pop!_OS post. The post's own
   inline CSS gives .left/.right 25%/75% float widths, which compound inside
   the grid tracks and shrink the figure to a sliver, so they are reset here.
   The figure is set as a plate on card stock, full column width, the copy
   beside it. */
.prose .row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1.5rem 2.25rem;
  align-items: center;
}

.prose .row .column {
  float: none;
  width: auto;
  padding: 0;
}

.prose .row .left {
  padding: 1rem;
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-card);
  background: var(--paper-texture) var(--surface-strong);
}

.prose .row .left img {
  width: 100%;
  max-height: 34rem;
  object-fit: contain;
  border-radius: var(--r-tile);
}

@media (min-width: 640px) {
  .prose .row {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  }
}

.prose :is(h1, h2, h3, h4, h5, h6) + :is(h2, h3, h4, h5, h6) {
  margin-top: 0.9em;
}

.prose .row :is(h1, h2, h3, h4, h5, h6) {
  margin-top: 0;
  border-bottom: 0;
  padding-bottom: 0;
}

.prose .row p + p {
  margin-top: 0.7rem;
}

/* The chart tab strip in the Nginx post. The post ships its own inline styles;
   these are scoped tighter so the Paper Edition wins. */
.prose .tab {
  display: flex;
  flex-wrap: wrap;
  height: auto;
  gap: 0;
  margin: 0;
  overflow: visible;
  white-space: normal;
  border: 1px solid var(--card-edge);
  border-bottom: 0;
  border-radius: var(--r-card) var(--r-card) 0 0;
  background: var(--paper-texture) var(--button-bg);
}

.prose .tab button {
  flex: 1 1 auto;
  padding: 0.6rem 0.9rem;
  font-family: var(--font-display);
  font-size: 0.9375rem;
  letter-spacing: 0.01em;
  color: var(--text-secondary);
  background: transparent;
  border: 0;
  border-right: 1px solid var(--rule);
  cursor: pointer;
  transition: background-color 0.2s ease, color 0.2s ease;
}

.prose .tab button:last-child {
  border-right: 0;
}

.prose .tab button:hover {
  background: var(--button-hover);
  color: var(--text-primary);
}

.prose .tab button.active {
  background: var(--button-primary-bg);
  color: var(--button-primary-text);
}

.prose .tabcontent {
  padding: 1rem;
  border: 1px solid var(--card-edge);
  border-radius: 0 0 var(--r-card) var(--r-card);
  background: var(--paper-texture) var(--card);
}

.prose .tabcontent img {
  border: 0;
  background: transparent;
}

/* Hidden when JavaScript is off (the noscript block in baseof). */
.jsonly { display: revert; }

/* ---------------------------------------------------------------------------
   Taxonomy pages
   --------------------------------------------------------------------------- */
.taxonomy-index {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
}

.taxonomy-index .chip {
  font-family: var(--font-display);
  font-size: 1rem;
  padding: 0.3rem 0.7rem;
}

.taxonomy-count {
  color: var(--text-subtle);
  font-variant-numeric: oldstyle-nums;
}

/* ---------------------------------------------------------------------------
   Comments
   --------------------------------------------------------------------------- */
.comments {
  margin-top: 3rem;
}

/* Disqus picks its light or dark theme by sampling the first opaque
   background behind #disqus_thread when the embed loads. Our surfaces are
   image-plus-colour shorthands, which it reads as light, so the ink edition
   got dark ink on a dark page. Give the thread its own flat, opaque fill in
   the page token; Disqus then samples an unambiguous colour, and paper.js
   resets the embed on toggle so it re-samples. The iframe's colour scheme
   follows the page so the browser never paints a white backdrop behind it. */
#disqus_thread {
  background-color: var(--bg);
  color: var(--text-primary);
}

.comments iframe {
  color-scheme: light;
}

html[data-theme='dark'] .comments iframe {
  color-scheme: dark;
}

/* ---------------------------------------------------------------------------
   Empty and error states
   --------------------------------------------------------------------------- */
.empty-state {
  padding-block: 4rem;
  text-align: center;
  color: var(--text-muted);
}

.error-page {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  padding-block: 5rem;
  text-align: center;
}

.error-code {
  font-family: var(--font-masthead);
  font-size: clamp(4rem, 14vw, 9rem);
  line-height: 1;
  color: var(--text-primary);
}

/* ---------------------------------------------------------------------------
   Motion
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  html { scroll-behavior: auto; }
}
