/* base.css — общий фундамент для всех страниц.
   Подключается ПЕРВЫМ, до страничного CSS (main.css/article.css/editorstat.css/thread.css/profile.css/map.css).
   Содержит то, что реально одинаково везде: шрифты, сброс, палитра, брейкпоинты
   и разметка, дословно продублированная в нескольких файлах. */

@import url('https://fonts.googleapis.com/css2?family=Archivo+Black&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap');

@font-face {
    font-family: "RS-extrabold";
    src: url('../fonts/RS-extrabold.otf') format('opentype');
    font-style: normal;
}
@font-face {
    font-family: "Gotham";
    src: url('../fonts/gotham_light.otf') format('opentype');
    font-weight: 300;
    font-style: normal;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* Атрибут hidden должен ПРЯТАТЬ. Браузер задаёт ему display: none своими
   стилями, но любое авторское правило с display это перебивает — и элемент
   остаётся на экране, хотя в разметке помечен скрытым.

   Наступили по-настоящему: `.editor-form { display: flex }` из этого же
   файла оставляла форму создания статьи видимой для гостя, хотя JS честно
   ставил form.hidden = true. Проверка тоже прошла мимо — она смотрела
   свойство .hidden, а не то, видно ли элемент.

   Правило общее, а не точечное: скрытых через hidden элементов на сайте
   много (предпросмотр редактора, пустые состояния, плашка черновика),
   и каждый следующий display в CSS ломал бы их по одному. */
[hidden] {
    display: none !important;
}

html {
    scroll-behavior: smooth;
    height: auto;
    overflow-x: hidden;
}

/* Палитра. Значения совпадают с тем, что уже используется по всему проекту —
   переменные пока не подставлены взамен существующих hex-значений в
   main.css/article.css/editorstat.css/thread.css/profile.css (чтобы не тащить
   риск глобальной замены по всем файлам разом), но доступны для новых стилей
   и постепенного переноса. */
:root {
    --color-dark: #1a1a1a;
    --color-darker: #111111;
    --color-light-bg: #e9e7e7;
    --color-white: #ffffff;
    --color-border-light: #cacaca;
    --color-border-dark: #2e2e2e;
    --color-muted: #888888;
    --color-text-light: #f0f0f0;

    /* Брейкпоинты — не CSS-свойство (custom media пока не поддерживается всеми
       браузерами), но фиксируем тут как единый источник правды для @media в
       страничных CSS-файлах. Проверочные ширины: 360 / 768 / 1024 / 1440. */
    --bp-mobile: 480px;
    --bp-tablet: 768px;
    --bp-laptop: 1024px;
}

/* ---- Общие карточки редактора статей (article.css + editorstat.css) ----
   Были дословно продублированы в обоих файлах — теперь один источник.
   .back-link здесь — вариант "по умолчанию" (абсолютное позиционирование,
   как на article.html/editorstat.html). thread.css подключается ПОСЛЕ
   base.css и переопределяет .back-link под свою вёрстку (обычный поток) —
   порядок подключения это гарантирует. */

.editor-page-container {
    position: relative;
    max-width: 1400px;
    margin: 0 auto;
    background: #ffffff;
    border-radius: 25px;
    border: 1px solid #cacaca;
    padding: 45px;
    min-height: 80vh;
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.15);
}

.back-link {
    position: absolute;
    top: 40px;
    left: 40px;
    display: inline-block;
    color: #1a1a1a;
    text-decoration: none;
    font-size: 14px;
    transition: opacity 0.2s ease;
}
.back-link:hover {
    opacity: 0.6;
}

.article-type-label {
    text-align: center;
    font-family: "Archivo Black", sans-serif;
    font-size: 13px;
    font-weight: 700;
    color: #999999;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    margin-bottom: -5px;
    display: none;
}
.article-type-label.visible {
    display: block;
}

.field-title {
    display: block;
    width: 100%;
    font-size: 40px;
    font-weight: 800;
    line-height: 1.15;
    text-align: center;
    margin-bottom: 40px;
    padding-top: 10px;
}

.editor-main-layout {
    display: flex;
    flex-direction: row;
    gap: 20px;
    align-items: flex-start;
    width: 100%;
}

.image-upload-group {
    width: 300px;
    display: flex;
    flex-shrink: 0;
}

/* ---- Общие примитивы формы ----
   Используются формой создания статьи на главной и страницами входа /
   регистрации. Раньше жили в main.css, но main.css — «только главная»,
   поэтому переехали сюда, к остальному общему. */

.editor-form {
    display: flex;
    flex-direction: column;
    gap: 20px;
    background-color: #ffffff;
    padding: 40px;
    border-radius: 20px;
    border: 1px solid #cacaca;
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.04);
}
.editor-group {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.editor-label {
    font-weight: 700;
    font-size: 14px;
    color: #1a1a1a;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.editor-input,
.editor-textarea,
.editor-select {
    width: 100%;
    padding: 16px;
    border-radius: 12px;
    border: 1px solid #cacaca;
    background-color: #f9f9f9;
    /* Поля формы не наследуют шрифт сами: без этой строки <textarea> берёт
       браузерный моноширинный, а <input> и <select> — системный. */
    font-family: inherit;
    font-weight: 500;
    font-size: 16px;
    color: #1a1a1a;
    outline: none;
    transition: border-color 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
}
.editor-textarea {
    min-height: 250px;
    resize: vertical;
}
.editor-input:focus,
.editor-textarea:focus,
.editor-select:focus {
    border-color: #1a1a1a;
    background-color: #ffffff;
    box-shadow: 0 0 0 1px #1a1a1a;
}
.editor-submit-btn {
    align-self: flex-start;
    padding: 16px 60px;
    background-color: #1a1a1a;
    color: #ffffff;
    border: none;
    border-radius: 16px;
    font-family: "Archivo Black", sans-serif;
    font-size: 16px;
    cursor: pointer;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.editor-submit-btn:hover {
    transform: translateY(-3px);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
}

/* ---- Обратная связь формы (login / register / new-thread) ----
   Сообщение над кнопкой и подсказка под полем. Раньше назывались .auth-message
   и .auth-hint и жили в auth.css, но их просит уже третья форма, а к «входу»
   они отношения не имеют. Показом управляет js/forms.js. */

.form-message {
    display: none;
    padding: 12px 16px;
    border-radius: 12px;
    font-size: 14px;
    line-height: 1.4;
}
.form-message.visible {
    display: block;
}
.form-message.error {
    background-color: #fdecec;
    border: 1px solid #e9b4b4;
    color: #8f2b2b;
}
.form-message.success {
    background-color: #eaf6ee;
    border: 1px solid #aed7bd;
    color: #1f6b3a;
}

.field-hint {
    font-size: 13px;
    color: #8a8a8a;
    line-height: 1.4;
}
.field-hint.error {
    color: #8f2b2b;
}

/* ---- Состояния загрузки и пустоты (UI.setLoading / UI.showMessage) ----
   Скелетон нужен не для красоты: без него асинхронный рендер выглядит как
   сломанная страница — сначала пусто, потом резко всё появилось. */

/* ЗАГЛУШКА ПОКАЗЫВАЕТСЯ НЕ СРАЗУ, а через 0.2с после того, как её поставили.
   Успел ответ прийти раньше — её не видно вообще.

   Иначе получается ровно обратное тому, ради чего скелетон нужен: на быстром
   ответе (а он такой и есть — сервер свой, сеть местная) три белых
   прямоугольника вспыхивают на сотню миллисекунд и читаются как сбой, а не
   как загрузка. Заметил автор на складе карточек.

   Сделано целиком в CSS, БЕЗ таймера в setLoading, и это не лень: часть
   страниц снимает заглушки не вызовом `setLoading(..., false)`, а просто
   затирая контейнер (`textContent = ''`). Отложенная вставка по таймеру
   в таком месте нарисовала бы заглушки ПОВЕРХ уже отрисованных данных —
   отменять его было бы некому. Задержка же появления снимается вместе
   с самим узлом, что бы его ни удалило. */
.skeleton {
    min-height: 240px;
    border-radius: 8px;
    background: linear-gradient(90deg, #1f1f1f 25%, #2a2a2a 50%, #1f1f1f 75%);
    background-size: 200% 100%;
    opacity: 0;
    animation: skeleton-shine 1.2s ease-in-out infinite,
               skeleton-in 0.15s linear 0.2s forwards;
}
/* На светлой подложке тот же скелетон, но светлее */
.skeleton--light {
    background: linear-gradient(90deg, #ececec 25%, #f6f6f6 50%, #ececec 75%);
    background-size: 200% 100%;
}

/* Формы заглушки. Базовая .skeleton — высокий блок под карточку обсуждения
   на threads.html; всё остальное задаётся модификатором.

   Смысл скелетона в том, чтобы место под контент было занято ЗАРАНЕЕ и
   вёрстка не прыгала, когда данные пришли. Поэтому размеры здесь не
   «на глаз», а повторяют то, что встанет на это место. */

/* Под .kart-iteml: та же ширина от --card-w и та же минимальная высота.
   flex-shrink: 0 — иначе в ленте заглушки сожмутся и ряд поедет. */
.skeleton--card {
    width: var(--card-w, 305px);
    min-height: 215px;
    flex-shrink: 0;
}

/* Строка текста: min-height базового класса надо погасить явно, иначе
   останется 240px и «строка» будет с полэкрана. */
.skeleton--line {
    min-height: 0;
    height: 14px;
    border-radius: 4px;
}

/* Блок пониже карточки — ответы в обсуждении, карточки в сетках профиля */
.skeleton--block {
    min-height: 90px;
}
@keyframes skeleton-shine {
    from { background-position: 200% 0; }
    to   { background-position: -200% 0; }
}
@keyframes skeleton-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}
/* Тем, кто просил не анимировать интерфейс, показываем ровный фон.

   `opacity: 1` здесь ОБЯЗАТЕЛЕН: погасив анимации, мы гасим и ту, что
   проявляет заглушку, — и без этой строки она осталась бы прозрачной
   навсегда. То есть у людей с отключённой анимацией скелетонов не было бы
   вовсе, и заметить это можно было бы только на их машине. */
@media (prefers-reduced-motion: reduce) {
    .skeleton {
        animation: none;
        opacity: 1;
    }
}

.state-empty,
.state-error {
    padding: 40px 20px;
    text-align: center;
    font-size: 15px;
    line-height: 1.6;
}
.state-empty {
    color: #8a8a8a;
}
.state-error {
    color: #b42318;
}

/* ---- Бейджи тредов/обсуждений (main.css + thread.css) ---- */
.disc-badge {
    padding: 4px 8px;
    border-radius: 4px;
    font-size: 0.75rem;
    font-weight: bold;
    text-transform: uppercase;
}
.theory { background: #2b5c8f; color: #fff; }
.discussion { background: #2b8f5c; color: #fff; }
.important { background: #8f2b2b; color: #fff; }

/* ---- Карточка обсуждения (главная + threads.html + user.html) ----
   Раньше жила целиком в main.css, но main.css — «только главная». Сюда
   переехал ВНЕШНИЙ ВИД карточки; её ШИРИНА осталась в main.css, потому что
   на главной карточка живёт в ленте и ширину ей считает fitCards()
   (--card-w, см. раздел 11 CLAUDE.md). На остальных страницах ширину задаёт
   сетка, поэтому здесь размеров нет намеренно. */

/* Высота карточки обсуждения — ФИКСИРОВАННАЯ, а не «не меньше».
   ---------------------------------------------------------------------------
   Было `min-height: 240px`, и этого оказалось мало. Карточки стоят рядом —
   в ленте на главной flex-строкой, на threads.html и в профиле сеткой, —
   а соседи по строке по умолчанию тянутся до высоты самого высокого.
   Значит одно длинное обсуждение задирало ВСЕ остальные.

   Замерено на боевом 25 августа: обсуждение «Единый стиль написания статей»
   с текстом на 2131 знак давало карточку в 1217px, и ровно столько же
   занимали одиннадцать соседних — включая пустые, где текста нет вовсе.
   На телефоне выходило 2024px: карточка в пять экранов.

   Одной фиксированной высоты МАЛО — нужна ещё обрезка заголовка и текста
   ниже. Без неё длинное обсуждение просто распирало бы карточку изнутри
   и вылезало за её границы.

   260px — это badge + два ряда заголовка + четыре строки текста + подвал,
   с отступами. Проверено замером на 1440, 900 и 390: содержимое помещается
   на всех трёх, подвал остаётся на месте. */
.discussion-card {
    background: #1a1a1a;
    border: 1px solid #333;
    border-radius: 8px;
    padding: 20px;
    display: flex;
    flex-direction: column;
    transition: transform 0.3s ease, border-color 0.3s ease;
    height: 260px;
    /* Страховка: если однажды появится блок, для которого обрезки ниже
       не хватит, он будет срезан по границе карточки, а не выпадет наружу
       поверх соседей. */
    overflow: hidden;
}
.discussion-card:hover {
    transform: translateY(-5px);
    border-color: #555;
}
/* Карточка целиком — ссылка на обсуждение (и на главной, и в списках) */
a.discussion-card {
    text-decoration: none;
}
/* Бейдж прижат влево только внутри карточки: на thread.html он стоит в
   обычном потоке, и глобальный align-self сдвинул бы его. */
.discussion-card .disc-badge {
    align-self: flex-start;
}
/* Заголовок и текст ОБРЕЗАЮТСЯ по числу строк — пара к фиксированной
   высоте выше. Заголовок пишет человек, и длина его ничем не ограничена:
   замер на 390px показал заголовок в ПЯТЬ строк (105px), а это уже
   половина карточки.

   Обрезаем по строкам, а не по числу знаков: буквы разной ширины, и «120
   знаков» на узком экране дают четыре строки, а на широком две. Считать
   надо то, что видно.

   Многоточие ставит сам браузер. */
.disc-title {
    color: #fff;
    font-size: 1.1rem;
    font-weight: 700;
    margin: 10px 0;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
/* flex-grow здесь БЫЛ и его пришлось убрать — на этом поймались.
   ---------------------------------------------------------------------------
   Он прижимал подвал к низу карточки, растягивая блок текста. А обрезка по
   строкам работает, только когда высоту блока определяет САМ текст: если
   высота задана извне (растяжением), браузер не обрезает по строке
   с многоточием, а просто отсекает лишнее по краю — и последняя строка
   оказывается разрезанной пополам.

   Замер этого НЕ ловил: он спрашивал «содержимое не помещается?» — а оно
   не помещалось в обоих случаях, и при честной обрезке, и при срезе.
   Увидеть удалось только на снимке экрана.

   Теперь подвал прижимает `margin-top: auto` у него самого (см. ниже),
   а текст занимает ровно свои четыре строки. */
.disc-text {
    color: #aaa;
    font-size: 0.9rem;
    line-height: 1.4;
    margin-bottom: 15px;
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.disc-footer {
    display: flex;
    justify-content: space-between;
    font-size: 0.8rem;
    color: #5f5f5f;
    border-top: 1px solid #2a2a2a;
    padding-top: 10px;
    /* Прижимает подвал к низу карточки. Раньше это делал flex-grow у текста,
       но он ломал обрезку по строкам — см. .disc-text выше. */
    margin-top: auto;
}

/* Имя автора внутри карточки ведёт в его профиль.
   Это НЕ <a>: вся карточка уже ссылка на обсуждение, а ссылка внутри ссылки
   недопустима — браузер такую разметку разбирает по-своему. Переход делает
   обработчик (threads.js и index-threads.js), он же гасит переход по самой
   карточке.

   Отсюда курсор и подсветка руками: у span их нет, а человек должен видеть,
   что имя нажимается. Правило ЗДЕСЬ, а не в threads.css: такие карточки
   есть и на главной, а она того файла не подключает. */
.disc-author--link {
    cursor: pointer;
    border-bottom: 1px solid transparent;
    transition: color .15s ease, border-color .15s ease;
}

.disc-author--link:hover,
.disc-author--link:focus-visible {
    color: #ffffff;
    border-color: rgba(255, 255, 255, .5);
    outline: none;
}

/* На светлой карточке белое подчёркивание не видно. */
.discussion-card--light .disc-author--link:hover,
.discussion-card--light .disc-author--link:focus-visible {
    color: #1a1a1a;
    border-color: rgba(26, 26, 26, .45);
}

/* Светлый вариант карточки — для страниц на светлом фоне (публичный
   профиль). Отдельный модификатор, а не переопределение по странице:
   к светлой теме сайта это и будет готовый набор цветов, останется
   переключать класс, а не переписывать правила.
   Бейджи (.theory/.discussion/.important) не трогаем: они цветные с белым
   текстом и читаются на обоих фонах. */
.discussion-card--light {
    background: #ffffff;
    border-color: #cacaca;
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.04);
}
/* Обводка при наведении светлее самой карточки, но заметно темнее покоя
   (#cacaca): почти чёрная рамка на белом читалась как выделение ошибки. */
.discussion-card--light:hover {
    border-color: #9a9a9a;
    box-shadow: 0 12px 30px rgba(0, 0, 0, 0.10);
}
.discussion-card--light .disc-title {
    color: #1a1a1a;
}
.discussion-card--light .disc-text {
    color: #5f5f5f;
}
.discussion-card--light .disc-footer {
    color: #999999;
    border-top-color: #e6e6e6;
}

/* ---- Адаптивность: элементы, которые ломаются на узких экранах ----
   Всё ниже — ТОЛЬКО внутри @media, к десктопным правилам выше не относится
   и их не переопределяет вне этих границ. */

@media (max-width: 768px) {
    .editor-page-container {
        padding: 24px 16px;
        border-radius: 16px;
    }
    .back-link {
        position: static;
        display: inline-block;
        margin-bottom: 24px;
    }
    .editor-main-layout {
        flex-direction: column;
    }
    .image-upload-group {
        width: 100%;
    }
    /* У .editor-main-layout стоит align-items: flex-start — в колонку
       элементы НЕ растягиваются, а сжимаются по содержимому. Блоку картинки
       ширину задали строкой выше, а колонка текста осталась без неё: она
       брала ширину по своему содержимому, а у полей ввода есть собственный
       минимум (браузер считает его по cols=20, у заголовка это ~263px).
       На 320px колонка получалась 289px и выпихивала страницу за край. */
    .editor-text-column {
        width: 100%;
    }
    .field-title {
        font-size: clamp(24px, 7vw, 40px);
    }
}

/* ============================================================
   ОБЩИЙ ФОН И ШРИФТ СТРАНИЦЫ
   Раньше это правило жило в main.css, и страницы без своего body (профиль,
   публичный профиль) держались на нём — из-за чего тянули весь файл главной.
   Здесь оно объявлено ПЕРВЫМ по каскаду, так что любая страница со своим
   body (тёмные thread/threads, auth, article, editorstat, map, new-thread)
   спокойно его перебивает: их CSS подключается позже.
   ============================================================ */
body {
    background-color: #e9e7e7;
    font-family: "Inter", sans-serif;
}

/* ============================================================
   ТЁМНЫЕ ЗАГОЛОВКИ СЕКЦИЙ
   Третий экран главной + разделы «Мои статьи» / «Мои обсуждения»
   в личном кабинете и на публичном профиле.
   ============================================================ */
.kart-headerdark {
    width: 100%;
    padding: 0 60px;
    margin-top: 30px;
    margin-bottom: 10px;
}
.kart-titledark {
    color: #1a1a1a;
    font-family: "Archivo Black", sans-serif;
    font-size: 20px;
    font-weight: 1000;
    margin-bottom: 8px;
    text-shadow: 0 0 30px rgba(0, 0, 0, 0.5),
                 0 0 60px rgba(0, 0, 0, 0.25),
                 0 0 100px rgba(0, 0, 0, 0.1);
}
.kart-linedark {
    border: none;
    border-top: 1px solid #333333;
    width: 100%;
}

/* ============================================================
   СЕТКА КАРТОЧЕК СТАТЕЙ
   Дерево «Все статьи» на главной и сетки в профилях.

   Ширину карточки берём из --card-w. На главной её считает fitCards()
   (раздел 11 CLAUDE.md), в профилях переменная не задана и работает
   запасное значение 305px — именно так это и было в main.css.
   ============================================================ */
.kart-blockl {
    width: 100%;
    margin-top: 30px;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 25px;
    align-items: flex-start;
}
.kart-iteml {
    flex-shrink: 0;
    width: var(--card-w, 305px);   /* см. --card-w у .kart-item */
    min-height: 215px;
    background-color: #ffffff;
    border-radius: 8px;
    border: 1px solid #cacaca;
    transition: box-shadow 0.3s ease, border-color 0.3s ease;
   display: flex;
   flex-direction: column;
   text-decoration: none;
}
.kart-iteml:hover {
    border-color: rgb(255, 255, 255);
    /* Радиусы 12/24 вместо 20/40. Карточка лежит внутри ленты, которая обрезает
       содержимое, а карман под тень по бокам не может быть шире зазора между
       карточками (25px) — иначе из-за края лезет полоска соседней карточки.
       Тень с радиусом 40px до этих 25px не догасала (замер: 202 у края, 229 на
       границе кармана при фоне 232) и обрывалась там заметной линией. С 24px
       она гаснет внутри кармана полностью. */
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1),
                0 0 12px rgba(0, 0, 0, 0.12),
                0 0 24px rgba(0, 0, 0, 0.12);
}
/* Карточка дерева, за которой нет опубликованной статьи: её ещё не написали
   или сняли в черновики. Остаётся на месте — дерево собрано автором вручную, —
   но перестаёт быть ссылкой: href="#" уносил страницу в самый верх главной.
   Класс вешает index-articles.js. */
.kart-iteml--empty {
    cursor: default;
    opacity: 0.5;
}
.kart-iteml--empty:hover {
    border-color: #cacaca;
    box-shadow: none;
}

.kart-iteml img {
 width: calc(100% - 15px);
    margin: 8px auto 0 auto;
    height: 165px;
    object-fit: cover;
    border-radius: 8px;
    display: block;
}
.kart-iteml p {
    padding: 6px 12px;
    font-family: "Gotham";
    font-size: 18px;
    color: #1a1a1a;
    text-align: center;
     font-weight: 800;
}
/* nowrap + overflow: hidden — не косметика, а условие работы adjustFonts():
   она ужимает подпись, пока scrollWidth больше clientWidth, а без обрезки
   эти величины всегда равны (раздел 11). */
.kart-iteml p, .kart-item p {
   white-space: nowrap;
    overflow: hidden;
    display: block;
    width: 100%;
    white-space: nowrap;
    overflow: hidden;
    box-sizing: border-box;
    text-align: center;
}
.kart-iteml-wrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    width: var(--card-w, 305px);   /* см. --card-w у .kart-item */
    flex-shrink: 0;
}

/* Карточки, лежащие прямо в сетке (профиль), а не в ленте карусели.
   В ленте лишнее обрезается, а в сетке обрезать нечему: жёсткие 305px на
   экране 320px выпирали за край и вызывали горизонтальную прокрутку всей
   страницы — заодно растягивая шапку до 325px.
   min() ничего не меняет, пока места хватает, и ужимает карточку на узких
   экранах. Селектор по прямому потомку: внутри .kart-blockl на главной лежит
   карусель, её карточкам резиновая ширина не нужна. */
.kart-blockl > .kart-iteml-wrap,
.kart-blockl > .kart-iteml-wrap > .kart-iteml {
    width: min(305px, 100%);
}

/* ============================================================
   КНОПКИ-ССЫЛКИ
   Первый экран главной («Начать изучение», «Все статьи») и 404.
   ============================================================ */
.main-buttons {
    display: flex;
    flex-direction: row;
    /* Кнопки — width:fit-content, в один ряд без wrap не сжимаются: если
       колонке не хватает ширины (та же история с чёрным блоком справа),
       вторая кнопка просто рисовалась поверх соседних картинок. flex-wrap
       ничего не меняет, пока места достаточно — включается только когда
       реально не помещается. */
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 40px;
    padding-bottom: 0px;
    z-index: 2;
}
.btn-main {
    display: inline-block;
    width: fit-content;
    padding: 14px 70px;
    background-color: #1a1a1a;
    color: #ffffff;
    border-radius: 20px;
    font-family: "Archivo Black", sans-serif;
    font-size: 17px;
    text-decoration: none;
    font-weight: 600;
    transition: box-shadow 0.3s ease, border-color 0.3s ease;
}
.btn-main:hover {
    border-color: #1a1a1a;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5),
                0 0 20px rgba(0, 0, 0, 0.28),
                0 0 40px rgba(0, 0, 0, 0.14);
}
.btn-outline {
    background-color: transparent;
    border: 1px solid #1a1a1a;
    color: #1a1a1a;
    transition: box-shadow 0.3s ease, border-color 0.3s ease;
    display: inline-block;
    width: fit-content;
    padding: 14px 70px;
    border-radius: 20px;
    font-family: "Archivo Black", sans-serif;
    font-size: 17px;
    text-decoration: none;
    font-weight: 600;
}
.btn-outline:hover {
    border-color: #ffffff;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5),
                0 0 20px rgba(0, 0, 0, 0.28),
                0 0 40px rgba(0, 0, 0, 0.14);
}

/* ---- Заголовки секций и кнопки на узких экранах ---- */

@media (max-width: 1024px) {
    .kart-headerdark {
        padding: 0 24px;
    }
}

@media (max-width: 900px) {
    .main-buttons {
        justify-content: center;
        flex-wrap: wrap;
    }
}

@media (max-width: 700px) {
    .kart-headerdark {
        padding: 0 20px;
    }
}

@media (max-width: 480px) {
    .btn-main,
    .btn-outline {
        padding: 14px 32px;
    }
}

/* ============================================================
   ШАПКА САЙТА
   Разметку рисует layout.js на КАЖДОЙ странице, поэтому стили живут здесь,
   а не в main.css. Раньше лежали в main.css, и ради них этот файл (63 КБ
   стилей главной) приходилось подключать всюду — см. раздел 4 CLAUDE.md.
   ============================================================ */

@keyframes headerSlideDown {
    from {
        opacity: 0;
        transform: translateY(-100%);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

header {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    z-index: 9999;
}
.header1 {
   background: rgb(10, 10, 10);
   height: 58px;
   width: 100%;
   display: flex;
    align-items: center;
    background-color: #1a1a1a;
    animation: headerSlideDown 0.9s cubic-bezier(0.22, 1, 0.36, 1) forwards;
    justify-content: space-between;
    padding: 0 60px;
    gap: 12px;
}
.headertext {
   margin-left: 0px;
    color: #ffffff;
    /* Кегль подстраивается так, чтобы самое длинное слово «Меллстройности»
       всегда помещалось в строку и не приходилось его обрезать.
       257px — то, что в шапке занято не заголовком (её боковые отступы плюс
       кнопки навигации), 9.8 — во столько раз это слово шире своего кегля.
       До ~510px ширины формула упирается в максимум и кегль остаётся 25px. */
    font-size: clamp(13px, calc((100vw - 257px) / 9.8), 25px);
    font-family: "Archivo Black", sans-serif;
   font-weight: 800;
   font-style: normal;
   text-shadow: 0 0 30px rgba(255, 255, 255, 0.2),
                 0 0 60px rgba(255, 255, 255, 0.1),
                 0 0 100px rgba(255, 255, 255, 0.07);
    /* .header1 держит фиксированную высоту 58px — заголовок не должен
       переноситься на вторую строку (вылезет за неё) и не должен раздувать
       flex-контейнер, выталкивая кнопки навигации за пределы экрана, где их
       обрежет html{overflow-x:hidden}. min-width:0 разрешает этому flex-item
       сжиматься меньше своей intrinsic-ширины, остальное — стандартное усечение. */
    min-width: 0;
    flex: 1 1 auto;
    overflow: hidden;
    /* Не обрезаем многоточием, а переносим второе слово на вторую строку.
       Межстрочный интервал подобран так, чтобы две строки умещались в 58px
       высоты шапки (2 x 25px x 1.05 = 52.5px). */
    line-height: 1.05;
    /* Свечению нужно место, иначе overflow: hidden обрезает его вплотную к
       тексту — особенно слева, где текст начинается ровно от края бокса.
       По высоте бокс растянут на всю шапку: тогда свечение заполняет её и
       обрывается ровно по её краю, а не вылезает на страницу под шапкой
       (раньше при переносе на две строки это было хорошо заметно).
       По горизонтали — запас в 50px; на узких экранах он ужимается до
       бокового отступа шапки, см. медиа-запросы. */
    height: 58px;              /* как высота .header1 */
    display: flex;
    align-items: center;
    padding: 0 50px;
    margin: 0 -50px;
    /* Из-за запаса бокс заголовка вылезает за шапку примерно на 39px вниз и
       накрывал собой полосу страницы под ней, перехватывая клики. Заголовок
       некликабелен по смыслу, поэтому просто убираем его из-под курсора. */
    pointer-events: none;
}
.nav-dropdown {
    position: relative;
    margin-left: auto;
    margin-right: 35px;
    flex-shrink: 0;
}
.header1 > .nav-btn {
    /* "Профиль" — прямой потомок .header1, в отличие от .nav-btn внутри
       .nav-dropdown (там это кнопка-триггер). Не даём ему сжиматься наравне
       с заголовком. */
    flex-shrink: 0;
}
.nav-btn {
    background: none;
    border: none;
    color: #ffffff;
    font-family: "Archivo Black", sans-serif;
    font-size: 15px;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    padding: 6px 0;
    display: inline-flex;
    align-items: center;
    position: relative;
}
.nav-dropdown-btn:hover {
    color: #ffffff;
}
.nav-btn::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 50%;
    width: 0;
    height: 2px;
    background-color: #ffffff;
    transition: width 0.3s ease, left 0.3s ease;
}
.nav-btn:hover::after {
    width: 100%;
    left: 0;
}
/* Вход и регистрация — отдельной группой у правого края шапки */
.header-auth {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-left: 30px;
    flex-shrink: 0;
}

/* Вошедший вместо «Вход / Регистрация»: аватар и имя. Подставляется
   в layout.js после ответа сервера — узнать, кто вошёл, можно только
   запросом, а шапка должна появиться сразу. */
.header-me {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    max-width: 190px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.header-me-avatar {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    background: #2a2a2a;
}
/* Кнопка «Выйти» — это <button>, а не ссылка: у неё своя рамка и шрифт,
   которые надо погасить, иначе она не совпадёт с соседними .nav-btn. */
.header-auth button.nav-btn {
    background: none;
    border: none;
    cursor: pointer;
    font: inherit;
    padding: 0;
}

/* Приглашения войти. Показываются на месте того, что гостю недоступно:
   формы ответа, формы создания статьи, кнопки «Редактировать».
   Намеренно спокойные — это подсказка, а не запрет. */
.reply-guest-note,
.editor-guest-note {
    margin: 14px 0 0 0;
    font-family: "Gotham", sans-serif;
    font-size: 15px;
    color: #8a8a8a;
}
.reply-guest-note a,
.editor-guest-note a,
.article-edit-link--guest {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 3px;
}
.reply-guest-note a:hover,
.editor-guest-note a:hover,
.article-edit-link--guest:hover {
    color: #d13c3c;
}
/* «Регистрация» — заполненная кнопка: это главное действие для гостя,
   и на фоне трёх одинаковых текстовых ссылок она иначе теряется. */
.nav-btn--solid {
    background-color: #ffffff;
    color: #111111;
    border-radius: 8px;
    padding: 7px 14px;
    transition: background-color 0.2s ease, transform 0.2s ease;
}
.nav-btn--solid:hover {
    background-color: #e0e0e0;
    transform: translateY(-1px);
}
/* Подчёркивание из .nav-btn на заполненной кнопке не нужно: оно рисуется
   поверх её собственного фона. */
.nav-btn--solid::after {
    content: none;
}
/* Дубли кнопок внутри выпадающего меню — только для узких экранов,
   включаются в @media (max-width: 900px). */
.nav-dropdown-narrow {
    display: none;
}

/* Черта между пунктами меню. Вид задан ЗДЕСЬ, а не в медиа-запросе, потому
   что чертой пользуются два разных случая: узкое меню (отделяет дубли кнопок
   шапки) и «Модерация» (отделяет служебный пункт от тех, которыми ходят
   читатели). В медиа-запросе осталась только видимость. */
.nav-dropdown-sep {
    display: none;
    height: 1px;
    background-color: #2e2e2e;
    margin: 6px 4px;
}

/* Видна на ЛЮБОЙ ширине. Обычная черта появляется только на узких экранах,
   а эту незачем прятать: «Модерация» стоит в меню всегда и всегда должна
   быть отделена. */
.nav-dropdown-sep--always {
    display: block;
}
.nav-dropdown-menu {
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%) translateY(-8px);
    margin-top: 12px;
    background-color: #1a1a1a;
    border: 1px solid #2e2e2e;
    border-radius: 12px;
    padding: 8px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 200px;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease;
    z-index: 100;
}
.nav-dropdown-menu.open {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
}
.nav-dropdown-item {
    color: #f0f0f0;
    text-decoration: none;
    font-weight: 600;
    font-size: 14px;
    padding: 10px 12px;
    border-radius: 8px;
    text-align: center;
    transition: background-color 0.2s ease, color 0.2s ease;
}
.nav-dropdown-item:hover {
    background-color: #2e2e2e;
    color: #ffffff;
}

/* Число рядом с «Проверка статей»: сколько ждёт проверки.
   Жёлтое, как и остальные пометки модерации (закреплено, закрыто), —
   чтобы взгляд узнавал их как один язык. */
/* Стили окна «это бета» (.beta-overlay, .beta-window и прочее) убраны
   30 августа вместе с самим окном — см. layout.js. Мёртвое правило в CSS
   через полгода не отличить от работающего, поэтому не оставляем. */

/* Красная точка «вам подарили карточку». В отличие от .nav-badge числа
   не показывает: важно, что что-то пришло, а сколько именно — видно
   в самой коллекции.

   Ставится в ТРИ места (см. layout.js): аватар в шапке, пункт «Профиль»
   в меню и сама кнопка «Навигация ▾». Последняя нужна потому, что на узких
   экранах пункт лежит внутри СВЁРНУТОГО меню — метка на нём не видна, пока
   меню не открыли. */
.nav-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    margin-left: 6px;
    border-radius: 50%;
    background-color: #e04b4b;
    /* Отрывает точку от базовой линии текста: без этого она сидит на строке
       и читается как точка в конце предложения, а не как метка. */
    vertical-align: 4px;
    flex-shrink: 0;
}

/* На кнопке «Навигация ▾» — только там, где кнопок справа уже нет.
   Порог тот же, что у .header-auth (900px): разойдутся — появится ширина,
   на которой метки не будет вовсе либо она задвоится. */
.nav-dot--narrow {
    display: none;
}
@media (max-width: 900px) {
    .nav-dot--narrow {
        display: inline-block;
    }
}

.nav-badge {
    display: inline-block;
    min-width: 20px;
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: 10px;
    background-color: #e8c26a;
    color: #1a1a1a;
    font-family: "Inter", sans-serif;
    font-size: 12px;
    font-weight: 700;
    line-height: 1.5;
    text-align: center;
    vertical-align: middle;
}

/* ---- Шапка на узких экранах ---- */

@media (max-width: 1024px) {
    .header1 {
        padding: 0 24px;
    }
    /* Запас под свечение не должен быть шире бокового отступа шапки — иначе
       бокс заголовка уходит за край экрана. Дальше края свечению всё равно
       некуда лечь, так что держим их вровень. */
    .headertext {
        padding-left: 24px;
        padding-right: 24px;
        margin-left: -24px;
        margin-right: -24px;
    }
    .nav-dropdown {
        margin-right: 16px;
    }
}

@media (max-width: 900px) {
    /* Пять элементов в строку шапки (заголовок, «Навигация», «Профиль»,
       «Вход», «Регистрация») перестают помещаться: кнопки занимают около
       470px, и заголовку не остаётся места — он обрезался уже на 600px, а на
       360px шапка переполнялась. Прячем кнопки и показываем те же ссылки
       внутри выпадающего меню: ни одна страница не становится недостижимой. */
    .header-auth,
    .header1 > .nav-btn {
        display: none;
    }
    .nav-dropdown-narrow {
        display: block;
    }
    /* Вид черты задан выше, в общем правиле, — здесь только показываем её.
       Держать копию высоты и цвета в двух местах значило бы однажды
       поправить одно и забыть другое. */
    .nav-dropdown-sep {
        display: block;
    }
    /* Кнопок справа больше нет, «Навигация» — последняя: отступ от края
       задаёт padding шапки, свой margin ей теперь ни к чему. */
    .nav-dropdown {
        margin-right: 0;
    }
    /* Раз кнопка встала к самому краю, центрированное под ней меню
       (left:50% + translateX(-50%)) наполовину уходит за экран, и
       html{overflow-x:hidden} его срезает. Прижимаем к правому краю кнопки,
       как обычный дропдаун. */
    .nav-dropdown-menu {
        left: auto;
        right: 0;
        transform: translateY(-8px);
    }
    .nav-dropdown-menu.open {
        transform: translateY(0);
    }
}

@media (max-width: 480px) {
    .header1 {
        padding: 0 16px;
        gap: 8px;
    }
    /* Здесь кнопки навигации сами становятся мельче, и заголовку достаётся
       больше места — поправка 194px вместо 257px. С прежней он был занижен
       (на 360px давал 13px вместо возможных 17px). Нижний порог тоже ниже:
       иначе на совсем узких окнах слово переставало помещаться. */
    .headertext {
        font-size: clamp(10px, calc((100vw - 194px) / 9.8), 25px);
        /* запас под свечение вровень с отступом шапки — см. правило на 1024px */
        padding-left: 16px;
        padding-right: 16px;
        margin-left: -16px;
        margin-right: -16px;
    }
    /* .nav-dropdown { margin-right: 0 } и прижатие меню к правому краю
       переехали в @media (max-width: 900px): с уходом кнопок в меню
       «Навигация» становится последней в шапке уже там, а не здесь. */
    .nav-btn {
        font-size: 13px;
    }
}

/* ---- Сетка карточек порциями ----
   Показываются первые шесть, остальное — по кнопке (UI.chunkGrid).
   Лишние карточки ПРЯЧУТСЯ, а не удаляются: из них собирается порядок
   при перетаскивании в профиле. */

.kart-iteml-wrap.card-hidden { display: none; }

/* Кнопка по центру сетки — то есть под средней карточкой ряда: сетка
   выровнена по левому краю, но при полном ряде её центр и есть центр
   средней карточки. width: fit-content обязателен — без него display: block
   растягивает кнопку на все 1100px, и получается полоса во всю ширину. */
/* Панель с кнопками. Две отдельные кнопки, а не одна с меняющейся надписью:
   одна не может одновременно и добавлять, и сворачивать, поэтому «Свернуть»
   появлялась только у того, кто дощёлкал до последней карточки. */
.show-more-row {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 10px;
    width: fit-content;
    margin: 4px auto 26px;
}

.show-more-row[hidden] { display: none; }

.show-more {
    display: block;
    width: fit-content;
    padding: 11px 22px;
    border: 1px solid #cacaca;
    border-radius: 12px;
    background: #ffffff;
    font-family: "Archivo Black", sans-serif;
    font-size: 13px;
    color: #1a1a1a;
    cursor: pointer;
    transition: border-color .2s ease, box-shadow .2s ease;
}

.show-more:hover {
    border-color: #1a1a1a;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, .1);
}

.show-more[hidden] { display: none; }

/* «Свернуть» — второстепенное действие рядом с главным, поэтому бледнее:
   иначе две одинаковые кнопки рядом читаются как равный выбор, и взгляд
   спотыкается о каждую. */
.show-more--less {
    background: transparent;
    border-color: #d8d8d8;
    color: #6a6a6a;
}

.show-more--less:hover {
    border-color: #8a8a8a;
    color: #1a1a1a;
    box-shadow: none;
}


/* ---- Полоса разделов модерации ----
   Три раздела ОДНОЙ страницы: очередь на проверку, список участников и склад
   карточек. Рисует полосу modtabs.js; у модератора вкладки склада нет вовсе.

   Здесь, а не в moderation.css, потому что оформление вкладок не принадлежит
   ни одному из разделов: они делят его поровну, и класс `.mod-tab` может
   понадобиться четвёртому разделу, который подключит свой файл стилей.

   Цвета светлые: все три страницы светлые, как статья и редактор. */

/* Вкладки — ТЕКСТ С ПОДЧЁРКИВАНИЕМ, как «Навигация ▾» в шапке, а не овальные
   кнопки (26 августа, решение автора). Приём тот же самый: полоска в ::after
   растёт от середины к краям.

   Различие одно, и оно намеренное: у шапки полоска появляется только при
   наведении, а здесь ещё и остаётся у активной вкладки. В шапке подчёркивание
   отвечает «сюда можно нажать», а тут ему приходится отвечать ещё и «вы
   находитесь здесь» — иначе, лишившись заливки, активный раздел стало бы
   нечем показать. */

.mod-tabs {
    display: flex;
    flex-wrap: wrap;
    /* Разный по осям: боковой зазор большой (без рамок вкладки иначе слипаются
       в одну строку слов), а между перенесёнными рядами маленький. */
    gap: 8px 28px;
    margin: 0 0 28px;
    padding-bottom: 14px;
    border-bottom: 1px solid #d5d3d3;
}

.mod-tab {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 0;
    background: none;
    border: none;
    font-family: "Inter", sans-serif;
    font-size: 15px;
    color: #6b6b6b;
    text-decoration: none;
    transition: color .2s ease;
}

/* Цвет полоски — свойство СОСТОЯНИЯ вкладки, а не наведения: серый у обычной,
   чёрный у активной. Задать серый в правиле `:hover` было первой мыслью и
   оказалось ошибкой: `background-color` не участвует в переходе, поэтому
   менялся мгновенно — при уходе курсора полоска СНАЧАЛА чернела и уже чёрной
   сворачивалась. Дописать цвет в `transition` тоже неверно: тогда он плавно
   переливался бы, чего никто не просил. */
.mod-tab::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 50%;
    width: 0;
    height: 2px;
    background-color: #a5a5a5;
    transition: width .3s ease, left .3s ease;
}

/* :not(.mod-tab--active) ОБЯЗАТЕЛЕН. Вкладки все до одной ссылки (их копируют
   и открывают в новой вкладке), поэтому активная тоже подходит под
   `a.mod-tab:hover` — а он специфичнее `.mod-tab--active`. Пока значения
   совпадают, вреда нет, но стоит развести цвета — и активная вкладка начнёт
   перекрашиваться под курсором. Порядок правил тут ничего не решает. */
a.mod-tab:not(.mod-tab--active):hover {
    color: #1a1a1a;
}
/* Наведение двигает ТОЛЬКО ширину. Цвет уже задан выше и по ходу перехода
   не меняется — иначе сворачивание проигрывалось бы не тем цветом. */
a.mod-tab:not(.mod-tab--active):hover::after {
    width: 100%;
    left: 0;
}

/* Активная отличается ЦВЕТОМ и полоской, но НЕ насыщенностью шрифта: жирное
   начертание шире обычного, и при каждом переключении полоса вкладок слегка
   переставлялась бы.

   Курсор обычный: нажатие на свою вкладку ничего не делает — modtabs.js
   выходит раньше, чем что-то переключит. Стрелка честнее «руки», которая
   обещает переход. */
.mod-tab--active {
    color: #1a1a1a;
    cursor: default;
}
/* `.mod-tab.mod-tab--active`, а не просто `.mod-tab--active`: у второго та же
   специфичность, что у `.mod-tab::after`, и решал бы порядок правил в файле —
   ровно тот капкан, на котором в этом проекте уже попадались `.card-leaving`
   и `.coll-card--fresh`. Удвоенный класс делает правило сильнее независимо
   от порядка. */
.mod-tab.mod-tab--active::after {
    width: 100%;
    left: 0;
    background-color: #1a1a1a;
}

/* Раздел страницы «Модерация». Спрятанный лежит под `hidden`; правило
   явное, чтобы будущее `display` у `.mod-pane` не отменило его молча —
   любое объявление display перебивает `hidden` из настроек браузера. */
.mod-pane[hidden] {
    display: none;
}

.mod-tab-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 999px;
    background: #b3261e;
    color: #ffffff;
    font-size: 12px;
    font-weight: 700;
}
/* Выворотки на активной вкладке БОЛЬШЕ НЕТ, и это не потеря, а следствие:
   тёмной заливки под кружком не осталось, а белый кружок на светлом фоне
   пропал бы совсем. Красный одинаково читается на обеих. */

/* ---- Появление блоков по прокрутке ----
   Переехало из main.css: анимация была только на главной, потому что
   там же лежал и её код. Теперь механизм общий (js/reveal.js).

   На главной класс .anim-hidden проставлен прямо в разметке, на остальных
   страницах его вешает скрипт — см. пояснение в reveal.js. */

.anim-hidden {
    opacity: 0;
    transform: translateY(40px);
    transition: opacity 1.4s cubic-bezier(0.25, 1, 0.5, 1),
                transform 0.7s cubic-bezier(0.25, 1, 0.5, 1);
}

.anim-visible {
    opacity: 1;
    transform: translateY(0);
}

/* Уход карточки при сворачивании сетки.
   ОБЯЗАТЕЛЬНО после .anim-visible: у обоих по одному классу, и решает
   порядок в файле — стоя выше, это правило было бы перебито и карточки
   пропадали бы рывком. Длительность совпадает с LEAVE_MS в ui.js.

   Уход короче появления (0.22с против 0.7с): убирать медленно то, что
   человек попросил убрать, — значит заставлять его ждать. */
.card-leaving {
    opacity: 0;
    transform: translateY(12px);
    transition: opacity .22s ease, transform .22s ease;
    pointer-events: none;
}

/* Внутренности крупного блока — то, что лежит ВНУТРИ уже анимируемой коробки:
   поля редактора, текст статьи, карточки в разделе очереди.

   Сдвиг короче и быстрее, чем у самой коробки. Полный сдвиг у обоих сразу
   читается как рывок в два приёма: коробка едет на 40px, и содержимое внутри
   неё едет ещё на 40px. Здесь содержимое именно ПРОЯВЛЯЕТСЯ в уже приехавшей
   коробке, лишь слегка подбираясь снизу. Класс вешает reveal.js. */
.anim-hidden.anim-inner {
    transform: translateY(16px);
    transition: opacity 0.9s cubic-bezier(0.25, 1, 0.5, 1),
                transform 0.5s cubic-bezier(0.25, 1, 0.5, 1);
}

/* И ОБЯЗАТЕЛЬНО ОБРАТНО. Класс `.anim-hidden` со всплывшего блока никто
   не снимает — показ добавляет `.anim-visible` поверх. У обычного блока это
   безобидно: оба правила по одному классу, и решает порядок в файле,
   а `.anim-visible` стоит ниже. А `.anim-hidden.anim-inner` — ДВА класса,
   он сильнее, и его сдвиг перебивал `translateY(0)` из `.anim-visible`.
   Значит всё внутреннее — текст статьи, поля редактора, строки списков —
   проявлялось, но НЕ доезжало: так и оставалось на 16px ниже своего места.

   Замерено покадрово: прозрачность шла 0 → 100%, а сдвиг стоял 16px
   от первого кадра до последнего.

   Правило обязано стоять ПОСЛЕ `.anim-hidden.anim-inner`: специфичность
   у них одинаковая, и решает порядок. Тот же капкан, что у `.card-leaving`
   и `.coll-card--fresh`. */
.anim-inner.anim-visible {
    transform: translateY(0);
}

/* Для части людей движение на экране — не украшение, а причина тошноты,
   и система об этом сообщает. Здесь страховка на случай, если класс всё же
   успел проставиться: показываем сразу и без перехода. */
@media (prefers-reduced-motion: reduce) {
    .anim-hidden,
    .anim-hidden.anim-inner,   /* сам по себе он специфичнее .anim-hidden
                                  и без этой строки перебил бы её здесь */
    .anim-visible {
        opacity: 1;
        transform: none;
        transition: none;
    }

    /* Уход тоже мгновенный. Сам ui.js в этом режиме класс не вешает вовсе,
       это страховка на случай, если он всё же успел проставиться. */
    .card-leaving {
        opacity: 0;
        transform: none;
        transition: none;
    }
}


/* ===========================================================================
   ДЛИННОЕ СЛОВО НЕ ДОЛЖНО РАЗДВИГАТЬ СТРАНИЦУ
   ===========================================================================

   Текст пишет человек, и он вправе прислать слово в тысячу букв без единого
   пробела. Браузер по умолчанию такое слово НЕ РАЗРЫВАЕТ: строка едет за
   край, а вместе с ней разъезжается и вся раскладка.

   Замерено на статье «До» с абзацем из одних «О»: колонка текста раздулась
   до 12239px при карточке в 1308, страница стала шире окна на 10865px,
   а картинка внутри взяла свои «100% ширины колонки» и выросла до тех же
   12239px. То есть раздутая картинка была не отдельной бедой, а следствием.

   Здесь собраны ВСЕ места, где показывается текст человека. Держать их
   вместе, а не по своим файлам, — сознательно: правило одно на всех, и когда
   появится новое такое место, его добавят сюда, а не будут искать по файлам.

   Отдельно от этого нужен `min-width: 0` тем колонкам, что лежат внутри
   flex: без него элемент не может стать уже своего содержимого, и перенос
   его уже не спасает (см. .editor-text-column в article.css). */

.field-title,              /* заголовок статьи */
.article-heading,          /* подзаголовки внутри статьи */
.article-body,             /* её текст */
.article-figure figcaption,
.thread-title,             /* обсуждение */
.thread-body,
.reply-text,
.disc-title,               /* карточка обсуждения */
.disc-text,
.moderation-card-title,    /* очередь проверки */
.rev-summary,              /* история правок */
.profile-name,             /* профиль */
.profile-bio,
.kart-iteml p,             /* подписи карточек */
.kart-item p,
.coll-card-title,          /* коллекционные карточки */
.coll-modal-title,
.coll-modal-desc,
.card-admin-title {
    overflow-wrap: break-word;
    word-break: break-word;
}
