/* ════════════════════════════════════════════
   ДОБРО ДОШЛИ
   One stylesheet for the whole site. Content files carry no styling
   of their own, so the design can be replaced here in one place.
   ════════════════════════════════════════════ */

/* ── ШРИФТЫ ──────────────────────────────────────────────────────────
   Всё лежит у нас, ничего не грузится со стороны. Файлы переменные:
   один на всё семейство вместо отдельного файла на каждое начертание.

   Один шрифт на весь сайт: заголовки отличаются от текста только весом.
   Golos Text сделан под русский и спокойно читается вдлинную.

   ПОЧЕМУ @font-face ТРИ РАЗА. Это не дубль и не ошибка — это три куска
   одного шрифта, и их разделяет строка unicode-range: кириллица,
   расширенная латиница, латиница. Браузер смотрит, какие буквы есть на
   странице, и качает только те куски, которые нужны: на русской странице
   — один файл вместо трёх.

   Если свести в одно объявление, unicode-range исчезнет, и браузер
   будет качать всё целиком. Загрузка шрифта вырастет втрое, а выгоды
   никакой. Трогать не нужно.
   ──────────────────────────────────────────────────────────────────── */
@font-face {
  font-family: 'Golos Text';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('/css/fonts/golos-text-cyrillic-wght-normal.woff2') format('woff2');
  unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
}
@font-face {
  font-family: 'Golos Text';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('/css/fonts/golos-text-latin-ext-wght-normal.woff2') format('woff2');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: 'Golos Text';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('/css/fonts/golos-text-latin-wght-normal.woff2') format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 16px; }

:root {
  /* ── ТИПОГРАФИКА ──
     Восемь стилей из кита дизайнера, и больше на сайте ничего нет:
     каждая надпись — один из них. Десктопные значения его, мобильные
     посчитаны от самого длинного слова: «Государственная» в 48 пунктах
     занимает 410 точек, а на телефоне под текст остаётся 342 — не
     влезает. При 30 занимает 256 и влезает даже в экран 320.

     Между крайними значениями браузер подбирает кегль сам, поэтому
     скачка на какой-то одной ширине нет.

        стиль    телефон        десктоп      начертание  трекинг
        h1       30 / 35        48 / 56      700         −1%
        h2       24 / 30        32 / 40      700         −0,5%
        h3       20 / 23        24 / 28      700          0
        лид      18 / 25        20 / 28      400          0
        текст    16 / 24        16 / 24      400          0
        мета     14 / 20        14 / 20      400          0
        цитата   16 / 28        16 / 28      500          0
        плашка   16 / 28        16 / 28      400/700      0

     Правка от 7 октября: дизайнер пересчитал интерлиньяжи и снял трекинг
     со всего, кроме двух верхних заголовков. Заголовки, лид и текст стали
     плотнее на два пункта, мета, цитата и плашка — просторнее на два.
     Логика видна: то, что читают залпом, сжалось, а то, что выхватывают
     глазами по строчке, разошлось. */
  --t-h1:    clamp(30px, 4.4vw, 48px);  --t-h1-lh:   1.167;
  --t-h2:    clamp(24px, 2.6vw, 32px);  --t-h2-lh:   1.25;
  --t-h3:    clamp(20px, 1.9vw, 24px);  --t-h3-lh:   1.167;
  --t-lead:  clamp(18px, 1.7vw, 20px);  --t-lead-lh: 1.4;
  --t-main:  16px;                      --t-main-lh: 1.5;
  --t-meta:  14px;                      --t-meta-lh: 1.43;
  /* Плашка живёт на том же кегле, что текст, но дышит шире — это отдельный
     интерлиньяж, а не «основной». */
  --t-callout-lh: 1.75;
  /* Цитата всего на две точки крупнее основного текста: разбивает полосу
     не кегль, а красная линейка слева. Почему так — в разделе про цитату
     ниже по файлу. */
  --t-quote: 18px;                      --t-quote-lh: 1.55;

  /* Таблица набрана мельче текста: в ячейке строка короткая, и крупный
     кегль только гонит таблицу в высоту. Шапка ещё на ступень мельче и
     капителью — она подпись к столбцу, а не его заголовок. */
  --t-table: 14px;  --t-table-lh: 1.45;  --t-table-head: 12px;

  --t-meta-w: 500;   /* мета по киту — Medium, а не Regular */
  --t-tight: -0.01em;                   /* −1%: только h1 */
  --t-half:  -0.005em;                  /* −0,5%: только h2 */
  --t-wide:  0;                         /* кит снял трекинг с меты */

  /* ── ШКАЛА ОТСТУПОВ ──
     Восьмиточечная сетка: все поля и промежутки на сайте — одна из этих
     ступеней, и больше ничего. Четвёрка в начале — половинная ступень,
     как принято в таких системах: ею набираются мелкие внутренние зазоры,
     где целых восемь уже много.

     Имя — это само число, а не «маленький» и «большой». Буквенные имена
     удобно читать, пока их три, а на десяти начинается спор, 24 — это
     «lg» или «xl», и переменную перестают угадывать и начинают искать.

     Девяносто значений по файлу округлены к ближайшей ступени; при равном
     расстоянии — вниз, потому что страницу просили ужать, а не раздуть.
     Что сдвинулось больше всего: боковые поля на телефоне с 20 на 16 и
     мелкие внутренние зазоры с 12 на 8.

     Исключение одно — поправки меньше четырёх точек. Это не отступы, а
     оптика: подчёркивание под ссылкой, строки списка в подвале, приём
     для экранного диктора в .visually-hidden. Там счёт идёт на пиксель,
     и сетка к ним отношения не имеет. */
  --space-4:   4px;
  --space-8:   8px;
  --space-16: 16px;
  --space-24: 24px;
  --space-32: 32px;
  --space-40: 40px;
  --space-48: 48px;
  --space-56: 56px;
  --space-64: 64px;
  --space-72: 72px;

  /* ── ВЕРТИКАЛЬНЫЙ РИТМ ──
     Второй столбец кита: сколько воздуха над элементом и под ним. Отступы
     не схлопываются — они складываются, как в макете: 8 под заголовком
     плюс 8 над абзацем дают 16. Поэтому поля, а не внешние отступы.

        элемент   сверху   снизу
        h1          0        24
        h2         48         8
        h3         24         8
        лид        24         8
        текст       8         0
        цитата     24        16
        плашка     32        16                                         */
  --p-h2-top:    var(--space-40);   /* 29.10: было 48 */
  --p-h3-top:    var(--space-24);
  --p-lead-top:  var(--space-32);   /* 29.10: было 24 */
  --p-head-bot:  var(--space-8);   /* общий низ у h2, h3 и лида */
  --p-h1-bot:    var(--space-24);
  --p-quote:     var(--space-24);   --p-quote-bot: var(--space-16);
  --p-callout:   var(--space-24);   --p-callout-bot: 0;   /* 27.10: было 40 и 16 */

  /* Воздух между абзацами. У дизайнера main_text получает сверху 8, и если
     понимать это буквально — по восемь точек на каждый абзац, — текст
     сливается в одну плиту: восемь точек это треть строки. Скорее всего
     в макете 8 стоит у блока текста целиком, а не у каждого абзаца.
     Держим это отдельной ручкой, чтобы решение было видно, а не спрятано
     в правиле. */
  --p-para:      var(--space-24);

  /* Воздух над списком. Меньше межабзацного: список продолжает фразу,
     которая его вводит («Понадобятся:»), и при 24 отрывался от неё.
     Двенадцать — половина межабзацного, ступени в шкале для неё нет,
     поэтому число стоит здесь, одно на весь файл. Правка 27 октября. */
  --p-list:      12px;

  /* Воздух перед вопросом в интервью. Он больше межабзацного нарочно:
     внутри ответа абзацы идут через 24, а новая пара «вопрос — ответ»
     начинается через 40 — так видно, где кончился один заход и начался
     следующий, даже если ответ занял пять абзацев. */
  --p-qa:        var(--space-32);   /* 29.10: было 40 — меньше, чем у h2 (40) */

  /* Колонка текста на карточке ленты: заголовок и лид делят её поровну.
     Размер подобран по лиду — по нему колонка и считалась исходно. */
  --card-col:    480px;   /* 30.10: было 400 — лид в 55–60 знаков, заголовок в три строки, а не в четыре */

  /* Ширина колонки чтения. Была 800: при кегле 16 это 89 знаков в
     строке, а читается спокойно 60–75. При 680 выходит 72. Кит требует
     этой правки молча — 16 пунктов в широкой колонке не работают. */
  --col: 680px;

  --header-h: 64px;

  /* Ширина страницы. На большом мониторе шапка, лента, список руководств
     и подвал больше не растягиваются на всё окно: содержимое стоит
     по центру в 1440 точках, а остаток окна уходит в поля поровну слева
     и справа. До 1488 точек ширины поле обычное, 24. Правка 29.10. */
  --page-max: 1440px;
  --page-x: max(var(--space-24), calc((100% - var(--page-max)) / 2 + var(--space-24)));
  /* Заголовок главной: высота вместе с его верхним отступом. */

  /* ── ЦВЕТА ──
     Шесть цветов на весь сайт плюс три исключения. До этой правки в файле
     лежало двадцать пять прописанных цветов, пятнадцать из них — оттенки
     серого, и соседние не различались глазом: #555, #666 и #6b6b6b стояли
     в одной и той же роли на разных страницах. Поменять «серый подписи»
     означало найти все четыре.

     Теперь роль определяет цвет, а не наоборот. Нужен новый оттенок —
     сначала вопрос, какая это роль; если роль уже есть, берём её цвет.

     Красный один на всё: ссылка при наведении, активный пункт, красная
     плашка. Он там, где ссылка и в покое выглядит ссылкой — подчёркнута
     или стоит в списке-навигаторе. И его нет на крупных заголовках
     карточек: заголовок и без того ведёт куда-то весь целиком. */
  --c-bg:      #FFFFFF;   /* фон страницы и карточек                      */
  --c-ink:     #111111;   /* текст, заголовки, сильные границы            */
  --c-accent:  #D83C0D;   /* ссылки, наведение, активное, красная плашка  */
  --c-muted:   #666666;   /* даты, авторы, подписи — второй голос         */
  --c-surface: #F2F2F2;   /* заливки: таблицы, плашки, место под фото     */
  --c-border:  #E0E0E0;   /* тонкие разделители и рамки полей ввода       */

  /* Седьмой серый, и он нужен. Шести цветов не хватает ровно на одно:
     отличить то, на что нельзя нажать, от того, на что можно. В списке
     руководств недописанный материал — не ссылка, и читатель должен
     видеть это, не наводя мышь. Если красить его основным серым, он
     станет неотличим от обычной подписи.

     Значение выбрано не на глаз: #888888 даёт на белом 3,5:1 — заметно
     светлее основного серого (5,7:1), но текст ещё читается. Прежний
     #c5c5c5 давал 1,9:1, то есть не читался вовсе.

     Тем же цветом набраны тонкие подчёркивания ссылок: это та же мысль —
     линия тише текста, но видна. */
  --c-quiet:   #888888;   /* неактивное и подчёркивания ссылок            */
}

/* Правка 29.10: на странице «Такой страницы нет» подвал стоит внизу
   экрана, а не посередине пустой страницы. */
body:has(> main.is-404) { min-height: 100vh; display: flex; flex-direction: column; }
body:has(> main.is-404) > main { flex: 1; }

body {
  background: var(--c-bg);
  color: var(--c-ink);
  font-family: 'Golos Text', system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none;}
img { display: block; max-width: 100%; }

/* Two rings, so the focus is visible on white, on black and on a photograph
   alike: the white one shows against dark, the black one against light. */
:focus-visible {
  outline: 2px solid var(--c-bg);
  outline-offset: 0;
  box-shadow: 0 0 0 4px var(--c-ink);
}

/* A card is a photograph with an absolutely positioned image on top, and in
   that arrangement the browser paints the picture over the outline. So the
   ring is a layer of its own, drawn above everything inside the card. */
.block-link, .next { position: relative; }

.block-link:focus-visible,
.next:focus-visible { outline: none; box-shadow: none; }

.block-link:focus-visible::after,
.next:focus-visible::after {
  content: "";
  position: absolute;
  inset: 4px;
  z-index: 10;
  border: 3px solid var(--c-bg);
  box-shadow: 0 0 0 3px var(--c-ink), inset 0 0 0 3px var(--c-ink);
  pointer-events: none;
}

/* Present for screen readers and search engines, invisible on screen. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Lets a keyboard or screen-reader user jump past the menu, which is
   repeated on every page. Invisible until it takes focus. */
.skip-link {
  position: fixed;            /* fixed, not absolute: it must stay reachable
                                 even when the page is already scrolled */
  left: 8px;
  top: -60px;
  z-index: 200;
  background: var(--c-ink);
  color: var(--c-bg);
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  letter-spacing: var(--t-wide);
  padding: var(--space-8) var(--space-16);
  transition: top 0.15s;
  line-height: var(--t-meta-lh);
}

.skip-link:focus { top: 8px; }

/* ── ШАПКА ── */
/* The bar itself is the site <header>; the two <nav> elements inside it are
   just groups of links — the menu and the languages — each with its own name.
   The class matters: <header> also marks the top of an article and of a
   section, and those must not turn into 48-pixel bars. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--c-bg);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-16);
  padding: 0 var(--page-x);
  height: var(--header-h);
  /* Прячется при прокрутке вниз, возвращается при прокрутке вверх. Двигаем
     только transform: браузер делает это на видеокарте, не пересчитывая
     раскладку страницы, поэтому листание остаётся плавным. Класс вешает
     js/header.js; без него шапка просто всегда на месте. */
  transition: transform 0.25s ease;
}

.site-header.is-hidden { transform: translateY(-100%); }

/* Если человек попросил систему не анимировать интерфейс — не анимируем:
   шапка остаётся видимой всегда. Скрипт это тоже проверяет и не включается,
   правило здесь на случай, если настройку поменяли при открытой странице. */
@media (prefers-reduced-motion: reduce) {
  .site-header { transition: none; }
  .site-header.is-hidden { transform: none; }
}

.site-header nav { display: flex; align-items: center; }

/* ── ЛОГОТИП И СТРОКА ИЗДАНИЯ ──
   Строка отбита от логотипа тонкой вертикальной линией: они рядом, но это
   не одна надпись. Мельче меню и серая — она объясняет, а не зовёт нажать,
   и спорить с навигацией ей незачем.

   Уже 1100 точек её нет: место в шапке там занято четырьмя пунктами меню и
   тремя языками, и втискивать туда ещё две строки текста значит сделать
   нечитаемым всё сразу. */
.head-brand { display: flex; align-items: center; gap: var(--space-24); min-width: 0; }

.logo { display: flex; align-items: center; flex: 0 0 auto; }
/* Высота 36, а не 28: на 64-точечной полосе прежний знак читался мелким.
   Пропорции не трогаем — задана только высота, ширину считает браузер. */
.logo img { height: 36px; width: auto; object-fit: contain; }
/* 30.10, п. 23 по просьбе дизайнера: знак 48 в высоту, пропорции те же.
   Только на широком экране: полоса там 64, сверху и снизу остаётся по 8.
   На телефоне знак прежний, 36, — там шапка в две строки. */
@media (min-width: 769px) { .logo img { height: 48px; } }

.head-slogan {
  margin: 0;
  padding-left: var(--space-24);
  border-left: 1px solid var(--c-border);
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  line-height: var(--t-meta-lh);
  color: var(--c-muted);
  max-width: 320px;
  letter-spacing: var(--t-wide);
}

@media (max-width: 1100px) {
  .head-slogan { display: none; }
}

.nav-links { display: flex; gap: var(--space-32); list-style: none; }

.nav-links a {
  display: block;
  padding: var(--space-24) var(--space-4);          /* слова 14px, площадь нажатия — 58 */
  font-size: var(--t-meta);
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--c-ink);
  transition: color 0.15s;
}

.nav-links a:hover { color: var(--c-accent); }
.nav-links a.is-current { font-weight: 700; }

/* ── СТРОКА О САЙТЕ ──
   Одна фраза под шапкой: что это за издание и для кого. Только на главной —
   там человек решает, его это сайт или нет. На странице материала он уже
   пришёл за конкретным текстом, и объяснение про весь проект отодвигало бы
   заголовок вниз без всякой пользы.

   Не в шапке, а под ней: шапка липкая и ездит за читателем, а такая фраза
   нужна один раз при встрече, а не всё время перед глазами. */
/* ── ПЕРЕКЛЮЧАТЕЛЬ ЯЗЫКОВ ── */
.lang-switch {
  display: flex;
  gap: var(--space-8);
  list-style: none;
  align-items: center;
}

/* Прямой потомок li — это сам код языка. Вложенный span внутри ссылки
   несёт название для экранного диктора и должен остаться размером
   в одну точку: без «>» отступы этого правила распирали его до 10×24,
   потому что .lang-switch span специфичнее, чем .visually-hidden. */
.lang-switch a,
.lang-switch li > span {
  display: block;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.1em;
  padding: var(--space-8) var(--space-4);
  transition: color 0.15s;
}

/* The language you are reading is marked by weight alone, the same way the
   current section is marked in the menu. */
.lang-switch .is-current {
  font-weight: 700;
  cursor: default;
}

/* Наведение красное, как везде по сайту, а не блёклое. Прозрачность здесь
   и была причиной: она гасила букву вместо того, чтобы её подсветить, и
   выглядело это поломкой, а не отзывом на мышь. */
.lang-switch a:hover,
.lang-switch .is-current:hover { color: var(--c-accent); }

/* Этот язык на сайте есть, но у этого материала его нет, поэтому ссылка
   ведёт на главную того языка, а не в пустую страницу. Отличается он
   тем же тихим серым, каким набрано всё неактивное на сайте, — раньше
   была прозрачность, то есть ещё один способ сказать то же самое. */
.lang-switch a.is-missing { color: var(--c-quiet); }
.lang-switch a.is-missing:hover { color: var(--c-accent); }

/* ── ОБЩИЕ ЭЛЕМЕНТЫ КАРТОЧЕК ──
   На карточке остались заголовок и лид. Подпись раздела и строка с датой
   и автором убраны — см. templates/card.php, там написано почему. */
/* Заголовок карточки держится той же колонки, что и лид под ним, — одной
   на двоих и заданной одним числом, чтобы они не могли разъехаться.

   Колонка нужна не для красоты: без неё заголовок тянулся во всю ширину
   своей половины, и на широком экране выходила строка, которую глаз не
   читает как заголовок — к концу строки он уже забыл начало. У снимка во
   весь блок это ограничение стояло, а у плашки рядом со снимком нет, и
   два соседних блока на главной набирались по-разному. Теперь правило
   одно и стоит у самого заголовка, а не у одного из мест, где он бывает. */
/* Правка 30.10 по просьбе дизайнера: заголовок на обложке — это h2, и
   набран он теперь как h2 в статье (32/40, трекинг −0,5%), один стиль на
   все обложки. Раньше стоял стиль h3 (24/28). */
.card-title {
  font-size: var(--t-h2);
  font-weight: 700;
  line-height: var(--t-h2-lh);   /* 1.08 × 1.1 */
  letter-spacing: var(--t-half);
  margin-bottom: var(--space-16);
  max-width: var(--card-col);
}

/* Серый «второй голос» — один цвет из палитры, а не чёрный, разбавленный
   прозрачностью. Прозрачность 0,6 / 0,7 / 0,75 давала ещё три оттенка
   серого сверх палитры. Правка 27 октября. */
.card-lede {
  font-size: var(--t-main);
  font-weight: 400;
  line-height: var(--t-main-lh);
  color: var(--c-muted);
  max-width: var(--card-col);
  letter-spacing: 0;
}

.block-link { cursor: pointer; }
/* При наведении заголовок своего цвета не меняет. Раньше ему сбавляли
   прозрачность до 0,7, и одно правило давало два противоположных
   результата: чёрный заголовок на белой плашке светлел, а белый поверх
   фотографии темнел — сквозь него проступал снимок. Белый заголовок
   должен оставаться белым.

   Знак наведения при этом не пропал: снимок под курсором притемняется
   сам, строкой ниже. Этого довольно — блок и так целиком ссылка, и
   курсор об этом говорит первым. */
.block-link img { transition: filter 0.3s, transform 0.4s; }
.block-link:hover img { filter: brightness(0.92); }
/* Правка 30.10: наведение заметнее — снимок чуть приближается (на 3%)
   внутри своей рамки, как в журнальных лентах. Рамка не двигается:
   у блоков стоит overflow: hidden. */
.block-link:hover img { transform: scale(1.03); }

/* Правка 29.10 по просьбе дизайнера: заголовок карточки тоже отзывается
   на наведение — тёмный светлеет, белый чуть темнеет, как у «Следующего
   материала». Не прозрачностью, а цветом из палитры: так сквозь белый
   заголовок не проступает фотография (из-за этого прозрачность здесь
   и убирали, см. выше). */
.block-link .card-title { transition: color 0.3s; }
.block-link:hover .card-title { color: var(--c-muted); }
.block-link:is(.block-hero, .block-banner, .block-dark):hover .card-title { color: var(--c-border); }

/* Panes shared by the split / dark / light cards. */
.block-pane-text {
  padding: var(--space-48);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 480px;
}

.block-pane-image { overflow: hidden; min-height: 480px; }
.block-pane-image img { width: 100%; height: 100%; object-fit: cover; }

.block-pane-over { position: relative; overflow: hidden; min-height: 480px; }
.block-pane-over img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* Text laid over a photograph. */
.block-overlay { position: absolute; inset: 0; }

.block-overlay-content {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  padding: var(--space-48);
  color: var(--c-bg);
}

/* Measured against the lightest pixels actually found under each line:
   at the old values the lede sat at 2.4:1 where 4.5:1 is required. */
.block-overlay-content .card-lede { color: rgba(255,255,255,0.72); }   /* было 0,95 × прозрачность 0,75 — вид тот же */
/* 30.10, п. 22 по просьбе дизайнера: на обложке с текстом поверх фото
   заголовок шире — до 560, лид остаётся в колонке 480. На планшете и
   телефоне ширину и так ограничивает сам блок. */
.block-overlay-content .card-title { max-width: 560px; }

/* ── ПЕРВЫЙ ЭКРАН ГЛАВНОЙ: РУКОВОДСТВА ──
   На месте, где раньше была фотография во весь экран, стоит список
   руководств. Высота та же: один экран без прокрутки, чтобы следующий
   блок начинался ровно за краем, а не выглядывал снизу наполовину.

   Раскладка списка своя не нужна — это тот же навигатор, что на странице
   руководств, те же .rubrics и .rubric-list. Один список, одни правила. */
/* Заголовок главной: что это за издание и что здесь делают. Стоит над
   первым экраном, а не внутри навигатора руководств, — навигатор под ним
   один из разделов, а не вся страница. */
/* Слоган издания на главной — единственный заголовок первого уровня
   на странице.

   Не самый крупный кегль в наборе, хотя это и h1. Под ним сразу идёт
   фотография во весь экран с собственным заголовком поверх, и слоган
   в 48 пунктов спорил бы с ней за внимание. Его дело — сказать, чем тут
   занимаются, и уступить место историям.

   Ширина по колонке чтения: строка в семьдесят знаков ломается надвое там,
   где надо, а не там, где кончился экран. */
/* Заголовок главной — тот же предмет, что заголовок раздела, и набран так
   же: один кегль, один вес, один трекинг, одни отступы. Раньше он был на
   ступень мельче (h2), и «Люди и места» на главной выглядели младше, чем
   «Люди» на своей странице, — хотя это одна и та же вещь, названная один
   раз крупно и один раз мелко. */
.home-title {
  font-size: var(--t-h1);
  font-weight: 700;
  line-height: var(--t-h1-lh);
  letter-spacing: var(--t-tight);
  margin: 0;
  padding: var(--space-40) var(--space-24) var(--space-24);
  max-width: calc(var(--col) + 48px);
  margin-left: calc(var(--page-x) - var(--space-24));   /* 29.10: вровень с лентой */
}

/* ── ЛЕНТА ──
   Карточки лежат на странице, а не упираются в края окна. Поле вокруг
   каждой и щель между ними делают их отдельными предметами на белом, —
   а не сплошной полосой фотографий от края до края, где непонятно, где
   кончается одна история и начинается следующая.

   Поле заодно показывает, что фон у сайта белый: без него страница со
   сплошными фотографиями читается как тёмная. */
.feed {
  display: flex;
  flex-direction: column;
  gap: var(--space-32);   /* 30.10: было 24 */
  padding: 0 var(--page-x) var(--space-24);
}

/* ── БЛОК: ГЛАВНЫЙ БАННЕР ── */
/* Потолок высоты — 720 точек.

   Раньше блок занимал весь экран без остатка: на мониторе 1080 это 1016
   точек фотографии, то есть первый экран целиком и ни строки текста. На
   широком столе такая обложка не впечатляет, а загораживает: человек
   пришёл за историями, а видит одну картинку и полосу прокрутки.

   Семьсот двадцать — высота, при которой под обложку ещё видно начало
   ленты на любом ноутбуке. На невысоком экране работает прежнее правило
   (экран минус шапка), потому что min берёт меньшее из двух: потолок
   опускает высоту там, где её много, и не трогает там, где её мало.

   Снимок при этом по-прежнему подрезается: это неизбежно, см. разбор
   в ревью. Полоса идёт во всю ширину, и показать в ней кадр целиком
   можно только одним способом — сделать полосу высотой с кадр, то есть
   вернуться к тому, от чего уходим. */
.block-hero {
  position: relative;
  display: block;
  width: 100%;
  height: min(calc(100vh - var(--header-h)), 720px);
  height: min(calc(100svh - var(--header-h)), 720px);
  min-height: 560px;
  overflow: hidden;
}

/* На главной первая фотография делит экран со слоганом, а не забирает его
   себе целиком. Раньше забирала: высота считалась от всего окна, слоган
   вставал сверху лишним этажом, и нижние восемьдесят восемь точек карточки
   вместе с лидом уезжали за край. Заголовок было видно, лид — нет.

   Высота слогана вычитается числом. Передать её соседу по разметке нечем,
   а обёртка, которая мерила бы её сама, разрезала бы ленту надвое и сломала
   подгрузку следующих страниц. Числу тут можно верить: слоган упирается
   в колонку чтения и во всех трёх языках занимает ровно две строки на
   большом экране и три на телефоне.

   Вычитается не вся высота слогана, а на сорок точек меньше: столько
   фотография выглядывает из-под нижнего края. У экрана, заполненного точно
   по границу, нет признака, что страница продолжается, и часть людей просто
   не прокручивает дальше. */
.feed > .block-hero:first-child {
  /* Тот же потолок, что и у остальных обложек: на высоком экране высоту
     задаёт он, на невысоком — прежний расчёт по экрану. */
  height: min(calc(100vh - var(--header-h) - 96px), 720px);
  height: min(calc(100svh - var(--header-h) - 96px), 720px);
}

/* Подписи этой карточки нижнего поля положено больше, чем остальным:
   сорок точек фотографии уходят за край окна, и подпись, лежащая
   в сорока восьми точках от низа, оказалась бы ровно на линии сгиба.
   Семьдесят две оставляют под лидом тридцать две точки воздуха. */
.feed > .block-hero:first-child .block-overlay-content { padding-bottom: var(--space-72); }

.block-hero > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.block-hero .block-overlay,
.block-banner .block-overlay {
  background: linear-gradient(to top, rgba(0,0,0,0.92) 0%, rgba(0,0,0,0.30) 28%, rgba(0,0,0,0.0) 62%, transparent 100%);
}

/* ── БЛОК: БАННЕР НА ВСЮ ШИРИНУ ── */
/* Та же мера для баннера: 70 процентов экрана, но не выше 560. На мониторе
   1080 это 756 точек против 560 — разница в треть, и она вся уходила в
   воздух над строкой и под ней. */
.block-banner {
  position: relative;
  display: block;
  width: 100%;
  height: min(70vh, 560px);
  min-height: 420px;
  overflow: hidden;
}

.block-banner > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Правка 29.10 по просьбе дизайнера: у баннера больше нет сплошного
   затемнения на весь снимок — та же растяжка снизу, что у главной
   карточки: темно только под текстом. */
.block-banner .block-overlay-content { max-width: 680px; }

/* ── БЛОКИ В ДВЕ КОЛОНКИ ── */
.block-split,
.block-dark,
.block-light { display: grid; grid-template-columns: 1fr 1fr; }

.block-dark .block-pane-text { background: var(--c-ink); color: var(--c-bg); }
.block-dark .block-pane-text .card-lede { color: rgba(255,255,255,0.6); }   /* было 0,8 × 0,75 — вид тот же */

/* ── ЗАГОЛОВОК РАЗДЕЛА ── */
/* Сорок точек от шапки до заголовка и двадцать четыре от заголовка до
   текста — одна пара на все страницы сайта: главную, раздел, руководство,
   статью. Раньше их было три разных (32, 56 и 72 сверху), и переход от
   шапки к тексту на каждой странице читался по-своему.

   Сорок — число дизайнера из прошлого круга правок. Двадцать четыре —
   из кита: столько воздуха кит отводит под h1. Так что снизу заголовок
   держит собственное правило, а сверху — правило страницы, и спорить им
   не о чем. Сверху больше, чем снизу: заголовок должен липнуть к тому,
   что под ним, а не висеть между шапкой и текстом ровно посередине. */
.section-head {
  padding: var(--space-40) var(--space-24) var(--space-24);
  max-width: 900px;
  margin-left: calc(var(--page-x) - var(--space-24));   /* 29.10: вровень с лентой */
}

.section-head h1 {
  font-size: var(--t-h1);
  font-weight: 700;
  line-height: var(--t-h1-lh);
  letter-spacing: var(--t-tight);
  margin-bottom: var(--p-h1-bot);
}

.section-head h1:last-child { margin-bottom: 0; }
/* Правка 29.10: если под заголовком раздела ничего нет (Люди, Места),
   отступа под самим заголовком не нужно — от заголовка до первой
   фотографии остаётся 24, ровно как от «Люди и места» на главной.
   Было 48. Когда под заголовком есть подпись, 24 между ними остаются. */

.section-head p {
  font-size: var(--t-lead);
  line-height: var(--t-lead-lh);
  max-width: 560px;
  color: var(--c-muted);   /* было opacity 0.7 */
  font-weight: 400;
  letter-spacing: 0;
}

.section-head-action { margin-top: var(--space-24); }
.section-head-action a { display: inline-block; padding: var(--space-8) 0; border-bottom: 1px solid var(--c-ink); }

.empty { padding: var(--space-72) var(--space-24); color: var(--c-muted); }   /* было opacity 0.6 */

/* ── КОНЕЦ ЛЕНТЫ: ссылка «дальше» ── */
.feed-more {
  padding: var(--space-48) var(--space-24) var(--space-64);
  display: flex;
  justify-content: center;
  border-top: 1px solid var(--c-ink);
}

.feed-more a {
  font-size: var(--t-meta);
  letter-spacing: var(--t-wide);
  font-weight: 600;
  border: 1px solid var(--c-ink);
  padding: var(--space-16) var(--space-24);
  transition: background 0.2s, color 0.2s;
  line-height: var(--t-meta-lh);
}

.feed-more a:hover { background: var(--c-ink); color: var(--c-bg); }
.feed-more.is-loading a { opacity: 0.4; pointer-events: none; }

.feed-end {
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  letter-spacing: var(--t-wide);
  color: var(--c-muted);   /* было opacity 0.6 */
  line-height: var(--t-meta-lh);
}

/* ════════════════════════════════════════════
   ГАЙДЫ — навигатор: все материалы на одной странице
   ════════════════════════════════════════════ */

/* Раскрывашек здесь нет. Рубрика, которую надо открыть, ставит между
   читателем и списком одно решение — и решение это про нашу редакционную
   классификацию, а не про его вопрос. «Можно ли снять квартиру без
   боравака» честно лезет сразу в три рубрики, так что выбор первой — это
   просьба угадать, как мы раскладываем по полкам. Поэтому видно всё сразу,
   а рубрики работают как способ разложить длинную страницу, а не как двери
   перед ней.

   Группы стоят газетными колонками: три на широком экране, две на среднем,
   одна на телефоне. Колонки не ради красоты — без них список из пяти рубрик
   уезжает на три экрана вниз, и рубрику от рубрики приходится искать
   прокруткой.

   Три толщины линий, и это главное в раскладке: строка переходов отбита
   сверху чёрной линией, гайды внутри рубрики — светло-серой в 1 пиксель,
   а между рубриками линий нет вовсе. Разделяет их не линия, а воздух и
   кегль заголовка: в колонках линия поперёк читалась бы как край колонки,
   а не как край группы. */
/* Сетка, а не газетные колонки.
   Колонки (columns: 3) переливали разделы сверху вниз, как текст, и второй
   ряд заголовков вставал на разной высоте: где над ним было шесть строк,
   где четыре. Глаз читает такие заголовки не как ряд равных разделов,
   а как случайную россыпь.

   В сетке высоту ряда задаёт самый длинный раздел в нём, и все заголовки
   следующего ряда начинаются с одной линии. Платим за это воздухом под
   короткими разделами — но пустое место под списком читается как поле,
   а сбитая линия заголовков читается как небрежность.

   Порядок при этом меняется с колоночного на строчный: разделы идут слева
   направо, как в тексте, а не сверху вниз по первой колонке. Это и есть
   порядок переезда, в котором они стоят в движке. */
/* Чёрной линейки над списком больше нет, и своего верхнего поля у списка
   тоже. Линейка отрезала навигатор от заголовка, под которым он стоит, —
   а это одна вещь: название раздела и его содержимое. Воздух между ними
   теперь ровно тот же, что между заголовком и текстом на любой другой
   странице, — его целиком даёт нижнее поле заголовка. */
.rubrics {
  margin: 0 var(--page-x);
  padding: 0 0 var(--space-72);
  max-width: 1440px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0 var(--space-64);
  align-items: start;
}

.rubric {
  margin: 0 0 var(--space-48);
}

/* Рубрика на ступень крупнее гайда внутри неё: это единственное, что
   показывает, кто кого содержит. */
.rubric-title {
  display: block;
  margin: 0 0 var(--space-8);
  font-size: var(--t-h3);
  font-weight: 700;
  line-height: var(--t-h3-lh);
  letter-spacing: 0;
  color: var(--c-quiet);
}
.rubric-title a:hover { color: var(--c-accent); border-bottom-color: var(--c-accent); }
.rubric-title a{ color: var(--c-ink); border-bottom: 1px solid var(--c-ink); }

/* ── СПИСОК ГАЙДОВ ВНУТРИ РУБРИКИ ── */
.rubric-list { list-style: none; margin: 0; padding: 0; }

/* Линеек между строками нет. Они чертили сетку там, где её никто не искал:
   список и так читается списком — по левому краю, по одинаковому кеглю,
   по ровному шагу. Линейка нужна, когда в строке несколько столбцов и глаз
   может съехать на соседнюю, а здесь столбец один.

   Вместо линейки работает воздух: шаг между строками чуть больше, чем был
   с ними, — иначе названия в две строки сливаются с соседними. */
.rubric-list li {
  margin: 0;
  padding: var(--space-4) 0;
}

/* Внутри навигатора название гайда — обычный текст со ссылкой, а не
   заголовок в полный голос: рубрика над ним должна оставаться крупнее.
   Подчёркивание тонкое и серое, чтобы список читался как список, а не как
   ряд подчёркнутых строк. */
.rubric-list .guide-title {
  font-size: var(--t-main);
  font-weight: 400;
  line-height: var(--t-main-lh);
  letter-spacing: 0;
  margin: 0;
}

.rubric-list .guide-title a {
  border-bottom: 1px solid var(--c-quiet);
}
.rubric-list .guide-title a:hover { color: var(--c-accent); border-bottom-color: var(--c-accent); }

/* Гайд, которого ещё нет. Не ссылка и не выглядит ссылкой: ни чёрного цвета,
   ни подчёркивания, нажать не на что, в пустую страницу не попасть. Отличие
   не только в цвете: подчёркивание либо есть, либо нет. */
.rubric-list .guide-title.is-soon { color: var(--c-quiet); }

/* ── КАЛЬКУЛЯТОР В ТЕКСТЕ ──
   Выглядит как плашка и стоит на той же серой заливке: читатель и так знает
   по этому фону, что перед ним вставка, а не продолжение статьи. Отличие
   одно — с ним можно разговаривать.

   Пустым не бывает виден: без скрипта внутри ничего нет, а поля и фон
   появляются вместе с содержимым. Поэтому фон задан не самой метке, а
   заголовку и полям внутри неё — точнее, метке, но только когда она
   непустая. */
/* Единственное скруглённое место на сайте, и это нарочно. Всё остальное —
   текст, который читают; калькулятор — прибор, в который тыкают. Мягкие углы
   отделяют его от страницы и говорят, что с ним можно повозиться. Радиус
   небольшой: ещё немного, и из прибора получится игрушка. */
.article-body > .calc:not(:empty) {
  background: var(--c-surface);
  padding: var(--space-24) var(--space-24) var(--space-24);
  margin: var(--space-40) 0;
  border-radius: 14px;
}

.calc-head {
  font-size: var(--t-main);
  font-weight: 700;
  line-height: var(--t-main-lh);
  letter-spacing: 0;
  margin: 0 0 var(--space-16);
}

/* На широком экране страна и дата стоят рядом, на узком — друг под другом.
   Переносится по месту, а не по ширине экрана: калькулятор может оказаться
   и в узкой колонке. */
.calc-row { display: flex; flex-wrap: wrap; gap: var(--space-16); }

.calc-field { display: flex; flex-direction: column; gap: var(--space-4); flex: 1 1 200px; }
.calc-field[hidden] { display: none; }

.calc-label {
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  line-height: var(--t-meta-lh);
  letter-spacing: var(--t-wide);
  color: var(--c-muted);
}

/* Поля белые на серой заливке: так видно, что это поля, а не текст.
   Высота 44 — палец попадает. Оба поля текстовые: и страна, и дата
   набираются, а не выбираются. */
.calc input[type="text"] {
  font: inherit;
  font-size: var(--t-main);
  line-height: var(--t-main-lh);
  color: var(--c-ink);
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  border-radius: 8px;
  padding: var(--space-8) var(--space-8);
  min-height: 44px;
  width: 100%;
  box-sizing: border-box;
  -webkit-appearance: none;
  appearance: none;
}

.calc input[type="text"]::placeholder { color: var(--c-quiet); }

.calc input[type="text"]:focus-visible {
  outline: 2px solid var(--c-ink);
  outline-offset: 1px;
}

/* ── ОТВЕТ ──
   Главная строка лежит в белом окошке, объяснение — под ним. Раньше это был
   один абзац, и дата выезда, ради которой всё затевалось, стояла у него
   в середине наравне с оговорками. Окошко вынимает её из текста: человек
   видит её раньше, чем начинает читать. */
.calc-answer { margin-top: var(--space-16); }

/* Подпись над окошком — та же, что над полями: ответ и есть третье поле,
   только заполняет его калькулятор. Там, где в окошке не дата, подписи нет,
   и пустая строка не должна занимать место. */
.calc-cap { display: block; margin-bottom: var(--space-4); }
.calc-cap:empty { display: none; }

.calc-out {
  background: var(--c-bg);
  border-radius: 10px;
  padding: var(--space-16) var(--space-16);
  margin: 0;
  font-size: var(--t-lead);
  line-height: var(--t-h3-lh);
  font-weight: 700;
  letter-spacing: 0;
}

/* Пока страна или дата не введены, окошко не отвечает, а просит — и держится
   тише: жирная чёрная строка «Укажите день въезда» читалась бы как ответ. */
.calc-out.is-ask {
  font-size: var(--t-main);
  line-height: var(--t-main-lh);
  font-weight: 500;
  letter-spacing: 0;
  color: var(--c-muted);
}

.calc-hint {
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  line-height: var(--t-meta-lh);
  letter-spacing: var(--t-wide);
  color: var(--c-muted);
  margin: var(--space-8) 0 0;
}

.calc-hint:empty { display: none; }

.calc-note {
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  line-height: var(--t-meta-lh);
  letter-spacing: var(--t-wide);
  color: var(--c-muted);
  margin: var(--space-16) 0 0;
}

/* ── ЧИТАЙТЕ ТАКЖЕ ──
   Подборка, собранная редактором руками, а не следующий материал по порядку.
   Стоит в конце текста и отделена чёрной линией: статья кончилась, дальше
   советы.

   Материал, который ещё пишется, стоит здесь серым и без подчёркивания —
   ровно как в списке руководств. Обещание, что он будет, честнее пустоты,
   а нажать не на что, и в несуществующую страницу читатель не попадёт. */
.article-body > .also {
  margin: var(--space-56) 0 0;
  border-top: 1px solid var(--c-ink);
  padding-top: var(--space-16);
}

.also h3 {
  font-size: var(--t-meta);
  font-weight: 700;
  line-height: var(--t-meta-lh);
  letter-spacing: var(--t-wide);
  color: var(--c-muted);
  margin: 0 0 var(--space-8);
}

.also ul { list-style: none; margin: 0; padding: 0; }

.also li {
  margin: 0;
  padding: var(--space-8) 0;
  border-bottom: 1px solid var(--c-border);
}
.also li:last-child { border-bottom: none; }

.also a { border-bottom: 1px solid var(--c-quiet); }
.also a:hover { color: var(--c-accent); border-bottom-color: var(--c-accent); }

.also li.is-soon { color: var(--c-quiet); }


@media (max-width: 1100px) {
  .rubrics { grid-template-columns: repeat(2, 1fr); gap: 0 var(--space-48); }
}

@media (max-width: 768px) {
  .rubrics { grid-template-columns: 1fr; margin: 0 var(--space-16); padding: 0 0 var(--space-64); }
  .rubric { margin-bottom: var(--space-40); }
}


/* ── СТРАНИЦА ОДНОГО ГАЙДА ──
   Строки с рубрикой и значком над заголовком больше нет: см. guide.php. */

/* ── СНОСКА К РУКОВОДСТВУ ──
   Оговорка о том, что руководство — не юридическая консультация. Стоит
   в конце текста, под звёздочкой, и набрана меткой: это примечание к
   инструкции, а не её часть, и в общий голос текста ей вставать незачем.

   Звёздочка висит на поле, а не съедает первую строку: текст сноски идёт
   ровным прямоугольником, как и положено примечанию. Отбивка сверху та
   же, с какой в тексте отбивается цитата, — это тоже отступление от
   основного потока, только последнее. */
.guide-note {
  max-width: var(--col);
  margin: 0 auto;
  /* Снизу 72 — столько же было под ссылкой «Все руководства», которая
     раньше замыкала страницу. Сноска теперь последняя, и воздух до подвала
     переехал к ней. */
  padding: var(--space-40) var(--space-24) var(--space-72);
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  line-height: var(--t-meta-lh);
  letter-spacing: var(--t-wide);
  color: var(--c-muted);
}

/* 30.10: the asterisk before the note is removed, by request. */

.guide-back {
  max-width: var(--col);
  margin: var(--space-56) auto 0;
  padding: 0 var(--space-24) var(--space-72);
}

.guide-back a {
  display: inline-block;
  padding: var(--space-8) 0;
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  letter-spacing: var(--t-wide);
  border-bottom: 1px solid var(--c-ink);
  padding-bottom: 2px;
  transition: color 0.15s, border-color 0.15s;
  line-height: var(--t-meta-lh);
}

.guide-back a:hover { color: var(--c-accent); border-bottom-color: var(--c-accent); }

.next-plain { grid-template-columns: 1fr; }

.page-tail { height: 80px; }

/* ════════════════════════════════════════════
   СТРАНИЦА СТАТЬИ
   ════════════════════════════════════════════ */

/* Интервью читается в колонке пошире, чем руководство, и вот почему.
   У руководства слева висит содержание, справа выноски — колонка зажата
   между ними, и шире ей быть некуда. У интервью содержания нет: вопросы
   сами по себе работают оглавлением, и место слева пустует.

   Восемьдесят один знак в строке вместо семидесяти двух. Это выше
   классических семидесяти пяти, и для сплошного текста я бы так не делал,
   но интервью — короткие реплики с жирными вопросами через каждые
   несколько строк: глаз не теряет строку, потому что ему не приходится
   долго идти подряд.

   Честно говоря, длину материала это чинит слабо: страница становится
   короче всего на десятую часть. От ощущения бесконечности спасает не
   ширина, а то, что по тексту расставлены вопросы, за которые цепляется
   взгляд. */
.is-article { --col: 680px; }   /* 30.10, п. 29: было 760 — колонка статьи теперь как у руководства */
/* Воздух под шапкой больше, чем щели внутри неё. Внутри шапки всё про одно
   и то же — что за материал, кто написал, о чём он, — и там хватает восьми
   точек. Под шапкой начинается другое: сам материал. Если оставить те же
   восемь, лид сливается с первым абзацем в одну плиту, и читатель не видит,
   где кончилось обещание и начался текст.
   Тридцать две под шапкой плюс восемь под лидом — сорок до текста
   у руководства и столько же до фотографии у статьи. */
.article-header { max-width: var(--col); margin: 0 auto; padding: var(--space-40) var(--space-24) var(--space-24); }

/* Выходные данные: дата, автор, иногда «поправлено».

   У руководства эта строка стоит над заголовком, у статьи — под текстом,
   и это разные вопросы, а не разнобой. Статью читают ради истории, она не
   стареет, и кто её написал — вопрос послесловия. Руководство читают ради
   порядка действий, который государство может поменять в любой месяц, и
   первое, что надо знать, — насколько оно свежее. */
.article-meta {
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  letter-spacing: var(--t-wide);
  line-height: var(--t-meta-lh);
  margin-bottom: var(--space-16);
}

/* Внизу страницы у строки своя колонка и свои поля: она лежит уже не внутри
   .article-header, и ширину с отступами взять ей не у кого. Линейки над
   строкой нет: с ней низ статьи получался полосатым — линия над автором и
   сразу линия над следующим материалом. Строку отделяет от текста воздух. */
.article-meta.is-foot {
  max-width: var(--col);
  margin: var(--space-56) auto 0;
  padding: var(--space-16) var(--space-24) var(--space-40);
}

/* Серым и с воздухом — только палочки-разделители. Куски самой строки тоже
   лежат в span'ах, и без этой оговорки они красились бы серым вместе
   с палочками и разъезжались полями. */
.article-meta span:not(.meta-part) { color: var(--c-muted); margin: 0 var(--space-4); }

/* Кусок строки не рвётся внутри себя: ни имя пополам, ни год отдельно от
   месяца. Строка переносится только на границе кусков — там, где палочка. */
.article-meta .meta-part { white-space: nowrap; }

/* «Руководство» в строке над заголовком — ссылка на все руководства.
   Вид — как у остальных ссылок-заголовков в разделе: подчёркивание
   линейкой, при наведении красное (правило наведения одно на весь сайт). */
.article-meta .meta-home { border-bottom: 1px solid var(--c-ink); transition: color 0.15s, border-color 0.15s; }
.article-meta .meta-home:hover { color: var(--c-accent); border-bottom-color: var(--c-accent); }

.article-header h1 {
  font-size: var(--t-h1);
  font-weight: 700;
  line-height: var(--t-h1-lh);
  letter-spacing: var(--t-tight);
  /* Под заголовком статьи своего поля нет: лид всегда идёт следом и
     сам отбивается сверху на 24. Было 24 + 24 = 48. Правка 27.10. */
  margin-bottom: 0;
}

/* От лида до текста — 32: восемь под лидом плюс двадцать четыре над
   первым абзацем. Поле шапки снизу нужно только перед обложкой; если
   за шапкой сразу текст (руководства), оно лишнее. Правка 27.10. */
.article-header:has(+ .article-body) { padding-bottom: 0; }

.lede {
  font-size: var(--t-lead);
  font-weight: 400;
  line-height: var(--t-lead-lh);
  padding-top: var(--p-lead-top);
  padding-bottom: var(--p-head-bot);
  letter-spacing: 0;
}

/* Обложка — такой же снимок во всю ширину, как figure.full в тексте, и
   место в стопке ей нужно то же: выше плавающего содержания, ниже шапки.
   Иначе белая плашка оглавления выезжает прямо на фотографию, с которой
   материал начинается. Правило продублировано у figure.full внизу файла;
   там же написано, почему именно 41. */
.article-cover { width: 100%; margin: var(--space-24) 0; position: relative; z-index: 41; }   /* 29.10: было 48 и 48 */
/* Перед обложкой поле шапки снизу не нужно: от лида до снимка остаются
   8 под лидом и 24 над обложкой — 32. Было 80. Правка 29.10. */
.article-header:has(+ .article-cover) { padding-bottom: 0; }
/* От обложки до текста — ровно 48: 24 под обложкой и 24 над первым
   блоком. Первому блоку статьи верхнее поле обычно снимается, и в статье
   без оглавления текст прилипал к снимку, а в статье с оглавлением
   выходило 72. После обложки первый блок своё поле сохраняет. */
.article-cover + .article-body > :first-child:not(.toc-float) { padding-top: var(--p-para); --note-top: var(--p-para); }
/* Высота обложки. Полоса 16:9 во всю ширину растёт вместе с экраном: на
   ноутбуке 1440 она выходила 810 точек — выше самого окна, на мониторе
   1920 — 1080. Теперь у неё два потолка, срабатывает меньший:
   — 800 точек: заметно ниже прежнего, но всегда выше большой карточки на
     главной (там потолок 720) — обложка статьи главнее карточки;
   — высота окна без шапки и без 48 точек: когда обложка доезжает до верха,
     под ней видна полоска текста, и ясно, что дальше есть чтение.
   Ширина не трогается: снимок по-прежнему во всю полосу, лишнее
   срезается сверху и снизу (object-fit: cover), а не сжимает кадр.
   svh — высота окна без выезжающей панели браузера на телефоне; строка
   с vh перед ней — для браузеров, которые svh не знают.

   height: auto обязателен. Без него высоту диктовал атрибут height из
   тега (у всех обложек 1067), пропорция 16:9 молчала, и обложка была
   1067 точек на любом экране — на телефоне шириной 390 тоже: узкая
   высокая щель вместо полосы. Та же ловушка описана у снимков в тексте. */
.article-cover img {
  width: 100%; height: auto; aspect-ratio: 16/9; object-fit: cover; background: var(--c-surface);
  max-height: min(800px, calc(100vh - var(--header-h) - var(--space-48)));
  max-height: min(800px, calc(100svh - var(--header-h) - var(--space-48)));
}

/* Что не обрезать у обложки. Поле «Обложка: что не обрезать» в админке
   (image_focus в файле). По умолчанию кадр режется поровну сверху и снизу;
   «верх» оставляет верх целым — для шпилей, башен, лиц, — «низ» наоборот.
   Работает везде, где обложка подрезается: на странице статьи, в карточке
   ленты и в блоке следующего материала. */
img.focus-top    { object-position: 50% 0; }
img.focus-bottom { object-position: 50% 100%; }

/* ── СОДЕРЖАНИЕ ──
   Блок в тексте: список подзаголовков, редакция сама решает, где он стоит.
   Список собирает движок из самих заголовков, в файле материала лежит пустая
   метка <nav class="toc"></nav> — устареть такой список не может.

   Заголовок «Содержание» не нужен: девять ссылок подряд после подводки
   читаются как оглавление и без подписи. Диктору же он нужен, поэтому
   стоит в aria-label, а не на экране.

   Без номеров. Номер в оглавлении обещает, что разделы пронумерованы и в
   самом тексте, — а они не пронумерованы. Порядок и так виден по порядку
   строк, считать их читателю незачем.

   Одна колонка, а не две: заголовок в 52 знака в колонке шириной в половину
   текста переносится на вторую строку и сбивает ритм соседней колонки.

   На широком экране этот блок прячется: там же стоит залипшее содержание
   слева, и два одинаковых списка на экране — лишний шум. Прячется он по
   классу, который ставит js/toc.js, а не сам по себе: если скрипт не
   отработал, блок в тексте остаётся на месте и работает как раньше. */
.article-body > .toc {
  margin: var(--space-32) 0 var(--space-40);
}

.article-body > .toc ol {
  list-style: none;
  margin: 0;
  padding: 0;
}

.article-body > .toc li { margin: 0; }

/* Строки разделены светлой линией: здесь она не несёт смысла, а только
   держит ряды, поэтому взята светлее обычной разделительной. Список
   читается и без неё — строки разделены ещё и отбивкой. */
.article-body > .toc a {
  display: block;
  padding: var(--space-8) 0;
  font-size: var(--t-main);
  line-height: var(--t-main-lh);
  text-decoration: none;
  border-bottom: 1px solid var(--c-border);
  letter-spacing: 0;
}

.article-body > .toc li:first-child a { border-top: 1px solid var(--c-ink); }

/* Подчёркивание появляется при наведении — то же, что у ссылок в тексте. */
.article-body > .toc a:hover {
  color: var(--c-accent);
  text-decoration: underline;
  text-decoration-color: var(--c-accent);
  text-decoration-thickness: 0.75px; /* 30.10, п. 15: было 0.5px, потом 1px */
  text-underline-offset: 3px;        /* 30.10, п. 15: 5px вернули к 3px */
}

/* ── СОДЕРЖАНИЕ СЛЕВА ──
   На широком экране содержание стоит в левом поле и никуда не девается:
   список названий открыт всё время. Прятать его до наведения значит
   заставлять искать навигацию курсором — место под неё и так пустует.

   Слева, а не справа, потому что правое поле занято выносками: они
   привязаны к своим абзацам, и вместе им там тесно.

   Плашка со скруглением: содержание — не часть текста, а отдельный предмет
   рядом с ним, и заливка говорит об этом честнее любой рамки. Это
   единственное скругление на сайте, и оно здесь именно поэтому: ничего
   похожего в тексте нет, спутать не с чем.

   Слева от списка — шкала с чёрной засечкой на текущем разделе: по ней
   видно, где читатель сейчас и сколько осталось.

   Ширина не задана числом, а считается от поля: сколько осталось слева от
   колонки чтения, столько плашка и занимает, но не шире 220.

   ГЛАВНОЕ: плашка не всплывает и не гаснет. Она стоит в левом поле статьи
   как обычный блок — начинается сразу под заглавной фотографией — и едет
   вместе с читателем (position: sticky). Раньше она висела посреди окна и
   включалась скриптом по месту прокрутки: появлялась будто сама по себе и
   успевала наехать на обложку. Теперь появляться ей неоткуда — она просто
   стоит там, где стоит, с первой секунды.

   Конец тоже сам собой: плашка занимает в сетке всю высоту текста статьи
   и ниже него не уезжает, поэтому у тегов и у блока «следующий материал»
   её нет без всякой проверки в скрипте.

   Место в стопке — 40, на единицу ниже снимка во всю ширину и широкой
   таблицы (41). Так и задумано: у этих блоков левого поля нет, они и есть
   вся ширина, и плашка уезжает под них, а не поверх. Кто поднимет это
   число выше 41 — вернёт баг, когда оглавление лежит на фотографии. */
.article-body > .toc-float {
  grid-column: 1;
  /* Конец строки ставит toc.js: плашка должна занимать все ряды сетки,
     иначе прилипание работает в высоту одного первого блока. Числом здесь
     не задать — рядов столько, сколько в статье абзацев. */
  grid-row: 1;
  position: sticky;
  top: calc(var(--header-h) + 24px);
  align-self: start;
  justify-self: start;
  /* 29.10: вровень с логотипом в шапке; было 24. Процент здесь — ширина
     левой колонки сетки, а не страницы, поэтому --page-x пересчитан
     через неё: колонка = (страница − колонка чтения) / 2. */
  margin-left: max(var(--space-24), calc(100% + (var(--col) - var(--page-max)) / 2 + var(--space-24)));
  z-index: 40;
  width: min(220px, calc(100% - 48px));
  display: grid;
  grid-template-columns: 3px minmax(0, 1fr);
  gap: var(--space-16);
  padding: var(--space-16) 0;
  overflow-x: hidden;           /* вбок не прокручивается никогда */
  overflow-wrap: break-word;
  /* Заливки нет: плашка стоит на поле, рядом с текстом, и прямоугольник
     читался как ещё один блок статьи. Держит её вертикальная линейка
     слева — она же показывает, какой раздел сейчас читают. */
  background: none;
  border-radius: 0;
  /* Длинное оглавление не должно вылезать за экран. */
  max-height: calc(100vh - var(--header-h) - 48px);
  overflow-y: auto;
}

/* Шкала: светлая линия во всю высоту и чёрная засечка. Высоту и положение
   засечки считает toc.js по месту текущей строки в списке. На сером фоне
   линия берётся темнее, чем была бы на белом. */
.toc-float .bar { position: relative; background: var(--c-border); }
.toc-float .bar i {
  position: absolute;
  left: 0;
  right: 0;
  background: var(--c-ink);
  transition: top 0.15s, height 0.15s;
}

.toc-float ol { list-style: none; margin: 0; padding: 0; }
.toc-float li { margin: 0; }

.toc-float a {
  display: block;
  padding: var(--space-4) 0;
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  line-height: var(--t-meta-lh);
  text-decoration: none;
  color: var(--c-muted);
  letter-spacing: var(--t-wide);
}

.toc-float a.here { color: var(--c-ink); font-weight: 700; }
.toc-float a:hover { color: var(--c-accent); }

/* Плашка теперь стоит внутри статьи, а значит её задевает общее правило
   ссылок в тексте: оно той же силы и написано ниже, поэтому в списке
   разделов появлялись подчёркивания. Снимаем их отдельным правилом —
   оно сильнее, и порядок строк на него больше не влияет. Оглавление и
   без подчёркиваний читается списком ссылок. */
.article-body > .toc-float a {
  text-decoration: none;
  transition: color 0.15s;
}
.article-body > .toc-float a:focus-visible {
  outline: 2px solid var(--c-surface);
  outline-offset: -2px;
  box-shadow: inset 0 0 0 4px var(--c-ink);
  background: none;
  color: var(--c-ink);
}

/* Кольцо фокуса общее по сайту; плашке оно нужно внутрь, иначе обрежется
   её же краем. */
.toc-float a:focus-visible {
  outline: 2px solid var(--c-surface);
  outline-offset: -2px;
  box-shadow: inset 0 0 0 4px var(--c-ink);
  color: var(--c-ink);
}

/* Порог посчитан, а не выбран на глаз: колонка чтения 800 точек стоит по
   центру, значит поле с каждой стороны — (ширина окна − колонка) / 2.
   Плашке нужно хотя бы 170 точек под названия плюс 48 на отступы, то есть
   поле от 218. При колонке 680 поле дорастает до 218 при ширине окна 1116,
   ближайшая круглая — 1120. Уже — плашки нет, и содержание читается
   блоком в тексте. */
/* Правка 27 октября: порог поднят до 1160. При 1120 поле было 212
   точек, на текст в плашке оставалось около ста, длинные слова
   («зарегистрироваться») в строку не влезали — плашка прокручивалась
   вбок и наезжала на колонку. Теперь у плашки нет боковых полей (фона
   у неё всё равно нет), и на тексте остаётся не меньше 160 точек:
   ширина 180 + отступы по 24 = поле 228, окно 680 + 2 × 228 + полоса
   прокрутки 15 = 1151, круглая — 1160. */
@media (min-width: 1160px) {
  .has-toc-float .article-body > .toc { display: none; }
}

/* Первая строка оглавления — вровень с первой строкой текста. Плашка и
   первый блок начинаются с одного ряда сетки, поэтому верхнее поле плашки
   равно верхнему полю первого блока минус 4 точки, которые даёт сама
   ссылка оглавления. Абзац и интервью начинаются через --p-para,
   подзаголовок — через --p-h2-top. Правка 29.10. */
/* :first-child — чтобы перебить общее правило «у первого блока статьи
   верхнего поля нет», которое ниже по файлу и снимало это поле у плашки
   (она и есть первый блок). Правка 30.10. */
/* 30.10, п. 16: плашка снова начинается в первом ряду, сразу под обложкой.
   Поле подзаголовка ей нужно, только когда содержание стоит в самом начале
   текста и первым видимым блоком идёт подзаголовок (руководства). Если
   перед содержанием есть абзац, плашка встаёт вровень с этим абзацем. */
.article-body > .toc-float:first-child { padding-top: calc(var(--p-para) - 4px); }
.article-body:has(> .toc-float + .toc + h2) > .toc-float { padding-top: calc(var(--p-h2-top) - 4px); }
/* То же, если сразу после содержания идёт h3 — правка 29.10. */
.article-body:has(> .toc-float + .toc + h3) > .toc-float { padding-top: calc(var(--p-h3-top) - 4px); }
/* Интервью, которое начинается с подзаголовка: поле интервью плюс поле h2. */
.article-body:has(> .toc-float + .toc + dl > h2:first-child) > .toc-float { padding-top: calc(var(--p-para) + var(--p-h2-top) - 4px); }

/* Селектор тот же, что у основного правила, иначе он слабее и плашка на
   узком экране не спрячется. */
@media (max-width: 1159px) {
  .article-body > .toc-float { display: none; }
}

/* ── ВЫНОСКА ──
   Книжное замечание на правом поле, без номера: она привязана к абзацу, в
   котором стоит. В файле материала лежит ВНУТРИ своего абзаца, в конце:

     <p>Текст абзаца.<span class="note">Замечание.</span></p>

   Внутри, а не рядом, по двум причинам. Во-первых, абзац сам становится
   точкой отсчёта, и выноска встаёт вровень с его первой строкой — считать
   ничего не нужно. Во-вторых, диктор читает её сразу после своего абзаца,
   а не отдельным куском неизвестно откуда.

   Правое поле, потому что левое занято полоской содержания. Вместе им там
   тесно: колонка чтения 800, выноска 220 и щель 16 — на экране уже 1360
   места на обоих уже нет. */
.article-body > p { position: relative; --note-top: var(--p-para); }

.note {
  position: absolute;
  left: 100%;               /* правый край колонки чтения */
  /* Вровень с ПЕРВОЙ СТРОКОЙ хозяина, а не с его верхним краем. Раньше
     стоял ноль, и выноска уезжала вверх ровно на величину верхнего поля
     абзаца — то есть висела в пустоте между абзацами, а не против текста,
     к которому относится.

     Величину поля выноске сообщает сам хозяин: рядом с каждым padding-top
     в разметке статьи стоит --note-top с тем же значением. Так два числа
     живут в одной строке и не разъезжаются. Там, где поле снято (первый
     блок статьи, первый вопрос, первый ответ после вопроса, первый абзац
     ответа), --note-top тоже ноль — и выноска остаётся на месте. */
  top: var(--note-top, 0px);
  width: 200px;
  /* От текста 32. Было 16, и выноска липла к тексту и к правому краю
     плашки так, что читалась как его продолжение, а не как заметка
     на полях. */
  margin-left: var(--space-32);
  /* Линии сверху нет: выноску и так видно по месту и по кеглю. Кегль на
     ступень мельче основного текста — это и говорит, что она на полях. */
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  line-height: var(--t-meta-lh);
  color: var(--c-muted);
  letter-spacing: var(--t-wide);
}

/* Ниже 1240 точек поля нет, и выноска встаёт под своим абзацем обычным
   блоком — как в книге, где на узкой полосе сноска уходит вниз.

   Порог считается, а не берётся на глаз: колонка чтения 800, выноска 200
   и щель 16 с каждой стороны — 1232. Округлено до 1240.

   То же самое делает js/notes.js с выноской, которой не хватило места
   рядом с соседкой: наезжающих выносок быть не должно. */
.note.is-under,
.article-body .note.is-under {
  position: static;
  display: block;
  width: auto;
  max-width: 520px;
  margin: var(--space-16) 0 0;
}

/* Выноска уходит под абзац, когда правому полю уже не хватает на её
   200 точек плюс 16 отступа: при колонке 680 это ширина окна 1112,
   круглая — 1120.

   Считается с запасом: колонка плюс дважды по 232 (выноска 200
   и отступ 32), хотя часть отступа выноска берёт из полей колонки.
   Руководство: 680 + 464 = 1144, круглая — 1160.
   У интервью колонка шире на восемьдесят точек, и поля ему перестаёт
   хватать раньше: 760 + 464 = 1224, круглая 1240.
   Правило ниже, отдельным запросом, потому что медиазапрос не умеет
   считать от переменной. */
/* 30.10, п. 29: колонка статьи теперь 680, как у руководства, и выноскам
   поля хватает с той же ширины 1160 — отдельный порог 1240 больше не нужен,
   правило ниже совпадает с общим. */
@media (max-width: 1159px) {
  .is-article .note {
    position: static;
    display: block;
    width: auto;
    max-width: 520px;
    margin: var(--space-16) 0 0;
  }
}

@media (max-width: 1159px) {
  .note {
    position: static;
    display: block;
    width: auto;
    max-width: 520px;
    margin: var(--space-16) 0 0;
  }
}

/* Неразрывный кусок: «19 000 RSD» или «стр. 5» не разорвутся на две строки. */
.nobr, nobr { white-space: nowrap; }

/* ── ТАБЛИЦА ──
   Сроки, пошлины, «что нужно для какого основания» — всё, что в тексте
   превращается в кашу, а таблицей читается за секунду.

   Заливки столбцов здесь больше нет. Она была: пять оттенков серого от
   светлого к тёмному, по столбцу на оттенок. Замеры контраста сходились,
   а на странице выходило плохо, и вот почему. Цвет в таблице должен
   что-то означать, иначе он лишний, — а тут он означал всего лишь
   «третий слева». Глаз же читает тёмное как важное, и самым весомым
   оказывался последний столбец, а первый, с названием, ради которого в
   таблицу и смотрят, — самым бледным. Плюс пять заливок встык давали на
   полосе серый прямоугольник, который спорил с текстом вокруг.

   Теперь таблица набрана, а не закрашена: кегль на ступень мельче текста,
   шапка капителью вразрядку, строки разделены волосяной линейкой, свод
   сверху и снизу — чёрной. Первый столбец чуть плотнее остальных: он у
   строки за вход.

   Ширина. Таблица от четырёх столбцов выходит из колонки чтения во всю
   страницу: в колонке её ячейки переносятся по три-четыре раза и таблица
   на экран не помещается. Пятистолбцовая таблица музеев в колонке
   занимала 1279 точек, во всю ширину — 540, и читается с одного взгляда.
   Таблица поуже остаётся в тексте: растягивать два столбца на полторы
   тысячи точек незачем.

   Ширину выбирает сам браузер, по четвёртому заголовку в шапке (:has).
   Где :has не понимают, таблица остаётся в колонке — это рабочий вид, а
   не поломка. Белый фон и место в стопке у широкой таблицы те же, что у
   снимка во всю ширину: она проходит ПОВЕРХ плавающего содержания, иначе
   полоска оглавления оказалась бы поверх ячеек.

   Правила общие для таблицы в тексте и таблицы внутри интервью: раньше
   это были два набора, и они успели разойтись — у второго, например,
   потерялась подпись. Разной у них осталась только ширина.

   Светло-серое поле под таблицей. Один оттенок на всю таблицу, а не по
   столбцу на оттенок: так заливка ничего не утверждает про важность
   столбцов, а просто собирает строки в один блок и отделяет его от текста.
   Тот же #F7F7F7, что у плашки, — на сайте это «фон для куска, который не
   абзац». На нём линейки строк чуть темнее, иначе их не видно.

   Подпись под таблицей необязательна — это обычный figcaption. */
.article-body figure.table {
  background: var(--c-surface);
  margin: var(--space-24) 0 0;   /* 29.10: было 40 и 40 — теперь как у плашки */
  overflow-x: auto;         /* единственное место на сайте, где можно
                               выехать за ширину: ломать таблицу на
                               карточки хуже, чем дать её прокрутить */
}

.article-body figure.table table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-table);
  line-height: var(--t-table-lh);
  letter-spacing: 0;
}

.article-body figure.table th {
  text-align: left;
  vertical-align: bottom;
  font-size: var(--t-table-head);
  /* Без капса: заголовки столбцов набраны как написаны. Разрядка 0,06em
     была нужна капсу и вместе с ним убрана. */
  letter-spacing: 0;
  font-weight: 700;
  color: var(--c-muted);
  padding: 0 var(--space-16) var(--space-8) 0;
  border-bottom: 1px solid var(--c-ink);
}

/* Правка 30.10 по просьбе дизайнера: цифры в таблицах одной ширины
   (табличные), чтобы суммы и сроки в столбце стояли разряд под разрядом.
   В шрифте Golos такие цифры есть, по умолчанию они пропорциональные. */
.article-body figure.table :is(th, td) { font-variant-numeric: tabular-nums; }

.article-body figure.table td {
  padding: var(--space-8) var(--space-16) var(--space-8) 0;
  vertical-align: top;
  border-bottom: 1px solid var(--c-border);
}

/* Свод таблицы снизу — такая же чёрная линия, как под шапкой: таблица
   должна кончаться, а не растворяться в странице. */
.article-body figure.table tbody tr:last-child td { border-bottom: 1px solid var(--c-ink); }
/* 30.10, п. 28 по просьбе дизайнера: если под таблицей нет подписи,
   нижней чёрной линии нет — таблицу заканчивает край серого поля. */
.article-body figure.table:not(:has(figcaption)) tbody tr:last-child td { border-bottom: 0; }

/* Последний столбец не отступает справа, иначе таблица не доходит до
   правого края колонки и выглядит сдвинутой влево. */
.article-body figure.table :is(th, td):last-child { padding-right: 0; }

/* Первый столбец — вход в строку, поэтому он на ступень плотнее. */
.article-body figure.table td:first-child { font-weight: 500; }

/* Строка итога набрана жирным — за ней читатель в таблицу пошлин и шёл.
   Класс ставится в разметке руками, а не вычисляется как «последняя
   строка»: не в каждой таблице последняя строка — итог, и правило,
   которое угадывает, однажды выделит жирным обычную строку. */
.article-body figure.table tr.total td { font-weight: 700; }

.article-body figure.table figcaption {
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  line-height: var(--t-meta-lh);
  color: var(--c-muted);
  margin-top: var(--space-16);
  text-transform: none;
  letter-spacing: var(--t-wide);
}

/* Поля внутри серого поля: текст не должен лежать вплотную к его краю.
   По бокам те же 24, что у абзаца, — левый край таблицы совпадает с левым
   краем текста. */
.article-body > figure.table { padding: var(--space-24); }
/* Правка 29.10: серое поле таблицы — в границах колонки текста, как
   плашка: по 24 с боков. На телефоне таблица по-прежнему во всю ширину. */
@media (min-width: 769px) {
  .article-body > figure.table { margin-left: var(--space-24); margin-right: var(--space-24); }
}

/* Таблица любой ширины стоит в колонке текста, как и всё остальное.
   Раньше таблица с четырьмя столбцами и больше выходила во всю ширину
   страницы; по решению редакции это убрано — серое поле не должно рвать
   колонку. Если столбцам тесно, таблица прокручивается вбок внутри
   своего поля (overflow-x выше), страница при этом не разъезжается. */

/* ── ПЛАШКА ──
   Прямоугольник с собственным заголовком, текстом и необязательным круглым
   портретом. Нужна там, где в статье говорит другой голос: предупреждение,
   короткая справка, реплика эксперта.

   Три вида, и только три. Не свободная раскраска: в файле материала стоит
   одно слово — grey, red или black, — а как это выглядит, решается здесь.
   Иначе вид расползётся по сотне статей и поменять облик сайта в одном
   месте станет нельзя.

   Цвета замерены, все три проходят норму 4,5:1 для основного текста:
     серая  #F2F2F2 с чёрным текстом   18,76:1
     чёрная #000000 с белым текстом    21,00:1
     красная #D83C0D с белым текстом    4,59:1

   Красный — не точный цвет логотипа #F14612: на нём белый текст даёт
   3,73:1 и не дотягивает. Взят тот же тон и та же насыщенность, светлота
   с 51% убрана до 45%. От логотипа отличается на 1,23:1 — глазом почти не
   поймать, а текст читается честно.

   Сама плашка стоит ровно по краям текста статьи — не шире. Раньше она
   вылезала на 24 точки с каждой стороны и правым краем почти упиралась
   в выноску на поле. Текст внутри отступает от края плашки на 24, то есть
   он чуть уже текста статьи — так плашка и читается как вставка.
   На телефоне колонка и так узкая, там плашка во всю её ширину. */
.article-body > .callout {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: var(--space-24);
  align-items: start;
  padding: var(--space-24) var(--space-24) var(--space-24);
  margin: var(--p-callout) var(--space-24) var(--p-callout-bot);
}

.callout-face {
  grid-row: 1 / span 3;
  width: 72px; height: 72px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
  background: var(--c-surface);
}

.callout h3 {
  grid-column: 2;
  font-size: var(--t-main);
  font-weight: 700;
  letter-spacing: 0;
  line-height: var(--t-callout-lh);
  margin: 0;
}

.callout p {
  grid-column: 2;
  font-size: var(--t-main);
  line-height: var(--t-callout-lh);
  letter-spacing: 0;
  margin: var(--space-8) 0 0;
}

/* Кто говорит. Необязательная строка, последняя в плашке. */
.callout .who {
  grid-column: 2;
  font-size: var(--t-meta);
  letter-spacing: var(--t-wide);
  font-weight: 600;
  margin-top: var(--space-8);
  line-height: var(--t-meta-lh);
}

/* Портрет необязателен. Без него колонка под него не остаётся пустой:
   сетка схлопывается в одну.

   Это правило стоит ПОСЛЕ правил для заголовка, текста и подписи — иначе
   они его перебивают: у них тот же вес, а при равном весе побеждает то,
   что записано ниже. Замечено на плашке без портрета: строка «кто говорит»
   уезжала во вторую колонку и вставала сбоку от текста. */
.callout:not(:has(.callout-face)) { grid-template-columns: 1fr; }

/* Картинки внутри плашки — образцы квитанций, бланков, скриншоты: то, что
   объясняется текстом этой же плашки. Во всю её ширину, целиком, без
   подрезки, на белом и в тонкой рамке — бланк на сером фоне плашки иначе
   сливается с ним. Подпись — обычная подпись к фото. */
.callout figure { grid-column: 1 / -1; margin: var(--space-16) 0 var(--space-8); }
.callout figure img {
  display: block;
  width: 100%;
  height: auto;
  background: var(--c-bg);
  border: 1px solid var(--c-border);
}
.callout:not(:has(.callout-face)) > * { grid-column: 1; }

/* Список в плашке. Своего стиля у него не было, и браузер ставил свои
   точки с полем в сорок — маркеры вылезали левее текста плашки. Теперь
   как в тексте статьи, только без бокового поля: край плашки и так
   задаёт отступ. */
.callout :is(ul, ol) {
  grid-column: 2;
  list-style: none;
  counter-reset: li;
  margin: 0;
  padding: var(--space-8) 0 0;
}
.callout:not(:has(.callout-face)) > :is(ul, ol) { grid-column: 1; }
.callout li {
  position: relative;
  padding-left: var(--space-24);
  font-size: var(--t-main);
  line-height: var(--t-callout-lh);
}
.callout li::before {
  position: absolute;
  left: 0;
}
.callout ul > li::before { content: '\2022'; }
.callout ol > li::before { counter-increment: li; content: counter(li) '.'; }

/* Ровные поля плашки. Абзацы внутри отбиваются друг от друга отступом
   сверху, и у первого он прибавлялся к полю плашки: над текстом выходило
   32 точки, под ним 24. Первому — ноль, последнему (например, картинке
   с подписью) — тоже ноль снизу: поле одно со всех сторон. */
.article-body > .callout > :first-child { margin-top: 0; }
.article-body > .callout > :last-child  { margin-bottom: 0; }

/* Воздух над плашкой равен воздуху под ней. Под плашкой 16 её собственного
   поля плюс 24 над следующим абзацем или подзаголовком — 40. Над ней теперь
   тоже 40: поле плашки. Но фото и интервью (<dl>) держат свой отступ снизу,
   и он прибавлялся: после снимка выходило 72 точки, после интервью 48 —
   плашка отрывалась от того, что над ней, и липла к тому, что под ней.
   Поэтому у соседа сверху нижний отступ снимается. */
/* Правка 29.10: заголовок после плашки отбивается сильнее абзаца —
   до h3 32 (8 у плашки + 24 у заголовка), до h2 40. До абзаца по-прежнему 24. */
.article-body > .callout:has(+ h3) { margin-bottom: var(--space-8); }

.article-body > figure:has(+ .callout),
.article-body > dl:has(+ .callout) { margin-bottom: 0; }

.callout.grey  { background: var(--c-surface); }
.callout.grey .who { color: var(--c-muted); }

.callout.black { background: var(--c-ink); color: var(--c-bg); }
.callout.black .who { color: rgba(255, 255, 255, 0.72); }

.callout.red   { background: var(--c-accent); color: var(--c-bg); }
.callout.red .who { color: rgba(255, 255, 255, 0.78); }

/* Ссылка внутри цветной плашки: серая линия на цветном фоне не видна,
   поэтому там она берёт цвет самого текста. */
.callout.black a,
.callout.red a { text-decoration-color: currentColor; }
.callout.black a:hover,
.callout.red a:hover { text-decoration-color: currentColor; }
.callout.black a:focus-visible,
.callout.red a:focus-visible { background: var(--c-bg); color: var(--c-ink); text-decoration-color: var(--c-ink); }

/* ── ССЫЛКА В ТЕКСТЕ ──
   Подчёркивание, а не рамка снизу: рамка ломается, когда ссылка переносится
   на другую строку, а подчёркивание переносится вместе с текстом.

   Текст ссылки ничем не отличается от обычного: цветной текст посреди абзаца
   читается как ошибка или как выделение, а не как ссылка. Отличает её только
   тонкая линия снизу, светлее самого текста.

   Толщина полпикселя: на экране с двойной плотностью точек это настоящая
   тонкая линия, на обычном — та же линия, отрисованная вполсилы. И там и
   там тоньше, чем целый пиксель.

   Цвет #a8a8a8 выбран Олей намеренно светлым: 2,42:1 к белому. Это ниже
   ориентира 3:1, который берут для линии, когда она единственный признак
   ссылки. Замеры соседних значений: #949494 — 3,03:1, #b8b8b8 — 1,99:1,
   #cccccc — 1,61:1. Чем светлее, тем труднее заметить ссылку на ярком
   свету, на дешёвом экране и немолодому глазу. Решение осознанное; если
   вернуться к ориентиру — ставить #949494, он же стоит на разделителях в
   списке гайдов.

   При наведении линия только чернеет, толщина не меняется. Скачок от
   2,42:1 до 21:1 заметен сам по себе, а линия остаётся той же — ничего
   не дёргается и не перерисовывается. */
.article-body a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--c-quiet);
  text-decoration-thickness: 0.75px; /* 30.10, п. 15: было 0.5px, потом 1px */
  text-underline-offset: 3px;        /* 30.10, п. 15: 5px вернули к 3px */
  transition: color 0.15s, text-decoration-color 0.15s;
}

.article-body a:hover { color: var(--c-accent); text-decoration-color: var(--c-accent); }

/* С клавиатуры — подсветка, а не кольцо. Общее кольцо фокуса на сайте
   обводит элемент снаружи, и вокруг ссылки посреди строки оно ложится
   прямо на соседние буквы: замерено — запятая сразу за ссылкой исчезала
   под рамкой. Подсветка занимает ровно место самой ссылки и соседей не
   трогает. Белое на чёрном —
   21:1. */
.article-body a:focus-visible {
  outline: none;
  box-shadow: none;
  background: var(--c-ink);
  color: var(--c-bg);
  text-decoration-color: var(--c-bg);
  text-decoration-thickness: 1px;
  padding: 0 2px;
  margin: 0 -2px;
}

/* В подписи к фотографии текст и так серый, и серая линия под ним
   сливается — там линия берёт цвет самого текста. */
.article-body figcaption a { text-decoration-color: currentColor; }

/* The body of an article is plain semantic HTML — p, h2, h3, ul, figure,
   blockquote, dl. No wrapper divs and no layout classes inside the content:
   this grid puts everything into the reading column by itself, and a figure
   marked "full" breaks out to the whole width. */
.article-body {
  display: grid;
  grid-template-columns: 1fr min(var(--col), 100%) 1fr;
}

.article-body > * { grid-column: 2; padding-left: var(--space-24); padding-right: var(--space-24); }

.article-body > p {
  font-size: var(--t-main);
  line-height: var(--t-main-lh);
  margin-bottom: 0;
  padding-top: var(--p-para);
  letter-spacing: 0;
}

/* Буквицы нет. Она была единственным украшением на сайте, который держится
   на том, что украшений не носит: вся разница между элементами сделана
   кеглем, весом и воздухом, а буквица — приём из другой системы, книжной.
   На экране она к тому же крадёт первую строку абзаца у того, кто читает
   с экранного диктора или просто быстро. Текст начинается с текста. */

/* Над заголовком много воздуха, под ним мало: так заголовок виден как
   начало нового куска, а не как подпись к пустому месту. Сорок восемь
   сверху и восемь снизу — из кита. */
.article-body > h2 {
  font-size: var(--t-h2);
  font-weight: 700;
  line-height: var(--t-h2-lh);
  letter-spacing: var(--t-half);
  margin: 0;
  padding-top: var(--p-h2-top);
  padding-bottom: var(--p-head-bot);
}

.article-body h3,
.article-body h3 a { text-underline-offset: 5px; }   /* линия не режет «д», «р», «у» */
/* 30.10, п. 15 по просьбе дизайнера: у ссылки в подзаголовке h3 линия
   0,75 и в 6 точках от букв — кегль крупнее, и отступ растёт вместе с ним. */
.article-body h3 a { text-decoration-thickness: 0.75px; text-underline-offset: 6px; }

.article-body > h3 {
  font-size: var(--t-h3);
  letter-spacing: 0;
  font-weight: 700;
  margin: 0;
  padding-top: var(--p-h3-top);
  padding-bottom: var(--p-head-bot);
  line-height: var(--t-h3-lh);
}

/* Первый абзац после заголовка прижат к нему: восемь точек под заголовком
   плюс восемь над абзацем — шестнадцать, как в ките. Между соседними
   абзацами воздуха больше: там он отделяет мысль от мысли, а здесь только
   заголовок от собственного текста. */
.article-body > h2 + p,  .article-body > h3 + p,
.article-body > h2 + ul, .article-body > h3 + ul,
.article-body > h2 + ol, .article-body > h3 + ol,
.article-body > h2 + dl, .article-body > h3 + dl {
  padding-top: var(--p-head-bot);
  --note-top: var(--p-head-bot);
}

/* Фото сразу под заголовком прижато к нему так же, как первый абзац:
   заголовок подписывает снимок под собой. С обычным полем фото в 40 точек
   заголовок повисал между текстом выше и снимком ниже и читался ничьим. */
.article-body > :is(h2, h3) + figure { margin-top: var(--p-head-bot); }
/* Правка 30.10: снимок перед подзаголовком. Его нижние 32 складывались
   с верхним полем заголовка (40), и от подписи до h2 выходило 72 —
   больше, чем между абзацем и h2. Перед заголовком нижнее поле снимка
   снимается: подпись отбивается от h2 так же, как абзац (40), от h3 — 24.
   Если после снимка идёт текст, ничего не меняется. */
.article-body > figure:has(+ :is(h2, h3)) { margin-bottom: 0; }

/* ── СПИСКИ ──
   Маркер стоит в своей колонке шириной 24 и прижат к её правому краю,
   текст начинается на 8 точек правее. Правый край нужен ради нумерованных
   списков: «9.» и «10.» при левом выравнивании разъезжаются, а при правом
   точки после цифр стоят одна под другой, и колонка цифр читается
   колонкой.

   Маркер рисуется стилями, а не пишется в тексте. У дизайнера в макете
   у каждой строки отдельный слой под маркер, и буквальный перенос этого
   в вёрстку означал бы, что редактор в каждом пункте пишет лишний тег.
   Редактор пишет обычный список, как писал, — всё остальное делают
   эти правила.

   Выравнивание по первой строке держится само: маркер лежит в начале
   строки с тем же интерлиньяжем, что текст, и его базовая линия совпадает
   с первой базовой линией пункта, сколько бы строк в пункте ни было. */
.article-body > ul,
.article-body > ol {
  margin-bottom: 0;
  padding-top: var(--p-list);
  padding-left: var(--space-24);      /* боковое поле колонки чтения, как у абзаца */
  list-style: none;
  counter-reset: li;
}

/* Вложенный список начинается от текста родителя, а не от его маркера,
   и своего верхнего поля не берёт: он часть того же пункта. */
.article-body > ul :is(ul, ol),
.article-body > ol :is(ul, ol) {
  list-style: none;
  counter-reset: li;
  padding: var(--space-8) 0 0;
  margin: 0;
}

.article-body > ul li,
.article-body > ol li {
  font-size: var(--t-main);
  line-height: var(--t-main-lh);
  letter-spacing: 0;
  position: relative;
  padding-left: var(--space-32);      /* 24 под маркер + 8 до первой буквы */
  margin-bottom: var(--space-8);      /* щель между пунктами */
}

.article-body > ul li:last-child,
.article-body > ol li:last-child { margin-bottom: 0; }

.article-body > ul li::before,
.article-body > ol li::before {
  position: absolute;
  left: 0;
  width: 24px;
  text-align: right;
  line-height: var(--t-main-lh);
}

/* Какой маркер — решает непосредственный родитель пункта, поэтому
   вложенный список своего вида не теряет. */
.article-body > ul > li::before,
.article-body > ul ul > li::before,
.article-body > ol ul > li::before { content: '\2022'; }

.article-body > ol > li::before,
.article-body > ul ol > li::before,
.article-body > ol ol > li::before {
  counter-increment: li;
  content: counter(li) '.';
}

/* Пояснения к образцу документа: номер пункта — красный кружок с белой
   цифрой, такой же, как выноски на самом бланке. Читатель находит пункт
   по виду метки, а не только по числу. Ставится классом на список:
   <ol class="legend">. Кружок стоит по центру первой строки пункта. */
.article-body > ol.legend > li::before {
  content: counter(li);
  left: 2px;
  top: calc((var(--t-main) * var(--t-main-lh) - 20px) / 2);
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--c-accent);
  color: var(--c-bg);
  font-size: 12px;
  font-weight: 700;
  line-height: 20px;
  text-align: center;
}

/* ── ЦИТАТА ──
   Цитата в тексте — не ссылка на источник, а крючок: звучная фраза, ради
   которой человек останавливается и возвращается в чтение. Пока она шла
   тем же кеглем, что текст, и отличалась одной полоской слева, работы этой
   она не делала — глаз проезжал мимо.

   Разбивает полосу не кегль, а линейка. Поэтому текст цитаты чёрный и
   всего на две точки крупнее основного (18 против 16), а работу делает
   широкая красная линейка слева — тот же красный, что у ссылок. Концы у
   неё ровные: скругление на сайте есть ровно одно, у плашки содержания,
   и оно там значит «это отдельный предмет рядом с текстом». Цитата —
   часть текста, и округлять её незачем.

   Вес 500, на ступень плотнее основного: жирное начертание на сайте
   занято заголовками, и цитата начала бы с ними спорить.

   Цветной текст и чередование трёх цветов убраны. Три цвета на цитатах
   читались как три разных сорта цитат, которых в журнале нет.

   Линейка стоит ВРОВЕНЬ с текстом абзаца, а не левее его. Раньше у цитаты
   было своё поле в 20 точек вместо общих 24, и линейка оказывалась на
   самом краю колонки — на двадцать четыре точки левее первой буквы
   соседнего абзаца, а на узком экране налезала на плашку содержания.
   Теперь блок отодвинут на 24 точки внутрь (margin-left), и линейка
   встаёт там, где начинается текст; сама цитата отбита от линейки ещё на
   24 — это и есть её отступ внутрь.

   Воздух сверху и снизу складывается из двух частей, и обе нужны.
   Внутренние 24 — поле внутри самой цитаты: текст не должен начинаться
   вровень с верхним концом линейки. Внешние 16 — отбивка от предыдущего
   абзаца. Без них цитата отстояла бы от текста ровно настолько же,
   насколько абзац от абзаца, и читалась бы не цитатой, а абзацем с
   полоской сбоку. */
.article-body > blockquote {
  color: var(--c-ink);
  margin: var(--space-16) 0 0 var(--space-24);
  padding-top: var(--p-quote);
  padding-bottom: var(--p-quote-bot);
  padding-left: var(--space-24);
  padding-right: var(--space-24);
  font-size: var(--t-quote);
  line-height: var(--t-quote-lh);
  /* Плотнее и основного текста, и ответа в интервью. Пятисотое начертание
     не годилось: ответы в интервью набраны им же, и цитата внутри
     интервью ничем от них не отличалась. */
  font-weight: 600;
  letter-spacing: 0;
  /* Линейки как рамки больше нет: рамка тянулась во всю высоту блока,
     вместе с верхним и нижним полем, и торчала над первой строкой и под
     последней. Теперь это отдельная полоска, и ростом она ровно с
     текстом.

     Пять точек сверху и снизу — половина приклада: при кегле 18 и
     интерлиньяже 1,55 строка занимает 28 точек, а сами буквы от верха
     выносного до низа подстрочного — 18. Разница 10 делится поровну над
     и под строкой. Сняв её, получаем полоску вровень с буквами. */
  position: relative;
}

.article-body > blockquote::before {
  content: '';
  position: absolute;
  left: 0;
  top: var(--p-quote);              /* во всю высоту строк — правка 27.10 */
  bottom: var(--p-quote-bot);
  width: 4px;
  background: var(--c-accent);
}

/* Цитата бывает и в несколько абзацев, и записывают её двояко: голым
   текстом внутри blockquote или абзацами внутри него. Оба вида должны
   выглядеть одинаково, поэтому у абзаца здесь снимаются его собственные
   поля, а воздух между абзацами ставится тем же способом, что и везде. */
.article-body blockquote p { margin: 0; }
.article-body blockquote p + p { padding-top: var(--p-para); }

/* Who is speaking: an optional last line of a quote, <p class="who">.
   Grey and small, like dates and bylines, so it reads as a caption to the
   quote and not as part of it. #666 on white is 5.74:1, above the 4.5:1 norm.
   Added 30.10. */
.article-body blockquote .who {
  padding-top: var(--space-8);
  font-size: var(--t-meta);
  line-height: var(--t-meta-lh);
  font-weight: 400;
  letter-spacing: var(--t-wide);
  color: var(--c-muted);
}

/* Speech: who is speaking, then what they said in a grey bubble.
   <aside class="speech"> holds the name, the role and a blockquote.
   The bubble points up at the name with a small tail, so the words are
   read as said by that person. Same inset as a callout, so the two stand
   on the same edges of the column. Text on #F2F2F2 is 18.76:1, the role
   (#666 on white) 5.74:1 — both above the 4.5:1 norm. Added 30.10. */
.article-body > .speech {
  margin: var(--p-callout) var(--space-24) var(--p-callout-bot);
}
/* Name and role stand on one line: "Оля Маркович, редактор …".
   Both are separate paragraphs in the file, so the comma between them is
   added here. 30.10. */
.speech .speech-name,
.speech .speech-role {
  display: inline;
  margin: 0;
  font-size: var(--t-meta);
  line-height: var(--t-meta-lh);
  font-weight: 400;
}
.speech .speech-name::after { content: ', '; }
.speech .speech-role { color: var(--c-muted); }
.speech > blockquote {
  position: relative;
  margin: var(--space-16) 0 0;
  padding: var(--space-24);
  background: var(--c-surface);
  border-radius: 20px;
}
.speech > blockquote::before {
  content: '';
  position: absolute;
  top: -12px;
  left: var(--space-24);
  border: 12px solid transparent;
  border-top: 0;
  border-bottom-color: var(--c-surface);
}
.speech > blockquote p {
  font-size: var(--t-main);
  line-height: var(--t-callout-lh);
  font-weight: 400;
}
@media (max-width: 768px) {
  .article-body > .speech { margin-left: 0; margin-right: 0; }
}

/* ── ИНТЕРВЬЮ: ВОПРОС — ОТВЕТ ──
   Обычный dl, размеченный тегами, без классов.

   Воздух между парами лежит НАД вопросом, а не под ответом. Так он
   устроен у заголовков выше по файлу, и по той же причине: отбивка
   принадлежит тому, кто начинает новый кусок. Пока сорок точек висели
   под ответом, ответ был обязан быть одним абзацем — стоило дописать
   второй, и отбивка оказывалась в середине ответа, а следующий вопрос
   прилипал к тексту. В интервью ответ из трёх абзацев — норма, а не
   исключение, поэтому правило перевёрнуто.

   Продолжение ответа набирается как ответ, в каком бы виде его ни
   написали: вторым dd, абзацем внутри dd или абзацем, стоящим в dl
   следом за ответом. Последнее по стандарту внутрь dl не кладут, но
   именно так его пишет рука, когда расшифровку разбивают на абзацы, —
   и лучше, чтобы это выглядело правильно, чем чтобы текст разъезжался
   из-за тега, которого не видно.

   Снизу интервью добирает до той же сорокаточечной отбивки, с какой внутри
   него идут пары: следующий абзац берёт свои 24, плюс эти 16. Иначе текст
   после интервью прилипал бы к последнему ответу так же близко, как к нему
   прилипают его собственные абзацы, и граница блока пропадала. */
.article-body > dl { margin-bottom: 0; padding-top: var(--p-para); }   /* 29.10: было 16 снизу */

/* Служебная строка перед текстом — «Имена героев изменены по их просьбе»
   и подобные. Мелко и серым, как подпись: это не часть рассказа, а
   примечание к нему. Пишется в файле статьи первой строкой:
   <p class="article-note">…</p> */
.article-body > p.article-note {
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  line-height: var(--t-meta-lh);
  letter-spacing: var(--t-wide);
  color: var(--c-muted);
}

/* Первое, что стоит в тексте, не отодвигается сверху: над ним заголовок
   материала со своим полем или фотография. Двойной воздух в начале
   читался бы как пропущенный кусок. Правило стоит после всех остальных,
   иначе его перебьёт любое из них: вес у них одинаковый. */
.article-body > :first-child { padding-top: 0; margin-top: 0; --note-top: 0px; }

.article-body dt {
  font-size: var(--t-main);
  line-height: var(--t-main-lh);
  font-weight: 700;
  margin: 0 0 var(--space-4);
  padding-top: var(--p-qa);
  --note-top: var(--p-qa);
  letter-spacing: 0;
}

/* Первый вопрос воздуха над собой не берёт: его уже дал сам dl. */
.article-body dl > dt:first-child { padding-top: 0; --note-top: 0px; }
/* То же для ответа, с которого начинается блок интервью. Так бывает, когда
   интервью разрезано снимком или цитатой: после них новый блок начинается
   сразу с ответа. Верхнее поле у блока уже есть (padding-top у dl), и поле
   ответа складывалось с ним — под снимком и под цитатой выходил двойной
   воздух, 48 точек вместо 24. */
.article-body dl > dd:first-child { padding-top: 0; --note-top: 0px; }

/* Воздух вокруг цитаты в интервью — одинаковый сверху и снизу.
   Раньше под цитатой выходило заметно больше, чем над ней (60 против 42
   внутри интервью, а когда цитата стоит между двумя блоками интервью —
   у блока над ней ещё и своё нижнее поле в 16 точек). Цитата «летала»:
   от текста над ней она отрывалась слабее, чем от текста под ней.
   Ответ сразу за цитатой берёт 8 точек вместо 24 — остальное даёт нижнее
   поле самой цитаты; а цитата сразу за блоком интервью не добавляет своё
   верхнее поле к нижнему полю блока. Итог измерен: от последней строки
   текста до цитаты 42 точки, от цитаты до следующего ответа или абзаца
   44–46 — и внутри интервью, и между его блоками. */
.article-body :is(dl, dd) > blockquote + :is(dd, p) { padding-top: var(--space-8); --note-top: var(--space-8); }
/* Вопрос после цитаты — на 16 точек дальше ответа: вопрос начинает новую
   пару, и этот шаг в иерархии сохраняется и здесь. */
.article-body :is(dl, dd) > blockquote + dt { padding-top: var(--space-24); --note-top: var(--space-24); }
/* Цитата, которой кончается блок интервью: её нижнее поле складывалось
   с нижним полем блока и с верхним полем следующего — под ней выходило 78
   точек. Без её нижнего поля следующий вопрос встаёт на те же 62, что
   и вопрос сразу за цитатой внутри блока. */
.article-body dl > blockquote:last-child { margin-bottom: 0; }

/* Воздух вокруг снимка — как вокруг цитаты: поровну сверху и снизу, около
   42 точек от строки текста до края снимка и от подписи до следующей строки.
   Раньше было неровно: в интервью 34 над снимком и 58 под ним, у снимка
   между двумя блоками интервью — 58 и 66, под снимком в обычном тексте 66.
   Подпись читалась оторванной от текста, к которому снимок относится.
   Таблицы (figure.table) живут по своим правилам и сюда не входят. */
.article-body :is(dl, dd) > figure:not(.table) { margin: var(--space-40) 0; }
.article-body :is(dl, dd) > figure:not(.table) + :is(dd, p),
.article-body > figure:not(.table) + p { padding-top: 0; --note-top: 0px; }
/* Вопрос после снимка — на 24 дальше, как и после цитаты: новая пара. */
.article-body :is(dl, dd) > figure:not(.table) + dt { padding-top: var(--space-24); --note-top: var(--space-24); }
/* Снимок между двумя блоками интервью: у блока над ним своё нижнее поле
   (16), у блока под ним — верхнее (24); оба складывались с полями снимка. */
.article-body > dl + figure:not(.table) { margin-top: var(--space-32); }   /* 29.10: было 24 — теперь 32 и 32, как у всех фото */
.article-body > figure:not(.table) + dl { padding-top: 0; }
/* Снимок сразу под цитатой: нижнее поле цитаты (16) уже стоит. */
.article-body :is(dl, dd) > blockquote + figure:not(.table) { margin-top: var(--space-24); }
.article-body > dl + blockquote { margin-top: 0; }

/* Ответ берёт верхнее поле всегда — кроме одного случая: когда он стоит
   сразу за своим вопросом. Там их разделяют шесть точек, и это нарочно:
   вопрос и ответ — одна пара, а не два соседних куска.
   Так правило покрывает разом всё, что может стоять перед ответом: другой
   ответ, абзац, цитата, список, снимок, таблица. Перечислять их по одному
   значило бы каждый раз вспоминать этот список заново — и забывать. */
.article-body dd {
  font-size: var(--t-main);
  line-height: var(--t-main-lh);
  font-weight: 500;
  margin: 0;
  padding-top: var(--p-para);
  --note-top: var(--p-para);
  letter-spacing: 0;
}
.article-body dl > dt + dd { padding-top: 0; --note-top: 0px; }

/* Ответ, продолженный абзацем: внутри ответа или следом за ним в dl. */
.article-body dl > p,
.article-body dd > p {
  font-size: var(--t-main);
  line-height: var(--t-main-lh);
  font-weight: 500;
  letter-spacing: 0;
  margin: 0;
  padding-top: var(--p-para);
  --note-top: var(--p-para);
}

/* Первый абзац внутри ответа — это и есть начало ответа. */
.article-body dd > p:first-child { padding-top: 0; --note-top: 0px; }

/* ── ВНУТРИ ИНТЕРВЬЮ РАБОТАЕТ ВСЁ ТО ЖЕ, ЧТО СНАРУЖИ ──
   Интервью — не список вопросов и ответов, а кусок статьи, и внутри него
   встречается ровно то же, что в любом другом месте: вынесенная цитата,
   список, фотография. Для читателя это само собой разумеется; для вёрстки
   нет, потому что вся типографика статьи висит на «прямом потомке
   .article-body», а внутри dl прямых потомков нет.

   Оттого всё, что оказывалось внутри интервью, теряло вид разом: цитата
   шла без линейки и без воздуха, у списка пропадали маркеры, фотография
   вставала в натуральную величину. Снаружи те же теги работали, внутри —
   нет, и догадаться об этом, глядя на текст в окне правки, было нельзя.

   Поэтому здесь перечислено то же самое ещё раз, для нутра интервью.
   Повторение — цена того, что колонка чтения построена сеткой: в сетке
   участвуют только прямые потомки, и ради них «прямой потомок» в тех
   правилах обязан остаться. Боковые поля при этом не повторяются: их
   отмерил сам dl, и внутри него всё уже стоит в колонке. */

/* Выноска на поле внутри интервью. Она стоит absolute и отмеряет своё
   место от ближайшего предка с position — то есть от своего абзаца.
   Снаружи таким предком служит правило «.article-body > p { position:
   relative }», внутри интервью его нет, и выноска улетала в правый
   верхний угол страницы, к самому её краю.

   Поэтому вопрос, ответ и абзац внутри ответа сами становятся точкой
   отсчёта. Ничего, кроме выносок, это не меняет: position: relative без
   сдвигов на вид элемента не влияет. */
.article-body :is(dt, dd),
.article-body :is(dl, dd) > p { position: relative; }

/* Подзаголовок внутри интервью: длинный разговор делят на части, и часть
   начинается заголовком ровно так же, как в любой статье. В содержание он
   попадает сам — оно собирается по всем h2 в тексте, где бы те ни стояли. */
.article-body :is(dl, dd) > h2 {
  font-size: var(--t-h2);
  font-weight: 700;
  line-height: var(--t-h2-lh);
  letter-spacing: var(--t-half);
  margin: 0;
  padding-top: var(--p-h2-top);
  padding-bottom: var(--p-head-bot);
}

.article-body :is(dl, dd) > h3 {
  font-size: var(--t-h3);
  font-weight: 700;
  line-height: var(--t-h3-lh);
  letter-spacing: 0;
  margin: 0;
  padding-top: var(--p-h3-top);
  padding-bottom: var(--p-head-bot);
}

/* Первый вопрос после подзаголовка прижат к нему — как первый абзац после
   заголовка в обычной статье: восемь точек, а не сорок. Сорок отбивают
   пару от пары, а здесь заголовок отбивает сам. */
.article-body dl > :is(h2, h3) + :is(dt, dd) { padding-top: var(--p-head-bot); --note-top: var(--p-head-bot); }

/* Цитата внутри интервью. Оформление то же, а левого отступа в 24 точки
   здесь не нужно: сам dl уже отодвинут на эти 24, и линейка без всякого
   margin встаёт ровно там, где начинается текст ответа. */
.article-body :is(dl, dd) > blockquote {
  color: var(--c-ink);
  margin: var(--space-16) 0;
  padding: var(--p-quote) var(--space-24) var(--p-quote-bot) var(--space-24);
  font-size: var(--t-quote);
  line-height: var(--t-quote-lh);
  font-weight: 600;
  letter-spacing: 0;
  position: relative;
}

.article-body :is(dl, dd) > blockquote::before {
  content: '';
  position: absolute;
  left: 0;
  top: var(--p-quote);              /* во всю высоту строк — правка 27.10 */
  bottom: var(--p-quote-bot);
  width: 4px;
  background: var(--c-accent);
}

.article-body :is(dl, dd) > :is(ul, ol) {
  margin: 0;
  padding: var(--p-list) 0 0 var(--space-24);
  list-style: none;
  counter-reset: li;
}

.article-body :is(dl, dd) > :is(ul, ol) li {
  font-size: var(--t-main);
  line-height: var(--t-main-lh);
  font-weight: 500;
  letter-spacing: 0;
  position: relative;
  padding-left: var(--space-32);
  margin-bottom: var(--space-8);
}
.article-body :is(dl, dd) > :is(ul, ol) li:last-child { margin-bottom: 0; }

.article-body :is(dl, dd) > :is(ul, ol) li::before {
  position: absolute;
  left: 0;
  width: 24px;
  text-align: right;
  line-height: var(--t-main-lh);
}
.article-body :is(dl, dd) > ul > li::before { content: '\2022'; }
.article-body :is(dl, dd) > ol > li::before {
  counter-increment: li;
  content: counter(li) '.';
}

/* Фотография внутри интервью — только в колонку. Во всю ширину экрана она
   отсюда вырваться не может: сетку держит .article-body, а здесь мы уже
   внутри dl, и «full» тут не сработает. Снимок на разворот ставят между
   интервью, не внутри. */
/* Таблица внутри интервью: вид у неё общий со всеми остальными, отличается
   только одним — во всю ширину ей не выйти. Сетку страницы держит
   .article-body, а здесь мы уже внутри dl. Таблицу, которой нужна вся
   ширина, ставят между интервью, а не внутри: админка так и делает, когда
   видит её на верхнем уровне. Боковые поля тут уже отмерил dl, своих
   добавлять нельзя — таблица уехала бы вправо на двадцать четыре точки. */
.article-body :is(dl, dd) > figure.table { margin: var(--space-24) 0 0; padding: 0; }   /* 29.10: было 32 и 32 */

.article-body :is(dl, dd) > figure { margin: var(--space-32) 0; }
.article-body :is(dl, dd) > figure img {
  width: 100%; height: auto; aspect-ratio: 3/2;
  object-fit: cover; background: var(--c-surface);
}

/* Фото в колонку и фото во всю ширину. */
.article-body > figure { margin: var(--space-32) 0; }   /* 27.10: было 40 — подпись ближе к своему снимку */
/* height: auto обязателен: без него высоту диктует атрибут height из
   тега, aspect-ratio молчит, и вертикальный кадр встаёт во весь рост
   вместо того, чтобы подрезаться. */
.article-body > figure img {
  width: 100%; height: auto; aspect-ratio: 3/2;
  object-fit: cover; background: var(--c-surface);
}

/* Вертикальный кадр в колонке своих пропорций не теряет.

   Снимок в колонке подрезается до 3:2 — от этого снимки в разных материалах
   встают одинаково и страница держит ритм. Но вертикальному кадру такая
   подрезка отнимает верх и низ: у портрета пропадает лоб и подбородок.
   Поэтому кадр, который выше своей ширины, выводится целиком, как снят.

   Какой кадр вертикальный, решает не глаз и не рука: сайт сам смотрит в файл
   и дописывает тегу class="tall" — measure_photos в engine/content.php.
   Отмечать такие снимки в тексте не нужно, и старые статьи починились сами.

   Ширина у вертикального кадра та же, что у горизонтального, — вся колонка.
   Левый край снимка стоит на той же линии, что текст, заголовки и подпись,
   правый — там же, где конец строки. Высота получается какая получается:
   кадр 2:3 в колонке на 712 точек вырастает почти на тысячу и на невысоком
   экране целиком не поместится. Это сознательно: снимок в колонке — часть
   рассказа, и мельче соседних он быть не должен.

   Селектор без знака «>» намеренно: внутри интервью снимок лежит глубже, в
   <dd>, и правило должно достать и там. Во всю ширину (figure.full) всё
   остаётся как было: это полоса 16:9 через весь экран, и вертикальный кадр
   в ней подрезается — его туда и ставят ради полосы.

   Правило одно и короткое: ширину, высоту и фон снимок берёт от соседей
   выше, здесь снимается только навязанная пропорция. */
.article-body figure:not(.full) img.tall {
  aspect-ratio: auto;
}

/* ── СНИМОК В РАМКЕ ──
   Нужна она ровно одному сорту картинок: тем, у кого собственный фон белый.
   Скриншот окна, схема, бланк, логотип — у таких кадров нет края, и на
   белой странице они растекаются: непонятно, где кончается картинка и
   начинается лист. Тонкая линейка возвращает край.

   Ставится классом на ФИГУРУ, а не на сам снимок, и это не вкусовщина.
   Движок дописывает снимку размеры и помечает вертикальные кадры, но
   только тем тегам, у которых своего класса нет (measure_photos в
   content.php). Повесь рамку на <img> — и вертикальное фото перестанет
   вставать целиком, а страница начнёт прыгать при загрузке, потому что
   размеры снимку больше никто не допишет.

   За колонку линейка не вылезает: box-sizing у всего документа border-box,
   рамка рисуется внутри ширины снимка, а не поверх неё.

   Полпикселя, как предлагалось, не берём по той же причине, что и у
   подвала: на обычном экране такая линия то пропадает, то рисуется в
   целый пиксель. Одна точка вторичным цветом ведёт себя предсказуемо.

   Во всю ширину рамки нет: там снимок и есть край экрана, обводить нечего. */
.article-body figure.framed:not(.full) img {
  border: 1px solid var(--c-border);
  /* Бланк и скриншот показываются целиком: подрезанная по 3:2 квитанция
     теряет нижнюю строку, а в документе важна каждая. */
  aspect-ratio: auto;
}

/* ── СНИМОК В ДВЕ ТРЕТИ КОЛОНКИ ──
   Третья ширина, между колонкой и ничем. Нужна там, где снимок — не часть
   рассказа, а справка при нём: скриншот окна, бланк, вывеска, обложка
   книги. В колонку такой кадр вставать не должен — он забирает экран у
   текста и обещает важность, которой в нём нет.

   Ширина — две трети колонки, подпись под снимком и той же ширины, что он:
   подпись принадлежит снимку, а не странице, и обрезана по нему. Треть
   строки справа остаётся пустой — это поле, а не потеря: узкий снимок тем
   и отличается от снимка в колонку, что не занимает строку целиком.

   Левый край снимка стоит на той же линии, что текст и заголовки: ширина
   меняется, сетка — нет.

   Вертикальный кадр и здесь не подрезается: об этом заботится общее
   правило img.tall выше. Рамка тоже работает — она в правиле framed не
   привязана ни к какой ширине, кроме «не во всю». */
/* Селектор без знака «>» — как у рамки и у «медиафайла». В интервью снимки
   стоят не прямо в тексте, а внутри <dl> между ответами, и правило со
   знаком «>» до них не доставало: кнопка «в две трети» ставила класс,
   а снимок всё равно вставал во всю колонку. */
.article-body figure.small {
  display: grid;
  grid-template-columns: 2fr 1fr;
  align-items: start;
}
/* Снимок и подпись оба в первой колонке, друг под другом: вторая колонка
   сетки существует только затем, чтобы первая вышла в две трети ширины. */
.article-body figure.small > * { grid-column: 1; }

/* На телефоне узкой ширины нет вовсе: колонка там и так с ладонь, и две
   трети от неё — это уже не «снимок поменьше», а мелкая картинка. Поэтому
   на телефоне узкий снимок встаёт как обычный, во всю колонку. */
@media (max-width: 768px) {
  .article-body figure.small { grid-template-columns: 1fr; }
}

/* ── СНИМОК, КОТОРЫЙ ОТКРЫВАЕТСЯ КРУПНЕЕ ──
   Отмечается в админке галкой «медиафайл». Нужна она там, где в снимке
   есть что разглядывать: скриншот с мелким текстом, схема, бланк, карта.
   Такой кадр стоит в тексте узким, а по щелчку разворачивается во весь
   экран — поверх страницы, не уводя читателя со статьи.

   Разворачивает его скрипт js/zoom.js, и он же делает снимок доступным с
   клавиатуры. Если скрипта нет, ничего не ломается: кадр просто стоит в
   тексте, как любой другой. Поэтому и курсор, и рамка фокуса включаются
   классом is-zoomable, который ставит скрипт, а не самим классом zoom:
   обещать увеличение, которого не будет, хуже, чем не обещать. */
.article-body figure.zoom img.is-zoomable { cursor: zoom-in; }
.article-body figure.zoom img.is-zoomable:focus-visible {
  outline: 2px solid var(--c-accent);
  outline-offset: 3px;
}

/* Сам экран со снимком. Фон почти чёрный и непрозрачный: это не «страница
   с затемнением», а отдельный просмотр, и полупрозрачный фон только мешал
   бы разглядывать то, ради чего его открыли. */
.lightbox {
  position: fixed; inset: 0; z-index: 200;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: var(--space-16);
  padding: var(--space-56) var(--space-24) var(--space-32);
  background: rgba(17, 17, 17, 0.96);
  cursor: zoom-out;
}

/* Снимок показываем целиком, как снят: никакой подрезки, никакого
   растягивания выше своего размера. */
.lightbox img {
  max-width: 100%; max-height: 82vh;
  width: auto; height: auto;
  object-fit: contain;
  background: var(--c-surface);
}

.lightbox figcaption {
  max-width: var(--col);
  text-align: center;
  /* Светло-серый на почти чёрном. Был отдельный #CCCCCC — теперь цвет
     тонких линий из палитры, на тёмном он читается так же. 27.10. */
  color: var(--c-border);
  margin: 0;
}

/* Закрыть можно щелчком где угодно и клавишей Esc — крестик стоит для
   тех, кто про это не знает. */
.lightbox .lightbox-close {
  position: absolute; top: var(--space-16); right: var(--space-16);
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  font: inherit; font-size: 24px; line-height: 1;
  color: var(--c-bg); background: none; border: 0; border-radius: 4px;
  cursor: pointer;
}
.lightbox .lightbox-close:hover { color: var(--c-accent); }
.lightbox .lightbox-close:focus-visible {
  outline: 2px solid var(--c-bg); outline-offset: -4px;
}

/* Пока открыт просмотр, страница под ним не едет: иначе колёсико
   прокручивает статью, а читатель смотрит на снимок и не понимает,
   почему, закрыв его, оказался в другом месте текста. */
html.is-zoomed, html.is-zoomed body { overflow: hidden; }

/* Две фотографии в одной фигуре встают рядом, а не одна под другой: пара
   и читается парой — два кадра одного места, две детали одного стола. У
   вертикальных снимков это ещё и единственный способ не растянуть статью:
   два кадра 2:3 в колонку подряд — это два экрана прокрутки, а рядом они
   занимают полэкрана. Подпись общая, под обоими. */
.article-body figure:has(img + img) {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8);
  align-items: start;
}

.article-body figure:has(img + img) figcaption { grid-column: 1 / -1; }

/* Снимок на всю ширину проходит ПОВЕРХ плавающего содержания, а не под
   ним. Содержание стоит на поле слева и ничему не мешает, пока поле есть;
   но у снимка во всю ширину поля нет — он и есть вся ширина. Белая плашка,
   выехавшая на фотографию, читается как сбой вёрстки, а не как оглавление.

   Поэтому снимок получает своё место в стопке — на единицу выше полоски и
   заметно ниже шапки (100). Полоска при этом не мигает и не исчезает: она
   честно уезжает под фотографию и выезжает из-под неё, как будто лежит
   слоем ниже. Так оно и есть. */
.article-body > figure.full {
  grid-column: 1 / -1; padding: 0; margin: var(--space-48) 0;
  position: relative; z-index: 41;
}
/* Правка 29.10: обложка и снимок «во всю ширину» — во всю ширину
   страницы, а не окна: на большом мониторе они стоят в тех же границах,
   что шапка и подвал. До 1488 точек ширины ничего не меняется. */
.article-body > figure.full,
.article-cover { margin-inline: calc(var(--page-x) - var(--space-24)); width: auto; }
.article-body > figure.full img { aspect-ratio: 16/9; }
.article-body > figure.full figcaption { padding: 0 var(--space-24); }

figcaption {
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  letter-spacing: var(--t-wide);
  color: var(--c-muted);
  margin-top: var(--space-8);
  line-height: var(--t-meta-lh);
}

.article-cover figcaption { padding: 0 var(--space-24); }

/* Теги идут сразу за выходными данными — это один служебный блок внизу
   страницы, а не два. Поэтому своего отступа сверху у них больше нет:
   воздух над ними уже отмерила строка с датой. */
.tags {
  max-width: var(--col);
  margin: 0 auto;
  padding: 0 var(--space-24) var(--space-72);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-8);
}

.tag {
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  letter-spacing: var(--t-wide);
  padding: var(--space-4) var(--space-8);
  border: 1px solid var(--c-ink);
  line-height: var(--t-meta-lh);
}

.next { display: grid; grid-template-columns: 1fr 1fr; border-top: 1px solid var(--c-border); }   /* 29.10: тонкая серая, как над подвалом */
/* 30.10, п. 19: линию над блоком убрали по просьбе дизайнера. */
.next { border-top: 0; }
/* 30.10, п. 21: при наведении снимок чуть приближается внутри своей рамки,
   как на обложках главной; рамка не двигается — у .next-img overflow: hidden. */
.next-img img { transition: transform 0.4s; }
.next:hover .next-img img { transform: scale(1.03); }
/* Правка 29.10: блок ниже и по ширине страницы. Колонка снимка — две
   пятых, снимок в ней в пропорции 3:2: на экране 1440 блок 384 точки
   высотой вместо 480, на большом мониторе не растёт дальше. */
@media (min-width: 769px) { .next:not(.next-plain) { grid-template-columns: 3fr 2fr; } }
.next { margin-inline: calc(var(--page-x) - var(--space-24)); }
/* Правка 30.10: переносы строк.
   Заголовки — balance: строки примерно равной длины, без одного слова
   на последней. Абзацы и лиды — pretty: браузер не оставляет короткое
   слово одно в последней строке. Старые браузеры это свойство просто
   пропускают, вёрстка от него не зависит. */
.home-title,
.section-head h1,
.article-header h1,
.article-body > h2,
.article-body > h3,
.article-body :is(dl, dd) > h2,
.article-body :is(dl, dd) > h3,
.card-title,
.next-title,
.callout h3,
.also h3,
.rubric-title { text-wrap: balance; }

.lede,
.card-lede,
.next-lede,
.section-head p,
.article-body > p,
.article-body dd,
.article-body dd > p { text-wrap: pretty; }

.next-lede {
  font-size: var(--t-main);
  font-weight: 400;
  line-height: var(--t-main-lh);
  color: var(--c-muted);
  max-width: var(--card-col);
  letter-spacing: 0;
}

.next-text {
  padding: var(--space-40) var(--space-32);
  display: flex;
  flex-direction: column;
  /* Внутри теперь только заголовок — надписи «Следующий материал»
     и «Читать» убраны: кликабелен весь блок, и отдельные «кнопки» в нём
     выглядели как ещё одна ссылка. Заголовок стоит посередине по высоте. */
  justify-content: center;
  gap: var(--space-16);   /* 29.10: было 32 — между заголовком и лидом, как в карточке */
}

.next-label { color: var(--c-muted);
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  line-height: var(--t-meta-lh);
  letter-spacing: var(--t-wide);
}

.next-title {
  max-width: var(--card-col);   /* 29.10: как заголовок карточки на главной */
  font-size: var(--t-h3);
  font-weight: 700;
  line-height: var(--t-h3-lh);   /* 1.1 × 1.1 */
  letter-spacing: 0;
  transition: opacity 0.2s;
}

.next:hover .next-title { opacity: 0.6; }
.next-arrow {
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  line-height: var(--t-meta-lh);
  letter-spacing: var(--t-wide);
}
/* Высота блока задаётся здесь, а не снимком. Раньше картинка стояла
   в сетке своим настоящим ростом, и вертикальная обложка растягивала
   блок почти на экран — с пустым белым полем вокруг заголовка. Теперь
   снимок лежит поверх ячейки и подрезается под неё. */
.next-img { position: relative; overflow: hidden; min-height: 320px; aspect-ratio: 3 / 2; background: var(--c-surface); }
.next-img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
/* 30.10, п. 27. Ячейка в пропорции 3:2 и не ниже 320 — значит, не уже 480.
   На экранах от 769 до 1300 колонка снимка уже 480, и ячейка вылезала за
   край страницы (на 780 — на 170 точек): страница ездила вбок, а снимок
   прыгал при изменении ширины окна. width: 100% и min-width: 0 разрешают
   ячейке быть уже своей пропорции: ширину берёт у колонки, высота не меньше 320,
   снимок встаёт целиком, остаток — серый фон, как и задумано выше. */
.next-img { min-width: 0; width: 100%; }
/* Правка 29.10: снимок не обрезается. Ячейка в пропорции 3:2 — в ней
   почти все наши обложки, и они встают целиком без полей. Обложка другой
   формы тоже встаёт целиком, а остаток ячейки — серый фон. */

/* ── ПОДВАЛ ──
   Одна полоса вместо двух. Верхняя часть с логотипом и двумя столбцами
   ссылок убрана: «Разделы» слово в слово повторяли верхнее меню, а второй
   список тех же трёх разделов внизу страницы ничего не добавлял.

   Осталось то, ради чего подвал и нужен: куда писать, кто это сделал и
   оговорка к руководствам. Слева адрес и зачем писать, справа выходные
   данные, под ними во всю ширину — оговорка.

   Линейка сверху была чёрной во всю ширину и резала страницу пополам:
   подвал читался как отдельный документ, пришитый к низу. Теперь она того
   же тона, что и все прочие разделители на сайте. Полпикселя, как
   предлагалось, не берём: на обычном экране такая линия то пропадает
   целиком, то рисуется в пиксель — одна точка вторичным цветом ведёт себя
   предсказуемо и выглядит так же тихо. */
.site-footer { border-top: 1px solid var(--c-border); }

.footer-bottom {
  display: flex;
  /* wrap-reverse, а не wrap: выходные данные стоят в вёрстке первыми, чтобы
     занять левый край, почта — справа. Когда на одну строку обе не влезают,
     wrap-reverse уносит почту наверх, а не вниз: на телефоне главное в
     подвале остаётся первым, а мелкий шрифт — последним. Всё это без
     контрольной ширины: она была бы у каждого языка своя. */
  flex-wrap: wrap-reverse;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-8) var(--space-40);
  padding: var(--space-32) var(--page-x);
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  line-height: var(--t-meta-lh);
  color: var(--c-muted);
  letter-spacing: var(--t-wide);
}

.footer-email a {
  font-size: var(--t-main);
  /* 500, а не 600: полужирная почта спорила с заголовками, а это
     подпись внизу страницы. Правка дизайнера, 27 октября. */
  font-weight: 500;
  border-bottom: 1px solid var(--c-ink);
  padding-bottom: 2px;
  color: var(--c-ink);
  transition: color 0.15s, border-color 0.15s;
  line-height: var(--t-main-lh);
  letter-spacing: 0;
}

.footer-email a:hover { color: var(--c-accent); border-bottom-color: var(--c-accent); }
/* 30.10, п. 26: подпись «Пишите нам» перед почтой — серая и мелкая, как
   выходные данные слева: она поясняет адрес, а не спорит с ним. */
.footer-email-label { margin-right: var(--space-4); }

/* Палочка серая и с воздухом, куски строки — нет: тот же приём, что в
   строке с датой и автором над материалом. */
.footer-meta span:not(.meta-part) { margin: 0 var(--space-4); }
.footer-meta .meta-part { white-space: nowrap; }
/* 30.10, п. 25 по просьбе дизайнера: выходные данные в две строки —
   «© 2026 Добро Дошли» и под ней «Сделано в Школе…». Палочка между ними
   больше не нужна и прячется. */
.footer-meta .meta-part { display: block; }
.footer-meta span:not(.meta-part) { display: none; }

.footer-meta a {
  color: inherit;
  border-bottom: 1px solid var(--c-quiet);
  transition: color 0.15s, border-color 0.15s;
}
.footer-meta a:hover { color: var(--c-accent); border-bottom-color: var(--c-accent); }

/* ── СЛУЖЕБНОЕ: замечания редактору, только в режиме отладки ──
   Единственное место, где цвета прописаны мимо палитры, и намеренно.
   В палитре нет цвета ошибки: красный в ней один и занят ссылками, а
   красить ошибку тем же красным, что ссылку, нельзя — это разные вещи.
   Блок виден только редактору при отладке, на сайт не попадает, поэтому
   оставлен как есть до решения дизайнера: заводим цвет ошибки в палитру
   или этот блок красим серым. */
.debug-problems {
  background: #fff4f4;
  border: 1px solid #d33;
  color: #900;
  margin: var(--space-16) var(--space-24);
  padding: var(--space-16) var(--space-16);
  font-size: var(--t-meta);
  font-weight: var(--t-meta-w);
  line-height: var(--t-meta-lh);
  letter-spacing: var(--t-wide);
}

.debug-problems ul { margin: var(--space-8) 0 0; padding-left: var(--space-16); }

/* ── МОБИЛЬНАЯ ВЁРСТКА ── */
@media (max-width: 768px) {
  /* На телефоне поле уже: 24 точки с каждой стороны от трёхсот девяноста
     заметно сужают и без того узкие карточки. */
  .feed { gap: var(--space-16); padding: 0 var(--space-16) var(--space-16); }
  .home-title { padding: var(--space-40) var(--space-16) var(--space-24); }

  /* Нижний предел высоты на телефоне мягче: на коротких экранах жёсткие
     пятьсот шестьдесят точек выталкивали за край не только фотографию,
     но и подпись вместе с ней. */
  .feed > .block-hero:first-child { min-height: 420px; }
  .feed > .block-hero:first-child .block-overlay-content { padding-bottom: var(--space-40); }

  .block-split, .block-dark, .block-light { grid-template-columns: 1fr; }
  .block-pane-text { min-height: auto; padding: var(--space-32) var(--space-16); }
  .block-pane-image, .block-pane-over { min-height: 280px; }
  .block-overlay-content { padding: var(--space-24) var(--space-16); }
  .section-head { padding: var(--space-40) var(--space-16) var(--space-24); }
  /* The display face is wide, and four menu items plus three languages no
     longer fit on one line at phone width. So the bar becomes two rows —
     no burger menu, everything stays visible. */
  :root { --header-h: 100px; }

  .site-header { flex-wrap: wrap; height: auto; padding: 0 var(--space-16); gap: 0; }
  .site-header > .logo { order: 1; height: auto; padding: var(--space-8) 0; }
  .site-header > .lang-switch-wrap { order: 2; margin-left: auto; }
  .site-header > .main-nav { order: 3; flex-basis: 100%; }   /* 29.10: линия над меню убрана по просьбе дизайнера */

  .nav-links { width: 100%; justify-content: space-between; gap: var(--space-4); }
  .nav-links a { font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase; padding: var(--space-16) 2px; }
  .lang-switch { gap: 0; }
  .lang-switch a, .lang-switch li > span { font-size: 12px; padding: var(--space-8) var(--space-4); letter-spacing: 0.03em; }
  .article-header { padding: var(--space-40) var(--space-16) var(--space-24); }
  .article-body > * { padding-left: var(--space-16); padding-right: var(--space-16); }
  .article-body > .callout { padding: var(--space-24) var(--space-16) var(--space-24); column-gap: var(--space-16); margin-left: 0; margin-right: 0; }
  .article-body > .toc a { font-size: 16px; padding: var(--space-8) 0; }
  .article-body > figure.table { padding: var(--space-16); }
  /* Во всю ширину на телефоне — это и есть ширина экрана, боковые поля
     нужны те же, что у текста. */
  .article-body figure.table :is(td, th) { padding-right: var(--space-8); }
  .callout-face { width: 56px; height: 56px; }
  .article-body > figure.full figcaption, .article-cover figcaption { padding: 0 var(--space-16); }
  .article-meta.is-foot { padding: var(--space-16) var(--space-16) var(--space-32); }
  .tags { padding: 0 var(--space-16) var(--space-64); }
  .guide-back { padding: 0 var(--space-16) var(--space-56); }
  .guide-note { padding-bottom: var(--space-56); }
  .feed-more { padding: var(--space-32) var(--space-16) var(--space-48); }
  .next { grid-template-columns: 1fr; }
  .next-img { min-height: 220px; }
  /* На телефоне почта и выходные данные встают друг под друга сами —
     полосе просто не хватает ширины на обе, и почта оказывается сверху. */
  .footer-bottom { padding: var(--space-24) var(--space-16) var(--space-32); }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ── ОДНО ПОДЧЁРКИВАНИЕ ССЫЛОК НА ВЕСЬ САЙТ ──
   Было три разных: в тексте статьи — тонкая серая линия (0,5 точки,
   #888, в 3 точках под буквами); в списке руководств, в строке над
   заголовком, в подвале и в «Читайте также» — линия рамкой в целую точку,
   у части ссылок чёрная. Чёрная толстая линия под целым столбцом
   заголовков кричала громче самих заголовков.

   Теперь у всех ссылок то же, что в тексте статьи: тонкая серая линия
   на одном расстоянии от букв, при наведении — красная вместе с текстом.
   Рамку снизу у этих ссылок снимаем: она стоит ниже подчёркивания и
   дала бы вторую линию. */
.rubric-title a,
.rubric-list .guide-title a,
.also a,
.guide-back a,
.article-meta .meta-home,
.section-head-action a,
.footer-email a,
.footer-meta a {
  border-bottom: 0;
  text-decoration: underline;
  text-decoration-color: var(--c-quiet);
  text-decoration-thickness: 0.75px; /* 30.10, п. 15: было 0.5px, потом 1px */
  text-underline-offset: 3px;        /* 30.10, п. 15: 5px вернули к 3px */
  transition: color 0.15s, text-decoration-color 0.15s;
}
.footer-email a { padding-bottom: 0; }
.rubric-title a:hover,
.rubric-list .guide-title a:hover,
.also a:hover,
.guide-back a:hover,
.article-meta .meta-home:hover,
.section-head-action a:hover,
.footer-email a:hover,
.footer-meta a:hover {
  color: var(--c-accent);
  text-decoration-color: var(--c-accent);
}

/* ── ДВА СНИМКА РЯДОМ ──
   <figure class="pair"> с двумя <img> и одной подписью. Для пары кадров,
   которые рассказывают одно и то же — как два снимка с каяков у Антона:
   друг под другом они расползались на два экрана, рядом читаются одной
   сценой.

   Оба кадра одной высоты и оба целиком, без обрезки. Ширину колонки
   пара делит по пропорциям кадров: сайт сам пишет каждому снимку его
   пропорцию (--ar, ширина к высоте), и кадр поуже получает меньше места.
   Раньше кадры подрезались до 3:4 или 4:3 — и у меню на свадьбе срезало
   верх и низ рамки.

   Ширина пары — вся колонка, щель 16 точек, подпись под обоими, во всю
   ширину. На телефоне пара остаётся парой: каждый кадр в полколонки ещё
   читается, а друг под другом они снова растянулись бы на два экрана. */
.article-body figure.pair {
  display: flex;
  flex-wrap: wrap;
  /* Между кадрами 16, а по вертикали ноль: расстояние до подписи задаёт
     сама подпись, как у любого снимка, — иначе оно сложилось бы с щелью. */
  column-gap: var(--space-16);
  row-gap: 0;
  align-items: flex-start;
}
.article-body figure.pair > img,
.article-body figure.pair > img.tall {
  flex: var(--ar, 1) 1 0;
  min-width: 0;
  width: auto;
  height: auto;
  aspect-ratio: auto;
}
.article-body figure.pair > figcaption { flex-basis: 100%; }
