/* ============================================================
   ТИШЕ — журнал: листинг и страница статьи
   Отдельный файл, потому что style.css и pages.css делит витрина:
   любая правка там расходится на весь сайт, а тут только раздел.
   Токены, сетка и примитивы берутся из style.css, здесь ничего
   не переопределяется глобально.
   Mobile-first, дальше только min-width.
   ============================================================ */

:root {
  /* Тёплый белый из палитры (тот же, что даёт текст на тёмных секциях).
     На полотне #E9E3E0 он читается как лист бумаги, положенный сверху,
     и при этом не вводит в систему новый тон. */
  --blog-paper: #F1EFEF;

  /* «Нить» — короткий отрезок акцента в углу карточки и над h2.
     Тот же приём, что тонкая линия в вау-блоках витрины. */
  --blog-thread: 28px;

  /* Мера строки статьи. Задана в rem, а не в ch: кегль внутри текста
     крупнее базового, и ch пересчитался бы в слишком узкую колонку. */
  --post-measure: 40rem;
}

/* ------------------------------------------------------------
   1. ЛИСТИНГ: ФИЛЬТР ПО ТЕМАМ
   ------------------------------------------------------------ */

/* Фильтр стоит между шапкой раздела и сеткой, поэтому дышит с обеих
   сторон одинаково: иначе он прилипает к заголовку и читается его частью. */
.blog__tags {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  margin-bottom: var(--space-7);
}

/* В style.css .chip — это обёртка радиокнопки калькулятора, у неё
   display: block и вся отрисовка живёт на вложенном span. Здесь чип
   это самостоятельная ссылка, поэтому вид собирается заново.
   Два класса в селекторе, чтобы правило било .chip независимо от порядка. */
.chip.chip--link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  /* тач-цель по DESIGN.md р. 7 — не меньше 48px */
  min-height: 48px;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--color-border-interactive);
  border-radius: var(--radius-pill);
  color: var(--color-ink);
  font-size: var(--fs-small);
  font-weight: 500;
  line-height: var(--lh-ui);
  text-decoration: none;
  overflow-wrap: anywhere;
  transition:
    background-color var(--dur-fast) var(--ease-out-soft),
    border-color var(--dur-fast) var(--ease-out-soft),
    color var(--dur-fast) var(--ease-out-soft);
}

/* Активная тема — единственная точка принятия решения в фильтре,
   поэтому она и забирает акцент, остальные чипы остаются контурными. */
.chip.chip--link.is-active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--blog-paper);
}

@media (hover: hover) and (pointer: fine) {
  .chip.chip--link:not(.is-active):hover {
    border-color: var(--color-line);
    color: var(--color-line);
  }
  .chip.chip--link.is-active:hover {
    background: var(--color-accent-hover);
    border-color: var(--color-accent-hover);
    color: var(--blog-paper);
  }
}

/* Счётчик статей — служебная цифра, она не должна спорить с названием темы */
.chip__count {
  font-size: var(--fs-eyebrow);
  font-variant-numeric: tabular-nums;
  color: var(--color-ink-muted);
}
.chip.chip--link.is-active .chip__count { color: rgba(241, 239, 239, .72); }

/* ------------------------------------------------------------
   2. ЛИСТИНГ: СЕТКА КАРТОЧЕК
   ------------------------------------------------------------ */

.blog {
  display: grid;
  gap: var(--space-5);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Колонка набирается автоматически от 300px: на 390 это одна колонка,
   на 768 две, на 1440 три. Отдельные брейкпоинты под сетку не нужны. */
@media (min-width: 600px) {
  .blog { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
}

.blog__item { display: flex; }

/* Карточка — вся ссылка целиком, а не заголовок внутри неё: на телефоне
   промахнуться по строке заголовка легче, чем по плитке.
   Строки заданы жёстко (обложка, текст), поэтому карточка без обложки
   не съезжает относительно соседей: она просто начинается со второй строки. */
.blog__link {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  background: var(--blog-paper);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-sharp);
  color: var(--color-ink);
  text-decoration: none;
  overflow: hidden;
  transition:
    border-color var(--dur-fast) var(--ease-out-soft),
    box-shadow var(--dur-base) var(--ease-out-soft),
    transform var(--dur-base) var(--ease-out-soft);
}

/* Нить в левом верхнем углу: короткий отрезок бордо, который при наведении
   протягивается на всю ширину карточки. Единственное движение в листинге,
   и оно объясняет, что плитка кликабельна, без слова «подробнее». */
.blog__link::before {
  content: "";
  position: absolute;
  inset: 0 auto auto 0;
  z-index: 1;
  width: var(--blog-thread);
  height: 2px;
  background: var(--color-accent);
  transition: width var(--dur-base) var(--ease-out-soft);
}

@media (hover: hover) and (pointer: fine) {
  .blog__link:hover {
    border-color: var(--color-border-interactive);
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);
  }
  .blog__link:hover::before { width: 100%; }
}

/* Клавиатура должна получать ту же подсказку, что и мышь */
.blog__link:focus-visible::before { width: 100%; }

@media (prefers-reduced-motion: reduce) {
  .blog__link,
  .blog__link::before { transition: none; }
  .blog__link:hover { transform: none; }
}

/* Обложка есть не у всех статей. Пропорция фиксирована, поэтому ряд
   карточек с картинками остаётся ровным независимо от исходных размеров. */
.blog__shot {
  margin: 0;
  background: var(--color-surface);
  aspect-ratio: 16 / 10;
  overflow: hidden;
}
.blog__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Отступ сверху разный: под обложкой текст стоит ближе к ней, а в карточке
   без картинки заголовок отодвинут от нити и верхнего края, иначе он
   выглядит вжатым в угол. */
.blog__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: var(--space-3);
  padding: var(--space-6) var(--space-5) var(--space-5);
}
.blog__shot + .blog__body { padding-top: var(--space-5); }

/* Заголовок — главное в карточке: люди приходят из поиска за ответом,
   а не за картинкой, поэтому он крупнее лида и набран заголовочным шрифтом. */
.blog__title {
  font-size: var(--fs-h4);
  font-weight: 600;
  text-wrap: balance;
}

.blog__excerpt {
  font-size: var(--fs-small);
  line-height: 1.6;
  color: var(--color-ink-muted);
}

/* Подвал прижат к низу: даты и подписи выстраиваются в одну линию по всему
   ряду, даже если у соседей разной длины заголовок и нет обложки. */
.blog__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
  margin-top: auto;
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border-subtle);
}

.blog__meta {
  font-size: var(--fs-small);
  color: var(--color-ink-muted);
}

.blog__more {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--color-accent);
}
.blog__more svg {
  width: 16px;
  height: 16px;
  transition: transform var(--dur-fast) var(--ease-out-soft);
}
@media (hover: hover) and (pointer: fine) {
  .blog__link:hover .blog__more svg { transform: translateX(4px); }
}
@media (prefers-reduced-motion: reduce) {
  .blog__more svg { transition: none; }
}

/* ------------------------------------------------------------
   2b. ЛИСТИНГ: ПАГИНАЦИЯ
   ------------------------------------------------------------ */

/* Тот же контурный чип, что у фильтра тем: пагинация — часть той же
   системы навигации по журналу, а не отдельный виджет. */
.blog__pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-7);
}

.blog__pager-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Цифра и «назад/дальше» — один и тот же примитив: контур, пилюля,
   тач-цель от 44px. Активная страница выделяется как активный чип. */
.blog__pager-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--color-border-interactive);
  border-radius: var(--radius-pill);
  color: var(--color-ink);
  font-size: var(--fs-small);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  line-height: var(--lh-ui);
  text-decoration: none;
  transition:
    background-color var(--dur-fast) var(--ease-out-soft),
    border-color var(--dur-fast) var(--ease-out-soft),
    color var(--dur-fast) var(--ease-out-soft);
}

.blog__pager-link.is-active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--blog-paper);
}

.blog__pager-link.is-disabled {
  border-color: var(--color-border-subtle);
  color: var(--color-ink-muted);
  opacity: .5;
}

@media (hover: hover) and (pointer: fine) {
  a.blog__pager-link:not(.is-active):hover {
    border-color: var(--color-line);
    color: var(--color-line);
  }
}

/* Разрыв в номерах — служебный символ, не кликабельная цель, поэтому
   ему хватает вертикального центрирования без рамки и паддингов чипа. */
.blog__pager-gap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  min-height: 44px;
  color: var(--color-ink-muted);
}

/* На узкой ширине список цифр — единственное, что может распереть строку;
   он единственный, кому разрешено переноситься на вторую строку. */
@media (max-width: 389px) {
  .blog__pager-list { row-gap: var(--space-2); }
}

/* ------------------------------------------------------------
   3. СТАТЬЯ: ОБЩАЯ КОЛОНКА
   ------------------------------------------------------------ */

/* Всё содержимое статьи идёт одной колонкой ограниченной ширины: шапка,
   обложка, текст, призыв и переходы стоят на одних полях, и глаз не ищет
   заново левый край на каждом блоке. */
.post {
  max-width: var(--post-measure);
  margin-inline: auto;
}

/* Дата стоит над заголовком, хотя в разметке идёт после него: так строка
   выходных данных читается как датировка, а не как подпись под шапкой.
   Порядок в коде оставлен смысловым, чтобы озвучка начинала с заголовка. */
.post__head {
  display: flex;
  flex-direction: column;
  padding-bottom: var(--space-6);
  border-bottom: 1px solid var(--color-border-subtle);
}

.post__title {
  order: 2;
  margin-top: var(--space-3);
  font-size: var(--fs-h2);
  text-wrap: balance;
}

.post__meta {
  order: 1;
  font-size: var(--fs-small);
  letter-spacing: var(--ls-ui);
  color: var(--color-ink-muted);
}

/* Лид набран акцентным шрифтом курсивом — тем же голосом, которым на витрине
   говорят выносные фразы. Это отделяет вступление от тела статьи без плашки. */
.post__lead {
  order: 3;
  margin-top: var(--space-5);
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.375rem, 1.1rem + 1.1vw, 1.875rem);
  line-height: var(--lh-quote);
  color: var(--color-ink);
}

.post__cover {
  margin: var(--space-7) 0 0;
  background: var(--color-surface);
  border-radius: var(--radius-sharp);
  overflow: hidden;
}
.post__cover img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

/* ------------------------------------------------------------
   4. СТАТЬЯ: ТЕЛО ТЕКСТА
   ------------------------------------------------------------ */

/* Кегль крупнее базового и межстрочный шире: это длинный текст, который
   читают с телефона в руке, а не интерфейсная подпись.
   Сброс в style.css снял маркеры и отступы у всех списков и абзацев,
   поэтому здесь ритм собирается с нуля. */
.post__body {
  margin-top: var(--space-7);
  font-size: var(--fs-body-lg);
  line-height: 1.72;
}

.post__body > * + * { margin-top: var(--space-5); }
.post__body > :first-child { margin-top: 0; }

/* Заголовок второго уровня — это смена темы, поэтому воздуха над ним
   заметно больше, чем под ним: разрыв читается как граница главы. */
.post__body h2 {
  margin-top: var(--space-8);
  font-size: var(--fs-h3);
  text-wrap: balance;
}
.post__body h2::before {
  content: "";
  display: block;
  width: var(--blog-thread);
  height: 2px;
  margin-bottom: var(--space-4);
  background: var(--color-accent);
}
.post__body h2 + * { margin-top: var(--space-4); }

.post__body h3 {
  margin-top: var(--space-7);
  font-size: var(--fs-h4);
}
.post__body h3 + * { margin-top: var(--space-3); }

/* Список: маркер — квадрат в 6px, а не точка. Прямой угол здесь тот же,
   что у --radius-sharp на кнопках и плитках, круглая точка выпадала бы. */
.post__body ul,
.post__body ol {
  padding-left: var(--space-5);
  list-style: none;
}
.post__body li { position: relative; }
.post__body li + li { margin-top: var(--space-3); }

.post__body ul > li::before {
  content: "";
  position: absolute;
  left: calc(var(--space-5) * -1);
  /* привязка к строке, а не к высоте пункта: у многострочного пункта
     маркер иначе уезжает в вертикальный центр */
  top: calc(0.86em - 3px);
  width: 6px;
  height: 6px;
  background: var(--color-accent);
}

.post__body ol { counter-reset: post-item; }
.post__body ol > li { counter-increment: post-item; }
.post__body ol > li::before {
  content: counter(post-item) ".";
  position: absolute;
  left: calc(var(--space-5) * -1);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--color-accent);
}

/* Выделение внутри абзаца держит основной тон: цветной жирный текст
   в длинном чтении рябит и спорит с акцентом на ссылках. */
.post__body strong,
.post__body b {
  font-weight: 700;
  color: var(--color-ink);
}

.post__body a {
  color: var(--color-link);
  font-weight: 500;
  text-decoration: underline;
}

.post__body blockquote {
  padding-left: var(--space-5);
  border-left: 2px solid var(--color-accent);
  font-family: var(--font-accent);
  font-style: italic;
  font-size: clamp(1.25rem, 1.05rem + 0.8vw, 1.625rem);
  line-height: var(--lh-quote);
}

/* Иллюстрация — пауза в чтении, а не случайная вставка: отступы вдвое
   больше, чем между абзацами (space-5). Первому элементу верхний убирает
   общее правило .post__body > :first-child, здесь трогать его не нужно. */
.post__body figure {
  margin: var(--space-7) 0;
}

/* Файлы всегда 1200×800, но пропорция держится через aspect-ratio, а не
   на атрибутах width/height: место под картинку резервируется до
   подгрузки в любом случае, а object-fit: cover не даёт кадру растянуться,
   если редактор один раз зальёт нестандартные стороны. Радиус — тот же
   --radius-soft, что у фотокарточек витрины (.works__shot, .dialog__img),
   а не --radius-sharp обложки поста: инлайн-картинка ближе к карточке. */
.post__body img {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: var(--radius-soft);
}

/* От планшета иллюстрация слегка выходит за меру текста в обе стороны —
   «дышит», не упираясь в колонку, но и не растягивается на весь экран.
   На этой ширине в контейнере уже есть запас (см. --container-max и
   --container-pad в style.css), поэтому выход не даёт горизонтальный скролл. */
@media (min-width: 768px) {
  .post__body figure {
    --figure-bleed: clamp(1.5rem, 3vw, 2.75rem);
    width: calc(100% + var(--figure-bleed) * 2);
    margin-inline: calc(var(--figure-bleed) * -1);
  }
}

.post__body figcaption {
  margin-top: var(--space-3);
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  color: var(--color-ink-muted);
  text-wrap: pretty;
}

.post__body code {
  padding: 2px 6px;
  background: var(--blog-paper);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-sharp);
  font-size: .9em;
}

.post__body hr {
  height: 1px;
  margin-block: var(--space-7);
  border: 0;
  background: var(--color-border-subtle);
}

/* Таблица в тексте — единственный блок, который может оказаться шире
   колонки, поэтому она прокручивается сама, а не тянет страницу. */
.post__body table {
  display: block;
  width: 100%;
  overflow-x: auto;
  border-collapse: collapse;
  font-size: var(--fs-small);
}
.post__body th,
.post__body td {
  padding: var(--space-3);
  border-bottom: 1px solid var(--color-border-subtle);
  text-align: left;
}

/* ------------------------------------------------------------
   5. СТАТЬЯ: ПРИЗЫВ И СОСЕДНИЕ СТАТЬИ
   ------------------------------------------------------------ */

/* Карточка замера стоит на цветной подложке — по DESIGN.md вторичный текст
   на ней теряет контраст, поэтому весь текст здесь основным --color-ink. */
.post__cta {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  margin-top: var(--space-8);
  padding: var(--space-5);
  background: var(--color-surface);
  border-left: 2px solid var(--color-accent);
  border-radius: var(--radius-sharp);
  color: var(--color-ink);
}
.post__cta p {
  margin: 0;
  font-size: var(--fs-body);
  line-height: 1.6;
}
.post__cta .btn { align-self: flex-start; }

.post__nav {
  display: grid;
  gap: var(--space-4);
  margin-top: var(--space-7);
}

.post__nav-link {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-height: 48px;
  padding: var(--space-4) var(--space-5);
  background: var(--blog-paper);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-sharp);
  color: var(--color-ink);
  text-decoration: none;
  transition:
    border-color var(--dur-fast) var(--ease-out-soft),
    box-shadow var(--dur-base) var(--ease-out-soft);
}
@media (hover: hover) and (pointer: fine) {
  .post__nav-link:hover {
    border-color: var(--color-border-interactive);
    box-shadow: var(--shadow-sm);
    color: var(--color-ink);
  }
}

/* «Раньше» и «Позже» набраны как надзаголовок: подпись служебная,
   вес должен уйти названию статьи. */
.post__nav-label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--color-accent);
}
.post__nav-label svg { width: 14px; height: 14px; }

.post__nav-title {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: var(--fs-body);
  line-height: 1.35;
  letter-spacing: var(--ls-heading);
}

/* Переход «позже» зеркалится: стрелка и текст уходят вправо, к краю,
   в сторону движения. На узком экране зеркалить нечего, там одна колонка. */
@media (min-width: 600px) {
  .post__nav { grid-template-columns: 1fr 1fr; }
  .post__nav-link--next {
    grid-column: 2;
    text-align: right;
  }
  .post__nav-link--next .post__nav-label { flex-direction: row-reverse; }
}

/* ------------------------------------------------------------
   5b. ЛИСТИНГ: ПРОМО-ПЛИТКА В ЛЕНТЕ
   ------------------------------------------------------------ */

/* Плитка встаёт в общую сетку .blog обычным <li>, но растягивается на всю
   ширину ряда — так она читается как пауза в ленте, а не как ещё одна статья. */
.blog__item--promo { grid-column: 1 / -1; }

.blog__promo {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  padding: var(--space-6);
  background: var(--color-surface);
  border-left: 2px solid var(--color-accent);
  border-radius: var(--radius-sharp);
  /* На --color-surface вторичный текст теряет контраст (см. правило в
     style.css), поэтому здесь весь текст держится на --color-ink. */
  color: var(--color-ink);
}
.blog__promo-title {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--fs-h3);
  font-weight: 600;
  text-wrap: balance;
}
.blog__promo-text {
  margin: var(--space-2) 0 0;
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--color-ink);
}
.blog__promo-cta { align-self: flex-start; }

@media (min-width: 768px) {
  .blog__promo {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-6);
  }
  .blog__promo-cta { flex-shrink: 0; }
}

/* ------------------------------------------------------------
   5c. СТАТЬЯ: ПОХОЖИЕ СТАТЬИ
   ------------------------------------------------------------ */

/* Блок стоит вне .post: мера в 40rem, которой держится текст статьи,
   слишком узкая для карусели на несколько карточек — нужна ширина контейнера. */
.related { margin-top: var(--space-8); }

/* Заголовок + иконка + линия, протянутая до края: тот же приём, что тонкая
   нить над h2 внутри текста статьи, но развёрнутый в горизонтальный разделитель. */
.related__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-6);
}
.related__head svg {
  width: 22px;
  height: 22px;
  color: var(--color-accent);
  flex-shrink: 0;
}
.related__title {
  margin: 0;
  font-size: var(--fs-h3);
  font-weight: 600;
  white-space: nowrap;
}
.related__head::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--color-border-subtle);
}

/* Трек прокрутки: overflow-x + scroll-snap, без единой строчки JS для самой
   прокрутки — стрелки только помогают, свайп и колесо работают без них. */
.related__carousel { position: relative; }

.related__track {
  display: flex;
  gap: var(--space-5);
  margin: 0;
  padding: 0 0 var(--space-1); /* небольшой запас снизу, чтобы тень карточки при hover не обрезалась overflow */
  list-style: none;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none; /* Firefox */
}
.related__track::-webkit-scrollbar { display: none; } /* Chrome, Safari */

@media (prefers-reduced-motion: no-preference) {
  .related__track { scroll-behavior: smooth; }
}

/* Мобильный: одна карточка почти во всю ширину с намёком на следующую —
   так понятно, что список продолжается, без подписи «листайте». */
.related__slide {
  flex: 0 0 auto;
  width: 85vw;
  max-width: 340px;
  scroll-snap-align: start;
}
@media (min-width: 600px) {
  .related__slide { width: calc((100% - var(--space-5)) / 2); max-width: none; }
}
@media (min-width: 960px) {
  /* На десктопе видно ровно три карточки, остальные уезжают за край */
  .related__slide { width: calc((100% - var(--space-5) * 2) / 3); }
}

/* Стрелки — крупные круглые кнопки по бокам карусели, приподнятые тенью
   над фотографией, стиль обычной витрины интернет-магазина. Только от
   планшета: на телефоне карусель листается пальцем, кнопка рядом со свайпом
   только мешала бы тач-цели. Вертикальная позиция (top) выставляется из JS
   по фактической высоте обложки — только так центр кнопки попадает точно на
   середину картинки на любой ширине экрана, а не на глазок в одном брейкпоинте. */
.related__arrow {
  display: none;
}
@media (min-width: 768px) {
  .related__arrow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    z-index: 2;
    /* До замера в JS — грубая догадка (середина всей карточки), после
       гидратации компонент переопределяет top инлайн-стилем в px. */
    top: 50%;
    width: 56px;
    height: 56px;
    padding: 0;
    background: var(--blog-paper);
    border: 1px solid var(--color-border-subtle);
    border-radius: 50%;
    box-shadow: var(--shadow-sm);
    color: var(--color-ink);
    cursor: pointer;
    transition:
      box-shadow var(--dur-fast) var(--ease-out-soft),
      color var(--dur-fast) var(--ease-out-soft),
      transform var(--dur-fast) var(--ease-out-soft),
      opacity var(--dur-fast) var(--ease-out-soft);
  }
  /* Круг наполовину лежит на крае блока, наполовину — на крайней карточке:
     привычный приём витрин магазинов, а не собственное изобретение. */
  .related__arrow--prev { left: 0; transform: translate(-50%, -50%); }
  .related__arrow--next { right: 0; transform: translate(50%, -50%); }
}
.related__arrow svg { width: 20px; height: 20px; }
@media (hover: hover) and (pointer: fine) {
  .related__arrow--prev:not(:disabled):hover { box-shadow: var(--shadow-md); color: var(--color-accent); transform: translate(-50%, -50%) scale(1.05); }
  .related__arrow--next:not(:disabled):hover { box-shadow: var(--shadow-md); color: var(--color-accent); transform: translate(50%, -50%) scale(1.05); }
}
/* Круглая кнопка не должна превращаться в глобальный сброс сфокуса на
   прямой угол — переопределяем border-radius из :focus-visible в style.css. */
.related__arrow:focus-visible { border-radius: 50%; }
/* На краю прокрутки стрелка не нужна — прячем, а не просто гасим клики,
   чтобы не было висящей активной с виду кнопки в никуда. */
.related__arrow:disabled { opacity: 0; pointer-events: none; }
@media (prefers-reduced-motion: reduce) {
  .related__arrow { transition: none; }
}

/* Карточка повторяет визуальный язык .blog__link (нить в углу, подъём при
   наведении), но живёт отдельным классом — это другой контекст (конец статьи,
   не листинг), и точечная переверстка одного не должна задевать другой. */
.related__card {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--blog-paper);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-sharp);
  color: var(--color-ink);
  text-decoration: none;
  overflow: hidden;
  transition:
    border-color var(--dur-fast) var(--ease-out-soft),
    box-shadow var(--dur-base) var(--ease-out-soft),
    transform var(--dur-base) var(--ease-out-soft);
}
.related__card::before {
  content: "";
  position: absolute;
  inset: 0 auto auto 0;
  z-index: 1;
  width: var(--blog-thread);
  height: 2px;
  background: var(--color-accent);
  transition: width var(--dur-base) var(--ease-out-soft);
}
@media (hover: hover) and (pointer: fine) {
  .related__card:hover {
    border-color: var(--color-border-interactive);
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);
  }
  .related__card:hover::before { width: 100%; }
}
.related__card:focus-visible::before { width: 100%; }
@media (prefers-reduced-motion: reduce) {
  .related__card,
  .related__card::before { transition: none; }
  .related__card:hover { transform: none; }
}

.related__shot {
  margin: 0;
  background: var(--color-surface);
  aspect-ratio: 16 / 9;
  overflow: hidden;
}
.related__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.related__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: var(--space-2);
  padding: var(--space-5);
}
.related__card-title {
  margin: 0;
  font-size: var(--fs-h4);
  font-weight: 600;
  text-wrap: balance;
}
.related__excerpt {
  margin: 0;
  font-size: var(--fs-small);
  line-height: 1.6;
  color: var(--color-ink-muted);
  /* Обрезка в две строки: описания разной длины не должны разъезжать ряд */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.related__meta {
  margin: auto 0 0;
  padding-top: var(--space-3);
  font-size: var(--fs-small);
  color: var(--color-ink-muted);
}

/* ------------------------------------------------------------
   6. ПЛАНШЕТ И ДЕСКТОП
   ------------------------------------------------------------ */

@media (min-width: 768px) {
  .blog { gap: var(--space-6); }
  .blog__body { padding: var(--space-6) var(--space-6) var(--space-5); }
  .blog__shot + .blog__body { padding-top: var(--space-5); }

  .post__cta {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-6);
    padding: var(--space-6);
  }
  .post__cta .btn { flex-shrink: 0; }
}
