/*
 * chrome.css - оформление ОБОЛОЧКИ сайта (шапка, шторка, подвал, подпись автора).
 * Заготовка комплекта Site Prompt: шаблоны/assets/css/chrome.css (08.09.2026, п. 134
 * оценщика: путь skeleton/ Фабрики у читателя комплекта не существует). ВСЕ правила
 * mobile-first.
 *
 * Имя сменено с blocks.css намеренно: «блоки» в фабрике - это 159 блоков библиотеки
 * владельца, а здесь оболочка движка. Одно слово на две разные вещи путало бы роль,
 * которой велено «собрать страницу из блоков».
 * header-nav - drawer, проходящий 6/6 критериев модалки гейта (доктрина R16-R19).
 */

/* ================= header-nav ================= */
.site-header {
  position: sticky; top: 0; z-index: var(--z-header, 100);
  height: var(--header-h);
  background: var(--glass-bg);
  backdrop-filter: blur(10px);
  border-bottom: var(--hairline);
}
.site-header__bar {
  height: var(--header-h);
  display: flex; align-items: center; gap: var(--s-3);
}
/* min-height 44 при картинке 36: тап-цель дотягивается до порога, а лого не растёт
 * и шапка в 60px остаётся прежней (гейт мерил 108x36). */
.site-header__logo { display: flex; align-items: center; flex: 0 0 auto; min-height: 44px; }
.site-header__logo img { height: 36px; width: auto; }
/* ЛОГОТИП В ТЁМНОЙ ТЕМЕ (06.09.2026). Пара файлов: layout.php печатает logo.png с
 * классом --light и logo-dark.png|svg с классом --dark, показывается один по
 * html[data-mode]. Канон переключения тот же, что у кнопки темы ниже: data-mode="dark"
 * поверх светлой базы, media-запроса на тему нет. Без второго файла классов нет -
 * поведение прежнее. */
.site-header__logo-img--dark { display: none; }
html[data-mode="dark"] .site-header__logo-img--light { display: none; }
html[data-mode="dark"] .site-header__logo-img--dark { display: inline-block; }
/* Одноцветный тёмный растр без пары: 'logo_ink' => true в config/site.php даёт классу
 * logo--ink белую заливку фильтром. Возвращено из pokerspro.ru (filter) 06.09.2026:
 * там правило жило в проектном skin.css, а следующий сайт с тёмным растром получил бы
 * невидимую шапку. */
html[data-mode="dark"] .site-header__logo img.logo--ink { filter: brightness(0) invert(1); }
.site-header__spacer { flex: 1 1 auto; }

/* CTA в шапке - компактная на мобиле, но не ниже порога тапа: было 40px. */
.site-header__cta { min-height: 44px; padding-inline: var(--s-4); font-size: var(--t-small); }

/* Бургер - ≥44px тап (R20) */
.nav-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; padding: 0;
  background: transparent; border: 1px solid var(--rule-strong); border-radius: var(--r-md);
  color: var(--text); cursor: pointer;
}
.nav-toggle__box { position: relative; width: 20px; height: 14px; }
.nav-toggle__box span { position: absolute; left: 0; width: 100%; height: 2px; background: currentColor; border-radius: 2px; transition: transform var(--dur-quick,.15s) var(--ease,ease), opacity var(--dur-quick,.15s) ease; }
.nav-toggle__box span:nth-child(1) { top: 0; }
.nav-toggle__box span:nth-child(2) { top: 6px; }
.nav-toggle__box span:nth-child(3) { top: 12px; }

/* Десктопная навигация - скрыта на мобиле */
.nav-desktop { display: none; }

/* ---- Выпадающий список хаба в шапке (11.09.2026, play-mines.click) ----
 * Разметка: .nav-desktop__group > a + button[data-nav-sub-toggle] + .nav-sub.
 * В покое список display:none (правило 03 про переполнение: скрытое - только
 * display:none). Раскрывают три вещи: наведение на группу, фокус внутри группы
 * (клавиатура) и класс is-open от кнопки (тап, app.js). На мобиле .nav-desktop
 * скрыта целиком, свой список у шторки ниже. */
.nav-desktop__group { position: relative; display: inline-flex; align-items: center; gap: 2px; }
.nav-desktop__more {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0; margin-left: -2px;
  background: transparent; border: 0; border-radius: var(--r-md);
  color: var(--text-mute); cursor: pointer;
}
.nav-desktop__more svg { width: 16px; height: 16px; transition: transform var(--dur-quick, .15s) var(--ease, ease); }
.nav-desktop__more:hover, .nav-desktop__group:hover .nav-desktop__more,
.nav-desktop__group.is-branch .nav-desktop__more { color: var(--brand); }
.nav-desktop__more[aria-expanded="true"] svg { transform: rotate(180deg); }
.nav-sub {
  display: none;
  position: absolute; top: calc(100% + 10px); left: 0;
  z-index: calc(var(--z-header, 100) + 1);
  min-width: 300px; max-width: calc(100vw - 32px); padding: var(--s-3);
  background: var(--surface); border: var(--hairline); border-radius: var(--r-lg);
  box-shadow: var(--shadow-pop);
}
/* «Мостик» над списком: курсор по пути от ссылки к списку не выпадает из группы. */
.nav-sub::before { content: ""; position: absolute; left: 0; right: 0; top: -12px; height: 12px; }
.nav-desktop__group:hover .nav-sub, .nav-desktop__group:focus-within .nav-sub, .nav-sub.is-open { display: block; }
.nav-sub__list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr; gap: 2px; }
.nav-desktop .nav-sub__list a {
  display: flex; align-items: center; min-height: 40px; padding: 0 var(--s-3);
  border-radius: var(--r-md); color: var(--text-dim); font-weight: var(--fw-medium); font-size: var(--t-small);
  white-space: nowrap; text-decoration: none;
}
.nav-desktop .nav-sub__list a:hover, .nav-desktop .nav-sub__list a[aria-current="page"] { background: var(--brand-soft); color: var(--text); text-decoration: none; }
.nav-desktop .nav-sub__all {
  display: flex; align-items: center; justify-content: center; min-height: 40px; margin-top: var(--s-2);
  border-top: var(--hairline); padding-top: var(--s-2); color: var(--brand); font-size: var(--t-small); font-weight: var(--fw-semi);
}

/* ---- Backdrop (критерий 6): fixed, покрывает вьюпорт ---- */
.nav-backdrop {
  position: fixed; inset: 0; z-index: var(--z-modal, 200);
  background: var(--overlay-dim); /* токен, не literal (08.09.2026, п. 97 оценщика) */
  display: none;
}
.nav-backdrop.is-open { display: block; }

/* ---- Drawer (критерии 1-5): mobile-first модальное меню ---- */
.nav-drawer {
  /* Закрыт: display:none (R19 - не transform, не opacity) */
  display: none;
  position: fixed;               /* критерий 1 */
  top: 0; right: 0; bottom: 0;
  width: min(86vw, 340px);
  z-index: calc(var(--z-modal, 200) + 1);
  background: var(--surface);
  border-left: var(--hairline);
  padding: var(--s-5) var(--s-4) calc(var(--s-5) + env(safe-area-inset-bottom));
  overflow-y: auto;
  flex-direction: column; gap: var(--s-2);
}
.nav-drawer.is-open { display: flex; }
.nav-drawer__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--s-4); }
.nav-drawer__title { font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--t-h4); }
.nav-drawer__close {
  width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid var(--rule-strong); border-radius: var(--r-md);
  color: var(--text); font-size: 22px; line-height: 1; cursor: pointer;
}
.nav-drawer__link {
  display: flex; align-items: center; min-height: 48px; padding: 0 var(--s-3);
  color: var(--text-dim); font-weight: var(--fw-medium); border-radius: var(--r-md); text-decoration: none;
}
.nav-drawer__link:hover, .nav-drawer__link[aria-current="page"] { background: var(--brand-soft); color: var(--text); text-decoration: none; }
.nav-drawer__cta { margin-top: var(--s-4); }
.nav-drawer__lang { display: flex; gap: var(--s-2); margin-top: var(--s-4); padding-top: var(--s-4); border-top: var(--hairline); }
.nav-drawer__lang a { flex: 1; text-align: center; min-height: 44px; display: flex; align-items: center; justify-content: center; border: 1px solid var(--rule-strong); border-radius: var(--r-md); color: var(--text-mute); }
.nav-drawer__lang a[aria-current="true"] { background: var(--brand-soft); color: var(--text); border-color: var(--brand); }

/* Скролл фона заблокирован при открытом меню (критерий 5) */
html.nav-open, html.nav-open body { overflow: hidden; }

/* Дети хаба в шторке - <details> под ссылкой хаба (11.09.2026). */
.nav-drawer__sub { border-radius: var(--r-md); }
.nav-drawer__sub-summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-2);
  min-height: 44px; padding: 0 var(--s-3); cursor: pointer; list-style: none;
  color: var(--text-mute); font-size: var(--t-small); font-weight: var(--fw-medium);
}
.nav-drawer__sub-summary::-webkit-details-marker { display: none; }
.nav-drawer__sub-summary::after { content: "+"; font-size: 18px; line-height: 1; margin-left: auto; }
.nav-drawer__sub[open] .nav-drawer__sub-summary::after { content: "-"; }
.nav-drawer__sub-count { display: inline-flex; align-items: center; justify-content: center; min-width: 22px; height: 22px; padding: 0 6px; border-radius: 999px; background: var(--brand-soft); color: var(--text); font-size: 12px; font-weight: var(--fw-semi); }
.nav-drawer__sub-list { list-style: none; margin: 0; padding: 0 0 var(--s-2) var(--s-3); display: grid; gap: 2px; }
.nav-drawer__link--sub { min-height: 40px; font-size: var(--t-small); font-weight: var(--fw-body); }

/* ================= footer ================= */
/* margin-top был --s-9 (96px): вместе с паддингом последней полосы это давало
 * 160px пустоты перед подвалом на 360 - пятую часть экрана ни о чём (замер
 * probe_layout, все 5 страниц). На мобиле 48, на 768 возвращается 96. */
.site-footer {
  background: var(--bg-2); border-top: var(--hairline);
  padding-block: var(--s-6);
  padding-bottom: calc(var(--s-6) + env(safe-area-inset-bottom));
  margin-top: var(--s-6);
}
/* СЕТКА ПОДВАЛА (08.09.2026, п.41, образец владельца - sneket .ftr__top): первым идёт
 * бренд-блок (знак, строка о сайте, переключатель языка), за ним колонки ссылок.
 * На мобильном всё в один столбец, бренд сверху во всю ширину; на 768+ колонки
 * ссылок - auto-fit вместо жёстких четырёх: треков столько, сколько колонок напечатал
 * layout по составу сайта, пустых не остаётся; на 1024+ бренд - первая широкая колонка.
 * minmax(0, 1fr) и min-width: 0 у детей: длинное слово в строке о сайте не растянет
 * трек и не даст горизонтальной прокрутки на 360. */
.site-footer__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-5); }
.site-footer__grid > * { min-width: 0; }
.site-footer__brand { display: grid; gap: var(--s-3); align-content: start; justify-items: start; }
.site-footer__logo { display: inline-flex; align-items: center; min-height: 44px; color: var(--text); text-decoration: none; }
.site-footer__logo img { height: 32px; width: auto; }
/* Пара для тёмной темы и одноцветный растр - те же правила, что у шапки, под своим
 * БЭМ-префиксом: __знак_сайта() в layout.php печатает классы site-footer__logo-img--light
 * и --dark, logo--ink - общий. */
.site-footer__logo-img--dark { display: none; }
html[data-mode="dark"] .site-footer__logo-img--light { display: none; }
html[data-mode="dark"] .site-footer__logo-img--dark { display: inline-block; }
html[data-mode="dark"] .site-footer__logo img.logo--ink { filter: brightness(0) invert(1); }
.site-footer__wordmark { font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--t-h4); color: var(--text); }
.site-footer__tagline { margin: 0; max-width: 46ch; color: var(--text-mute); font-size: var(--t-small); line-height: var(--lh-base); }
/* Переключатель языка - та же коробка, что в шторке (.nav-drawer__lang): 44px, рамка,
 * текущий язык подсвечен; но по содержимому, а не на всю ширину блока. */
.site-footer__lang { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.site-footer__lang a {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; min-width: 44px; padding-inline: var(--s-3);
  border: 1px solid var(--rule-strong); border-radius: var(--r-md);
  color: var(--text-mute); font-size: var(--t-small); text-decoration: none;
}
.site-footer__lang a[aria-current="true"] { background: var(--brand-soft); color: var(--text); border-color: var(--brand); }
/* Заголовок колонки подвала. Раньше это был <h4> прямо в разметке, и он давал
 * разрыв уровней заголовков после <h2> страницы - ловится и правилом свода про
 * пропуск уровней, и Lighthouse (heading-order). Теперь layout печатает абзац с
 * этим классом, вид прежний. Возвращено из play-mines.click 02.09.2026. */
.site-footer__title,
.site-footer__col h4 { font-size: var(--t-small); text-transform: uppercase; letter-spacing: .05em; color: var(--text-faint); margin-bottom: var(--s-3); }
/* 32px было ниже порога тапа: гейт считал по 9-11 таких ссылок на каждой
 * странице (R20, 44px). В столбик, пальцем, промахнуться легче всего именно тут. */
.site-footer__col a { display: block; min-height: 44px; line-height: 44px; color: var(--text-mute); }
.site-footer__col a:hover { color: var(--text); }
/* Колонка хаба в подвале (11.09.2026): список детей в два столбца от 480px, на
 * 1024+ занимает два трека сетки, чтобы шестнадцать ссылок не тянули подвал вниз. */
.site-footer__cols2 { display: grid; grid-template-columns: minmax(0, 1fr); column-gap: var(--s-4); }
.site-footer__legal { margin-top: var(--s-6); padding-top: var(--s-5); border-top: var(--hairline); color: var(--text-faint); font-size: var(--t-small); }
/* Дисклеймер шёл вплотную к последней ссылке колонки - читался как ещё один пункт
 * меню. Отбиваем его воздухом от сетки разделов. */
.site-footer__disclaimer { margin-top: var(--s-5); color: var(--text-faint); font-size: var(--t-small); }

/* НИЖНЯЯ ПОЛОСА ПОДВАЛА (08.09.2026, п.41, образец владельца - sneket .ftr__bottom):
 * волосяная линия сверху, внутри в строку - значок 18+, дисклеймер, ссылка
 * ответственной игры; юрстрока с © - своей строкой во всю ширину. Старые правила
 * .site-footer__legal и __disclaimer выше живы для сайтов, собранных до полосы; внутри
 * полосы их отступы и вторая линия снимаются - линия у полосы одна. Дисклеймер тянется
 * (flex-basis 240px): на 360 рядом со значком помещается, ссылка переносится под него. */
.site-footer__bottom {
  display: flex; flex-wrap: wrap; align-items: flex-start;
  gap: var(--s-3) var(--s-4);
  margin-top: var(--s-6); padding-top: var(--s-5); border-top: var(--hairline);
}
.site-footer__bottom .site-footer__disclaimer { flex: 1 1 240px; margin: 0; }
.site-footer__bottom .site-footer__legal { flex: 1 1 100%; margin: 0; padding: 0; border-top: 0; }
/* Значок 18+ - маленький бейдж: обводка, скругление, --t-tiny. Цвет danger, как у
 * образца: это возрастная пометка, а не ещё одна серая строка. aria-hidden ставит
 * layout - возраст назван словами в дисклеймере рядом. */
.site-footer__age {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  min-width: 36px; height: 24px; padding-inline: var(--s-2);
  border: 1.5px solid var(--danger); border-radius: var(--r-soft);
  color: var(--danger); font-size: var(--t-tiny); font-weight: var(--fw-bold);
  letter-spacing: .04em; line-height: 1;
}
.site-footer__rg {
  display: inline-flex; align-items: center; flex: 0 0 auto; min-height: 44px;
  color: var(--text-mute); font-size: var(--t-small); font-weight: var(--fw-semi);
}
.site-footer__rg:hover { color: var(--text); }

/* ================= брейкпоинты (min-width только) ================= */
@media (min-width: 768px) {
  .nav-toggle { display: none; }
  .nav-desktop { display: flex; align-items: center; gap: var(--s-4); }
  .nav-desktop a { color: var(--text-dim); font-weight: var(--fw-medium); text-decoration: none; } /* меню - не абзац: подчёркивание base.css здесь читается как старина */
  .nav-desktop a:hover, .nav-desktop a[aria-current="page"] { color: var(--brand); text-decoration: none; }
  .nav-desktop__group.is-branch > a { color: var(--brand); }
  .site-header__cta { min-height: 44px; font-size: var(--t-body); }
  /* На десктопе drawer/backdrop не участвуют */
  .nav-drawer, .nav-backdrop { display: none !important; }
  html.nav-open, html.nav-open body { overflow: auto; }
  .site-footer { padding-block: var(--s-7); margin-top: var(--s-9); }
  /* Колонки по составу, а не четыре жёстко (08.09.2026, п.41); бренд на 768-1023 ещё
   * во всю ширину сверху - трёх треков по 180 на планшете рядом с ним не хватит. */
  .site-footer__grid { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--s-7); }
  .site-footer__brand { grid-column: 1 / -1; }
  .site-footer__col a { min-height: 32px; line-height: 32px; }
  .site-footer__rg { min-height: 32px; }
  .stamp__in { padding-block: var(--s-5); }
}
@media (min-width: 1024px) {
  .nav-sub { min-width: 520px; }
  .nav-sub__list { grid-template-columns: 1fr 1fr; }
  /* Бренд - первая широкая колонка, ссылки - auto-fit следом (08.09.2026, п.41).
   * auto-fit при фиксированном первом треке законен: у обоих minmax фиксированный
   * минимум; пустые треки схлопываются вместе с промежутками. */
  .site-footer__grid { grid-template-columns: minmax(220px, 1.4fr) repeat(auto-fit, minmax(160px, 1fr)); }
  .site-footer__brand { grid-column: auto; }
  .site-footer__col--wide { grid-column: span 2; }
}

/* ================= page-meta (E-E-A-T бар) ================= */
.page-meta { background: var(--bg-2); border-bottom: var(--hairline); }
.page-meta .container { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); padding-block: var(--s-3); }
.page-meta__item { font-size: var(--t-small); color: var(--text-faint); }
.page-meta__item time { color: var(--text-mute); }

/* ================= stamp (полоса «Последнее обновление») =================
 * 08.09.2026, п.33, образец владельца - sneket .stamp. Печатает layout.php в самом низу
 * <main>: подпись, дата в единственном <time> страницы полужирным цветом текста и, при
 * непустом авторе в настройках, «Сверял: имя» за вертикальной линией. Тёмная тема -
 * теми же токенами (--bg-2, --rule, --text): своих цветов у полосы нет. Правила
 * .page-meta выше оставлены: их могут держать собранные сайты; заготовка их больше не
 * печатает. Отступ по вертикали --s-4, на 768+ --s-5 (в блоке брейкпоинтов). */
.stamp { margin-top: var(--s-6); border-top: var(--hairline); background: var(--bg-2); }
.stamp__in {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--s-2) var(--s-3);
  padding-block: var(--s-4);
  color: var(--text-faint); font-size: var(--t-small); line-height: var(--lh-base);
}
.stamp__date { color: var(--text); font-weight: var(--fw-semi); }
.stamp__by { padding-left: var(--s-3); border-left: 1px solid var(--rule-strong); }
/* Полоса стоит последней в <main> - подвал прижимается к ней вплотную: на снимке 1280
 * между двумя полосами одного фона оставалось 96px пустого поля (штатный margin-top
 * подвала), и они читались как разрыв. Только при .stamp последним ребёнком main, через
 * :has() - страницы без полосы и старые сайты правило не трогает. */
main:has(> .stamp:last-child) + .site-footer { margin-top: 0; }

/* ================= page-author (подпись автора под H1) =================
 * Разметка приходит из блока blocks/ (партиал автора; прежняя папка партиалов
 * внутри content/ с именем на «_» снята 08.09.2026, п. 28 оценщика: такие имена в
 * отгрузку не едут, партиалы живут в blocks/) и намеренно
 * переиспользует .page-meta__item - своих классов у неё почти нет. Здесь ровно то,
 * чего служебной строке не хватает под заголовком: свой отступ, кругляш аватарки
 * и тап-порог у имени.
 *
 * ПОДПИСЬ - ОБЫЧНЫЙ АБЗАЦ С ИНЛАЙНОВЫМ СОДЕРЖИМЫМ. Не делать её flex/grid: голые
 * текстовые узлы («Автор:», «· главный редактор») станут отдельными элементами
 * раскладки, и должность рассыплется в колонку по слогам. Проверено на себе
 * 2026-08-15: первая версия этого блока была grid и ломала подпись именно так.
 *
 * До появления стилей имя-ссылка имело коробку 272x22 - ниже жёсткого порога 24px
 * (гейт: R20 «text link below 24px» на всех пяти страницах). */
.page-author { margin-block: var(--s-3) var(--s-5); line-height: 1.6; }
/* base.css делает все img блочными (img{display:block;height:auto}) - аватарке это
 * рвёт строку и убивает заданный размер. Возвращаем инлайн явно. */
.page-author__face {
  display: inline-block; width: 32px; height: 32px;
  border-radius: var(--r-pill); object-fit: cover;
  vertical-align: -9px; margin-right: var(--s-2);
}
.page-author__name { display: inline-block; padding-block: 3px; color: var(--text-dim); font-weight: var(--fw-semi); }

/* Полоса раскрытия партнёрского интереса. Стоит выше шапки намеренно: раскрытие обязано
   попасться читателю ДО первой партнёрской ссылки (CAP 3.3), а первая ссылка - кнопка в
   шапке. Мелкая, приглушённая, но не спрятанная: display:none здесь был бы обманом. */
.affiliate-disclosure {
  margin: 0;
  padding: 6px 16px;
  font-size: 12px;
  line-height: 1.4;
  text-align: center;
  color: var(--color-text-muted, #6b7280);
  background: var(--color-surface-muted, #f3f4f6);
  border-bottom: 1px solid var(--color-border, #e5e7eb);
}

/* ================= кнопка «наверх» =================
   Правило владельца от 29.08.2026: круглая кнопка со стрелкой вверх в правом нижнем
   углу, на каждой странице. JS (initBackToTop в app.js) вешает .is-visible после 600px
   прокрутки; до этого кнопка не занимает места и не ловит клики.

   ПОЧЕМУ visibility, А НЕ display:none. С display элемент выпадает из раскладки, и
   переход не проигрывается вовсе - кнопка появлялась бы рывком. visibility + opacity
   дают плавность и при этом честно убирают её из-под курсора и с пути читалки. */
.to-top {
  position: fixed;
  right: var(--gutter);
  bottom: var(--gutter);
  z-index: var(--z-sticky);
  display: grid;
  place-items: center;
  /* MOBILE-FIRST (08.09.2026, п. 96 оценщика): базово - узкий экран, кнопка мельче и
     ближе к краю, чтобы не закрывать содержимое; 44px - ровно порог тапа --tap-min.
     Здесь стояло правило max-width: 479px, запрещённое 03 (медиа-запросы только min-width). */
  width: 44px;
  height: 44px;
  padding: 0;
  border: var(--hairline);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-pop);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity var(--dur-base) var(--ease),
              transform var(--dur-base) var(--ease),
              visibility var(--dur-base) var(--ease);
}
.to-top.is-visible { opacity: 1; visibility: visible; transform: none; }
.to-top:hover { background: var(--brand); color: var(--on-brand); border-color: var(--brand); }
.to-top svg { width: 22px; height: 22px; }

/* От 480px кнопка крупнее и отступает на ширину поля. */
@media (min-width: 480px) {
  .site-footer__cols2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .to-top { width: 48px; height: 48px; right: var(--gutter); bottom: var(--gutter); }
}

/* ================= лайтбокс =================
   Правило владельца от 29.08.2026: картинка в блоке или в слайдере открывается по клику
   в лайтбоксе. Оверлей создаёт app.js один на страницу; здесь только оформление.

   Это МОДАЛЬНЫЙ ДИАЛОГ по тем же семи свойствам, что и мобильное меню (03-ВЁРСТКА):
   position:fixed, role=dialog, aria-modal, подложка, фокус внутрь и назад, Escape,
   скролл фона заблокирован. Свойства держит JS, вид - здесь. */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: none;
  place-items: center;
  padding: var(--gutter);
  background: var(--overlay); /* токены оверлеев - tokens.css (08.09.2026, п. 97 оценщика) */
  /* ОТКРЫТИЕ В ДВА ШАГА (08.09.2026, п.42). В покое opacity 0; app.js ставит is-open
     (display:grid), затем, после принудительного пересчёта стилей, is-visible - переход
     проигрывается от display:grid, а не от display:none, где переходов нет. Скрытое
     состояние ОСТАЁТСЯ display:none (правило 03: скрытый оверлей только через
     display:none): is-open снимается после transitionend по opacity. Размытие подложки
     -webkit- первым: Safari до 18 знает только префикс. */
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity 220ms var(--ease, cubic-bezier(.2, .7, .2, 1));
}
/* MOBILE-FIRST (08.09.2026, п. 96 оценщика): базово - узкий экран, стрелки в потоке
   ПОД картинкой, а не поверх неё. ЗАМЕР 29.08.2026, кадр 360px: картинка занимает
   всю ширину, и стрелки по бокам ложились прямо на неё - закрывали края того самого
   скриншота, ради которого лайтбокс и открывали. Машинная проверка этого не видит:
   элементы на месте, размеры в норме. Поймано глазами на снимке. Стрелки, прижатые
   к низу экрана (первая попытка правки), отрывались от снимка и читались как
   элементы страницы под подложкой. Картинка ниже (62vh вместо 78vh) - чтобы ряду
   кнопок хватило места. Здесь стояло max-width: 639px, запрещённое правилом 03;
   десктопная раскладка - в блоке min-width: 768px ниже. */
.lightbox.is-open {
  display: grid;
  grid-template-columns: auto auto;
  grid-auto-rows: min-content;
  align-content: center;
  justify-content: center;
  gap: var(--s-3);
}
.lightbox.is-visible { opacity: 1; }
html.lb-open, html.lb-open body { overflow: hidden; }

.lightbox__figure {
  margin: 0; display: grid; gap: var(--s-2); justify-items: center; max-height: 100%;
  grid-column: 1 / -1; /* узкий экран: кадр во всю ширину, стрелки строкой под ним */
  /* Кадр чуть уменьшен в покое и встаёт в масштаб вместе с подложкой (п.42). */
  transform: scale(.96);
  transition: transform 220ms var(--ease, cubic-bezier(.2, .7, .2, 1));
}
.lightbox.is-visible .lightbox__figure { transform: none; }
.lightbox__img {
  max-width: 100%;
  max-height: 62vh;
  width: auto;
  height: auto;
  border-radius: var(--r-md);
  background: var(--surface-2);
  /* Смена кадра стрелками (п.42): app.js вешает is-swapping перед новым src и снимает
     по load - старый кадр гаснет, новый проявляется. aspect-ratio контейнера app.js
     ставит инлайном из width/height исходной картинки, чтобы коробка не прыгала. */
  transition: opacity 150ms var(--ease, cubic-bezier(.2, .7, .2, 1));
}
.lightbox__img.is-swapping { opacity: 0; }
/* Движение урезано - все переходы лайтбокса 0 мс; app.js при этом закрывает окно сразу,
   не дожидаясь transitionend, которого при нулевой длительности не бывает. */
@media (prefers-reduced-motion: reduce) {
  .lightbox, .lightbox__figure, .lightbox__img { transition-duration: 0ms; }
}
.lightbox__caption {
  margin: 0;
  max-width: var(--container-prose);
  color: var(--on-overlay);
  font-size: var(--t-small);
  line-height: var(--lh-base);
  text-align: center;
}
.lightbox__count { color: var(--on-overlay-mute); font-size: var(--t-tiny); }

/* Кнопки лайтбокса. Белые на затемнении: подложка всегда тёмная независимо от скина,
   и токены поверхности здесь дали бы серое на сером - поэтому свои токены оверлея
   (tokens.css --overlay-*, --on-overlay; 08.09.2026, п. 97 оценщика: здесь стояли
   literal-цвета, и заготовка не проходила греп 03 «слои целы»). */
.lightbox__btn {
  position: absolute;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 1px solid var(--overlay-rule);
  border-radius: var(--r-pill);
  background: var(--overlay-btn);
  color: var(--on-overlay);
  cursor: pointer;
  transition: background var(--dur-quick) var(--ease);
}
.lightbox__btn:hover { background: var(--overlay-btn-hover); }
.lightbox__btn:focus-visible { outline: 2px solid var(--on-overlay); outline-offset: 2px; }
.lightbox__btn svg { width: 22px; height: 22px; }
.lightbox__close { top: var(--gutter); right: var(--gutter); }
/* Узкий экран: стрелки в потоке под картинкой (см. .lightbox.is-open выше). */
.lightbox__prev,
.lightbox__next { position: static; }
/* Одиночная картинка: стрелок нет вовсе, JS их прячет - место под них не резервируется. */
.lightbox__btn[hidden] { display: none; }

/* ШИРОКИЙ ЭКРАН (min-width, 08.09.2026, п. 96 оценщика): кадр выше, стрелки поверх
   подложки по бокам от него - на 768+ картинке есть куда отступить от краёв. */
@media (min-width: 768px) {
  .lightbox.is-open {
    grid-template-columns: none;
    grid-auto-rows: auto;
    align-content: normal;
    justify-content: normal;
    gap: 0;
  }
  .lightbox__img { max-height: 78vh; }
  .lightbox__figure { grid-column: auto; }
  .lightbox__prev  { position: absolute; left: var(--gutter);  top: 50%; transform: translateY(-50%); }
  .lightbox__next  { position: absolute; right: var(--gutter); top: 50%; transform: translateY(-50%); }
}

/* Курсор-подсказка: картинка кликабельна. Указатель ставится ссылке-обёртке, а не
   картинке: без JS ссылка ведёт на файл, и это законный переход, а не «мёртвый» клик. */
.lb-link { display: block; cursor: zoom-in; }

/* ================= СЛОЙ СОВРЕМЕННОСТИ (часть 4 app.js, 31.08.2026) =================
   Всё прогрессивно: нет разметки - ни одно правило не срабатывает; цвета и движение -
   только токенами. Механика (кто ставит классы и когда) описана в заголовке части 4. */

/* ---- кнопка темы (layout.php, data-action="themeToggle") ----
   Та же коробка, что у бургера: 44px, рамка, скругление. Иконки обе в разметке,
   видима одна: луна в светлой («переключи в тёмную»), солнце в тёмной. */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; padding: 0; flex: 0 0 auto;
  background: transparent; border: 1px solid var(--rule-strong); border-radius: var(--r-md);
  color: var(--text); cursor: pointer;
}
.theme-toggle:hover { background: var(--brand-soft); }
.theme-toggle svg { width: 20px; height: 20px; }
.theme-toggle__sun { display: none; }
html[data-mode="dark"] .theme-toggle__sun  { display: block; }
html[data-mode="dark"] .theme-toggle__moon { display: none; }

/* ---- появление карточек (data-reveal) ----
   Исходное скрытие ТОЛЬКО под html.js-reveal - класс ставит часть 4, и только когда
   наблюдатель реально заведён (есть IntersectionObserver, движение не урезано).
   Без JS класса нет - элементы видимы, страница не зависит от скрипта. */
html.js-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur-slow) var(--ease-out),
              transform var(--dur-slow) var(--ease-out);
}
html.js-reveal [data-reveal].is-revealed { opacity: 1; transform: none; }
/* Ремень к подтяжкам: даже если js-reveal каким-то образом встал при reduced-motion,
   элементы видимы сразу (сам наблюдатель при reduce не заводится вовсе). */
@media (prefers-reduced-motion: reduce) {
  html.js-reveal [data-reveal] { opacity: 1; transform: none; transition: none; }
}

/* ---- галерея (data-gallery): рельса + стрелки + счётчик ----
   Рельса со scroll-snap живёт и без JS - листается пальцем и колесом. Часть 4
   добавляет панель .gallery-nav ПОСЛЕ рельсы только при 2+ кадрах. */
[data-gallery] {
  display: flex;
  gap: var(--s-3);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
[data-gallery] > * { flex: 0 0 auto; scroll-snap-align: start; }
[data-gallery] img { border-radius: var(--r-md); }

.gallery-nav {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-top: var(--s-3);
}
.gallery-nav__btn {
  display: grid; place-items: center;
  width: var(--tap-min); height: var(--tap-min); padding: 0;
  border: 1px solid var(--rule-strong); border-radius: var(--r-pill);
  background: var(--surface); color: var(--text);
  cursor: pointer;
  transition: background var(--dur-quick) var(--ease), border-color var(--dur-quick) var(--ease);
}
.gallery-nav__btn:hover:not(:disabled) { background: var(--brand); color: var(--on-brand); border-color: var(--brand); }
.gallery-nav__btn:disabled { opacity: .38; cursor: default; }
.gallery-nav__btn svg { width: 20px; height: 20px; }
.gallery-nav__count { color: var(--text-mute); font-size: var(--t-small); min-width: 4.5em; text-align: center; }

/* ---- тост (showToast) ----
   Один на страницу, последний текст побеждает. Снизу по центру, над кнопкой
   «наверх» (--z-toast выше --z-sticky). visibility по той же причине, что у
   .to-top: с display:none переход не проигрывается. */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(var(--gutter) + 64px);
  transform: translate(-50%, 8px);
  z-index: var(--z-toast);
  max-width: min(92vw, 480px);
  padding: var(--s-3) var(--s-5);
  border: var(--hairline);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--text);
  font-size: var(--t-small);
  box-shadow: var(--shadow-pop);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-base) var(--ease),
              transform var(--dur-base) var(--ease),
              visibility var(--dur-base) var(--ease);
}
.toast.is-shown { opacity: 1; visibility: visible; transform: translate(-50%, 0); }

/* ---- демо-фасад игры (data-demo-src) ----
   До клика: постер + кнопка запуска. После (.is-loaded): iframe на месте постера,
   кнопка полного экрана. Пропорции держит фасад, а не iframe - постер и рамка
   занимают одну и ту же коробку, загрузка не дёргает страницу. */
.demo-facade {
  position: relative;
  margin: 0;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border: var(--hairline);
  border-radius: var(--r-lg);
  background: var(--surface-2);
  box-shadow: var(--shadow-card);
}
.demo-facade__poster { width: 100%; height: 100%; object-fit: cover; }
.demo-facade__actions {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: var(--overlay-veil); /* токен, не literal (08.09.2026, п. 97 оценщика) */
}
.demo-facade.is-loaded .demo-facade__poster,
.demo-facade.is-loaded .demo-facade__actions { display: none; }
.demo-facade__frame { width: 100%; height: 100%; border: 0; display: block; }
/* Кнопка полного экрана - ПОД фасадом, в потоке: поверх iframe она закрывала бы игру. */
.demo-facade__fullscreen { margin-top: var(--s-3); }

/* ---- хлебные крошки ----
 * Layout печатает их на каждой внутренней странице списком <ol> (иначе правило
 * паритета не засчитывает пункты), а оформления в заготовке не было вовсе: под
 * шапкой оставался голый нумерованный список «1. Главная / 2. Заголовок». Замер
 * 03.09.2026 на pokerspro.ru, возвращено в комплект тем же днём. */
.breadcrumbs { padding-block: var(--s-4) 0; }
.breadcrumbs__list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2);
  font-size: var(--t-small); color: var(--text-mute);
}
.breadcrumbs__item { display: flex; align-items: center; gap: var(--s-2); min-width: 0; }
.breadcrumbs__item + .breadcrumbs__item::before {
  content: "/"; color: var(--text-faint); flex: 0 0 auto;
}
.breadcrumbs__item a { color: var(--text-mute); text-decoration: none; }
.breadcrumbs__item a:hover { color: var(--brand); text-decoration: underline; }
.breadcrumbs__item[aria-current] {
  color: var(--text-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
