/* ============================================================
   МАТЕРИАЛЫ — страница каталога, детальная материала и страница серии.

   Подключается после site.css через {% block extra_css %} только на
   страницах раздела: лендинг лишних килобайт не грузит.

   Все радиусы, тени, отступы, шрифты, длительности и большая часть
   цветов берутся из :root в site.css. Единственные новые цвета —
   шесть пастельных тонов серий (docs/SPEC.md §9 разрешает ровно это),
   объявлены в одном месте — блоком ниже.

   Порядок блоков:
     1. Тона серий
     2. Мелкие компоненты (.btn--ghost, .tag, .mat-badge, .tile--acc)
     3. Первый экран страницы
     4. «Популярные материалы»: сетка и карточка
     5. Заглушка обложки
     6. «Серии материалов»: карточка, лента, точки
     7. Каталог с фильтрами
     8. Полоса преимуществ
     9. Нижний блок и форма подписки
    10. Детальная страница и крошки
    11. Моушн-дополнения
   ============================================================ */


/* ============================================================
   1. ТОНА СЕРИЙ МАТЕРИАЛОВ
   Ключи совпадают с Series.Accent (apps/materials/models.py):
   blue / green / purple / orange / rose / teal.
     soft  — фон карточки серии, верх градиента заглушки обложки
     hover — фон карточки серии при наведении
     tint  — низ градиента заглушки обложки
     line  — тонкая граница карточки и заглушки
     deep  — иконка серии, ссылка «Смотреть все», корешок, активная точка
   Контраст всех пар посчитан в specs/design-materials.md §1.4:
   провалов ниже 4.5:1 для текста и 3:1 для индикаторов нет.
   ============================================================ */
:root{
  --accent-blue-soft:#E7F0FA;   --accent-blue-hover:#DCE9F7;   --accent-blue-tint:#D3E4F5;   --accent-blue-line:#B9D3EC;   --accent-blue-deep:#1B6699;
  --accent-green-soft:#E7F2E9;  --accent-green-hover:#DCECDF;  --accent-green-tint:#D3E8D8;  --accent-green-line:#B7D9C0;  --accent-green-deep:#2C6E49;
  --accent-purple-soft:#EDEAF8; --accent-purple-hover:#E4E0F4; --accent-purple-tint:#DEDAF2; --accent-purple-line:#C7C0E8; --accent-purple-deep:#5546A8;
  --accent-orange-soft:#FBEDDD; --accent-orange-hover:#F8E6D2; --accent-orange-tint:#F6DFC6; --accent-orange-line:#EDCBA4; --accent-orange-deep:#9C5410;
  --accent-rose-soft:#F6E9F2;   --accent-rose-hover:#F2E2ED;   --accent-rose-tint:#EEDAE8;   --accent-rose-line:#E0C2D6;   --accent-rose-deep:#8C3F76;
  --accent-teal-soft:#E3F0EF;   --accent-teal-hover:#D9EAE9;   --accent-teal-tint:#CFE4E2;   --accent-teal-line:#B0D2CF;   --accent-teal-deep:#136B66;

  /* Активный тон. По умолчанию голубой: материал без серии не проваливается
     в «серую дыру», а получает тот же тон, что и Material.accent в моделях. */
  --acc-soft:  var(--accent-blue-soft);
  --acc-hover: var(--accent-blue-hover);
  --acc-tint:  var(--accent-blue-tint);
  --acc-line:  var(--accent-blue-line);
  --acc-deep:  var(--accent-blue-deep);

  /* Геометрия страницы материалов */
  --series-pad: 20px;   /* внутренний отступ карточки серии; лента использует его для выноса */
  /* 132px, а не 118: при 118 подпись «Writing: Letters & Emails» не влезала
     в две строки и обрезалась многоточием почти у половины материалов. */
  --strip-w: 132px;     /* ширина мини-обложки в ленте на мобильном */
  --strip-gap: 12px;    /* шаг ленты */
}

/* Один класс переопределяет все пять переменных — дальше их наследует
   всё вложенное: фон, граница, иконка, ссылка, заглушка, корешок, точки.
   Имена классов зафиксированы контрактом Material.cover_placeholder_class. */
.series-card--blue,   .cover-ph--blue,   .mat-card--blue,   .mat-detail--blue{
  --acc-soft:var(--accent-blue-soft); --acc-hover:var(--accent-blue-hover);
  --acc-tint:var(--accent-blue-tint); --acc-line:var(--accent-blue-line);
  --acc-deep:var(--accent-blue-deep);
}
.series-card--green,  .cover-ph--green,  .mat-card--green,  .mat-detail--green{
  --acc-soft:var(--accent-green-soft); --acc-hover:var(--accent-green-hover);
  --acc-tint:var(--accent-green-tint); --acc-line:var(--accent-green-line);
  --acc-deep:var(--accent-green-deep);
}
.series-card--purple, .cover-ph--purple, .mat-card--purple, .mat-detail--purple{
  --acc-soft:var(--accent-purple-soft); --acc-hover:var(--accent-purple-hover);
  --acc-tint:var(--accent-purple-tint); --acc-line:var(--accent-purple-line);
  --acc-deep:var(--accent-purple-deep);
}
.series-card--orange, .cover-ph--orange, .mat-card--orange, .mat-detail--orange{
  --acc-soft:var(--accent-orange-soft); --acc-hover:var(--accent-orange-hover);
  --acc-tint:var(--accent-orange-tint); --acc-line:var(--accent-orange-line);
  --acc-deep:var(--accent-orange-deep);
}
.series-card--rose,   .cover-ph--rose,   .mat-card--rose,   .mat-detail--rose{
  --acc-soft:var(--accent-rose-soft); --acc-hover:var(--accent-rose-hover);
  --acc-tint:var(--accent-rose-tint); --acc-line:var(--accent-rose-line);
  --acc-deep:var(--accent-rose-deep);
}
.series-card--teal,   .cover-ph--teal,   .mat-card--teal,   .mat-detail--teal{
  --acc-soft:var(--accent-teal-soft); --acc-hover:var(--accent-teal-hover);
  --acc-tint:var(--accent-teal-tint); --acc-line:var(--accent-teal-line);
  --acc-deep:var(--accent-teal-deep);
}


/* ============================================================
   2. МЕЛКИЕ КОМПОНЕНТЫ
   ============================================================ */

/* Кнопка-контур: «Смотреть все материалы», «Посмотреть материал».
   Граница — --c-muted (5.33:1 на белом). --line-strong даёт 1.42:1
   и как граница контрола проваливает WCAG 1.4.11, поэтому запрещён.
   ::before/::after уже описаны у .btn — подменяем только наполнение,
   подъём, плавность и :active наследуются без лишних строк. */
.btn--ghost{
  background: #FFFFFF; color: var(--c-ink);
  border: 1.5px solid var(--c-muted);
  box-shadow: none;
}
.btn--ghost::before{ background: var(--s-cream); }
.btn--ghost::after{ box-shadow: var(--shadow-md); }
.btn--ghost .icon{ stroke: var(--c-ink); }
@media (hover: hover) and (pointer: fine){
  .btn--ghost:hover{ border-color: var(--c-ink); }
}

/* Чип тега материала. Отдельный компонент, а не модификатор .chip:
   у .chip паддинги 10/16 и шрифт 14px — для узкой карточки крупно. */
.tag-list{ display: flex; flex-wrap: wrap; gap: 6px; list-style: none; }
.tag{
  display: inline-flex; align-items: center;
  background: var(--s-cream); border: 1px solid var(--line); border-radius: var(--r-pill);
  padding: 4px 10px; font-weight: 600; font-size: 12px; line-height: 1.4;
  color: var(--c-ink-2);            /* 10.55:1 на креме */
}

/* Пилюля «Авторский материал». Имя не .badge: на лендинге .badge —
   жёлтый уголок «Основное направление». */
.mat-badge{
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  background: var(--s-info); color: var(--c-ink);   /* 14.78:1 */
  border-radius: var(--r-pill); padding: 5px 12px;
  font-weight: 700; font-size: 12px; line-height: 1.2;
}
.mat-badge .icon{ width: 14px; height: 14px; stroke: var(--c-note); flex-shrink: 0; }

/* Кремовая .tile на пастельном фоне сливается — на карточке серии она белая.
   Приём взят у .review-map лендинга. */
.tile--acc{ background: #FFFFFF; }
.tile--acc .icon{ stroke: var(--acc-deep); }


/* ============================================================
   3. ПЕРВЫЙ ЭКРАН СТРАНИЦЫ (SPEC §7.1)
   ============================================================ */

/* Тот же градиент, что у .hero лендинга: переход между страницами не «моргает». */
.mat-hero{
  background: linear-gradient(180deg, #FFFFFF 0%, var(--s-cream) 100%);
  padding-block: 40px 48px;
}
@media (min-width: 1024px){ .mat-hero{ padding-block: 72px 80px; } }

.mat-hero-grid{ display: grid; gap: 28px; }
@media (min-width: 1024px){
  .mat-hero-grid{ grid-template-columns: 1.05fr .95fr; gap: 48px; align-items: center; }
}
@media (min-width: 1280px){ .mat-hero-grid{ gap: 64px; } }

.mat-hero-copy{ max-width: 560px; }
.mat-hero h1{ font-size: var(--fs-h1); font-weight: 700; line-height: var(--lh-display); }

/* Строка-тезис с жёлтой чертой. В разметке классы идут парой
   (`hero-thesis mat-hero-thesis`): первый даёт анимацию черты из site.css,
   геометрия продублирована здесь, чтобы страница материалов не зависела
   от того, в каком файле в итоге окажутся стили Hero лендинга. */
.mat-hero-thesis{
  position: relative; margin-top: 20px; padding-left: 17px;
  font-weight: 700; font-size: var(--fs-thesis); line-height: 1.45;
  max-width: var(--measure);
}
.mat-hero-thesis .accent-bar{
  position: absolute; left: 0; top: 2px; bottom: 2px; width: 3px;
  background: var(--c-brand); border-radius: 2px;
}

.mat-hero-lead{
  margin-top: 12px; font-size: var(--fs-lead); line-height: var(--lh-body);
  color: var(--c-muted);                      /* 4.94:1 на креме */
  max-width: var(--measure);
}

/* Три фичи — существующие .chip. Самый длинный чип ≈ 203px < 335px контента
   на 375px, поэтому чипы просто переносятся в две строки.
   Некликабельны (.chip{cursor:default}) — правило 44px к ним не применяется. */
.mat-hero-feats{ margin-top: 26px; display: flex; flex-wrap: wrap; gap: 10px; list-style: none; }
/* Плашек первого экрана в админке может не быть — тогда пустой список
   не должен оставлять после себя отступ. */
.mat-hero-feats:empty{ display: none; }

.mat-hero-media{ margin: 0; min-width: 0; }
/* height:auto обязателен: в разметке у <img> стоят width/height 1536×1024,
   и без сброса высоты браузер считает бокс «жёстко заданным» — aspect-ratio
   игнорируется, картинка растягивается на 1024px по высоте и при ширине
   колонки ~510px кадрируется в портрет: в кадре остаётся окно со шторой
   и крышка ноутбука. Со сбросом рамка становится пейзажной 3:2 — ровно
   пропорция снимка, поэтому кроп нулевой и видно блокнот, пособия и чашку. */
.mat-hero-photo{
  display: block; width: 100%; height: auto;
  aspect-ratio: 3 / 2; object-fit: cover; object-position: 50% 55%;
  border-radius: var(--r-xl); box-shadow: var(--shadow-md);
  /* LQIP из assets_src/derivatives.json: снимает белую дыру до загрузки,
     второго сетевого запроса не создаёт. */
  background: var(--s-cream-deep) url("data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDABQODxIPDRQSEBIXFRQYHjIhHhwcHj0sLiQySUBMS0dARkVQWnNiUFVtVkVGZIhlbXd7gYKBTmCNl4x9lnN+gXz/2wBDARUXFx4aHjshITt8U0ZTfHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHz/wAARCAAQABgDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDrGmX+8PwrIvr5nDIQNuat3c5juUjBwjDnArONrbuju7ncCerYrNu+iNErasPNENmzyAjHtRVdrueFiuzzIRxleeKKzuVZn//Z") center / cover no-repeat;
}

/* Сентинел для липкой CTA-полоски — аналог .hero-end-sentinel лендинга. */
.mat-hero-sentinel{ height: 1px; }

/* Сжатый вариант первого экрана: каталог с фильтрами и страница серии. */
.mat-hero--compact{ padding-block: 32px 28px; }
.mat-hero--compact .mat-hero-media,
.mat-hero--compact .mat-hero-feats{ display: none; }
@media (min-width: 1024px){ .mat-hero--compact{ padding-block: 40px 36px; } }


/* ============================================================
   4. «ПОПУЛЯРНЫЕ МАТЕРИАЛЫ»: СЕТКА И КАРТОЧКА (SPEC §7.2)
   ============================================================ */

/* Порядок в DOM: заголовок → карточки → кнопка. На мобильном кнопка
   «Смотреть все» стоит под карточками (сначала товар, потом «ещё»),
   с 768px тем же гридом уезжает в правый верхний угол — как в макете.
   Дублировать разметку не нужно. */
.mat-popular-inner{ display: grid; grid-template-areas: "head" "grid" "action"; }
.mat-popular-inner > .section-head{ grid-area: head; }
.mat-popular-inner > .mat-grid{ grid-area: grid; }
.head-action{ grid-area: action; width: 100%; margin-top: 24px; }

@media (min-width: 768px){
  .mat-popular-inner{
    grid-template-columns: 1fr auto;
    grid-template-areas: "head action" "grid grid";
    align-items: end;
  }
  .head-action{ width: auto; margin-top: 0; margin-bottom: 28px; }
}
@media (min-width: 1024px){
  .head-action{ margin-bottom: 40px; }   /* совпадает с .section-head{margin-bottom:40px} */
}

.mat-grid{ display: grid; gap: 16px; list-style: none; }
.mat-grid > li{ display: grid; }        /* карточки ряда одной высоты */
@media (min-width: 768px){ .mat-grid{ grid-template-columns: repeat(2, 1fr); gap: 20px; } }
@media (min-width: 1024px){ .mat-grid{ grid-template-columns: repeat(3, 1fr); } }

/* Карточка — колонка: строка «обложка + шапка», под ней тело, растянутое
   на всю оставшуюся высоту. Блок действий внутри тела прижат к низу
   (`.mat-actions{margin-top:auto}`), поэтому карточки ряда одной высоты,
   а кнопки стоят на одной горизонтали (SPEC-preview §10). */
.mat-card{
  position: relative;
  display: grid; gap: var(--sp-3);
  grid-template-columns: 96px minmax(0, 1fr);
  grid-template-rows: auto 1fr;
  grid-template-areas: "cover head" "body body";
  background: #FFFFFF; border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm); padding: var(--sp-4);
}
@media (min-width: 400px){ .mat-card{ grid-template-columns: 112px minmax(0, 1fr); } }
@media (min-width: 640px){
  .mat-card{
    grid-template-columns: clamp(104px, 30%, 132px) minmax(0, 1fr);
    grid-template-areas: "cover head" "cover body";
    padding: var(--sp-5);
  }
}

.mat-card > .mat-cover{ grid-area: cover; align-self: start; }
.mat-head{ grid-area: head; min-width: 0; }
.mat-foot{ grid-area: body; min-width: 0; display: flex; flex-direction: column; }

/* Заголовок ровно в две строки: иначе длинное название толкает карточку
   вниз и ряд разъезжается по высоте (SPEC-preview §10). */
.mat-title{
  margin-top: var(--sp-2); font-size: 1.0625rem; line-height: 1.3;
  display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden;
  overflow-wrap: anywhere;
}
.mat-head > .mat-title:first-child{ margin-top: 0; }
@media (min-width: 1024px){ .mat-title{ font-size: var(--fs-h3); } }

/* Единственная ссылка карточки: её ::after растянут на всю площадь.
   Кнопка «Посмотреть материал» и теги ссылками не являются — один
   таб-стоп на карточку, доступное имя = название материала. */
.mat-stretch{ color: inherit; text-decoration: none; }
.mat-stretch::after{ content: ""; position: absolute; inset: 0; border-radius: inherit; z-index: 1; }
.mat-stretch:focus-visible{ outline: none; }
.mat-stretch:focus-visible::after{ outline: 3px solid var(--focus-color); outline-offset: 2px; }

.mat-meta{
  margin-top: var(--sp-2); display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  max-width: none;                               /* иначе глобальное p{max-width:62ch} сузит */
  font-size: var(--fs-caption); color: var(--c-muted);   /* 5.33:1 на белом */
}
.mat-meta .icon{ width: 15px; height: 15px; stroke: var(--c-muted); }

/* Ровно три строки на всех ширинах: одинаковая высота текстового блока —
   половина обещанной симметрии. Четвёртая строка на десктопе снова
   рассинхронизировала бы карточки ряда. */
.mat-desc{
  max-width: none; color: var(--c-muted); font-size: 15px; line-height: 1.55;
  display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden;
}

.mat-card .tag-list{ margin-top: var(--sp-4); gap: var(--sp-2); }
.mat-dot{ color: var(--line-strong); }   /* разделитель мета-строки, декоративный */

/* --- Блок действий карточки (SPEC-preview §3, §10) -----------------------
   margin-top:auto прижимает блок к низу карточки, padding-top даёт ≥20px
   воздуха до чипов — ровно то, чего клиенту не хватало («отступов между
   бейджами и кнопкой нет вообще»).

   Раскладка одна на всех ширинах и предсказуема по высоте:
     строка 1 — «Скачать PDF» (или плашка «Скоро добавим файл») + глаз;
     строка 2 — «Посмотреть материал» во всю ширину.
   z-index поднимает блок над растянутым ::after заголовка, иначе клик
   по «Скачать» уходил бы на ссылку карточки. */
.mat-actions{
  position: relative; z-index: 2;
  margin-top: auto; padding-top: var(--sp-5);
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--sp-3); align-items: center;
}
.mat-actions > .mat-cta{ grid-column: 1 / -1; }

/* Кнопка «Посмотреть материал» — не контрол, а надпись: она дублирует
   заголовок карточки. Клики сквозь неё уходят на растянутую ссылку. */
.mat-cta{ pointer-events: none; width: 100%; }
.mat-dl{ width: 100%; }

/* Файла пока нет: спокойная плашка вместо кнопки, той же высоты 44px —
   карточки ряда не разъезжаются из-за того, что у соседа файл загружен. */
.mat-soon{
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 44px; padding: 0 12px; max-width: none;
  background: var(--s-cream); border: 1px dashed var(--line-strong);
  border-radius: var(--r-sm);
  /* line-height 1.2, а не наследуемая 1.6: иначе плашка выше кнопки на 3px
     и первая строка блока действий у соседних карточек не совпадает. */
  font-weight: 600; font-size: 14px; line-height: 1.2;
  color: var(--c-muted-strong);  /* 5.92:1 на креме */
}
.mat-soon .icon{ width: 17px; height: 17px; stroke: var(--c-muted-strong); flex-shrink: 0; }

/* «Быстрый просмотр»: иконка-глаз, цель касания 44×44 (WCAG 2.5.8). */
.mat-quick{
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; flex-shrink: 0;
  border: 1.5px solid var(--c-muted); border-radius: var(--r-sm);
  background: #FFFFFF; color: var(--c-ink); text-decoration: none;
  transition: border-color var(--dur-micro) var(--ease-standard),
              background-color var(--dur-micro) var(--ease-standard);
}
.mat-quick .icon{ width: 20px; height: 20px; stroke: var(--c-ink); }
@media (hover: hover) and (pointer: fine){
  .mat-quick:hover{ border-color: var(--c-ink); background: var(--s-cream); }
}

@media (hover: hover) and (pointer: fine){
  .mat-card:hover .mat-title{
    text-decoration: underline; text-underline-offset: 3px;
    text-decoration-thickness: 2px; text-decoration-color: var(--c-brand);
  }
  .mat-card:hover .mat-cta{ border-color: var(--c-ink); }
  .mat-card:hover .mat-cta::before{ opacity: 1; }
  .mat-card:hover .mat-cta .icon{ transform: translateX(3px); }
  .mat-card:hover .mat-cover-img{ transform: scale(1.04); }
}
.mat-cover-img{ transition: transform var(--dur-panel) var(--ease-standard); }

/* Возврат к букве макета одним классом на .mat-grid:
   обложка сверху во всю ширину, бейдж — в правом верхнем углу. */
@media (max-width: 639.98px){
  .mat-grid--stacked .mat-card{
    grid-template-columns: 1fr;
    grid-template-areas: "cover" "head" "body";
  }
  .mat-grid--stacked .mat-card > .mat-cover{ width: 100%; }
  .mat-grid--stacked .mat-badge{
    position: absolute; top: 24px; right: 24px; z-index: 2;
    background: rgba(255, 255, 255, .94); border: 1px solid var(--line);
    box-shadow: var(--shadow-sm);
  }
}


/* ============================================================
   5. ЗАГЛУШКА ОБЛОЖКИ (SPEC §11.4)
   Обложек-файлов на старте нет — материалы рендерятся заглушкой:
   ноль запросов, ноль байт трафика, ноль CLS.
   ============================================================ */
.mat-cover{
  aspect-ratio: 3 / 4; border-radius: var(--r-md); overflow: hidden;
  background: var(--s-cream-deep);
}
.mat-cover-img{ width: 100%; height: 100%; object-fit: cover; display: block; }
/* Варианты размера для реальной обложки — рифма к .cover-ph--mini / --lg */
.mat-cover--mini{ border-radius: var(--r-sm); }
.mat-cover--lg{ border-radius: var(--r-lg); }
/* Обложки нет — на её месте первая страница пособия (SPEC-preview §4).
   Страница A4 (1:1.41) в боксе 3:4 подрезается снизу: выравниваем по верху,
   чтобы в кадр гарантированно попали заголовок и начало первого задания. */
.mat-cover--page{ background: #FFFFFF; border: 1px solid var(--line); }
.mat-cover--page .mat-cover-img{ object-position: 50% 0; }

.cover-ph{
  position: relative; display: flex; align-items: flex-end;
  /* Единицы контейнера для названия: см. .cover-ph-title */
  container-type: inline-size;
  padding: 10px 10px 10px 13px;
  border: 1px solid var(--acc-line);
  background:
    /* мягкий блик сверху-справа — «глянец обложки» */
    radial-gradient(120% 80% at 85% 0%, rgba(255, 255, 255, .75), transparent 60%),
    linear-gradient(155deg, var(--acc-soft) 0%, var(--acc-tint) 100%);
}
/* Корешок книги слева — рифма к .spine из hero-арта лендинга */
.cover-ph-spine{
  position: absolute; left: 0; top: 0; bottom: 0; width: 6px;
  background: var(--acc-deep);
}
/* Две «линии текста» — намёк на страницу, чисто декоративно */
.cover-ph::before{
  content: ""; position: absolute; left: 16px; right: 14px; top: 16px; height: 2px;
  border-radius: 1px; background: var(--acc-deep); opacity: .28;
  box-shadow: 0 8px 0 var(--acc-deep);
}
/* Название внутри заглушки набирается в долях ширины самой обложки (cqi),
   поэтому одинаково смотрится и на 96px в карточке, и на 300px на детальной,
   а главное — влезает целиком: line-clamp здесь нет, и «Conditionals Step by
   Step» больше не обрывается посреди слова. overflow-wrap:anywhere страхует
   от единственного слишком длинного слова. Расчёт: самое длинное название
   в базе — 27 символов, при 96px обложке это 11px кегль и 5 строк из 7 доступных. */
.cover-ph-title{
  position: relative; z-index: 1;
  font-family: var(--font-serif); font-weight: 600;
  font-size: clamp(10px, 11.5cqi, 22px); line-height: 1.22;
  color: var(--c-ink);                      /* 13.4–14.0:1 на середине градиента */
  text-wrap: balance; text-shadow: 0 1px 0 rgba(255, 255, 255, .5);
  overflow-wrap: anywhere; hyphens: auto;
}

/* Компактный вариант для ленты серии: название идёт подписью ПОД обложкой.
   Внутри его нет — на 70px серифный текст 11px нечитаем и дублировал бы подпись. */
.cover-ph--mini{ padding: 8px 8px 8px 12px; border-radius: var(--r-sm); }
.cover-ph--mini .cover-ph-spine{ width: 4px; }
.cover-ph--mini::before{ left: 12px; right: 10px; top: 10px; box-shadow: 0 6px 0 var(--acc-deep); }

/* Крупный вариант для детальной страницы */
.cover-ph--lg{ padding: 16px 16px 16px 24px; border-radius: var(--r-lg); }
.cover-ph--lg .cover-ph-spine{ width: 9px; }


/* ============================================================
   6. «СЕРИИ МАТЕРИАЛОВ»: КАРТОЧКА, ЛЕНТА, ТОЧКИ (SPEC §7.3)
   ============================================================ */
/* minmax(0, 1fr) вместо неявной колонки: у `.series-strip` min-content равен
   ширине всех четырёх обложек (≈548px), и неявная колонка грида раздувалась
   до этой величины — карточка серии становилась шире вьюпорта и обрезалась
   `body{overflow-x: clip}` вместе с четвёртой обложкой и ссылкой «Смотреть все».
   min-width:0 на карточке и на ленте закрепляет результат: лента получает
   ширину карточки и скроллится внутри себя, а точки-пагинация наконец
   выполняют условие scrollWidth > clientWidth и появляются. */
.series-grid{ display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
@media (min-width: 1024px){ .series-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; } }
@media (min-width: 1280px){ .series-grid{ grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.series-card{
  min-width: 0;                    /* см. пояснение у .series-grid */
  background: var(--acc-soft); border: 1px solid var(--acc-line);
  border-radius: var(--r-xl); padding: var(--series-pad);
  display: flex; flex-direction: column; gap: 14px;
  /* Браузер не считает лейаут и не красит карточку вне вьюпорта.
     На .mat-card этого делать нельзя: они на первом экране и участвуют
     в [data-reveal] — пропущенный рендер сломал бы IntersectionObserver. */
  content-visibility: auto; contain-intrinsic-size: auto 340px;
  transition: background-color var(--dur-base) var(--ease-standard);
}
@media (min-width: 1024px){ .series-card{ --series-pad: 24px; } }
@media (hover: hover) and (pointer: fine){
  /* Подъёма нет: карточка серии — контейнер, а не ссылка. Меняем только фон. */
  .series-card:hover{ background: var(--acc-hover); }
}

.series-head{
  display: grid; align-items: center; gap: 6px 12px;
  grid-template-columns: auto 1fr;
  grid-template-areas: "icon title" "link link";
}
@media (min-width: 480px){
  .series-head{ grid-template-columns: auto 1fr auto; grid-template-areas: "icon title link"; }
}
.series-head .tile{ grid-area: icon; width: 44px; height: 44px; }
.series-head .tile .icon{ width: 24px; height: 24px; }
.series-title{ grid-area: title; font-size: 1.125rem; line-height: 1.25; min-width: 0; }

.series-link{
  grid-area: link; justify-self: start;
  display: inline-flex; align-items: center; gap: 6px; min-height: 44px;
  font-weight: 700; font-size: 14px; color: var(--acc-deep);   /* 4.95–6.27:1 на своём фоне */
  text-decoration: none; white-space: nowrap;
}
@media (min-width: 480px){ .series-link{ justify-self: end; } }
.series-link .icon{
  width: 16px; height: 16px; stroke: currentColor;
  transition: transform 200ms var(--ease-standard);
}
@media (hover: hover) and (pointer: fine){
  .series-link:hover{ text-decoration: underline; text-underline-offset: 4px; text-decoration-thickness: 2px; }
  .series-link:hover .icon{ transform: translateX(4px); }
}

.series-sub{
  max-width: none; color: var(--c-muted-strong); font-size: 14.5px; line-height: 1.5;
  display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden;   /* «подзаголовок в 2 строки» */
}

.series-strip{
  min-width: 0;                    /* см. пояснение у .series-grid */
  display: grid; grid-auto-flow: column; grid-auto-columns: var(--strip-w);
  gap: var(--strip-gap); list-style: none;
  overflow-x: auto;
  overscroll-behavior-inline: contain;   /* не уводит страницу и не триггерит back-swipe */
  scroll-snap-type: x proximity;         /* не mandatory: mandatory дерётся с пальцем в Safari */
  scroll-padding-inline: var(--series-pad);
  /* лента вылезает на всю ширину карточки — обложки доезжают до края,
     видно, что «есть ещё» */
  margin-inline: calc(var(--series-pad) * -1);
  padding-inline: var(--series-pad);
  /* место фокус-кольцу (3px + offset 2px), иначе overflow его срежет */
  padding-block: 6px; margin-block: -6px;
  scrollbar-width: none;
}
.series-strip::-webkit-scrollbar{ display: none; }

/* На мышке полосу прокрутки оставляем — это аффорданс */
@media (pointer: fine){
  .series-strip{ scrollbar-width: thin; scrollbar-color: var(--acc-line) transparent; }
  .series-strip::-webkit-scrollbar{ display: block; height: 6px; }
  .series-strip::-webkit-scrollbar-thumb{ background: var(--acc-line); border-radius: 3px; }
}
@media (prefers-reduced-motion: no-preference){ .series-strip{ scroll-behavior: smooth; } }

.strip-item{ scroll-snap-align: start; min-width: 0; }
.strip-link{ display: grid; gap: 8px; text-decoration: none; border-radius: var(--r-sm); }
.strip-link:focus-visible{ outline: 3px solid var(--focus-color); outline-offset: 2px; }
.strip-link .mat-cover{
  transition: transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard);
}
/* Подпись не обрезаем вовсе: при --strip-w 132px самое длинное название
   («True Detective: Transcripts») укладывается в три строки. Обложки в ленте
   выровнены по верху, поэтому разная высота подписей ничего не ломает. */
.strip-caption{
  font-size: 12px; line-height: 1.35; font-weight: 600;
  color: var(--c-muted-strong);            /* 5.39–5.56:1 на пастели */
  overflow-wrap: anywhere;
}
@media (hover: hover) and (pointer: fine){
  .strip-link:hover .mat-cover{ transform: translateY(-3px); box-shadow: var(--shadow-md); }
  .strip-link:hover .strip-caption{ color: var(--c-ink); }
}
.strip-link:active .mat-cover{ transform: none; }

/* С 600px все четыре обложки помещаются: лента становится обычной строкой,
   скролл и точки не нужны (арифметика — design-materials.md §7.4). */
@media (min-width: 600px){
  .series-strip{
    grid-auto-columns: minmax(0, 1fr);
    overflow-x: visible; margin-inline: 0; padding-inline: 0;
    scroll-snap-type: none;
  }
  .strip-dots{ display: none; }
}

/* Точки-пагинация. Без JS — декоративные <i> внутри aria-hidden-контейнера,
   с JS модуль заменяет их на <button> (static/js/materials.js). */
.strip-dots{ display: flex; justify-content: center; gap: 2px; margin-top: 2px; }
.strip-dots[hidden]{ display: none; }
.strip-dots i,
.strip-dots button{
  display: block; position: relative;
  width: 44px; height: 44px;              /* цель касания */
  border: 0; background: none; padding: 0; border-radius: 50%;
}
.strip-dots i::after,
.strip-dots button::after{
  content: ""; position: absolute; left: 50%; top: 50%; translate: -50% -50%;
  width: 8px; height: 8px; border-radius: var(--r-pill);
  background: var(--c-muted);             /* 4.50–4.64:1 на пастели, порог 1.4.11 — 3:1 */
  transition: width var(--dur-micro) var(--ease-standard),
              background-color var(--dur-micro) var(--ease-standard);
}
/* Активная точка: сплошной тон серии + удлинение до 20px —
   состояние передаётся не только цветом. */
.strip-dots i:first-child::after,
.strip-dots button[aria-current="true"]::after{
  width: 20px; border-radius: 4px; background: var(--acc-deep);
}
@media (hover: hover) and (pointer: fine){
  .strip-dots button:hover::after{ background: var(--acc-deep); }
}
.strip-dots button:focus-visible{
  outline: 3px solid var(--focus-color); outline-offset: -4px; border-radius: 12px;
}
.strip-dots button:active::after{ scale: .9; }

/* Первый экран страницы серии: тон серии вместо кремового градиента. */
.series-hero{ background: var(--acc-soft); }
.series-hero .tile{ margin-bottom: 14px; }
.series-hero .mat-hero-lead{ color: var(--c-muted-strong); }   /* на пастели только strong */
.series-count{
  margin-top: 10px; font-size: var(--fs-caption); color: var(--c-muted-strong); max-width: none;
}


/* ============================================================
   7. КАТАЛОГ С ФИЛЬТРАМИ (SPEC §6)
   ============================================================ */
.mat-filters{ margin-bottom: 24px; }
.filter-row{
  display: flex; gap: 8px; list-style: none;
  overflow-x: auto; overscroll-behavior-inline: contain;
  scroll-snap-type: x proximity;
  /* лента фильтров доезжает до края экрана — видно, что она листается */
  margin-inline: calc(var(--gutter) * -1); padding-inline: var(--gutter);
  padding-block: 6px; margin-block: -6px;    /* место фокус-кольцу */
  scrollbar-width: none;
}
.filter-row::-webkit-scrollbar{ display: none; }
.filter-row > li{ scroll-snap-align: start; }
.tag--link{
  display: inline-flex; align-items: center; min-height: 44px;
  padding-inline: 14px; text-decoration: none; white-space: nowrap;
}
.tag--link[aria-current="page"]{
  background: var(--c-brand); border-color: var(--c-brand); color: var(--c-ink);  /* 9.38:1 */
  font-weight: 700;
}
@media (hover: hover) and (pointer: fine){
  .tag--link:hover{ background: var(--s-cream-deep); border-color: var(--line-strong); }
}
@media (min-width: 768px){
  .filter-row{ flex-wrap: wrap; overflow: visible; margin-inline: 0; padding-inline: 0; }
  .tag--link{ min-height: 36px; }
}
.filter-count{ margin-top: 14px; font-size: var(--fs-caption); color: var(--c-muted-strong); max-width: none; }
/* Применённый фильтр по тегу: сам тег и ссылка «Сбросить» — иначе человек
   не понимает, почему в каталоге три карточки вместо двадцати семи. */
.filter-active{
  margin-top: 14px; max-width: none;
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3);
  font-size: var(--fs-caption);
}
.filter-active a{
  min-height: 44px; display: inline-flex; align-items: center;
  color: var(--c-ink-2); text-decoration: underline; text-underline-offset: 3px;
}

/* Пустая выдача каталога */
.mat-empty{
  padding: 32px 20px; text-align: center;
  background: var(--s-cream); border-radius: var(--r-lg);
}
.mat-empty p{ margin-inline: auto; color: var(--c-muted-strong); }
.mat-empty .btn{ margin-top: 20px; }

/* Постраничная навигация каталога — на случай, если вид пагинирует выдачу. */
.pager{
  margin-top: 28px; display: flex; flex-wrap: wrap; align-items: center;
  justify-content: center; gap: 12px 16px;
}
.pager-status{ font-size: var(--fs-caption); color: var(--c-muted-strong); max-width: none; }

/* Возврат в общий каталог со страницы серии */
.series-back{ margin-top: 28px; }
@media (max-width: 479.98px){ .series-back .btn{ width: 100%; } }
.series-hero .breadcrumbs{ margin-bottom: 14px; }


/* ============================================================
   8. ПОЛОСА ПРЕИМУЩЕСТВ (SPEC §7.4)
   ============================================================ */
.benefits-grid{ display: grid; gap: 24px; list-style: none; }
.benefits-grid:empty{ display: none; }   /* плашек с placement=benefits может не быть */
@media (min-width: 768px){ .benefits-grid{ grid-template-columns: repeat(2, 1fr); gap: 28px 32px; } }
@media (min-width: 1024px){ .benefits-grid{ grid-template-columns: repeat(4, 1fr); gap: 32px; } }

.benefit{ content-visibility: auto; contain-intrinsic-size: auto 180px; }
/* Приём взят у .review-map: кремовая плитка на кремовой панели невидима. */
.benefit .tile{ background: #FFFFFF; }
.benefit h3{
  margin-top: 14px; font-family: var(--font-sans); font-weight: 700;
  font-size: 17px; line-height: 1.35;
}
.benefit p{ margin-top: 8px; color: var(--c-muted-strong); font-size: 15px; }  /* 5.92:1 на креме */


/* ============================================================
   9. НИЖНИЙ БЛОК И ФОРМА ПОДПИСКИ (SPEC §7.5)
   ============================================================ */
.subscribe-band{ display: grid; gap: 28px; }
@media (min-width: 900px){
  .subscribe-band{ grid-template-columns: 1fr 1fr; gap: 48px; align-items: start; }
  /* Разделитель — тот же приём, что у .about-item лендинга */
  .sub-form-wrap{ border-left: 1px solid var(--line-strong); padding-left: 48px; }
}

.sub-note{ display: grid; grid-template-columns: auto 1fr; gap: 14px; align-items: start; }
.sub-note .tile{ background: #FFFFFF; }
.sub-note p{ font-size: var(--fs-lead); line-height: 1.55; color: var(--c-ink-2); }

/* Якорь #subscribe: после редиректа страница не должна упереться в шапку. */
.sub-form-wrap{ scroll-margin-top: calc(var(--header-h) + 12px); }

.sub-title{ font-size: 1.25rem; line-height: 1.35; }
@media (min-width: 1024px){ .sub-title{ font-size: 1.5rem; } }
/* Сама форма подписки (.sub-form, .field-row, .sub-submit) и общие компоненты
   полей (.field-input, .field-error, .field-hint, .consent, .hp-field,
   .form-success) живут в static/css/forms.css — один код на лендинг,
   детальную материала и эту полосу. Здесь остаётся только окружение блока:
   раскладка полосы, заметка слева и заголовок. Страницы раздела подключают
   forms.css в {% block extra_css %}. */

/* ============================================================
   10. ДЕТАЛЬНАЯ СТРАНИЦА МАТЕРИАЛА И КРОШКИ (SPEC §7.6)
   ============================================================ */
.mat-detail{ padding-block: 20px 0; }

.breadcrumbs ol{
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; list-style: none;
  font-size: var(--fs-caption); color: var(--c-muted-strong);
}
.breadcrumbs li + li::before{ content: "/"; margin-right: 8px; color: var(--line-strong); }
.breadcrumbs a{ color: inherit; text-decoration: none; padding-block: 10px; }  /* цель ≥44px по высоте */
@media (hover: hover) and (pointer: fine){
  .breadcrumbs a:hover{ text-decoration: underline; text-underline-offset: 3px; }
}
.breadcrumbs [aria-current="page"]{ color: var(--c-ink); font-weight: 600; }
/* На 375px крошки не переносятся в три строки, а прокручиваются. */
@media (max-width: 479.98px){
  .breadcrumbs ol{
    flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-inline: contain; scrollbar-width: none;
    margin-inline: calc(var(--gutter) * -1); padding-inline: var(--gutter);
  }
  .breadcrumbs ol::-webkit-scrollbar{ display: none; }
  .breadcrumbs li{ white-space: nowrap; }
}

.detail-grid{ margin-top: 16px; display: grid; gap: 24px; }
@media (min-width: 900px){
  .detail-grid{ grid-template-columns: 300px minmax(0, 1fr); gap: 48px; align-items: start; }
  .detail-media{ position: sticky; top: calc(var(--header-h) + 20px); }
}
/* На мобильном обложка НЕ во всю ширину: 3:4 на 335px = 447px пустоты до заголовка. */
.detail-media > .mat-cover{ width: min(180px, 48%); box-shadow: var(--shadow-md); }
@media (min-width: 900px){ .detail-media > .mat-cover{ width: 100%; } }

.detail-title{ margin-top: 10px; font-size: var(--fs-h1); line-height: var(--lh-display); }
.detail-sub{ margin-top: 10px; font-size: var(--fs-lead); color: var(--c-muted); }
.detail-main .tag-list{ margin-top: 16px; }

.detail-meta{
  margin-top: 20px; display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px 20px;
  background: var(--s-cream); border-radius: var(--r-md); padding: 16px 18px;
}
@media (min-width: 600px){ .detail-meta{ grid-template-columns: repeat(4, 1fr); } }
.detail-meta dt{ font-size: var(--fs-caption); color: var(--c-muted-strong); }
.detail-meta dd{ margin-top: 2px; font-weight: 700; font-size: 15px; }
.detail-meta dd a{ color: var(--acc-deep); text-underline-offset: 3px; }

/* Скачивание — первое действие страницы: на мобильном кнопки в столбик
   во всю ширину, с 480px в строку (SPEC-preview §3, §10). */
.detail-actions{ margin-top: 22px; display: grid; gap: var(--sp-3); }
@media (min-width: 480px){
  .detail-actions{ grid-auto-flow: column; justify-content: start; align-items: center; }
}
.detail-dl{ font-size: 1.0625rem; }
@media (min-width: 480px){ .detail-dl{ height: 56px; padding-inline: 26px; } }
/* Мета рядом с кнопкой: «PDF · 2,4 МБ · 42 страницы» */
.detail-dl-meta{
  margin-top: 10px; max-width: none;
  font-size: var(--fs-caption); color: var(--c-muted-strong);   /* 5.92:1 */
}
.mat-soon--lg{ min-height: 52px; padding: 0 20px; font-size: 15px; }

.detail-text{ margin-top: 24px; }
.detail-text p{ font-size: var(--fs-lead); line-height: 1.7; color: var(--c-ink-2); max-width: var(--measure); }
.detail-text p + p{ margin-top: 14px; }

.detail-inside{ margin-top: 28px; }
.detail-inside h2{ font-size: var(--fs-h3); }
.inside-list{ margin-top: 14px; display: grid; gap: 10px; list-style: none; }
/* .plan-item и .icon-check переиспользуются с лендинга без единой новой строки */
.inside-list .plan-item{ align-items: flex-start; font-size: 15px; color: var(--c-ink-2); }
.inside-list .plan-item .icon-check{ margin-top: 2px; }

/* Подводка над формой записи на пробное занятие (SPEC-preview §5).
   margin-bottom обязателен: без него абзац прилипал к первой подписи формы. */
.form-lead{ margin-top: 6px; margin-bottom: var(--sp-5); color: var(--c-muted-strong); }


/* ============================================================
   11. «ЗАГЛЯНИТЕ ВНУТРЬ»: ЛЕНТА СТРАНИЦ И ЛАЙТБОКС (SPEC-preview §4)

   Без JS работает всё, кроме лайтбокса: лента прокручивается пальцем
   и колесом, каждая миниатюра — обычная ссылка на полноразмерную страницу,
   а <dialog> без атрибута open просто не показывается.
   ============================================================ */
.preview-band{
  margin-top: 28px; padding: var(--sp-5);
  background: var(--s-cream); border-radius: var(--r-lg);
  scroll-margin-top: calc(var(--header-h) + 12px);   /* якорь #preview из каталога */
}
.preview-title{ font-size: var(--fs-h3); }

.pv-strip{
  margin-top: 14px; display: grid; grid-auto-flow: column;
  grid-auto-columns: 132px; gap: var(--sp-3); list-style: none;
  overflow-x: auto; overscroll-behavior-inline: contain;
  scroll-snap-type: x proximity;
  /* лента доезжает до края панели — видно, что страниц больше */
  margin-inline: calc(var(--sp-5) * -1); padding-inline: var(--sp-5);
  padding-block: 6px; margin-block: 14px -6px;       /* место фокус-кольцу */
  scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent;
}
@media (min-width: 600px){ .pv-strip{ grid-auto-columns: 168px; } }
@media (prefers-reduced-motion: no-preference){ .pv-strip{ scroll-behavior: smooth; } }

.pv-item{ scroll-snap-align: start; min-width: 0; }
.pv-thumb{
  position: relative; display: block; border-radius: var(--r-sm); overflow: hidden;
  background: #FFFFFF; border: 1px solid var(--line); box-shadow: var(--shadow-sm);
  transition: transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard);
}
.pv-thumb img{ display: block; width: 100%; height: auto; }
.pv-thumb:focus-visible{ outline: 3px solid var(--focus-color); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine){
  .pv-thumb:hover{ transform: translateY(-3px); box-shadow: var(--shadow-md); }
}
/* Номер страницы — подсказка «это 3-я, всего их больше» */
.pv-num{
  position: absolute; right: 6px; bottom: 6px;
  min-width: 22px; height: 22px; padding: 0 6px; border-radius: var(--r-pill);
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(28, 28, 28, .78); color: #FFFFFF;
  font-weight: 700; font-size: 12px; line-height: 1;
}

.preview-foot{
  margin-top: 16px; display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--sp-3) var(--sp-5);
}
.preview-note{ max-width: none; font-size: var(--fs-caption); color: var(--c-muted-strong); }

/* --- Лайтбокс -------------------------------------------------------- */
.pv-dialog{
  /* margin:auto центрирует модалку. Явно, потому что глобальный сброс
     `*{margin:0}` перебивает браузерное правило для <dialog>. */
  margin: auto;
  width: min(96vw, 900px); max-width: none; max-height: 92dvh;
  padding: 0; border: 0; border-radius: var(--r-lg);
  background: #FFFFFF; box-shadow: var(--shadow-lg); color: var(--c-ink);
  overflow: hidden;
}
.pv-dialog::backdrop{ background: rgba(28, 28, 28, .62); }
/* Фон не прокручивается, пока открыт лайтбокс. Через :has(), а не классом
   из JS: одно правило, нечего рассинхронизировать. Браузер без :has()
   просто оставит фон прокручиваемым — лайтбокс от этого не ломается. */
html:has(.pv-dialog[open]){ overflow: hidden; }
.pv-box{ display: grid; grid-template-rows: auto minmax(0, 1fr) auto; max-height: 92dvh; }

.pv-bar{
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--line); background: #FFFFFF;
}
.pv-bar--foot{
  border-bottom: 0; border-top: 1px solid var(--line);
  flex-wrap: wrap; justify-content: space-between;
}
.pv-name{
  max-width: none; min-width: 0; flex: 1;
  font-weight: 700; font-size: 15px; line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pv-close,
.pv-arrow{
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; flex-shrink: 0; padding: 0;
  background: #FFFFFF; border: 1.5px solid var(--c-muted); border-radius: var(--r-sm);
  cursor: pointer;
}
.pv-close .icon, .pv-arrow .icon{ width: 20px; height: 20px; stroke: var(--c-ink); }
.pv-arrow[disabled]{ opacity: .45; cursor: default; }
@media (hover: hover) and (pointer: fine){
  .pv-close:hover, .pv-arrow:not([disabled]):hover{ border-color: var(--c-ink); background: var(--s-cream); }
}

.pv-viewport{
  display: grid; grid-auto-flow: column; grid-auto-columns: 100%;
  overflow-x: auto; overscroll-behavior-inline: contain;
  scroll-snap-type: x mandatory;
  background: var(--s-cream-deep);
  scrollbar-width: none;
}
.pv-viewport::-webkit-scrollbar{ display: none; }
.pv-viewport:focus-visible{ outline: 3px solid var(--focus-color); outline-offset: -3px; }
@media (prefers-reduced-motion: no-preference){ .pv-viewport{ scroll-behavior: smooth; } }

.pv-slide{
  margin: 0; scroll-snap-align: center; min-width: 0;
  display: flex; align-items: center; justify-content: center;
  padding: var(--sp-4);
}
.pv-slide img{
  display: block; max-width: 100%; max-height: calc(92dvh - 190px);
  width: auto; height: auto;
  border-radius: var(--r-sm); box-shadow: var(--shadow-md); background: #FFFFFF;
}

.pv-nav{ display: flex; align-items: center; gap: var(--sp-3); }
.pv-counter{
  max-width: none; min-width: 62px; text-align: center;
  font-weight: 700; font-size: 14px; color: var(--c-ink-2);
}
.pv-dl{ margin-left: auto; }


/* ============================================================
   12. МОУШН-ДОПОЛНЕНИЯ
   Новых @keyframes не вводим: bar-grow объявлен в site.css внутри
   такого же @media, поэтому доступен здесь без дублирования.
   ============================================================ */
@media (prefers-reduced-motion: no-preference){
  /* Жёлтая черта тезиса на первом экране страницы материалов.
     Класс .hero-thesis стоит на элементе первым, поэтому геометрия
     и анимация уже наследуются; правило ниже — страховка на случай,
     если тезис останется только с .mat-hero-thesis. */
  html.js .mat-hero-thesis .accent-bar{ transform: scaleY(0); transform-origin: top; }
  html.js .mat-hero-thesis.is-revealed .accent-bar{ animation: bar-grow 320ms var(--ease-out) 160ms both; }
}
