/* ========================================
   NEWS ARTICLE PAGE STYLES
   ======================================== */

/* === PROGRESS BAR === */
.news-progress-bar {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 3px;
    background: transparent;
    z-index: 1100;
}

.news-progress-fill {
    height: 100%;
    width: 0%;
    background: var(--accent);
    transition: width 0.1s linear;
}

/* === HERO === */
.news-hero {
    position: relative;
    overflow: hidden;
}

/* У ОБЛОЖКИ СТАТЬИ НЕТ ПОЛА — ТОЛЬКО ПОТОЛОК (08.10).
   ЗАМЕР высоты обложки против высоты окна ДО правки: 923/900 · 864/768 ·
   900/1024 · 880/390 · 422/844 — на телефоне лёжа шапка была вдвое выше
   экрана, а у ПУСТОЙ статьи 721 при теле 196, то есть в 3.7 раза выше самой
   новости; таких статей 27 из 31.
   У РАЗДЕЛОВ РОВНО НАОБОРОТ: там стоит ПОЛ (--oblozhka-pol), потому что
   обложка несёт название раздела и цифры и схлопнуться ей нельзя. Здесь
   товар — текст новости, и обложка обязана уместиться вместе с заголовком в
   один экран. Высота идёт ПО СОДЕРЖИМОМУ (отношение кадра), сверху её
   держит потолок долями окна.
   420 — прежнее число этого места, оно осталось верхней границей на широком
   экране; доля окна забирает узкие и низкие виды. */
.news-statya-hero {
    --oblozhka-potolok: min(46vh, 420px);
}

/* НА НИЗКОМ ГОРИЗОНТАЛЬНОМ ЭКРАНЕ ПОТОЛОК НИЖЕ. ЗАМЕР после правки на
   844 × 390: верх заголовка 401 при экране 390 — обложка 46vh = 179
   съедала его вместе с шапкой и полосой возврата, и обещание «заголовок
   виден без прокрутки» не выполнялось ровно на одном виде из пяти.
   Делим ВЫСОТОЙ И ПОВОРОТОМ, а не новой шириной: ширины в медиа только
   640 и 992. Тот же приём, которым у обложек разделов снят пол
   (css/tokens.css:619). */
@media (max-height: 500px) and (orientation: landscape) {
    .news-statya-hero { --oblozhka-potolok: 30vh; }
}

.news-hero-bg {
    position: relative;
    overflow: hidden;
}

/* Потолок режет только то, что в него не влезло, и режет ПО ЦЕНТРУ
   (object-fit), а не по нижнему краю, как это делала коробка с фиксом. */
.news-statya-hero .news-hero-bg img {
    display: block;
    width: 100%;
    height: auto;
    max-height: var(--oblozhka-potolok);
    object-fit: cover;
    transform: scale(1.1);
    will-change: transform;
}

.news-hero-overlay {
    position: absolute;
    inset: 0;
    /* Лёгкое затемнение у нижнего края, чтобы афиша переходила в фон страницы */
    background: linear-gradient(to top, var(--bg-primary) 0%, transparent 35%);
}

/* Шапка режет афишу по ширине: вертикальные постеры теряют даты и состав.
   Кнопка открывает исходник целиком — сама по себе такая возможность
   незаметна, поэтому она подписана, а не спрятана в клик по картинке. */
.news-hero-zoom {
    position: absolute;
    top: var(--space-4);
    right: var(--space-4);
    z-index: 2;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    /* ВЫСОТУ ДЕРЖИТ СТУПЕНЬ, А НЕ ПОЛЯ — описание Button 17:82 говорит это
       прямым текстом. ЗАМЕР 08.10 давал 146 x 33 при цели нажатия 44. */
    height: 44px;
    padding: 0 var(--space-4);
    border: var(--bw-hair) solid var(--alpha-white-20);
    border-radius: 999px;
    background: rgba(10, 10, 10, 0.55);
    backdrop-filter: blur(8px);
    color: var(--neutral-white);
    font-size: var(--fs-xs);
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s;
}

.news-hero-zoom svg { width: 15px; height: 15px; }

.news-hero-zoom:hover {
    border-color: var(--accent);
    background: rgba(10, 10, 10, 0.75);
}

@media (max-width: 640px) {
    /* На узком экране подпись съедает место, значка достаточно. Цель
       нажатия остаётся 44 x 44 — ступень, а не остаток полей. */
    .news-hero-zoom { top: var(--space-3); right: var(--space-3); width: 44px; padding: 0; justify-content: center; }
    .news-hero-zoom span { display: none; }
}

/* МЕРА СТРОКИ — 80ch, решение 05.10. ЗАМЕР колонки ДО правки: 837 · 855 ·
   734 · 807 · 358, то есть на 1024 колонка была ШИРЕ десктопной, а 855 при
   кегле 16 — около 107 знаков в строке. Колонка объявлена ОДИН раз и здесь:
   заголовок обложки, тело статьи, теги, оценка и похожие статьи стоят на
   одной мере, иначе они разъезжаются по левому краю.
   «Похожие статьи» на эту меру НЕ встают: это витрина, и её ширину задаёт
   ширина карточки, а не мера строки (правило 07.10). */
.news-article-page {
    /* Потолок видео — тот же, что у фотографии в тексте: один потолок на оба,
       иначе «такой же размер» держится на честном слове. Ширина и высота
       карточки инстаграма — замером на живом встраивании. */
    --video-potolok: min(64vh, 520px);
    --video-shirina-ig: 400px;
    --video-vysota-ig: 560px;
    /* МЕРА СЧИТАЕТСЯ ПО КОРОБКЕ СОДЕРЖИМОГО. Первый заход поставил
       min(80ch, 100%) на коробку С ПОЛЯМИ, и ЗАМЕР тут же показал прежнюю
       беду в новом виде: 744 · 762 · 700 · 326 · 770 — на 1024 колонка
       СНОВА оказалась шире десктопной, потому что --gutter сам сжимается
       вместе с окном и отъедал от меры разное число пикселей.
       Поля прибавлены к пределу, и тогда содержимое ровно 80ch на всех
       широких видах, а на узких его забирает 100%. */
    --statya-kolonka: min(calc(80ch + 2 * var(--gutter)), 100%);
}

.news-hero-content {
    position: relative;
    z-index: 1;
    max-width: var(--statya-kolonka);
    width: 100%;
    margin: 0 auto;
    /* Небольшой отступ снизу: дальше идёт ещё отступ самой статьи, и вместе
       они давали пустое поле в четверть экрана между датой и первым абзацем */
    padding: var(--space-md) var(--gutter) var(--space-md);
}

/* Ссылка «Назад к новостям» переехала в общую полосу .kslt-back-wrap */

/* ЗНАЧОК — ЭТО Badge 27:53, А НЕ СВОЙ ПРЯМОУГОЛЬНИК. ЗАМЕР 08.10 давал
   113 x 26, кегль 12 вес 600, поля 4/14; описание компонента требует высоту
   24, поля 0/8 и 11 Medium. Совпали только разрядка и капс. */
.news-category-badge {
    display: inline-flex;
    align-items: center;
    height: 24px;
    padding: 0 var(--space-2);
    border-radius: var(--radius-full);
    font-size: var(--fs-2xs);
    font-weight: var(--fw-medium);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: var(--space-3);
}

.news-category-results {
    background: var(--alpha-lime-12);
    color: var(--accent);
}

.news-category-interview {
    background: rgba(99, 102, 241, 0.15);
    color: #818cf8;
}

.news-category-announcement {
    background: rgba(251, 191, 36, 0.15);
    color: #fbbf24;
}

/* Мировые новости. Своего цвета у них не было вовсе, и метка брала цвет
   ссылки — синий, чужой сайту. Заметно это стало, только когда категорию
   начали наполнять. */
.news-category-world {
    background: rgba(56, 189, 248, 0.14);
    color: #38bdf8;
}

/* ---- Своя обложка ----
   Мировые новости приходят без картинки, и место закрывает снимок из нашего
   набора (см. js/news-covers.js). Чтобы кадр читался как наш, а не как
   случайная картинка из интернета, кладём поверх знак КСЛТ и лёгкую тень
   под него. Тень только по низу: гасить снимок целиком нельзя — обложка
   перестаёт цеплять взгляд, это проверено на образце. */
/* ЗНАК И ЗАТЕМНЕНИЕ ЖИВУТ ВНУТРИ СВОЕГО КАДРА, А НЕ НА ВСЮ СТРАНИЦУ.
   ЗАМЕР 08.10, вечер: `.news-own-cover::after` при карточке 327 × 245
   получал коробку 1512 × 861 — РАЗМЕР ОКНА. Потому что `inset: 0` считается
   от ближайшего ПОЗИЦИОНИРОВАННОГО предка, а у `.news-related-img` его не
   было: отсчёт уезжал к корню страницы. `overflow: hidden` тут не спасает —
   он не режет то, чья коробка висит снаружи него.
   Отсюда и то, что видно глазами: тёмная полоса поперёк всей страницы и
   знак КСЛТ в правом нижнем углу ЭКРАНА, поверх текста статьи.
   Лечится одной строкой: носитель знака сам становится точкой отсчёта.
   ЭЛЕМЕНТ, ВИСЯЩИЙ СНАРУЖИ СВОЕЙ КОРОБКИ, ОТСЧИТЫВАЕТСЯ ОТ ЧУЖОЙ. */
.news-own-cover {
    position: relative;
}

.news-own-cover::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(to top, var(--alpha-black-50), rgba(0, 0, 0, 0) 45%);
    pointer-events: none;
}

/* ЗНАК — ЭЛЕМЕНТ, А НЕ ПСЕВДО. Псевдо `::before` у карточки витрины ЗАНЯТО:
   им рисуется сама афиша (`css/style.css:6217`), и знак его перебивал бы —
   карточка осталась бы без картинки. Поэтому знак один на три места: шапка
   статьи, карточка «похожей» и карточка витрины. ОДНО ПОНЯТИЕ — ОДНО
   ПОВЕДЕНИЕ: до 08.10 на витрине списка знака не было вовсе, хотя кадр там
   такая же наша подмена. */
/* ВЕС ПРАВИЛА РЕШАЕТ, А НЕ НАМЕРЕНИЕ. Знак — картинка внутри `.tc-image`, а
   у витрины есть своё правило `.tc-image img` (style.css:6228) весом (0,1,1):
   оно перебивало и размер, и положение — ЗАМЕР дал знак 314 × 150 в потоке
   вместо 42 × 14 в углу. Удвоение класса уравнивает вес, как в раскладке
   витрины 08.10. */
.news-znak.news-znak {
    position: absolute;
    right: 10px;
    bottom: 8px;
    width: 42px;
    height: 14px;
    opacity: 0.75;
    z-index: 2;
    pointer-events: none;
}

/* В шапке новости всё крупнее: обложка во весь экран, знак под стать */
.news-hero-bg .news-znak.news-znak {
    right: 20px;
    bottom: 16px;
    width: 78px;
    height: 26px;
}

/* СТУПЕНИ, А НЕ ПЛАВАЮЩИЙ КЕГЛЬ. Стояло clamp(1.8rem, 4.5vw, 3rem), и
   ЗАМЕР давал 48 · 46 · 38 · 26 · 21 — четыре числа из пяти мимо шкалы
   11·12·14·16·18·21·26·32·40. Крутилка --fs-hero даёт 40 · 40 · 32 · 26 · 32
   — ту же лестницу, что у шести приведённых разделов. Вес и межстрочный
   тоже крутилками: 800 и 1.1 числом были вторым определением того же. */
.news-statya-hero h1 {
    font-size: var(--fs-hero);
    font-weight: var(--fw-extrabold);
    color: var(--text-primary);
    line-height: var(--lh-tight);
    margin-bottom: var(--space-2);
}

/* ПАРА «ЗАГОЛОВОК + ПОДЗАГОЛОВОК» ЕДЕТ ОДНОЙ ГРАНИЦЕЙ: подзаголовок стоит
   на своей крутилке того же семейства (21 · 21 · 18 · 16 · 18), и ступень
   между ним и заголовком сохраняется на каждом виде. */
.news-subtitle {
    font-size: var(--fs-hero-sub);
    color: var(--text-secondary);
    line-height: var(--lh-snug);
    margin-bottom: var(--space-md);
}

.news-hero-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-md);
}

.news-meta-item {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    color: var(--text-muted);
    font-size: var(--fs-sm);
}

.news-meta-item svg {
    opacity: 0.7;
    flex-shrink: 0;
}

/* === ARTICLE BODY === */
.news-article-body {
    max-width: var(--statya-kolonka);
    margin: 0 auto;
    padding: var(--section-y-sm) var(--gutter) var(--section-y);
}

/* Paragraph */
.news-paragraph {
    font-size: var(--fs-md);
    line-height: var(--lh-relaxed);
    color: var(--text-secondary);
    margin-bottom: var(--space-md);
}

/* Heading */
.news-heading {
    color: var(--text-primary);
    margin-top: var(--space-lg);
    margin-bottom: var(--space-sm);
}

h2.news-heading {
    font-size: var(--fs-xl);
    font-weight: var(--fw-bold);
}

h3.news-heading {
    font-size: var(--fs-lg);
    font-weight: var(--fw-semibold);
}

/* Image / Figure */
.news-figure {
    margin: var(--space-lg) 0;
    border-radius: var(--radius-lg);
    overflow: hidden;
}

.news-figure img {
    width: 100%;
    height: auto;
    display: block;
}

.news-figure figcaption {
    padding: var(--space-sm);
    text-align: center;
    font-size: var(--fs-sm);
    color: var(--text-muted);
    font-style: italic;
    background: var(--bg-card);
}

/* НИЖНЕЙ ГАЛЕРЕИ БОЛЬШЕ НЕТ. Правила `.news-gallery*` снесены 09.10
   вместе с блоком в js/news.js: разметку, на которую они стояли, не
   выдаёт больше никто. МЁРТВЫМ КОД НАЗВАН ПОСЛЕ ПРОВЕРКИ — поиск по
   проекту не нашёл ни одного места, где эти классы ставятся. Фото в
   тексте показывает лента, её правила — `.news-carousel*`. */

/* Quote */
.news-quote {
    margin: var(--space-lg) 0;
    padding: var(--space-md) var(--space-lg);
    border-left: var(--bw-heavy) solid var(--accent);
    background: var(--bg-card);
    border-radius: 0 var(--radius-md) var(--radius-md) 0;
}

.news-quote-body {
    position: relative;
}

.news-quote-icon {
    color: var(--accent);
    opacity: 0.3;
    margin-bottom: var(--space-2);
}

.news-quote-body p {
    font-size: var(--fs-base);
    line-height: var(--lh-relaxed);
    color: var(--text-secondary);
    font-style: italic;
}

.news-quote-author {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-sm);
}

.news-quote-author img {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    object-fit: cover;
}

.news-quote-author span {
    font-size: var(--fs-sm);
    font-weight: var(--fw-semibold);
    color: var(--text-primary);
}

/* Stats */
.news-stats {
    display: flex;
    gap: var(--space-sm);
    margin: var(--space-lg) 0;
    padding: var(--space-md);
    background: var(--bg-card);
    border: var(--bw-hair) solid var(--border-subtle);
    border-radius: var(--radius-lg);
    flex-wrap: wrap;
}

.news-stat-item {
    flex: 1;
    min-width: 80px;
    text-align: center;
    padding: var(--space-xs) 0;
}

.news-stat-value {
    display: block;
    font-size: var(--fs-xl);
    font-weight: var(--fw-extrabold);
    color: var(--accent);
    line-height: var(--lh-tight);
}

.news-stat-label {
    display: block;
    font-size: var(--fs-xs);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-top: var(--space-1);
}

/* ДВА ОПРЕДЕЛЕНИЯ НА ОДНО ИМЯ — БЕДА РОДИЛАСЬ РОВНО НА ШВЕ: класс
   .news-list носила И эта вставка в тексте статьи, И секция страницы
   списка (ниже, витрина). Секции доставались отступы вставки, вставке —
   отступы секции. Вставка переименована: имя .news-list осталось у витрины,
   она старше и шире. */
.news-tekst-spisok {
    margin: var(--space-md) 0;
    padding-left: var(--space-md);
}

.news-tekst-spisok li {
    font-size: var(--fs-base);
    line-height: var(--lh-normal);
    color: var(--text-secondary);
    margin-bottom: var(--space-2);
    position: relative;
}

.news-tekst-spisok li::marker {
    color: var(--accent);
}

/* === POLL === */
.news-poll {
    margin: var(--space-lg) 0;
    padding: var(--space-lg);
    background: var(--bg-card);
    border: var(--bw-hair) solid var(--border-subtle);
    border-radius: var(--radius-lg);
}

.news-poll-question {
    font-size: var(--fs-md);
    font-weight: var(--fw-bold);
    color: var(--text-primary);
    margin-bottom: var(--space-md);
}

.news-poll-options {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.news-poll-option {
    display: block;
    width: 100%;
    padding: var(--space-3) var(--space-4);
    background: var(--bg-elevated);
    border: var(--bw-hair) solid var(--border-subtle);
    border-radius: var(--radius-md);
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: var(--fs-base);
    font-weight: var(--fw-medium);
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s;
    text-align: left;
}

.news-poll-option:hover {
    border-color: var(--accent);
    background: var(--alpha-lime-06);
}

/* Poll Results */
.news-poll-results {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.news-poll-result-item {
    margin-bottom: 0;
}

.news-poll-result-item.voted .news-poll-result-label {
    color: var(--accent);
    font-weight: var(--fw-semibold);
}

.news-poll-result-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: var(--space-1);
}

.news-poll-result-label {
    font-size: var(--fs-sm);
    color: var(--text-secondary);
}

.news-poll-result-pct {
    font-size: var(--fs-sm);
    font-weight: var(--fw-bold);
    color: var(--text-primary);
}

.news-poll-result-bar {
    height: 8px;
    background: var(--bg-elevated);
    border-radius: var(--radius-full);
    overflow: hidden;
}

.news-poll-result-fill {
    height: 100%;
    background: var(--accent);
    border-radius: var(--radius-full);
    transition: width 0.6s ease;
}

.news-poll-result-item.voted .news-poll-result-fill {
    background: var(--accent);
}

.news-poll-total {
    font-size: var(--fs-xs);
    color: var(--text-muted);
    text-align: center;
    margin-top: var(--space-2);
}

/* === TAGS === */
.news-tags {
    max-width: var(--statya-kolonka);
    margin: 0 auto;
    padding: 0 var(--gutter) var(--section-y-sm);
}

.news-section-title {
    font-size: var(--fs-md);
    font-weight: var(--fw-bold);
    color: var(--text-primary);
    margin-bottom: var(--space-md);
}

.news-tags-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

/* Высота — ступень кнопок xs 28, а не остаток полей 6 + 6 */
.news-tag {
    display: inline-flex;
    align-items: center;
    height: 28px;
    padding: 0 var(--space-4);
    background: var(--bg-card);
    border: var(--bw-hair) solid var(--border-subtle);
    border-radius: var(--radius-full);
    color: var(--text-secondary);
    font-size: var(--fs-sm);
    font-weight: var(--fw-medium);
    text-decoration: none;
    transition: border-color 0.2s, color 0.2s;
}

.news-tag:hover {
    border-color: var(--accent);
    color: var(--accent);
}

/* === REACTIONS === */
.news-reactions {
    max-width: var(--statya-kolonka);
    margin: 0 auto;
    padding: 0 var(--gutter) var(--section-y-sm);
    text-align: center;
}

.news-reactions .news-section-title {
    text-align: center;
}

.news-reactions-list {
    display: flex;
    justify-content: center;
    gap: var(--space-4);
}

/* ЕДИНСТВЕННЫЙ НАСТОЯЩИЙ ПРОВАЛ КОНТРАСТА НА СТРАНИЦЕ: у <button> свой
   цвет текста от браузера — buttontext, то есть чёрный, и ЗАМЕР 08.10 дал
   rgb(0,0,0) на #111111 = 1.11 при норме 4.5. Цвет берётся из токена, и
   тогда всё, что внутри кнопки не красится само, читается.
   Высоту даёт ступень, а не поля. `transition: all` убран: он анимировал и
   то, что анимировать нельзя. */
.news-reaction-btn {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    min-height: 52px;
    padding: var(--space-3) var(--space-4);
    color: var(--text-secondary);
    background: var(--bg-card);
    border: var(--bw-hair) solid var(--border-subtle);
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s, transform 0.2s, box-shadow 0.2s;
}

.news-reaction-btn:hover {
    border-color: var(--border-light);
    transform: translateY(-2px);
}

.news-reaction-btn.active {
    border-color: var(--accent);
    background: var(--alpha-lime-12);
    box-shadow: 0 0 10px var(--accent-subtle);
    cursor: default;
}
.news-reaction-btn.active:hover {
    transform: none;
}
.news-reaction-check {
    font-size: var(--fs-2xs);
    color: var(--accent);
    font-weight: var(--fw-bold);
    position: absolute;
    top: var(--space-1);
    right: var(--space-1);
}

.news-reaction-emoji {
    font-size: var(--fs-xl);
    line-height: 1;
}

.news-reaction-count {
    font-size: var(--fs-sm);
    font-weight: var(--fw-semibold);
    line-height: var(--lh-none);
    color: var(--text-secondary);
}

.news-reaction-btn.active .news-reaction-count {
    color: var(--accent);
}

/* Bounce animation */
@keyframes news-bounce {
    0% { transform: scale(1); }
    30% { transform: scale(1.3); }
    50% { transform: scale(0.9); }
    70% { transform: scale(1.1); }
    100% { transform: scale(1); }
}

.news-reaction-bounce .news-reaction-emoji {
    animation: news-bounce 0.4s ease;
}

/* === GUEST MODAL === */
.news-guest-overlay {
    position: fixed;
    inset: 0;
    z-index: 9999;
    background: var(--alpha-black-60);
    backdrop-filter: blur(8px);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.25s ease;
    padding: var(--space-5);
}
.news-guest-overlay.visible { opacity: 1; }
.news-guest-modal {
    background: var(--bg-elevated);
    border: var(--bw-hair) solid var(--border-subtle);
    border-radius: 16px;
    padding: var(--space-8) var(--space-6);
    max-width: 380px;
    width: 100%;
    text-align: center;
    position: relative;
    transform: translateY(20px) scale(0.95);
    transition: transform 0.25s ease;
}
.news-guest-overlay.visible .news-guest-modal {
    transform: translateY(0) scale(1);
}
.news-guest-modal-close {
    position: absolute;
    top: 12px;
    right: 16px;
    background: none;
    border: none;
    color: var(--text-secondary);
    font-size: var(--fs-xl);
    cursor: pointer;
    line-height: 1;
}
.news-guest-modal-close:hover { color: var(--neutral-white); }
.news-guest-modal-icon {
    font-size: var(--fs-3xl);
    margin-bottom: 12px;
}
.news-guest-modal-title {
    font-size: var(--fs-lg);
    font-weight: var(--fw-bold);
    color: var(--neutral-white);
    margin-bottom: var(--space-2);
}
.news-guest-modal-text {
    font-size: var(--fs-sm);
    color: var(--text-secondary);
    margin-bottom: var(--space-5);
    line-height: var(--lh-normal);
}
/* Высота — ступень кнопок md 44, а не поля 12 + 12 */
.news-guest-modal-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 44px;
    padding: 0 var(--space-8);
    background: var(--accent);
    color: var(--neutral-black);
    font-weight: var(--fw-bold);
    border-radius: var(--radius-sm);
    text-decoration: none;
    transition: opacity 0.2s;
}
.news-guest-modal-btn:hover { opacity: 0.85; }

/* Страница статьи — одна сплошная поверхность. Раньше тело текста было
   прозрачным на чёрном, а соседние секции на оттенок светлее, и вокруг статьи
   шли заметные полосы. Фон держит страница, выделяются только карточки. */
/* В общих стилях сайта есть `section:not(.hero)` с фоном на оттенок светлее
   и полосой сверху. На странице статьи это давало заметные ступени: шапка,
   «Оцените статью», «Похожие новости» и спонсоры — каждая своим прямоугольником.
   Селектор ниже тяжелее общего, поэтому вся страница идёт одним полотном. */
body.news-article-page main > section,
body.news-article-page .section-sponsors-compact {
    background: transparent;
    border-top: none;
}

/* Общее правило секций добавляет по 70 точек сверху и снизу. Шапке статьи
   они ни к чему: под ней сразу идёт текст со своим отступом. */
body.news-article-page 

/* Отступы блоков внизу страницы складывались попарно: 80 снизу у одного плюс
   70–80 сверху у следующего давали по полтора экрана пустоты между реакциями,
   похожими статьями и спонсорами. */
body.news-article-page .news-article-body {
    padding-bottom: var(--space-lg);
}

body.news-article-page .section-sponsors-compact {
    padding-top: var(--space-lg);
}

/* === RELATED ARTICLES === */
.news-related {
    max-width: var(--container-narrow);
    margin: 0 auto;
    padding: var(--section-y-sm) var(--gutter);
    border-top: var(--bw-hair) solid var(--border-subtle);
}

.news-related .news-section-title {
    text-align: center;
    margin-bottom: var(--space-lg);
}

.news-related-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-md);
}

.news-related-card {
    background: var(--bg-card);
    border: var(--bw-hair) solid var(--border-subtle);
    border-radius: var(--radius-lg);
    overflow: hidden;
    text-decoration: none;
    transition: border-color 0.3s, transform 0.3s, box-shadow 0.3s;
}

.news-related-card:hover {
    border-color: var(--border-light);
    transform: translateY(-4px);
    box-shadow: var(--shadow-lg);
}

/* 180 и 200 на узком виде — два числа мимо шкалы на одно понятие. Короб
   держит ОТНОШЕНИЕ, и тогда он один на все виды. */
.news-related-img {
    aspect-ratio: 4 / 3;
    overflow: hidden;
}

.news-related-img img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.3s;
}

.news-related-card:hover .news-related-img img {
    transform: scale(1.05);
}

.news-related-info {
    padding: var(--space-md);
}

/* Высота значка — ступень Badge 27:53, поля 0/8 */
/* ОДНО ПОНЯТИЕ — ОДИН ВЕС: значок категории в шапке статьи и значок на
   карточке похожей статьи стояли 500 и 600. Badge 27:53 говорит 11 Medium. */
.news-related-category {
    display: inline-flex;
    align-items: center;
    height: 24px;
    padding: 0 var(--space-2);
    border-radius: var(--radius-full);
    font-size: var(--fs-2xs);
    font-weight: var(--fw-medium);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: var(--space-2);
}

.news-related-info h3 {
    font-size: var(--fs-base);
    font-weight: var(--fw-bold);
    color: var(--text-primary);
    line-height: var(--lh-snug);
    margin-bottom: var(--space-2);
}

.news-related-date {
    font-size: var(--fs-xs);
    color: var(--text-muted);
}

/* === NEWS LIST — HERO === */
/* Шапка раздела «Новости» — как на странице турниров: снимок во всю ширину,
   затемнение и текст поверх него, а не под ним */
/* Высота — та же, что у «Турниров» и остальных разделов: один сайт,
   шапки должны читаться одинаково */
.news-hero-list {
    position: relative;
    display: flex;
    align-items: center;
    /* ПОЛ И ВОЗДУХ ОБЛОЖКИ — ОБЩИЕ КРУТИЛКИ РАЗДЕЛА (решение Кости 04.10,
       воздух приведён 08.10). Стояло 460 при 360 у приведённых разделов,
       своё 275 на 768 и свой отступ у содержимого — воздуха выходило два.
       Теперь воздух объявлен ОДИН раз и здесь же, как у «Поиска игрока»
       (css/partners.css:20). */
    padding: var(--oblozhka-vozduh) var(--pad-x) var(--oblozhka-vozduh-niz);
    min-height: var(--oblozhka-pol);
    overflow: hidden;
}

.news-hero-list .news-hero-bg {
    position: absolute;
    inset: 0;
    height: 100%;
}

.news-hero-list .news-hero-bg img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.news-hero-overlay-list {
    /* Ровное затемнение: текст лежит по центру снимка, а не у нижнего края */
    background: linear-gradient(to top, var(--bg-primary) 0%, var(--alpha-black-60) 45%, var(--alpha-black-60) 100%);
}

.news-hero-content-list {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: var(--container-narrow);
    margin: 0 auto;
    /* ВОЗДУХ ОБЛОЖКИ ОБЪЯВЛЕН ОДИН РАЗ — у самой обложки. Свой отступ
       содержимого складывался с её собственным: замер 08.10 дал 32 + 24
       сверху на десктопе и 24 + 0/16 на телефоне. Ноль ставим явно: базовый
       класс .news-hero-content несёт свой отступ для ОТДЕЛЬНОЙ новости. */
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-lg);
}

.news-list-header {
    text-align: center;
}

.news-list-header h1 {
    /* СТУПЕНЬ, А НЕ ПЛАВАЮЩИЙ КЕГЛЬ: замер 07.10 дал 21 на телефоне при
       ступени 26 у приведённых разделов. Крутилки те же, что у «Услуг»,
       «Кортов», «Тренеров» и «Поиска игрока». */
    font-size: var(--fs-hero);
    font-weight: var(--fw-extrabold);
    line-height: var(--lh-tight);
    color: var(--text-primary);
    margin-bottom: 0;
    max-width: 760px;
    margin-left: auto;
    margin-right: auto;
}

/* === NEWS LIST — FILTERS === */
/* ВИТРИНА СПИСКА — ПО ШИРИНЕ ОБЩЕГО ЯЩИКА: сетка на 12 колонок считает
   ширину от него, и узкий ящик давал 506 вместо 676 (замер 08.10) */
.news-list-page {
    max-width: var(--container-max);
    width: 100%;
    margin: 0 auto;
    padding: var(--space-6) var(--gutter) var(--section-y-sm);
}

/* === PAGINATION === */
/* ПОЛОСА СТРАНИЦ ИДЁТ ПО ШИРИНЕ СВОЕЙ ВИТРИНЫ — правило 07.10. Своих
   кнопок у страницы больше нет: пятая копия (.news-page-btn и соседи)
   снесена, рисует общий компонент polosa-stranic.js */
.news-pagination {
    --polosa-shirina: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    gap: var(--space-2);
    max-width: var(--container-max);
    margin: 0 auto;
}

.news-pagination:empty { padding: 0; }

/* === NOT FOUND === */
.news-not-found {
    display: none;
    padding: var(--section-y) var(--pad-x);
    text-align: center;
}

.news-not-found-icon {
    font-size: var(--fs-4xl);
    margin-bottom: var(--space-md);
}

.news-not-found h1 {
    font-size: var(--fs-2xl);
    font-weight: var(--fw-extrabold);
    color: var(--text-primary);
    margin-bottom: var(--space-sm);
}

.news-not-found p {
    font-size: var(--fs-md);
    color: var(--text-secondary);
    margin-bottom: var(--space-lg);
    max-width: 400px;
}

.news-not-found-btn {
    display: inline-flex;
    align-items: center;
    height: 44px;
    padding: 0 var(--space-8);
    background: var(--accent);
    color: var(--neutral-black);
    font-weight: var(--fw-bold);
    font-size: var(--fs-base);
    border-radius: var(--radius-full);
    text-decoration: none;
    transition: background 0.2s, transform 0.2s;
}

.news-not-found-btn:hover {
    background: var(--accent-hover);
    transform: translateY(-1px);
}

/* === SCROLL ANIMATIONS === */
.news-animate {
    opacity: 0;
    transform: translateY(20px);
    transition: opacity 0.5s ease, transform 0.5s ease;
}

.news-animate.news-visible {
    opacity: 1;
    transform: translateY(0);
}

/* === RESPONSIVE === */
@media (max-width: 992px) {
    .news-related-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* ГРАНИЦ ДВЕ — 640 И 992, ТРЕТЬЕЙ НЕ ЗАВОДИТСЯ.
   Было три чужих: 768, 480 и 375. Они пришли сюда до правила о сетке и
   уцелели 08.10 только потому, что страница новости была отдельным куском.
   Что куда уехало:
   · доля высоты окна (50vh) и три кегля заголовка — СНЯТЫ ВОВСЕ: высоту
     держит потолок обложки, кегль — крутилка --fs-hero;
   · подзаголовок — снят: его держит --fs-hero-sub;
   · .news-article-container — снят как мёртвый: класса нет ни в одном html
     и ни в одном js, проверено поиском по продукту;
   · кегль абзаца 14 на 375 — снят: тело статьи читают подряд, и ниже 16
     Safari на iOS зумит страницу;
   · остальное сведено в 640. */
@media (max-width: 640px) {
    .news-hero-content {
        padding: 0 var(--pad-x) var(--section-y-sm);
    }

    .news-article-body {
        padding: var(--section-y-sm) var(--pad-x);
    }

    .news-tags {
        padding: 0 var(--pad-x) var(--space-md);
    }

    .news-reactions {
        padding: 0 var(--pad-x) var(--section-y-sm);
    }

    .news-related {
        padding: var(--section-y-sm) var(--pad-x);
    }

    .news-hero-meta {
        flex-direction: column;
        gap: var(--space-xs);
    }

    .news-related-grid {
        grid-template-columns: 1fr;
    }

    /* Движения обложки на телефоне нет: прокрутка там и есть движение */
    .news-statya-hero .news-hero-bg img {
        transform: none !important;
    }

    .news-stats {
        gap: var(--space-2);
    }

    .news-stat-item {
        min-width: var(--space-16);
    }

    .news-stat-value {
        font-size: var(--fs-md);
    }

    h2.news-heading {
        font-size: var(--fs-lg);
    }

    .news-quote {
        padding: var(--space-sm) var(--space-md);
    }

    .news-reactions-list {
        gap: var(--space-3);
    }

    .news-reaction-btn {
        padding: var(--space-3);
    }

    .news-reaction-emoji {
        font-size: var(--fs-lg);
    }

    .news-not-found h1 {
        font-size: var(--fs-xl);
    }

    .news-not-found-btn {
        width: 100%;
        justify-content: center;
        /* 320 — ширина из Search field 50:67, а не подгонка под телефон */
        max-width: 320px;
    }
}

/* ---- Текст новости из редактора ---- */
/* Текст статьи — основным цветом и без полупрозрачности. Раньше тело
   проявлялось по прокрутке, и на длинной статье оставалось тусклым.
   Сглаживание возвращаем обычное: antialiased на тёмном фоне делает светлые
   буквы тоньше, и белый текст читается как серый. Кегль чуть крупнее —
   статью читают подряд, а не проглядывают. */
.news-html,
.news-html p,
.news-html li,
.news-html figure {
    color: var(--text-primary, var(--neutral-white));
    opacity: 1;
    -webkit-font-smoothing: auto;
    -moz-osx-font-smoothing: auto;
}

/* МЕЖСТРОЧНЫЙ ИЗ ЛЕСТНИЦЫ: 1.8, 1.75 и 1.7 — три числа на один уровень, и
   ни одного на ступени 1 · 1.1 · 1.3 · 1.5 · 1.65. Абзац — relaxed 1.65,
   строка списка — normal 1.5: список читают глазом вниз, а не подряд. */
.news-html {
    font-size: var(--fs-base);
    line-height: var(--lh-relaxed);
}

.news-html p { margin: 0 0 var(--space-sm); line-height: var(--lh-relaxed); }
.news-html h3 { margin: var(--space-md) 0 var(--space-xs); font-size: var(--fs-lg); }
.news-html ul,
.news-html ol { margin: 0 0 var(--space-sm); padding-left: var(--space-6); }
.news-html li { margin-bottom: var(--space-2); line-height: var(--lh-normal); }
.news-html a { color: var(--accent); }

/* Фото и видео, вставленные внутрь текста */
.news-html figure { margin: var(--space-md) 0; }
/* ВИДЕО ЖИВЁТ ПО ПРАВИЛАМ ФОТОГРАФИИ — ОДИН ПОТОЛОК НА ОБА.
   Было: `width: 100%` и отношение 16/9 намертво, то есть всякое видео шло
   во всю колонку и всегда ландшафтом. Фото при этом вписывается целиком и
   остаётся портретом. ОДНО ПОНЯТИЕ, ДВА ПОВЕДЕНИЯ.
   Отношение задаёт ИСТОЧНИК в момент вставки (js/admin/core/editor.js), а
   не угадывает страница: ютуб и вимео 16/9, инстаграм — карточка. */
.news-html figure iframe {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    max-height: var(--video-potolok);
    border: 0;
    border-radius: var(--radius-md);
    margin: 0 auto;
}

/* ВСТРАИВАНИЕ ИНСТАГРАМА — КАРТОЧКА ПОСТА, А НЕ ВИДЕО. ЗАМЕР живой ссылки
   08.10 (reel/DeGhCRWI39u, без входа): высота 2098 при ширине 1456 — шапка
   аккаунта, кадр, «111 likes», поле комментария, кнопка «View profile». И
   она белая: на нашем фоне это белый прямоугольник в полстраницы.
   РЕШЕНИЕ КОСТИ «а»: своего скрипта инстаграма на страницы не ставим, а
   коробке даём форму кадра и обрезаем лишнее намеренно — нам нужен кадр, а
   не чужой интерфейс. Числа коробки сняты замером на живом встраивании. */
/* ЧУЖОЙ ИНТЕРФЕЙС РЕЖЕТСЯ НАМЕРЕННО — слово Кости 08.10: «надо будет
   обрезать, чтобы не показывало нижнюю часть и верхнюю часть тоже».
   Сверху инстаграм рисует полосу с именем аккаунта и кнопкой «View
   profile», снизу — лайки, поле комментария и пустой хвост. Нам нужен
   КАДР, а не чужой интерфейс. Коробке даём форму ролика (9:16), а сам
   кадр внутри сдвигаем вверх на высоту шапки и растим на шапку плюс низ —
   лишнее уезжает за край.
   ЧИСЛА СНЯТЫ ЗАМЕРОМ живого встраивания при ширине 400: шапка 54,
   низ 240 (полоса значков, «178 likes», поле комментария и хвост). */
:root,
.news-article-page {
    --ig-shapka: 54px;
    --ig-niz: 240px;
    /* ФОРМА САМОГО РОЛИКА — ЕДИНСТВЕННОЕ ЧИСЛО, КОТОРОЕ ЗАМЕРИТЬ НЕЧЕМ:
       кадр чужой, внутрь не заглянуть. ПОСЧИТАНО по снимку живого
       встраивания: при ширине 313 видео занимало 375 — отношение 0.835,
       то есть инстаграмовские 4:5 с небольшим запасом. Ставим 4/5 и режем
       по нему; это крутилка, и подкручивается она одним числом. */
    --ig-kadr: 4 / 5;
}

.news-html figure:has(> .news-video-ig) {
    overflow: hidden;
    border-radius: var(--radius-md);
    max-width: var(--video-shirina-ig);
    margin-inline: auto;
}

.news-html figure:has(> .news-video-ig) {
    position: relative;
    /* Видно ровно ролик, без чужой шапки и без лайков */
    aspect-ratio: var(--ig-kadr);
}

.news-html figure .news-video-ig {
    position: absolute;
    left: 0;
    top: calc(-1 * var(--ig-shapka));
    width: 100%;
    /* ОТНОШЕНИЕ, А НЕ ЧИСЛО. Стояла высота 560 при ширине 400 — инстаграм
       рисует вертикальный ролик 9:16 плюс свою шапку с именем аккаунта и
       низ, и в 560 это не влезало: внутри кадра появлялась СВОЯ полоса
       прокрутки (замер 08.10 — Костя увидел её глазами). 400 × 820:
       видео 9:16 даёт 711, шапка 54, низ 55. От ширины теперь считается
       высота, поэтому на телефоне кадр сжимается целиком, а не режется. */
    /* Высота — видимая часть плюс то, что срезаем сверху и снизу */
    height: calc(100% + var(--ig-shapka) + var(--ig-niz));
    aspect-ratio: auto;
    max-height: none;
    border-radius: 0;
}

/* ---- Видео в общей ленте со снимками ---- */
/* СЛОВО КОСТИ 08.10: «можно будет все видео тоже в одну карусель к фото, а
   не отдельно». Короб видео стоит В ТОЙ ЖЕ сцене, что и крупный снимок, и
   переключение меняет видимость, а не разметку: иначе каждый шаг ленты
   перезагружал бы чужой проигрыватель. */
.news-carousel-video {
    position: absolute;
    inset: 0;
    overflow: hidden;
    background: var(--bg-elevated);
    display: flex;
    align-items: center;
    justify-content: center;
}

/* РОЛИК ВПИСЫВАЕТСЯ В КОРОБКУ, А НЕ РАСТЯГИВАЕТ ЕЁ. Отношение коробки
   снято с ПЕРВОГО кадра ленты (решение 08.10: иначе она прыгала бы на
   каждом листании), а в одной ленте теперь стоят и портретный снимок, и
   вертикальный ролик. Рамка берёт всю высоту и свою ширину по форме
   ролика; внутри неё кадр сдвинут вверх на чужую шапку. */
.news-carousel-ramka {
    position: relative;
    display: block;
    height: 100%;
    aspect-ratio: var(--ig-kadr);
    max-width: 100%;
    overflow: hidden;
}

.news-carousel-ramka iframe {
    position: absolute;
    left: 0;
    width: 100%;
    border: 0;
}

.news-carousel-ramka .news-video-ig {
    top: calc(-1 * var(--ig-shapka));
    height: calc(100% + var(--ig-shapka) + var(--ig-niz));
}

/* У YouTube и Vimeo своего интерфейса в кадре нет — режем только форму */
.news-carousel-ramka:has(> .news-video-yt),
.news-carousel-ramka:has(> .news-video-vm) { aspect-ratio: 16 / 9; }

.news-carousel-ramka .news-video-yt,
.news-carousel-ramka .news-video-vm {
    top: 0;
    height: 100%;
}

/* У ВИДЕО МИНИАТЮРЫ НЕТ, И ЭТО РЕШЕНИЕ: кадр инстаграма закрыт, картинку
   оттуда не достать без их ключа. Плитка со знаком «играть» честнее чужого
   снимка, выданного за кадр ролика. */
.news-carousel-thumb--video {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-elevated);
    border: var(--bw-hair) solid var(--border-subtle);
}

.news-carousel-igrat {
    font-size: var(--fs-lg);
    line-height: var(--lh-none);
    color: var(--text-secondary);
}

.news-carousel-thumb--video.active .news-carousel-igrat { color: var(--accent); }

/* ---- Просмотр фотографии поверх страницы ---- */
.news-viewer {
    position: fixed;
    inset: 0;
    z-index: 10000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-10);
    background: var(--alpha-black-85);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}

.news-viewer-img {
    max-width: 92vw;
    max-height: 88vh;
    object-fit: contain;
    border-radius: var(--radius-md);
}

.news-viewer-close,
.news-viewer-nav {
    position: absolute;
    background: var(--alpha-white-08);
    border: var(--bw-hair) solid var(--alpha-white-12);
    color: var(--neutral-white);
    cursor: pointer;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s;
}

.news-viewer-close:hover,
.news-viewer-nav:hover { background: var(--alpha-white-12); }

.news-viewer-close {
    top: var(--space-6);
    right: var(--space-6);
    width: 44px;
    height: 44px;
    font-size: var(--fs-xl);
    line-height: 1;
}

.news-viewer-nav {
    top: 50%;
    transform: translateY(-50%);
    width: 52px;
    height: 52px;
    /* 52 — ступень кнопок, цель нажатия с запасом: просмотрщик листают
       пальцем по краю экрана */
    font-size: var(--fs-2xl);
    line-height: 1;
}

.news-viewer-prev { left: var(--space-6); }
.news-viewer-next { right: var(--space-6); }

.news-viewer-count {
    position: absolute;
    bottom: var(--space-6);
    left: 0;
    right: 0;
    text-align: center;
    color: var(--alpha-white-50);
    font-size: var(--fs-sm);
}

/* Фото внутри текста: вписываем целиком, не обрезая — на снимках с турниров
   по краям стоят люди, и кадрирование отрезает их. Крупный вид — по нажатию.
   ОДНО ОПРЕДЕЛЕНИЕ: ниже стояло второе, через :has, и оно побеждало весом —
   width: 100% перебивал width: auto, и снимок всё-таки растягивался во всю
   колонку вопреки этому самому замечанию. Потолок — долей окна, 520 осталось
   верхней границей широкого экрана. */
.news-html figure img {
    display: block;
    width: auto;
    max-width: 100%;
    height: auto;
    max-height: min(64vh, 520px);
    margin: 0 auto;
    border-radius: var(--radius-md);
    cursor: zoom-in;
}

@media (max-width: 640px) {
    /* 42 было мимо шкалы И ниже цели нажатия 44. Ступень вниз — 44, а не 42:
       палец на телефоне не меньше, чем на десктопе. */
    .news-viewer { padding: var(--space-4); }
    .news-viewer-nav { width: 44px; height: 44px; font-size: var(--fs-xl); }
    .news-viewer-prev { left: var(--space-2); }
    .news-viewer-next { right: var(--space-2); }
}

/* ---- Лента снимков: больше двух фотографий ---- */
/* КОРОБКА БЕРЁТ ОТНОШЕНИЕ ПЕРВОГО КАДРА, А НЕ ЛАНДШАФТ ПО ПРИВЫЧКЕ.
   ЗАМЕР 08.10: все 15 фотографий статьи — портрет 0.75 (3:4), а коробка
   была 834 x 560; ПОСЧИТАНО из этих чисел — видно 420 x 560, по бокам 414
   пустых пикселей, ровно половина ширины. Снимки с турниров делают на
   телефон, поэтому портрет будет всегда.
   Отношение приходит крутилкой --kadr-shirina-k (ширина/высота первого
   кадра, её ставит js/news.js); 1.3333 — запасное, пока кадр не загрузился.
   Высоту держит потолок долями окна, ширина следует за отношением — и тогда
   крыльев нет вовсе, а кадр другой формы лежит на подложке по центру.
   ПОДЛОЖКА — РЕШЕНИЕ КОСТИ 08.10: ступень выше --bg-card, то есть
   --bg-elevated. #111111 на фоне #0A0A0A даёт 1.048 — поверхность есть в
   коде, а на экране её нет, и поля читались дырой, а не полями карточки. */
.news-carousel {
    --galereya-potolok: min(70vh, 560px);
    margin: var(--space-lg) 0;
}

.news-carousel-stage {
    position: relative;
    width: min(100%, calc(var(--galereya-potolok) * var(--kadr-shirina-k, 1.3333)));
    aspect-ratio: var(--kadr-shirina-k, 1.3333);
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-elevated);
    border: var(--bw-hair) solid var(--border-subtle);
    border-radius: var(--radius-lg);
    overflow: hidden;
}

/* КАДР — КНОПКА, А НЕ КАРТИНКА: окно открывается и с клавиатуры, и фокус
   после закрытия возвращается сюда, а не в тело страницы. Кнопка — только
   обёртка: своей краски, полей и рамки у неё нет. */
.news-carousel-kadr {
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    background: none;
    display: block;
    cursor: zoom-in;
}

.news-carousel-kadr:focus-visible {
    outline: var(--bw-thick) solid var(--accent);
    outline-offset: -2px;
}

.news-carousel-main {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

/* Снимок в тексте тоже нажимается с клавиатуры — у него role="button" */
.news-html figure img:focus-visible {
    outline: var(--bw-thick) solid var(--accent);
    outline-offset: 2px;
}

.news-carousel-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--fs-xl);
    line-height: 1;
    color: var(--neutral-white);
    background: var(--alpha-black-50);
    border: var(--bw-hair) solid var(--alpha-white-12);
    border-radius: 50%;
    cursor: pointer;
    transition: background 0.2s;
    z-index: 1;
}

.news-carousel-nav:hover { background: var(--alpha-black-85); }
.news-carousel-prev { left: var(--space-3); }
.news-carousel-next { right: var(--space-3); }

.news-carousel-count {
    position: absolute;
    right: var(--space-3);
    bottom: var(--space-3);
    padding: var(--space-1) var(--space-3);
    font-size: var(--fs-xs);
    color: var(--alpha-white-72);
    background: var(--alpha-black-50);
    border-radius: var(--radius-full);
}

.news-carousel-thumbs {
    display: flex;
    justify-content: center;     /* пока лента короче ширины — держим по центру */
    gap: var(--space-2);
    margin-top: var(--space-3);
    overflow-x: auto;
    padding-bottom: var(--space-1);
}

/* МИНИАТЮРА БЕРЁТ ТО ЖЕ ОТНОШЕНИЕ, ЧТО ГЛАВНЫЙ КАДР. Стояло 88 x 64 с
   object-fit: cover — у портретного кадра срезался верх и низ, то есть лица,
   и ни 88, ни 64 не стояли на шкале.
   Высота 64 объявлена здесь нарочно и одна на все виды: при портрете 3:4
   она даёт ширину 48, и обе стороны остаются не меньше цели нажатия 44.
   Прежняя ступень вниз (68 x 50) давала ширину 37 — палец мимо. */
.news-carousel-thumb {
    flex: 0 0 auto;
    height: 64px;
    aspect-ratio: var(--kadr-shirina-k, 1.3333);
    padding: 0;
    border: var(--bw-thick) solid transparent;
    border-radius: var(--radius-md);
    overflow: hidden;
    background: none;
    cursor: pointer;
    opacity: 0.55;
    transition: opacity 0.2s, border-color 0.2s;
}

.news-carousel-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.news-carousel-thumb:hover { opacity: 0.85; }
.news-carousel-thumb.active { opacity: 1; border-color: var(--accent); }

/* Стрелки остаются 44 x 44 на всех видах: описание Icon button 40:93 прямо
   говорит, что под палец годится только lg 44. Было 36 на узком виде. */

/* Карточка мировой новости уводит на сайт источника, а не на нашу страницу:
   наполнить свою нечем — чужой текст мы не перепечатываем. Стрелка
   предупреждает, что уйдём наружу: без неё переход в новую вкладку
   выглядит поломкой. */
.news-outside .tc-title::after,
.news-outside .news-related-info h3::after {
    content: ' \2197';
    color: var(--accent);
    font-weight: var(--fw-bold);
    white-space: nowrap;
}

/* === СНИМКИ В ТЕКСТЕ === */
/* === ЛЕНТА МИНИАТЮР: ЛИСТАНИЕ === */
/* Когда снимков много, лента шире экрана. Стрелки по краям листают её; если
   всё помещается, они прячутся и не мешают. */
.news-thumbs-row {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}
.news-thumbs-row .news-carousel-thumbs {
    flex: 1 1 auto;
    scroll-behavior: smooth;
    scrollbar-width: none;
}
.news-thumbs-row .news-carousel-thumbs::-webkit-scrollbar { display: none; }

.news-thumbs-nav {
    flex: 0 0 auto;
    width: 28px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--fs-md);
    line-height: 1;
    color: var(--neutral-white);
    background: var(--alpha-black-50);
    border: var(--bw-hair) solid var(--alpha-white-12);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background 0.2s, opacity 0.2s;
}
.news-thumbs-nav:hover:not(:disabled) { background: var(--alpha-black-85); }
.news-thumbs-nav:disabled { opacity: 0.3; cursor: default; }

.news-thumbs-row.news-thumbs-fits .news-thumbs-nav { display: none; }

/* ========================================================================
   СПИСОК ПОБЕДИТЕЛЕЙ

   ЗАМЕР 08.10 на «Завершение и итоги ТБШ 2026»: 58 отдельных абзацев,
   каждый короче 60 знаков, у каждого в начале значок места; тегов <ul> и
   <ol> — НОЛЬ. Строка занимала 28 в высоту при содержимом около 140 из 837
   ширины колонки, и весь список уходил вниз на 1624.
   Разметку восстанавливает js (собратьПобедителей). Здесь — раскладка: две
   колонки на широких видах, одна на 640, заголовок категории на всю ширину
   и не разорванный между колонками.
   ПОЧЕМУ ЗАГОЛОВОК НА ВСЮ ШИРИНУ: иначе он садится в низ колонки, а его
   шесть строк уезжают в следующую — читатель видит категорию без имён и
   имена без категории.
   ======================================================================== */
.news-pobediteli {
    columns: 2;
    column-gap: var(--space-6);
    margin: 0 0 var(--space-4);
}

/* ВЕС: .news-html h3 (0,1,1) перебивает одноклассовое имя, и ЗАМЕР дал
   кегль 21 от него, а вес 600 — отсюда: один уровень, два владельца.
   Родитель в селекторе уравнивает вес, и уровень объявлен здесь целиком.
   21 — тот же h3 статьи: заголовок категории и есть подзаголовок в тексте. */
.news-html .news-pobediteli-gruppa {
    column-span: all;
    font-size: var(--fs-lg);
    margin: var(--space-4) 0 var(--space-3);
    font-weight: var(--fw-semibold);
    line-height: var(--lh-snug);
    color: var(--text-primary);
}

.news-html .news-pobediteli-gruppa:first-child { margin-top: 0; }

/* ВЕС ПРАВИЛА РЕШАЕТ, А НЕ НАМЕРЕНИЕ: .news-html ul (0,1,1) перебивает
   одноклассовое имя, и `padding: 0` не доезжал — ЗАМЕР дал отступ 24 от
   общего правила тела статьи. Отступ оставляем (имена стоят под своей
   категорией), но объявляем его ЗДЕСЬ и один раз. */
.news-html .news-pobediteli-spisok {
    margin: 0;
    padding-left: var(--space-6);
    list-style: none;
}

.news-pobediteli-spisok li {
    /* Строка не разрывается между колонками: имя и место — одно целое */
    break-inside: avoid;
    margin: 0 0 var(--space-2);
    line-height: var(--lh-normal);
}

@media (max-width: 640px) {
    /* ГРАНИЦА ОДНОЙ КОЛОНКИ — 640, А НЕ 480: правило файла-сетки */
    .news-pobediteli { columns: 1; }
}

/* ========================================================================
   ВИТРИНА НОВОСТЕЙ — 07.10, ПРОБА ДО СОГЛАСИЯ
   Карточка — компонент .tc (карточка турнира лендинга) целиком: своего
   ничего не рисуем, слово Кости. Здесь только РАСКЛАДКА: крупная слева на
   два ряда, четыре боковые 2 × 2 справа, ряд из четырёх снизу.
   Ширины ПОСЧИТАНЫ и совпадают с лендингом до точки: коробка 1377, сетка
   12 колонок, зазор 24 → крупная 6 колонок = 676, мелкая 3 колонки = 326.
   ======================================================================== */
.news-grid {
    /* ШАГ СТРАНИЦЫ — КОЛОНОК × РЯДОВ: девять на широком виде (крупная на
       два ряда, четыре боковые 2 × 2, ряд из четырёх), семь на узких
       (крупная во всю ширину плюс два целых ряда). Число читает js. */
    --novostey: 9;
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: var(--space-6);
    align-items: stretch;
    max-width: var(--container-max);
    margin: 0 auto;
}

/* КЛАСС НАПИСАН ДВАЖДЫ НЕ ПО ОШИБКЕ. Витрина несёт ОБА класса: от
   .tournaments-grid она берёт типографику карточки на телефоне, а от
   .news-grid — свою раскладку. У лендинга правила расстановки записаны
   через :nth-child (css/style.css:6096-6099) и весят больше простого
   `.news-grid > .tc` — ЗАМЕР 08.10 показал результат: карточки 4-9 стояли
   span 4 вместо span 3, и вместо «2 × 2 сбоку плюс ряд из четырёх»
   выходило «одна сбоку плюс ряды по три». Удвоение уравнивает вес, а
   порядок файлов (news.css после style.css) решает спор. */
.news-grid.news-grid > .tc { grid-column: span 3; }

/* Крупная занимает половину ширины и ОБА ряда боковых: высота «большая =
   две справа» получается отношением, а не числом — при любой длине
   заголовков. Афиша внутри добирает остаток высоты (правило .tc-featured
   .tc-image в style.css), поэтому дыры внизу не остаётся.

   ПОПРАВКА К ЗАМЕРУ 08.10, СДЕЛАНА 13.10. Тогда в таблице стояла ОДНА
   строка на восемь карточек — «боковая 310 × 278». А видов карточки здесь
   ДВА: четыре справа, чью высоту держит крупная, и ряд из четырёх снизу,
   чью высоту не держало ничто. Нижний ряд в замер не попал вовсе, и ряды
   разъехались: на 1024 верхние 254, нижние 278; на 1512 наоборот, 265 и
   254. ДВА РАЗНЫХ ВИДА ПОД ОДНИМ ИМЕНЕМ В ЗАМЕРЕ — ЭТО ПРОПУЩЕННЫЙ
   УРОВЕНЬ.

   `grid-auto-rows: 1fr` равняет ВСЕ ряды сетки между собой: отношение
   «крупная = две боковые плюс зазор» от этого не меняется, а нижний ряд
   перестаёт жить своей жизнью. Замораживается то же отношение, только
   теперь оно накрывает все восемь карточек, а не две. */
.news-grid.news-grid {
    grid-auto-rows: 1fr;
}

.news-grid.news-grid > .tc:nth-child(1) {
    grid-column: span 6;
    grid-row: span 2;
}

@media (max-width: 992px) {
    /* Колонка 227 — четыре в нижнем ряду становятся узкими, ставим три.
       И крупная уходит во всю ширину: ЗАМЕР ПРОБЫ на 768 дал ряд «крупная
       плюс ОДНА боковая» — соседка висела в ряду одна. */
    .news-grid { gap: var(--space-4); --novostey: 7; }
    .news-grid.news-grid > .tc { grid-column: span 4; }
    .news-grid.news-grid > .tc:nth-child(1) { grid-column: span 12; grid-row: auto; }
}

@media (max-width: 640px) {
    /* НА ТЕЛЕФОНЕ НОВОСТИ ИДУТ ПО ОДНОЙ. Две в ряд — раскладка кортов,
       тренеров и поиска игрока, и она там права: у карточки человека имя
       в два слова. У новости товар — ЗАГОЛОВОК. ЗАМЕР 08.10 на 390: колонка
       названия 137, обрезка на второй строке, срезано 4 заголовка из 7
       (79, 86, 88 и 82 знака); на остальных четырёх видах не срезан ни один.
       Так же читают новости Google News, Apple News и BBC — одна колонка,
       заголовок целиком. Цена: лента длиннее, «витрины» на телефоне нет. */
    .news-grid { gap: var(--space-3); --novostey: 7; }
    .news-grid.news-grid > .tc { grid-column: span 12; }
    .news-grid.news-grid > .tc:nth-child(1) { grid-column: span 12; grid-row: auto; }

    /* Три строки вместо двух: в колонке на всю ширину (306) три строки
       берут 90 знаков — длиннее самого длинного заголовка замера (88).
       Вес селектора взят у правила лендинга (css/style.css:6525), иначе
       оно же и перебьёт: у него родитель в селекторе. */
    .news-grid.news-grid .tc .tc-title,
    .news-grid.news-grid .tc-featured .tc-title {
        -webkit-line-clamp: 3;
    }
}

/* ВИТРИНА ИДЁТ ПО ШИРОКОЙ КОРОБКЕ (правило 07.10): замер пробы дал крупную
   506 вместо посчитанных 676 — витрину сжимала узкая коробка страницы. */

/* КРУПНАЯ У НОВОСТИ — АФИША СВЕРХУ, А НЕ СЛЕВА. У турнира крупная высотой
   в ОДИН ряд, и «афиша слева» там читается. У новости она на ДВА ряда, и
   замер пробы показал, во что это превращается: колонка афиши 264 при
   высоте 650 — вертикальная щель, в которую горизонтальный снимок 16:9
   входит крошечным. Поэтому у новостей крупная одноколоночная, а высоту
   добирает афиша. */
.news-grid.news-grid > .tc.tc-featured { grid-template-columns: 1fr; }
.news-grid.news-grid > .tc.tc-featured .tc-image { height: auto; flex: 1 1 auto; min-height: 0; }

/* Своя секция списка: ровно те отступы, что нужны списку, — у секции
   «ничего не найдено» они были рассчитаны на пустой экран (128 сверху и
   снизу) и на центрирование. */
.news-list { padding: var(--space-6) var(--pad-x) var(--section-y); text-align: left; }
.news-empty { grid-column: 1 / -1; padding: var(--space-10) var(--space-6); text-align: center; }
.news-empty-title { font-size: var(--fs-lg); font-weight: var(--fw-semibold); color: var(--text-primary); margin: 0 0 var(--space-2); }
.news-empty-hint { font-size: var(--fs-base); color: var(--text-secondary); margin: 0; }

/* КАПС — СВОЙСТВО ЗАГОЛОВКА СЕКЦИИ, А НЕ НАЗВАНИЯ КАРТОЧКИ. У крупной
   карточки заголовок стоит тегом h2 (иерархия h1 → h2 → h3 без пропуска
   уровня), а глобальное правило h2 в style.css несёт uppercase — замер
   стенда 07.10 показал «ЗАВЕРШЕНИЕ И ИТОГИ ТБШ 2026» капсом. На эталоне
   капса нет только потому, что там карточка-h3. Снимаем у названия. */
.news-grid .tc-title { text-transform: none; }

/* ПРАВИЛА ВИТРИНЫ ЛЕНДИНГА, КОТОРЫЕ СПИСКУ НЕ ПОДХОДЯТ. Они про тизер на
   главной — «показываем три, остальное под кнопкой „Все турниры“». У
   страницы со списком и пагинацией прятать нечего: что не влезло, уходит
   на следующую страницу, а не исчезает. */
@media (max-width: 992px) {
    .news-grid.tournaments-grid > .tc:nth-child(n+4),
    .news-grid.tournaments-grid > .tc:nth-child(n+6) { display: flex; }
}
@media (max-width: 640px) {
    .news-grid.tournaments-grid > .tc:nth-child(n+4) { display: flex; }
}
/* И фиксированных высот ряда у списка нет: карточки выравнивает сетка.

   ПОПРАВКА 13.10: оговорка стояла только на ПЕРВЫЕ ТРИ карточки
   (`:nth-child(-n+3)`), и четвёртая с хвостом держали чужую высоту с
   лендинга. Замер на 844: дорожки сетки РАВНЫЕ по 303, а карточки 4–7
   стояли 270 — то есть не растягивались на свою дорожку. Это и есть
   «клетка-ребёнок грида не растягивается» из трекера, только в публичной
   части. Оговорка распространена на ВСЕ карточки списка. */
.news-grid.tournaments-grid > .tc { height: auto; min-height: 0; }

/* ========================================
   ДВИЖЕНИЕ ПО ПРОСЬБЕ СИСТЕМЫ — 08.10
   ======================================== */
/* Правило не новое: оно уже стоит на «Игроках» (css/players.css:1032) и
   «Услугах» (css/services.css:1095) — переносим без нового разбора.
   Выключаем ВСЁ движение файла, а не только списка: один выключатель на
   страницу, иначе на шве статьи и списка движение останется.
   Карточку общего компонента гасим СВОИМ селектором — у .tc своего правила
   нет (css/style.css:6101), а лендинг мы не трогаем. */
@media (prefers-reduced-motion: reduce) {

    .news-animate {
        opacity: 1;
        transform: none;
        transition: none;
    }

    .news-reaction-btn.bounce {
        animation: none;
    }

    .news-hero-bg img{
        transform: none;
        transition: none;
    }

    .news-grid > .tc,
    .news-grid > .tc:hover,
                                                                      
                                                                         
                                                    
    .news-pagination .pl-page-btn,
    .news-pagination button,
    .news-not-found-btn,
    .news-not-found-btn:hover,
    .news-carousel-nav,
    .news-carousel-thumb,
    .news-thumbs-nav,
    .news-progress-bar{
        transition: none;
        transform: none;
    }
}
