/* AFK Careers – minimal, type-driven, narrow column.
   Inspired by emilkowal.ski / jakub.kr / benji.org / howmuch.tax */

:root {
  --bg: #fafafa;
  --fg: #111;
  --muted: #8b8b8b;
  --subtle: #d8d8d8;
  --accent: #111;
  --hover: #e6e6e6;
  --border: #ececec;
  /* Geist (Vercel, free) — modern geometric sans designed for editorial UI.
     Variable `--serif` name is historical; the font is sans, paired with Geist Mono. */
  --serif: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --mono: 'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0c0c0d;
    --fg: #ededed;
    --muted: #7a7a7a;
    --subtle: #2a2a2c;
    --accent: #ededed;
    --hover: #1a1a1c;
    --border: #1a1a1c;
  }
}

[data-theme="light"] {
  --bg: #fafafa;
  --fg: #111;
  --muted: #8b8b8b;
  --subtle: #d8d8d8;
  --accent: #111;
  --hover: #e6e6e6;
  --border: #ececec;
}

[data-theme="dark"] {
  --bg: #0c0c0d;
  --fg: #ededed;
  --muted: #7a7a7a;
  --subtle: #2a2a2c;
  --accent: #ededed;
  --hover: #1a1a1c;
  --border: #1a1a1c;
}

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

html {
  background: var(--bg);
  color: var(--fg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Geist OT-features: ss02 = slashed zero (clearer in tabular dates / amounts).
     Geist looks great with defaults; only enable what's worth the bytes. */
  font-feature-settings: 'ss02';
  /* Reserve scrollbar space so the column doesn't shift between pages */
  scrollbar-gutter: stable;
  overflow-y: scroll;
}

/* ---- typography micro-rules (apply to whole document) --------------
   Per jakub.kr/writing/details-that-make-interfaces-feel-better#text-wrapping:
   - `balance` for short headings & hero / list / CTA copy → equal line
     widths, no single-word last line.
   - `pretty` for body prose → no orphans on the last line of paragraphs.
*/
h1, h2, h3,
.intro-text,
.post-title,
.post-subscribe { text-wrap: balance; }
p, li { text-wrap: pretty; }

body {
  font-family: var(--serif);
  font-size: 15px;
  line-height: 1.65;
  letter-spacing: -0.005em;
  max-width: 680px;
  padding: 56px 28px 32px;
  margin: 0 auto;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
}

/* Sticky footer: main grows to fill remaining vertical space,
   pushing the footer to the bottom of the viewport on short pages.
   Long content scrolls naturally — footer is NOT position:sticky. */
.site-main { flex: 1 0 auto; }

a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid var(--subtle);
  transition: border-color .15s ease, color .15s ease;
}
a:hover { border-bottom-color: var(--accent); }

/* ---- header ------------------------------------------------------ */

.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 96px;
}

.brand {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-weight: 600;
  font-size: 15px;
  letter-spacing: -0.02em;
  border: none;
  color: var(--fg);
}
.brand-mark {
  display: inline-block;
  position: relative;
  overflow: hidden;
  background: var(--fg);
  color: var(--bg);
  padding: 2px 6px;
  border-radius: 4px;
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.02em;
  transition: transform 300ms cubic-bezier(0.4, 0.1, 0.3, 1);
}
.brand-letters {
  display: inline-flex;
  gap: 0;
  position: relative;
  z-index: 2;
}
.brand-letters > span {
  display: inline-block;
  transition: transform 380ms cubic-bezier(0.55, 0.06, 0.4, 0.95), opacity 380ms ease;
}

/* fx layer — JS injects the active variant's content into here */
.brand-fx {
  position: absolute;
  inset: 0;
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
  color: var(--bg); /* SVGs use currentColor */
}
.brand-fx > svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* Common: when any fx is playing, badge scales and letters fade */
.brand-mark.is-playing { transform: scale(1.06); }
.brand-mark.is-playing .brand-letters > span { opacity: 0; }

/* ============================================================
   fx-zzz — letters fly out + 3 "zZz" spans appear and bob
   ============================================================ */
.brand-mark.fx-zzz.is-playing .brand-letters > span:nth-child(1) {
  transform: translateX(20px) rotate(-12deg); transition-delay: 0ms;
}
.brand-mark.fx-zzz.is-playing .brand-letters > span:nth-child(2) {
  transform: translateX(20px) rotate(-12deg); transition-delay: 60ms;
}
.brand-mark.fx-zzz.is-playing .brand-letters > span:nth-child(3) {
  transform: translateX(20px) rotate(-12deg); transition-delay: 120ms;
}
.brand-mark.fx-zzz .brand-fx > span {
  display: inline-block;
  font-weight: 700;
  opacity: 0;
  transform: translateY(4px);
}
.brand-mark.fx-zzz .brand-fx > span:nth-child(1) { font-size: 8px; }
.brand-mark.fx-zzz .brand-fx > span:nth-child(2) { font-size: 11px; }
.brand-mark.fx-zzz .brand-fx > span:nth-child(3) { font-size: 14px; }
.brand-mark.fx-zzz.is-playing .brand-fx > span {
  animation: brand-zzz-enter 400ms ease forwards, brand-zzz-bob 1.6s ease-in-out infinite;
}
.brand-mark.fx-zzz.is-playing .brand-fx > span:nth-child(1) { animation-delay: 380ms, 780ms; }
.brand-mark.fx-zzz.is-playing .brand-fx > span:nth-child(2) { animation-delay: 480ms, 880ms; }
.brand-mark.fx-zzz.is-playing .brand-fx > span:nth-child(3) { animation-delay: 580ms, 980ms; }
@keyframes brand-zzz-enter {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes brand-zzz-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-2px); }
}

/* ============================================================
   fx-battery — battery pops in, fills, drains, then low-batt blinks
   ============================================================ */
.brand-mark.fx-battery .brand-fx .batt-shell {
  transform-box: fill-box; transform-origin: center;
  transform: scale(0); opacity: 0;
}
.brand-mark.fx-battery .brand-fx .batt-fill {
  transform-box: fill-box; transform-origin: left center;
  transform: scaleX(0);
}
.brand-mark.fx-battery.is-playing .brand-fx .batt-shell {
  animation: br-batt-shell 400ms cubic-bezier(0.3, 1.3, 0.4, 1) 300ms forwards,
             br-batt-blink 1.6s ease-in-out 2400ms infinite;
}
.brand-mark.fx-battery.is-playing .brand-fx .batt-fill {
  animation: br-batt-fill 200ms ease 700ms forwards,
             br-batt-drain 1400ms cubic-bezier(0.4, 0, 0.6, 1) 900ms forwards;
}
@keyframes br-batt-shell {
  0%   { transform: scale(0);    opacity: 0; }
  70%  { transform: scale(1.32); opacity: 1; }
  100% { transform: scale(1.2);  opacity: 1; }
}
@keyframes br-batt-fill {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}
@keyframes br-batt-drain {
  0%   { transform: scaleX(1); }
  100% { transform: scaleX(0.06); }
}
@keyframes br-batt-blink {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.25; }
}

/* ============================================================
   fx-flower — stem grows, leaves pop, petals bloom, head sways
   ============================================================ */
.brand-mark.fx-flower .brand-fx .stem {
  fill: none; stroke: currentColor; stroke-width: 3.6;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 44; stroke-dashoffset: 44;
}
.brand-mark.fx-flower .brand-fx .leaf,
.brand-mark.fx-flower .brand-fx .bud,
.brand-mark.fx-flower .brand-fx .petal,
.brand-mark.fx-flower .brand-fx .core,
.brand-mark.fx-flower .brand-fx .spark {
  transform-box: fill-box;
}
.brand-mark.fx-flower .brand-fx .leaf { transform: scale(0); opacity: 0; transform-origin: var(--lo-x, 0%) var(--lo-y, 50%); }
.brand-mark.fx-flower .brand-fx .leaf-1 { --lo-x: 100%; --lo-y: 60%; }
.brand-mark.fx-flower .brand-fx .leaf-2 { --lo-x: 0%; --lo-y: 60%; }
.brand-mark.fx-flower .brand-fx .bud { transform: scale(0); opacity: 0; transform-origin: 50% 100%; }
.brand-mark.fx-flower .brand-fx .petal { transform: scale(0); opacity: 0; transform-origin: 50% 100%; }
.brand-mark.fx-flower .brand-fx .core { transform: scale(0); opacity: 0; transform-origin: center; }
.brand-mark.fx-flower .brand-fx .spark { opacity: 0; transform-origin: center; }
.brand-mark.fx-flower .brand-fx .flower-head { transform-box: fill-box; transform-origin: 50% 100%; }
.brand-mark.fx-flower .brand-fx .core circle { fill: var(--fg); }

.brand-mark.fx-flower.is-playing .brand-fx .stem {
  animation: br-stem-grow 1100ms cubic-bezier(0.55, 0.05, 0.4, 1) 250ms forwards;
}
.brand-mark.fx-flower.is-playing .brand-fx .leaf-1 {
  animation: br-leaf-pop 600ms cubic-bezier(0.2, 1.4, 0.4, 1) 700ms forwards;
}
.brand-mark.fx-flower.is-playing .brand-fx .leaf-2 {
  animation: br-leaf-pop 600ms cubic-bezier(0.2, 1.4, 0.4, 1) 880ms forwards;
}
.brand-mark.fx-flower.is-playing .brand-fx .bud {
  animation: br-bud-rise 500ms cubic-bezier(0.3, 1.3, 0.4, 1) 1150ms forwards;
}
.brand-mark.fx-flower.is-playing .brand-fx .petal {
  animation: br-petal-bloom 650ms cubic-bezier(0.2, 1.5, 0.4, 1) forwards;
}
.brand-mark.fx-flower.is-playing .brand-fx .petal-1 { animation-delay: 1400ms; }
.brand-mark.fx-flower.is-playing .brand-fx .petal-2 { animation-delay: 1470ms; }
.brand-mark.fx-flower.is-playing .brand-fx .petal-3 { animation-delay: 1540ms; }
.brand-mark.fx-flower.is-playing .brand-fx .petal-4 { animation-delay: 1610ms; }
.brand-mark.fx-flower.is-playing .brand-fx .petal-5 { animation-delay: 1680ms; }
.brand-mark.fx-flower.is-playing .brand-fx .core {
  animation: br-core-pop 450ms cubic-bezier(0.2, 1.6, 0.4, 1) 1850ms forwards;
}
.brand-mark.fx-flower.is-playing .brand-fx .flower-head {
  animation: br-head-sway 2400ms ease-in-out 2050ms infinite;
}
.brand-mark.fx-flower.is-playing .brand-fx .spark {
  animation: br-spark-twinkle 1600ms ease-in-out infinite;
}
.brand-mark.fx-flower.is-playing .brand-fx .spark-1 { animation-delay: 2050ms; }
.brand-mark.fx-flower.is-playing .brand-fx .spark-2 { animation-delay: 2350ms; }
.brand-mark.fx-flower.is-playing .brand-fx .spark-3 { animation-delay: 2650ms; }

@keyframes br-stem-grow {
  from { stroke-dashoffset: 44; }
  to   { stroke-dashoffset: 0; }
}
@keyframes br-leaf-pop {
  0%   { transform: scale(0) rotate(-8deg); opacity: 0; }
  60%  { transform: scale(1.1) rotate(2deg); opacity: 1; }
  100% { transform: scale(1) rotate(0deg);  opacity: 1; }
}
@keyframes br-bud-rise {
  0%   { transform: scale(0) translateY(2px); opacity: 0; }
  100% { transform: scale(1) translateY(0);   opacity: 1; }
}
@keyframes br-petal-bloom {
  0%   { transform: scale(0); opacity: 0; }
  70%  { transform: scale(1.1); opacity: 1; }
  100% { transform: scale(1);  opacity: 1; }
}
@keyframes br-core-pop {
  0%   { transform: scale(0); opacity: 0; }
  70%  { transform: scale(1.2); opacity: 1; }
  100% { transform: scale(1);   opacity: 1; }
}
@keyframes br-head-sway {
  0%, 100% { transform: rotate(-3deg); }
  50%      { transform: rotate(3deg); }
}
@keyframes br-spark-twinkle {
  0%, 100% { transform: scale(0); opacity: 0; }
  50%      { transform: scale(1); opacity: 0.9; }
}

/* ============================================================
   fx-tractor — tractor drives across with smoke puffs
   ============================================================ */
.brand-mark.fx-tractor .brand-fx .tractor-translate {
  transform: translateX(-58px); opacity: 0;
}
.brand-mark.fx-tractor .brand-fx .tractor-body {
  transform-box: fill-box; transform-origin: center;
}
.brand-mark.fx-tractor .brand-fx .smoke {
  transform-origin: 5.4px 1px; opacity: 0;
}
.brand-mark.fx-tractor.is-playing .brand-fx .tractor-translate {
  opacity: 1;
  transition: opacity 200ms ease 350ms;
  animation: br-tractor-drive 2000ms linear 380ms forwards;
}
.brand-mark.fx-tractor.is-playing .brand-fx .tractor-body {
  animation: br-tractor-shake 350ms ease-in-out 600ms infinite;
}
.brand-mark.fx-tractor.is-playing .brand-fx .smoke {
  animation: br-smoke-puff 1400ms ease infinite;
}
.brand-mark.fx-tractor.is-playing .brand-fx .smoke-1 { animation-delay: 600ms; }
.brand-mark.fx-tractor.is-playing .brand-fx .smoke-2 { animation-delay: 950ms; }
.brand-mark.fx-tractor.is-playing .brand-fx .smoke-3 { animation-delay: 1300ms; }
.brand-mark.fx-tractor.is-playing .brand-fx .smoke-4 { animation-delay: 1650ms; }
@keyframes br-tractor-drive {
  0%   { transform: translateX(-58px); }
  100% { transform: translateX(115px); }
}
@keyframes br-tractor-shake {
  0%, 100% { transform: translateY(0); }
  20% { transform: translateY(-0.6px); }
  40% { transform: translateY(0.4px); }
  60% { transform: translateY(-0.3px); }
  80% { transform: translateY(0.2px); }
}
@keyframes br-smoke-puff {
  0%   { transform: translate(0, 0) scale(0.25); opacity: 0; }
  15%  { transform: translate(-0.4px, -1.5px) scale(0.7); opacity: 0.7; }
  50%  { transform: translate(-1.5px, -4.5px) scale(1.1); opacity: 0.7; }
  100% { transform: translate(-3.5px, -10px) scale(1.6); opacity: 0; }
}

/* ============================================================
   fx-clock — face draws in, ticks fade in, hands extend then spin
   ============================================================ */
.brand-mark.fx-clock .brand-fx .clock-face {
  stroke-dasharray: 132;
  stroke-dashoffset: 132;
}
.brand-mark.fx-clock .brand-fx .clock-tick { opacity: 0; }
.brand-mark.fx-clock .brand-fx .clock-hand-h,
.brand-mark.fx-clock .brand-fx .clock-hand-m {
  transform-box: fill-box;
  transform-origin: 0% 50%;
  transform: scaleX(0);
}
.brand-mark.fx-clock.is-playing .brand-fx .clock-face {
  animation: br-clock-circle 900ms cubic-bezier(.5,.1,.4,1) 250ms forwards;
}
.brand-mark.fx-clock.is-playing .brand-fx .clock-tick {
  animation: br-clock-tickin 220ms ease forwards;
}
.brand-mark.fx-clock.is-playing .brand-fx .clock-tick-1 { animation-delay: 900ms; }
.brand-mark.fx-clock.is-playing .brand-fx .clock-tick-2 { animation-delay: 970ms; }
.brand-mark.fx-clock.is-playing .brand-fx .clock-tick-3 { animation-delay: 1040ms; }
.brand-mark.fx-clock.is-playing .brand-fx .clock-tick-4 { animation-delay: 1110ms; }
.brand-mark.fx-clock.is-playing .brand-fx .clock-hand-h {
  animation: br-clock-handin 220ms ease 1200ms forwards,
             br-clock-h-spin 6s linear 1450ms infinite;
}
.brand-mark.fx-clock.is-playing .brand-fx .clock-hand-m {
  animation: br-clock-handin 220ms ease 1260ms forwards,
             br-clock-m-spin 1.5s linear 1450ms infinite;
}
@keyframes br-clock-circle { to { stroke-dashoffset: 0; } }
@keyframes br-clock-tickin { to { opacity: 1; } }
@keyframes br-clock-handin { to { transform: scaleX(1); } }
@keyframes br-clock-h-spin { to { transform: scaleX(1) rotate(360deg); } }
@keyframes br-clock-m-spin { to { transform: scaleX(1) rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .brand-mark,
  .brand-letters > span,
  .brand-fx *,
  .brand-fx > svg * {
    transition: none !important;
    animation: none !important;
  }
}

.brand-name {
  color: var(--fg);
  position: relative;
  top: 1px;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 28px;
  font-size: 15px;
}
.site-nav a {
  color: var(--muted);
  border: none;
  display: inline-block;
  transition: color .18s ease, transform .25s cubic-bezier(.34, 1.56, .64, 1);
}
.site-nav a:hover {
  color: var(--fg);
  transform: translateY(-1px);
}
.site-nav a:active { transform: translateY(0) scale(0.95); }

/* About page header: AFK logo replaced with a back-link to home */
.site-back {
  color: var(--muted);
  border: none;
  font-size: 15px;
  display: inline-block;
  transition: color .18s ease, transform .25s cubic-bezier(.34, 1.56, .64, 1);
}
.site-back:hover { color: var(--fg); transform: translateY(-1px); }
.site-back:active { transform: translateY(0) scale(0.95); }

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  width: 30px;
  height: 30px;
  border-radius: 50%;
  padding: 0;
  cursor: pointer;
  transition: border-color .18s ease, color .18s ease, transform .25s cubic-bezier(.34, 1.56, .64, 1);
}
.theme-toggle svg { display: block; }
.theme-toggle:hover {
  border-color: var(--fg);
  color: var(--fg);
  transform: scale(1.08);
}
.theme-toggle:active { transform: scale(0.94); }

/* ---- language toggle -------------------------------------------- */

.lang-toggle-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  width: 30px;
  height: 30px;
  border-radius: 50%;
  padding: 0;
  font: inherit;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.01em;
  line-height: 1;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color .18s ease, color .18s ease, transform .25s cubic-bezier(.34, 1.56, .64, 1);
  font-variant-numeric: tabular-nums;
}
.lang-toggle-btn:hover {
  border-color: var(--fg);
  color: var(--fg);
  transform: scale(1.08);
}
.lang-toggle-btn:active { transform: scale(0.94); }

/* ---- intro ------------------------------------------------------- */

.intro {
  padding-top: 0;
  margin-bottom: 96px;
}
.intro h1 {
  font-size: 30px;
  line-height: 1.15;
  letter-spacing: -0.025em;
  font-weight: 600;
  /* 32px to match .post-header's margin-bottom on About + Post pages.
     Same gap below the H1 across all three page types. */
  margin-bottom: 32px;
}
.intro h1 .dim {
  color: #bdbdbd;
  font-weight: 500;
}
[data-theme="dark"] .intro h1 .dim { color: #4a4a4a; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .intro h1 .dim { color: #4a4a4a; }
}
.intro-text {
  font-size: 15px;
  line-height: 1.6;
  color: var(--fg);
}

/* ---- post list -------------------------------------------------- */

.year-section {
  margin-bottom: 32px;
}
.year-heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: var(--serif);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0;
  color: var(--muted);
  /* Sticky header: pins to top while .post-list scrolls under.
     padding-top: 8px = breathing room above so filter button doesn't touch edge.
     padding-bottom: 26px = 25px (original) + 1px buffer below the divider. */
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--bg);
  margin-bottom: 27px;
  padding-top: 8px;
  padding-bottom: 26px;
}
/* Divider sits 1px above the element bottom — at the original 25px-below-text
   position. Pre-scroll layout matches the original. */
.year-heading::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 1px;
  border-bottom: 1px solid var(--border);
}
.year-heading-text {
  display: inline-block;
  font-variant-numeric: tabular-nums;
}
.post-meta time {
  font-variant-numeric: tabular-nums;
}

/* ---- filter ----------------------------------------------------- */

.filter-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  width: 30px;
  height: 30px;
  border-radius: 50%;
  cursor: pointer;
  padding: 0;
  transition: color .18s ease, border-color .18s ease, background .18s ease,
              transform .25s cubic-bezier(.34, 1.56, .64, 1);
}
.filter-icon-btn:hover {
  color: var(--fg);
  border-color: var(--fg);
  transform: scale(1.08);
}
.filter-icon-btn:active { transform: scale(0.94); }
.filter-icon-btn[aria-expanded="true"] {
  color: var(--bg);
  background: var(--fg);
  border-color: var(--fg);
}
.filter-icon-btn svg {
  display: block;
}
.filter-count {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 14px;
  height: 14px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--fg);
  color: var(--bg);
  font-family: var(--mono);
  font-size: 9px;
  line-height: 14px;
  text-align: center;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  display: none;
}
.filter-count.visible { display: block; }

/* Interruptible expand/collapse via grid-template-rows.
   Outer panel uses display: grid; the inner wrapper is the single grid row.
   Switching 0fr ↔ 1fr smoothly animates height and is interruptible mid-flight. */
.filter-panel {
  display: grid;
  grid-template-rows: 0fr;
  margin-top: -10px;
  margin-bottom: 0;
  border-bottom: 1px solid transparent;
  transition: grid-template-rows .28s ease, margin-bottom .28s ease, border-color .28s ease;
  /* Sticky right under .year-heading. Collapsed (0fr) → renders nothing.
     Opened → pins below the heading with the same solid bg.
     `top` ≈ heading height (8 padding-top + ~33 content + 26 padding-bottom). */
  position: sticky;
  top: 67px;
  z-index: 4;
  background: var(--bg);
}
.filter-panel.open {
  grid-template-rows: 1fr;
  margin-bottom: 16px;
  border-bottom-color: var(--border);
}
.filter-panel-inner {
  overflow: hidden;
  min-height: 0;
  padding: 0;
  /* Pad transition matches the panel collapse so we don't get a sudden
     20px height jump at the start of the close. */
  transition: padding .28s ease;
}
.filter-panel.open .filter-panel-inner {
  padding: 2px 0 4px;
}
/* Enter: stagger rows with subtle blur. Exit: snappy fade, no blur. */
.filter-panel .filter-row {
  opacity: 0;
  /* Start 4px ABOVE final position; on open they ease down into place
     instead of rising up. */
  transform: translateY(-4px);
  transition: opacity .18s ease, transform .18s ease;
}
.filter-panel.open .filter-row {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
  transition: opacity .35s ease, transform .35s ease, filter .35s ease;
}
.filter-panel.open .filter-row:nth-child(1) { transition-delay: 60ms; }
.filter-panel.open .filter-row:nth-child(2) { transition-delay: 120ms; }
.filter-panel.open .filter-row:nth-child(3) { transition-delay: 180ms; }

.filter-row {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: 24px;
  align-items: start;
  padding: 24px 0;
}
/* Trim outer padding on the first/last rows: the panel already has its own
   top/bottom edges, so a full 24px feels heavy at the seam. */
.filter-row:first-child { padding-top: 12px; }
.filter-row:last-child { padding-bottom: 12px; }
.filter-row + .filter-row { border-top: 1px dashed var(--border); }
.filter-row-label {
  font-size: 14px;
  color: var(--muted);
  /* Vertically centre the label against the 30px chip row in the right
     column so labels align with chip text regardless of row content. */
  display: flex;
  align-items: center;
  min-height: 30px;
}
.filter-row-control {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.chip {
  display: inline-flex;
  align-items: center;
  height: 30px;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  font: inherit;
  font-size: 14px;
  padding: 0 12px;
  border-radius: 999px;
  cursor: pointer;
  box-sizing: border-box;
  transition: color .15s, border-color .15s, background .15s;
}
.chip:hover { color: var(--fg); border-color: var(--muted); }
.chip.active {
  color: var(--bg);
  background: var(--fg);
  border-color: var(--fg);
}

/* Country row label hosts the text + an expand/collapse icon button.
   Flexbox so the button sits inline with "Страна" / "Country". */
.filter-row--country .filter-row-label {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding-top: 0;
  min-height: 30px;
}
.country-toggle-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  width: 30px;
  height: 30px;
  border-radius: 50%;
  padding: 0;
  cursor: pointer;
  transition: color .18s ease, border-color .18s ease, background .18s ease,
              transform .25s cubic-bezier(.34, 1.56, .64, 1);
}
/* Notification dot — appears on the expand icon when at least one
   currently-selected country is hidden inside the collapsed overflow,
   so the user can see "you have hidden selections" at a glance. */
.country-toggle-dot {
  position: absolute;
  top: -1px;
  right: -1px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--fg);
  box-shadow: 0 0 0 2px var(--bg);
  pointer-events: none;
}
.country-toggle-dot[hidden] { display: none; }
.country-toggle-btn:hover {
  color: var(--fg);
  border-color: var(--fg);
  transform: scale(1.08);
}
.country-toggle-btn:active { transform: scale(0.94); }
.country-toggle-btn svg { display: block; }
.country-toggle-btn[hidden] { display: none; }
.country-toggle-btn .icon-expand[hidden],
.country-toggle-btn .icon-collapse[hidden] { display: none; }

/* Collapsed: hide chips that JS marked as overflowing past the visible
   row count. The cutoff is measured at runtime via offsetTop grouping,
   so it adapts to chip widths and viewport. */
.filter-row--country.country-collapsed .filter-row-control .chip.is-overflow {
  display: none;
}

/* Counter pseudo-chip ("+12") sits at the end of the visible chips when
   collapsed and acts as a second click target that expands the list. */
.chip-counter {
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.chip-counter:hover { color: var(--fg); border-color: var(--muted); }
.filter-row--country:not(.country-collapsed) .chip-counter { display: none; }

.filter-row--meta { margin-bottom: 16px; }
.filter-row--meta .filter-row-control { gap: 6px 8px; }

/* Meta-chip behaves like .chip — but toggling shows a meta-line under post
   titles instead of filtering posts. No input; pure display toggle. */
.meta-chip {
  display: inline-flex;
  align-items: center;
  height: 30px;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  font: inherit;
  font-size: 14px;
  padding: 0 12px;
  border-radius: 999px;
  cursor: pointer;
  box-sizing: border-box;
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.meta-chip:hover { color: var(--fg); border-color: var(--muted); }
.meta-chip.active {
  color: var(--bg);
  background: var(--fg);
  border-color: var(--fg);
}
/* "Сбросить" lives in the year heading next to the filter icon and is
   only visible when the filter panel is open. */
.year-heading-actions {
  display: inline-flex;
  align-items: center;
  gap: 22px;
}
.filter-reset {
  background: transparent;
  border: none;
  color: var(--muted);
  font: inherit;
  font-size: 15px;
  letter-spacing: 0;
  text-transform: none;
  cursor: pointer;
  padding: 4px 0;
  /* Hidden by default; revealed only when at least one country chip or
     attribute meta-chip is active (regardless of whether panel is open). */
  opacity: 0;
  transform: translateX(6px);
  pointer-events: none;
  transition: color .18s ease, opacity .25s ease, transform .25s ease;
}
.filter-reset:hover { color: var(--fg); }
/* JS toggles `.has-active` (any chip selected) and `.filter-open` (panel
   expanded) on .year-section. Reset is visible only when BOTH are true —
   panel is open AND there's something to reset. Plain classes beat :has()
   for reliability across browsers and stale caches. */
.year-section.has-active.filter-open .filter-reset {
  opacity: 1;
  transform: translateX(0);
  pointer-events: auto;
  transition-delay: .12s;
}

.empty-state {
  text-align: center;
  color: var(--muted);
  padding: 48px 0;
  font-size: 15px;
}

.post-list {
  list-style: none;
}
.post-row { margin: 0; }

.post-link {
  display: grid;
  grid-template-columns: 56px 1fr auto;
  gap: 12px;
  align-items: baseline;
  padding: 12px 0;
  border: none;
  border-bottom: 1px solid transparent;
  color: var(--fg);
}
.post-link:hover {
  border-bottom-color: transparent;
}

.post-date {
  font-size: 15px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.post-title-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
  /* Smooth opacity transition for the "dim others" hover treatment below */
  transition: opacity .18s ease;
}
.post-title {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--fg);
}
/* Meta-lines container under the title.
   - Always rendered with min-height equal to ONE line of meta text, so
     toggling a single attribute doesn't change post height.
   - flex-wrap lets multiple active attributes share a line, then wrap
     onto the next line only when they don't fit. The container grows
     vertically only on actual wrap. */
.post-meta-lines {
  display: flex;
  flex-wrap: wrap;
  column-gap: 18px;
  row-gap: 2px;
  margin-top: 4px;
  /* 16px font × ~1.3 line-height ≈ 21px reserved slot */
  min-height: 21px;
}
/* Each meta-line is hidden until JS adds .visible. Hidden items are pulled
   out of flex flow so the wrap calculation only considers active items. */
.post-meta-line {
  display: none;
  font-size: 15px;
  color: rgb(139, 139, 139);
  line-height: 1.3;
  white-space: nowrap;
}
.post-meta-line.visible {
  display: inline-block;
}

/* 3-dot difficulty indicator: ●○○ easy / ●●○ medium / ●●● hard.
   Inline-flex keeps the dots together as one unit even inside flex-wrap. */
.post-meta-line .dots {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  vertical-align: middle;
  /* Lift slightly so dots align optically with adjacent text x-height */
  position: relative;
  top: -1px;
}
.post-meta-line .dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: 1px solid rgb(139, 139, 139);
  background: transparent;
}
.post-meta-line .dot.filled {
  background: rgb(139, 139, 139);
}
.post-country {
  font-size: 15px;
  color: var(--muted);
  margin-left: 8px;
  transition: opacity .18s ease;
}
/* Inline country chip: lives inside .post-meta-lines as the first item.
   Desktop hides it (the right-column .post-country shows the country there).
   Mobile shows it and hides the right-column block — see the @media block. */
.post-country-inline {
  display: none;
  font-size: 15px;
  color: rgb(139, 139, 139);
  line-height: 1.3;
  white-space: nowrap;
}

/* "Dim others" hover treatment: when any post-link in the list is hovered,
   the title-col (title + meta-lines) and country of every OTHER row fade to
   35% opacity. The hovered row stays full opacity. Date is untouched.
   Gated to (hover: hover) so it doesn't trigger on touch devices, where
   tapping during scroll would otherwise leave most rows looking disabled. */
@media (hover: hover) {
  .post-list:hover .post-link:not(:hover) .post-title-col,
  .post-list:hover .post-link:not(:hover) .post-country {
    opacity: 0.35;
  }
}

/* ---- post page -------------------------------------------------- */

.post-header {
  margin-bottom: 32px;
}

.post-cover {
  position: relative;
  margin: 0 0 40px;
  border-radius: 8px;
  overflow: hidden;
  /* Near-invisible placeholder tint — barely-there until the image lands. */
  background: rgba(0, 0, 0, 0.04);
  /* Cover format is locked at 1600 × 900 (16:9). Every cover renders in
     this fixed-ratio box regardless of the source image, which (a) lets
     the figure reserve the exact placeholder height up front so there's
     no content jump on load, and (b) keeps page rhythm consistent across
     posts. Source images for new posts MUST be produced at 1600 × 900
     (afk-pipeline/Supabase/TG) so object-fit: cover doesn't crop them. */
  aspect-ratio: 16 / 9;
}
[data-theme="dark"] .post-cover {
  background: rgba(255, 255, 255, 0.04);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .post-cover {
    background: rgba(255, 255, 255, 0.04);
  }
}

/* Subtle inner edge — drawn via a pseudo-element OVER the img so it stays
   visible (inset shadow on the parent gets covered by the in-flow img).
   It's a shadow (not a border) per design — 10% black, follows the rounded
   corners via border-radius: inherit. */
.post-cover::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
  z-index: 2;
}
[data-theme="dark"] .post-cover::after {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .post-cover::after {
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
  }
}
.post-cover.is-loaded {
  min-height: 0;
}

/* Calm skeleton — slow diagonal shimmer until the image loads. */
.post-cover::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(
    105deg,
    transparent 30%,
    rgba(0, 0, 0, 0.05) 50%,
    transparent 70%
  );
  background-size: 250% 100%;
  background-position: 150% 0;
  animation: cover-skeleton-sweep 2.4s ease-in-out infinite;
  transition: opacity 500ms ease;
}
[data-theme="dark"] .post-cover::before {
  background: linear-gradient(
    105deg,
    transparent 30%,
    rgba(255, 255, 255, 0.06) 50%,
    transparent 70%
  );
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .post-cover::before {
    background: linear-gradient(
      105deg,
      transparent 30%,
      rgba(255, 255, 255, 0.06) 50%,
      transparent 70%
    );
  }
}
.post-cover.is-loaded::before {
  opacity: 0;
  animation: none;
}
@keyframes cover-skeleton-sweep {
  0%   { background-position: 150% 0; }
  100% { background-position: -50% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .post-cover::before { animation: none; }
}

.post-cover img {
  position: relative;
  display: block;
  /* Fill the figure's fixed-ratio box exactly — object-fit: cover crops
     to the figure's aspect ratio, keeping covers visually uniform. */
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Round the img directly so corners visibly clip even when parent
     overflow:hidden is unreliable across browsers (some Safari versions
     skip clipping if the child has its own stacking context). */
  border-radius: 8px;
}

.post-meta {
  font-size: 15px;
  color: var(--muted);
  margin-bottom: 96px;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
  /* Back-link goes left, the right-side group [country] [date] [copy] is
     pushed flush right via `space-between`. */
  justify-content: space-between;
  /* FIXED height (not min-height): 30px = the new icon-button diameter.
     Country pill is sized to match. H1 below always lands at the same Y. */
  height: 30px;
  /* Slide up from below on page load — gives a sense of arrival. */
  animation: meta-enter .55s cubic-bezier(.25, .46, .45, .94) both;
}
.post-meta-right {
  display: inline-flex;
  align-items: center;
  gap: 28px;
}
@keyframes meta-enter {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .post-meta { animation: none; }
}

/* ---- post page entry transition --------------------------------------
   When the user lands on an article page (from the home list), replay the
   conceptual transition: the site header — visually the same element they
   just clicked through from — flies up, shrinks and blurs out, while the
   post-meta rises into the slot it just vacated, and the rest of the
   content (h1, cover, body, subscribe CTA) staggers in from below.
   End state is identical to v0.1 focused-reading mode: site header gone,
   post-meta at the top of the column.

   Selector: `body.is-post` (set in BASE_HEAD via render_post). The
   `.site-header` is a sibling of `.post-page main`, not a descendant, so
   we hook the rule on the body class to keep browser support broad.
*/
/* Default state for direct visit / refresh / back-forward / paste-URL:
   the site header is REMOVED from the document (display: none), not
   just hidden. Visibility-hidden kept the element in flow with negative
   margins, which created scroll-restoration quirks on refresh — the
   browser sometimes re-rendered the page 20–30px lower than expected.
   With display: none there's nothing to collapse around, and the main
   column sits cleanly at body padding-top. */
body.is-post .site-header {
  display: none;
}

/* From-home entry: re-introduce the header into flow (display: flex
   matches the static .site-header rule) and run the fly-out animation.
   The `came-from-home` class is set on <html> by the inline <head>
   script before first paint. */
html.came-from-home body.is-post .site-header {
  display: flex;
  animation: post-page-header-fly 0.7s cubic-bezier(0.5, 0, 1, 1) both;
  pointer-events: none;
  will-change: transform, opacity, filter, margin-bottom;
}

/* Negative main margin only applies when the header is in flow
   (came-from-home). Math: at end of animation, header margin-bottom is
   -16. Adjacent negative margins collapse to the more negative one, so
   we need -30 to override the header's -16 and pull main exactly to
   y = body_padding (56) + header_height (30) + collapsed (-30) = 56. */
html.came-from-home body.is-post .post-page {
  margin-top: -30px;
}
@keyframes post-page-header-fly {
  0% {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
    margin-bottom: 16px;
  }
  /* Opacity hits 0 at the halfway mark (0.35s of 0.7s) — 2x faster than
     the rest of the animation. translateY / filter / margin-bottom keep
     interpolating cubic-bezier(0.5, 0, 1, 1)ly across the full duration. */
  50% {
    opacity: 0;
  }
  100% {
    opacity: 0;
    transform: translateY(-100%);
    filter: blur(2px);
    margin-bottom: -16px;
  }
}

/* Total wall-clock = 0.7s. Header gets a 0.1s head start: by the time
   the content's opacity ramps up enough to be perceived (~35% into its
   keyframes), the header is already mid-flight, so the user reads both
   as moving together rather than the header leading. All five content
   selectors share one animation — no stagger.
   - Header:  0s delay, 0.7s duration
   - Content: 0.1s delay, 0.6s duration
   Both end at t=0.7s.
   Only run on from-home entry — same `came-from-home` gate. */
html.came-from-home .post-page .post-meta {
  animation: post-page-meta-rise 0.6s cubic-bezier(0.5, 0, 1, 1) 0.1s both;
}
@keyframes post-page-meta-rise {
  0%   { opacity: 0; transform: translateY(1.25px); }
  100% { opacity: 1; transform: translateY(0); }
}

html.came-from-home .post-page .post-header h1,
html.came-from-home .post-page .post-cover,
html.came-from-home .post-page .post-body,
html.came-from-home .post-page .post-subscribe {
  animation: post-page-rise 0.6s cubic-bezier(0.5, 0, 1, 1) 0.1s both;
}
@keyframes post-page-rise {
  0%   { opacity: 0; transform: translateY(0.875px); }
  100% { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  /* No motion: skip the choreography entirely even when coming from
     home. Default branch already has no animation. */
  html.came-from-home body.is-post .site-header,
  html.came-from-home .post-page .post-meta,
  html.came-from-home .post-page .post-header h1,
  html.came-from-home .post-page .post-cover,
  html.came-from-home .post-page .post-body,
  html.came-from-home .post-page .post-subscribe {
    animation: none;
  }
}
.back-link::before {
  content: "\2190";
  margin-right: 8px;
  display: inline-block;
  /* Optical alignment: the "←" glyph sits a hair too low against text x-height */
  transform: translateY(-0.5px);
  transition: transform .2s ease;
}
.back-link:hover::before {
  /* Tiny nudge left signals "go back" without being noisy */
  transform: translate(-2px, -0.5px);
}
.post-meta a {
  color: var(--muted);
  border: none;
}
.post-meta a:hover { color: var(--fg); }
.post-meta .dot { color: var(--subtle); }

/* Copy-link button — pushed to the right edge of the post-meta row.
   Mirrors the size/feel of the theme + filter icon-buttons. */
.copy-link-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 50%;
  color: var(--muted);
  cursor: pointer;
  transition: color .18s ease, border-color .18s ease, background .18s ease,
              transform .25s cubic-bezier(.34, 1.56, .64, 1);
}
.copy-link-btn:hover {
  color: var(--fg);
  border-color: var(--fg);
  transform: scale(1.08);
}
.copy-link-btn:active { transform: scale(0.94); }
.copy-link-btn svg { display: block; }
.copy-link-btn .check-icon { display: none; }
/* "Copied!" feedback: chain → checkmark, button briefly fills in fg color. */
.copy-link-btn.copied {
  color: var(--bg);
  background: var(--fg);
  border-color: var(--fg);
}
.copy-link-btn.copied .copy-icon  { display: none; }
.copy-link-btn.copied .check-icon { display: block; }
.post-country-tag {
  display: inline-flex;
  align-items: center;
  height: 30px;
  padding: 0;
  border-radius: 999px;
  font-size: 14px;
  box-sizing: border-box;
  color: var(--muted);
}

.post-header h1 {
  font-size: 30px;
  line-height: 1.15;
  letter-spacing: -0.025em;
  font-weight: 600;
}

/* Pixel-perfect vertical alignment of `.post-meta` and `<h1>` across all pages.
   - On article + about pages, `.post-meta` sits at the very top of `.post-header`
     (no padding, no offset). Its min-height (24px) + margin-bottom (20px) = 44px
     of space before the `<h1>` follows.
   - On the index page there's no `.post-meta`, so `.intro` reserves the exact
     same 44px via `padding-top`. The H1 then lands at the same Y on every page. */

.post-body p {
  margin: 0 0 24px;
  font-size: 15px;
  line-height: 1.7;
}
/* Inline post-body images: visual rounding only — source files stay sharp.
   Border is a shadow (not a CSS border) at 10% black, following the radius. */
.post-body img {
  max-width: 100%;
  height: auto;
  border-radius: 8px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
}
[data-theme="dark"] .post-body img {
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .post-body img {
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1);
  }
}
.post-body p strong { font-weight: 600; }
.post-body p em { color: var(--muted); font-style: italic; }
.post-body p strong em, .post-body p em strong { color: var(--fg); }
.post-body hr {
  border: none;
  height: 1px;
  background: var(--bg);
  margin: 40px auto;
  width: 60px;
}
.post-body .closer {
  text-align: center;
  color: var(--muted);
  font-size: 15px;
  margin-top: 40px;
}

.post-body h2 {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.005em;
  margin: 48px 0 16px;
}

/* ---- facts block ------------------------------------------------- */

.fact {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 28px;
  padding: 18px 0;
  border-top: 1px solid var(--border);
  font-size: 15px;
}
.fact:last-of-type { border-bottom: 1px solid var(--border); }
.fact-label {
  color: var(--muted);
  font-weight: 500;
  font-size: 15px;
  letter-spacing: -0.005em;
}
.fact-label strong { color: var(--fg); font-weight: 500; }
.fact-body { line-height: 1.6; }
.fact-body strong { font-weight: 600; }

/* ---- proof-link (external-link icon) ---------------------------- */
/* Igor's spec (2026-04-29 v2): inline an external-link SVG glyph next to
   the claim it backs — no parentheses, stroked at #8b8b8b. The generic
   `a` rule elsewhere paints a border-bottom under every anchor, so we
   explicitly remove it for `.proof-link`. The SVG inherits its stroke
   from the anchor's `color`, hence `currentColor` in the path. */
.proof-link,
.proof-link:hover,
.proof-link:focus,
.proof-link:active {
  text-decoration: none;
  border-bottom: none;
  color: #8b8b8b;
}
.proof-link {
  margin-left: 0;
  margin-right: 3px;
  display: inline-flex;
  align-items: center;
  vertical-align: -2px;            /* aligns icon visually with x-height */
  transition: color 120ms ease, transform .25s cubic-bezier(.34, 1.56, .64, 1);
}
.proof-link:hover {
  color: var(--fg);
  transform: scale(1.08);
}
.proof-link:active {
  transform: scale(0.94);
}
.proof-link-icon {
  display: block;                  /* kill anchor-baseline gap */
}
/* Keyboard focus stays visible for accessibility, but discreet. */
.proof-link:focus-visible {
  outline: 1px dashed var(--muted);
  outline-offset: 2px;
  border-radius: 2px;
}

/* ---- "Стандартный путь" arrow-bullet list ----------------------- */
/* Each step is a <li> with two children:
     <span class="path-arrow">→</span><span class="path-step">…</span>
   The arrow is gray (#8b8b8b — explicitly requested by the editor) and
   carries a slight extra space after itself for breathing room.
   Scoping under .post-body so we beat the .post-body p { margin: 0 0 24px }
   default — otherwise the path-title <p> would collect a 24px gap before
   the bullet list (which is wrong: title and bullets read as one unit). */
.post-body .path-title {
  margin: 24px 0 0;          /* zero bottom margin; the list adds its own gap */
  font-size: 15px;
}
.post-body .path-title strong { font-weight: 600; }
.post-body .path-list {
  list-style: none;
  padding: 0;
  margin: 6px 0 24px;        /* 6px gap from the title above */
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 15px;
  line-height: 1.6;
}
.post-body .path-list li {
  display: grid;
  grid-template-columns: 15px 1fr;   /* 15px holds the arrow + a bit of padding */
  align-items: baseline;
  gap: 8px;                          /* extra space after the arrow */
}
.post-body .path-arrow {
  color: #8b8b8b;
  user-select: none;
  font-feature-settings: "tnum";
}
.post-body .path-step {
  color: var(--fg);
}

@media (max-width: 600px) {
  body { padding: 40px 20px 80px; }
  .fact {
    grid-template-columns: 1fr;
    gap: 6px;
  }
  .post-link {
    grid-template-columns: 50px 1fr;
  }
  .post-country {
    /* On mobile the country is shown inside .post-meta-lines as the first
       chip, so the dedicated right-column block is hidden here. */
    display: none;
  }
  .post-country-inline {
    display: inline-block;
  }
  .intro h1 { font-size: 28px; }
  .post-header h1 { font-size: 28px; }
  .site-header { flex-wrap: wrap; gap: 14px; margin-bottom: 56px; }
  .site-nav { gap: 14px; flex-wrap: wrap; }
  .filter-row {
    grid-template-columns: 1fr;
    gap: 8px;
  }
  /* Mobile stacks label above chips; drop the 30px min-height reserved
     for desktop column alignment so the gap between rows stays tight. */
  .filter-row-label { min-height: 0; }
  /* Tighter horizontal padding on meta-chips so the four labels wrap into
     exactly 2 rows on a 375px viewport instead of stacking 3-4 deep. */
  .filter-row--meta .meta-chip { padding: 0 10px; }
  .post-meta .back-link,
  .site-header .site-back {
    width: 30px;
    height: 30px;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    font-size: 0;
    color: var(--muted);
    background: transparent;
    transition: color .18s ease, border-color .18s ease, background .18s ease,
                transform .25s cubic-bezier(.34, 1.56, .64, 1);
  }
  .post-meta .back-link::before,
  .site-header .site-back::before {
    content: "\2190";
    font-size: 15px;
    margin-right: 0;
    transform: none;
    transition: none;
  }
  .post-meta .back-link:hover,
  .site-header .site-back:hover {
    color: var(--fg);
    border-color: var(--fg);
    transform: scale(1.08);
  }
  .post-meta .back-link:hover::before,
  .site-header .site-back:hover::before {
    transform: none;
  }
  .post-meta .back-link:active,
  .site-header .site-back:active {
    transform: scale(0.94);
  }
}

/* ---- post nav (prev / next) ------------------------------------- */

.post-subscribe {
  margin-top: 96px;
  padding-top: 32px;
  padding-bottom: 80px;
  border-top: 1px solid var(--border);
  text-align: center;
}
.post-subscribe a {
  color: var(--muted);
  border: none;
  font-size: 15px;
  transition: color .18s ease;
}
.post-subscribe a:hover { color: var(--fg); }

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

.site-footer {
  margin-top: 32px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: 15px;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}
.site-footer a {
  color: var(--muted);
  border: none;
}
.site-footer a:hover { color: var(--fg); }
.footer-tagline { font-style: italic; margin: 0; }

/* Hide footer on article pages — they end with their own subscribe CTA. */
body.is-post .site-footer { display: none; }

/* ---- selection -------------------------------------------------- */
::selection {
  background: var(--fg);
  color: var(--bg);
}
