/*
 * Подгрузка ленты порциями и лоадер первой загрузки (MAI-73).
 * Цвета, отступы, размеры и длительности — только через токены (tokens.css).
 * Макеты: «A · Главная» (состояние «Загрузка», нижний ряд-скелетон), «Дизайн-система».
 * Брейкпоинты: до 640 px, 641–1024 px, от 1025 px.
 *
 * Метки на <html> ставят скрипты; без них (без JavaScript) страница выглядит так:
 *   data-loader     — loader.js, первая загрузка за сессию: показан лоадер, остальное содержимое скрыто;
 *   data-lazy-feed  — feed.js, htmx на месте: у сторожа вместо ссылки «Показать ещё» скелетон.
 */

/* Сторож следующей порции */

/*
 * Подгрузка заранее. В hx-trigger htmx 2.0.11 нет rootMargin, поэтому сторож сам заходит на --sentinel-lead
 * вверх: отступ сверху делает его коробку выше (наблюдатель htmx следит за всей коробкой), а равный
 * отрицательный внешний отступ возвращает содержимое на прежнее место. Коробка накрывает нижние ряды,
 * поэтому сама для мыши прозрачна, а её содержимое нет.
 */
.feed__sentinel {
  display: flex;
  flex-direction: column;
  gap: var(--skeleton-gap);
  margin-top: calc(-1 * var(--sentinel-lead));
  padding-top: var(--sentinel-lead);
  pointer-events: none;
}

.feed__sentinel > * {
  pointer-events: auto;
}

.feed__more,
.feed__retry,
.feed__restart {
  align-self: center;
}

.feed__retry {
  cursor: pointer;
}

/* Скелетон, подпись, кнопка «Повторить» и ссылка «К началу ленты» нужны только с подгрузкой */

.skeleton,
.feed__status,
.feed__retry,
.feed__restart {
  display: none;
}

html[data-lazy-feed] .feed__more {
  display: none;
}

html[data-lazy-feed] .skeleton {
  display: flex;
  gap: var(--feed-gap);
}

html[data-lazy-feed] .feed__status {
  display: block;
  align-self: center;
  color: var(--muted);
  font-size: var(--font-size-12);
  line-height: var(--line-height-ui);
  text-align: center;
}

/* Ошибка: вместо скелетона подпись «Не удалось загрузить» и кнопка */

html[data-lazy-feed] .feed__sentinel[data-state="error"] .skeleton {
  display: none;
}

html[data-lazy-feed] .feed__sentinel[data-state="error"] .feed__retry {
  display: inline-flex;
}

/* Ответ 400 (курсор негоден, лента изменилась): повтор не поможет, вместо кнопки ссылка в начало ленты */

html[data-lazy-feed] .feed__sentinel[data-state="stale"] .skeleton {
  display: none;
}

html[data-lazy-feed] .feed__sentinel[data-state="stale"] .feed__restart {
  display: inline-flex;
}

/*
 * Скелетон: три блока. Доля ширины каждого равна его пропорции, поэтому при любой ширине ряда
 * блоки одной высоты, как карточки настоящего ряда.
 */

.skeleton__block {
  min-width: 0;
  background: linear-gradient(90deg, var(--photo) 0, var(--line) 50%, var(--photo) 100%);
  background-size: var(--skeleton-shimmer-size) 100%;
  animation: skeleton-shimmer var(--duration-shimmer) linear infinite;
}

.skeleton__block--wide {
  flex: var(--skeleton-ratio-wide) 1 0;
  aspect-ratio: var(--skeleton-ratio-wide);
}

.skeleton__block--mid {
  flex: var(--skeleton-ratio-mid) 1 0;
  aspect-ratio: var(--skeleton-ratio-mid);
}

.skeleton__block--tall {
  flex: var(--skeleton-ratio-tall) 1 0;
  aspect-ratio: var(--skeleton-ratio-tall);
}

@keyframes skeleton-shimmer {
  from {
    background-position: calc(-1 * var(--skeleton-shimmer-shift)) 0;
  }

  to {
    background-position: var(--skeleton-shimmer-shift) 0;
  }
}

/* Конец ленты */

.feed__end {
  align-self: center;
  color: var(--muted);
  font-size: var(--font-size-12);
  line-height: var(--line-height-ui);
}

/* Лоадер первой загрузки: область под шапкой, содержимое страницы на это время скрыто */

.loader {
  display: none;
}

html[data-loader] main {
  position: relative;
  overflow: hidden;
}

html[data-loader] .loader {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--loader-gap);
  min-height: var(--loader-min-height);
}

/*
 * Остальное содержимое остаётся в разметке и в раскладке (картинки первого ряда грузятся), но не видно
 * и не занимает места: main обрезает его по высоте лоадера.
 */
html[data-loader] .loader ~ * {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  visibility: hidden;
  pointer-events: none;
}

html[data-loader] .site-footer {
  display: none;
}

.loader__icon {
  display: flex;
  animation: loader-spin var(--duration-spin) linear infinite;
}

.loader__body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--loader-text-gap);
  width: var(--loader-bar-width);
}

.loader__text {
  font-size: var(--font-size-16);
}

.loader__track {
  width: 100%;
  height: var(--loader-bar-height);
  background-color: var(--line);
}

.loader__bar {
  height: 100%;
  background-color: var(--accent);
  animation: loader-grow var(--duration-bar) ease-out infinite;
}

@keyframes loader-spin {
  to {
    transform: rotate(360deg);
  }
}

@keyframes loader-grow {
  from {
    width: var(--loader-bar-from);
  }

  to {
    width: var(--loader-bar-to);
  }
}

/* Телефон: блоки скелетона друг под другом, как ряды ленты */

@media (max-width: 640px) {
  html[data-lazy-feed] .skeleton {
    flex-direction: column;
  }
}

/* Меньше движения: без вращения, полосы и блика (общее правило в base.css делает то же для всех анимаций) */

@media (prefers-reduced-motion: reduce) {
  .loader__icon,
  .loader__bar,
  .skeleton__block {
    animation: none;
  }

  .loader__bar {
    width: var(--loader-bar-static);
  }

  .skeleton__block {
    background: var(--photo);
  }
}
