/* =====================================================================
   Блог — только то, чего нет в docs/stylesheets/extra.css.
   Токены (--ui-*) приходят оттуда: блог и документация используют один
   набор цветов, радиусов и теней, поэтому здесь их не переопределяем.
   ===================================================================== */

/* ---- Лента: сетка плиток ------------------------------------------ */
/* Плитки — это <article class="md-post md-post--excerpt">, которые плагин
   blog кладёт прямо в .md-content__inner рядом с заголовком и пагинацией.
   :has() отличает страницу ленты от страницы статьи, где такой разметки нет. */
.md-content__inner:has(> .md-post--excerpt) {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 1.2rem;
}
/* Пагинация остаётся в DOM датчиком прокрутки и запасным вариантом без JS,
   поэтому не display:none — иначе у неё не будет бокса и наблюдатель не сработает. */
.md-feed--infinite .md-pagination {
  height: 0;
  margin: 0;
  overflow: hidden;
  visibility: hidden;
}
/* Заголовок ленты и пагинация — во всю ширину сетки. */
.md-content__inner:has(> .md-post--excerpt) > :not(.md-post--excerpt) {
  grid-column: 1 / -1;
}
/* В index.md нет заголовка, но Material всё равно печатает пустой <header>. Высоты у
   него нет, а строку в сетке он занимает — и добавляет к отступу сверху лишние 1.2rem. */
.md-content__inner > header.md-typeset:not(:has(*)) {
  display: none;
}
/* Лента начинается сразу под вкладками: у статьи отступ в 1.5rem отделяет заголовок от
   шапки, а плитке с картинкой такая подушка не нужна. */
.md-main__inner:has(.md-post--excerpt) {
  margin-top: 0.8rem;
}

/* ---- Поля контента: один и тот же край на всех страницах ------------ */
/* Ниже 76.25em Material сам держит по 0.8rem с каждой стороны — там всё ровно.
   Выше он добавляет запас под сайдбары: слева 1.2rem (двумя разными правилами —
   на ленте от видимого левого сайдбара, на статье через `.md-content--post`),
   справа 1.2rem от колонки оглавления. Сайдбары у блога скрыты или пусты, поэтому
   запас превращается в перекос: левый край уезжает от логотипа, правый не доходит
   до поиска. Гасим и выставляем края сами. Селекторы длинные, чтобы перебить
   авторские — специфичность у них (0,5,0). */
@media screen and (min-width: 76.25em) {
  /* слева — под логотипом и первой вкладкой шапки */
  [dir] .md-sidebar--primary:not([hidden]) ~ .md-content > .md-content__inner,
  [dir] .md-content--post > .md-content__inner {
    margin-left: 0.8rem;
  }
  /* справа — вровень с поиском и правым краем плиток ленты */
  [dir] .md-sidebar--secondary:not([hidden]) ~ .md-content > .md-content__inner {
    margin-right: 0.2rem;
  }
  /* …кроме статей, где оглавление действительно есть: там правое поле — зазор до него.
     Проверяем по пунктам внутри .md-nav--secondary: сам сайдбар Material рендерит
     всегда, даже когда в статье нет заголовков, и атрибута hidden на нём нет. */
  body:has(.md-nav--secondary .md-nav__item) .md-sidebar--secondary ~ .md-content > .md-content__inner {
    margin-right: 1.2rem;
  }
}

/* ---- Ритм ленты: 1 широкая → 3 → 2 и снова с начала ----------------- */
/* Шесть колонок — общий знаменатель для рядов по три (span 2) и по два (span 3).
   Считаем :nth-of-type, а не :nth-child: заголовок и пагинация — не <article>,
   поэтому в нумерацию не лезут. Цикл из шести совпадает с pagination_per_page: 12,
   так что и на /page/2/, и при бесконечной подгрузке ритм продолжается ровно. */
@media screen and (min-width: 60em) {
  .md-content__inner:has(> .md-post--excerpt) {
    grid-template-columns: repeat(6, 1fr);
  }
  /* ряд из трёх */
  .md-post--excerpt {
    grid-column: span 2;
  }
  /* ряд из двух */
  .md-post--excerpt:nth-of-type(6n + 5),
  .md-post--excerpt:nth-of-type(6n) {
    grid-column: span 3;
  }

  /* В узких плитках текст перевешивал картинку: у постов из телеграм-канала до
     <!-- more --> идут два абзаца, и каждый обрезался отдельно — до восьми строк.
     Абзацы режем по-разному: первый в таких постах — короткое приветствие, ему
     хватит строки, а суть во втором. Где абзац один (все статьи из Ghost) —
     ему достаются обычные две-три строки. Всё после второго абзаца не нужно.
     :not(:has(> img)) отделяет текст от обложки: она тоже <p>. */
  .md-post--excerpt:not(:nth-of-type(6n + 1)) .md-post__content {
    & > p:not(:has(> img:only-child)) {
      -webkit-line-clamp: 2;
    }
    & > p:not(:has(> img:only-child)):has(~ p:not(:has(> img:only-child))) {
      -webkit-line-clamp: 1;
    }
    & > p:not(:has(> img:only-child)) ~ p:not(:has(> img:only-child)) {
      -webkit-line-clamp: 2;
    }
    & > p:not(:has(> img:only-child)) ~ p:not(:has(> img:only-child)) ~ p:not(:has(> img:only-child)) {
      display: none;
    }
  }

  /* Широкая: картинка слева, текст справа. */
  .md-post--excerpt:nth-of-type(6n + 1) {
    grid-column: span 6;
    display: grid;
    grid-template-columns: 1.4fr 1fr;
    /* Строк с запасом, последняя 1fr: она забирает остаток высоты, если текста
       меньше картинки, а пустые min-content-строки высоты не добавляют. Без этого
       остаток размазывался по всем строкам и под карточкой висела полоса воздуха. */
    grid-template-rows: repeat(6, min-content) 1fr;
    column-gap: 0.6rem;
    padding-bottom: 0;

    & p:has(> img:only-child) {
      grid-column: 1;
      grid-row: 1 / -1;
    }
    & p > img:only-child {
      height: 100%;
    }
    & > *,
    & .md-post__content > * {
      grid-column: 2;
      padding-right: 1.6rem;
    }
    & .md-post__header {
      margin-top: 1.4rem;
    }
    & .md-post__content h2 {
      font-size: 1.5rem;
    }
    & .md-post__content > p:not(:has(> img:only-child)) {
      /* Три строки, чтобы колонка текста не переросла картинку: она задаёт высоту. */
      -webkit-line-clamp: 3;
      font-size: 0.78rem;
    }
    & .md-post__action {
      padding-bottom: 1.4rem;
    }
  }
}

/* ---- Боковые колонки: в блоге они пустые ---------------------------- */
/* Блок статьи со ссылкой «Повернутись на головну» и «Метадані» не нужен ни на
   каком экране: дату оттуда переносит под текст blog.js, а на узких экранах он
   вообще уезжает под статью и висит там заголовком с иконкой календаря. */
.md-sidebar--post {
  display: none;
}
/* Слева Material повторяет верхнее меню — в блоге это те же семь табов, что уже
   есть в шапке. Ниже 76.25em эта колонка превращается в меню под гамбургером,
   то есть остаётся единственной навигацией, поэтому прячем только на десктопе. */
@media screen and (min-width: 76.25em) {
  .md-sidebar--primary {
    display: none;
  }
}
/* Справа — оглавление. У ленты и у страниц без подзаголовков оно пустое, и вместо
   него остаётся полоса воздуха. Условие по содержимому, а не по типу страницы:
   у статьи с подзаголовками оглавление полезно и остаётся на месте. */
.md-sidebar--secondary:not(:has(.md-nav__link)) {
  display: none;
}

/* ---- Плитка -------------------------------------------------------- */
.md-post--excerpt {
  display: flex;
  flex-direction: column;
  height: 100%;
  margin: 0;
  position: relative;
  cursor: pointer;
  padding-bottom: 0.9rem;
  overflow: hidden;
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-radius-lg);
  box-shadow: var(--ui-shadow-sm);
  background: var(--ui-surface);
  transition: box-shadow 0.18s var(--ui-ease),
              border-color 0.18s var(--ui-ease);
}
.md-post--excerpt:hover {
  border-color: var(--ui-border-strong);
  box-shadow: var(--ui-shadow-md);
}

/* Обложка лежит внутри .md-post__content, а дата — снаружи, в .md-post__header.
   display:contents убирает промежуточный бокс, и оба становятся соседями в одном
   flex-контейнере: тогда картинку можно поднять наверх обычным order. */
.md-post--excerpt .md-post__content {
  display: contents;
}
.md-post--excerpt > *,
.md-post--excerpt .md-post__content > * {
  padding-left: 1rem;
  padding-right: 1rem;
}
.md-post--excerpt p:has(> img:only-child) {
  order: -1;
  margin: 0;
  padding: 0;
}
.md-post--excerpt p > img:only-child {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.md-post--excerpt .md-post__header {
  margin: 0.7rem 0 0;
}
.md-post--excerpt .md-post__content h2 {
  margin: 0.2rem 0 0.4rem;
  font-size: 1.05rem;
  line-height: 1.35;
}
.md-post--excerpt .md-post__content h2 a {
  color: var(--ui-text);
  text-decoration: none;
}
/* Кликабельна вся плитка: ссылка заголовка растягивается на неё невидимым слоем.
   Без JS, поэтому средний клик и «открыть в новой вкладке» работают как у обычной
   ссылки. Цена — текст внутри плитки перестаёт выделяться мышью. */
.md-post--excerpt .md-post__content h2 a::after {
  content: "";
  position: absolute;
  inset: 0;
}
/* Позиционированные элементы при равном z-index рисуются в порядке DOM, а слой
   выше принадлежит заголовку — значит «Читати далі» остаётся кликабельным. */
.md-post--excerpt .md-post__action {
  position: relative;
}
/* Ссылки внутри тизера — обычный текст: в плитке они выглядели вкраплениями
   другого цвета и уводили мимо статьи. Кликается вся карточка целиком. */
/* Растянутый слой заголовка перехватывает клик сам: достаточно не делать ссылку
   позиционированной, и она перестаёт быть кликабельной — вместо неё открывается
   статья. pointer-events: none тут не годится, клик тогда проваливается мимо. */
.md-post--excerpt .md-post__content > p a {
  color: inherit;
  text-decoration: none;
}

/* Тизеры разной длины иначе рвут высоту плиток в ряду. */
.md-post--excerpt .md-post__content > p:not(:has(> img:only-child)) {
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 0;
  font-size: 0.72rem;
  color: var(--ui-text-muted);
}

.md-post--excerpt .md-post__action {
  margin-top: auto;
  padding-top: 0.7rem;
}

/* ---- Страница статьи ----------------------------------------------- */
/* Текст статьи лежит прямо в .md-content__inner: обёртки .md-post__content,
   как в ленте, здесь нет. */
/* Обложка во всю ширину колонки, как было в Ghost. В статьях (в отличие от ленты)
   glightbox оборачивает каждую картинку в <a>, поэтому селектор без прямого
   потомка, а самому <a> нужен блочный бокс — иначе снизу остаётся отступ строки. */
.md-content__inner > p:first-of-type img {
  width: 100%;
  /* Часть обложек — вертикальные картинки на весь экран. Приводим к тому же 16:9,
     что и плитка в ленте: широкие обложки видно целиком, подрезаются только высокие. */
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: var(--ui-radius);
}
.md-content__inner > p:first-of-type > a.glightbox {
  display: block;
}
/* Ghost ставил <hr> между смысловыми блоками — их в статьях сотни,
   поэтому делаем разделитель тише, чем дефолтный. */
.md-content__inner > hr {
  margin: 1.6em 0;
  border-bottom-color: var(--ui-border);
}

.md-post__date {
  margin-top: 2rem;
  padding-top: 0.8rem;
  border-top: 1px solid var(--ui-border);
  font-size: 0.7rem;
  color: var(--ui-text-muted);
}

/* Обложка только для плитки в ленте и соцпревью: в самой статье вместо неё сразу
   плеер (см. blog/posts/video-checkbox.md). В ленте картинка лежит внутри
   .md-post--excerpt, поэтому под этот селектор — «прямой абзац статьи» — не попадает.
   glightbox оборачивает картинку в <a>, отсюда второй вариант. */
.md-content__inner > p:has(> img.feed-only),
.md-content__inner > p:has(> a > img.feed-only) {
  display: none;
}
/* Ролики из телеграм-канала квадратные: на всю ширину колонки такой занял бы больше
   экрана целиком, поэтому ограничиваем по ширине и центрируем. */
.md-content__inner video {
  display: block;
  /* Ограничиваем и по ширине, и по высоте: ролики бывают квадратные и вертикальные,
     вертикальный при одной только ширине занял бы два экрана. */
  max-width: min(26rem, 100%);
  max-height: 32rem;
  margin: 0 auto;
  border-radius: var(--ui-radius);
}

/* Видео. У Ghost размеры стояли атрибутами, при импорте их снимаем: фиксированные
   612x344 не влезали бы в колонку. Без них iframe рисуется дефолтными 300x150. */
.md-content__inner iframe {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  height: auto;
  border: 0;
  border-radius: var(--ui-radius);
}
/* Вертикальные ролики (YouTube Shorts) в широком 16:9 показывались бы полосой
   чёрного по бокам — задаём им пропорции экрана телефона. */
.md-content__inner iframe.vertical {
  max-width: 20rem;
  aspect-ratio: 9 / 16;
}
/* Обратная сторона: видео в плитке ленты не показываем. Правило идёт после
   предыдущего — специфичность у них одинаковая, решает порядок. */
.md-post--excerpt iframe {
  display: none;
}

/* ---- «Читайте також» под статьёй ------------------------------------ */
/* Список формирует hooks/related_posts.py, разметку — overrides/main.html.
   Блок лежит перед футером, поэтому сетка ленты и правила статьи его не задевают. */
.md-related {
  border-top: 1px solid var(--ui-border);
  background: var(--ui-surface-muted, #fafafa);
}
.md-related__inner {
  /* Боковые поля — как у ленты и у текста статьи: слева под логотипом, справа вровень
     с поиском и оглавлением. См. комментарий к полям .md-content__inner ниже. */
  padding: 1.6rem 0.2rem 2rem 0.8rem;
}
/* Когда у статьи есть оглавление, текст кончается раньше края сетки — на ширину
   колонки оглавления (12.1rem) плюс зазор до неё (1.2rem). Блок рекомендаций лежит
   вне .md-main, поэтому подхватить эту ширину можно только вычитанием вручную:
   иначе карточки уезжают правее текста и правых краёв на странице становится два. */
@media screen and (min-width: 76.25em) {
  body:has(.md-nav--secondary .md-nav__item) .md-related__inner {
    padding-right: 13.3rem;
  }
}
.md-related__title {
  margin: 0 0 1rem;
  font-size: 0.9rem;
  color: var(--ui-text-muted);
  font-weight: 500;
}
.md-related__list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.2rem;
}
/* .md-typeset красит и подчёркивает любые ссылки внутри — гасим адресно. */
.md-typeset .md-related__card,
.md-typeset .md-related__card:hover {
  display: block;
  color: inherit;
  text-decoration: none;
}
.md-related__card img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: var(--ui-radius);
  transition: box-shadow 0.18s var(--ui-ease);
}
.md-related__card:hover img {
  box-shadow: var(--ui-shadow-md);
}
.md-related__card-title {
  display: block;
  margin-top: 0.6rem;
  font-weight: 700;
  line-height: 1.35;
}
.md-related__card-text {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin-top: 0.25rem;
  font-size: 0.72rem;
  color: var(--ui-text-muted);
}

/* Штатная навигация «Назад / Вперед» у Material показывает те же соседние статьи,
   что и блок выше, — оставляем что-то одно. Тема включает её правилом
   .md-footer__inner:not([hidden]), поэтому просто display:none не перебивает. */
.md-footer__inner:not([hidden]) {
  display: none;
}

/* Ссылки в подвале — справа от копирайта, как было в Ghost. Размер, цвет и отступы
   те же, что у .md-copyright, иначе правая половина выглядит крупнее левой. */
.md-footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0 1rem;
  margin: auto 0.6rem;
  padding: 0.4rem 0;
  font-size: 0.64rem;
  color: var(--md-footer-fg-color--lighter);
  white-space: nowrap;
}
.md-footer-links a {
  color: inherit;
}
.md-footer-links a:hover {
  color: var(--md-footer-fg-color);
}
