/* ================================================================
   Подкидной дурак — оформление.

   Три правила, из которых выведено всё остальное:

   1. Экран телефона держится в высоте окна. Ряды — карты соперника,
      стол в два ряда, подсказка, своя рука, кнопки — считаются честно,
      поэтому не наползают друг на друга даже в шторке Telegram
      высотой 420 точек.
   2. Горизонтальной прокрутки нет никогда: страница зафиксирована,
      всё, что шире экрана, просто не рисуется за его краем.
   3. Цвета берём у Telegram (он присылает свои переменные для светлой
      и тёмной темы), а если их нет — работают наши, «зелёное сукно».

   Ни картинок, ни шрифтов из интернета: масти — обычные символы,
   рубашка карты — узор из полосок средствами CSS. Свой шрифт лежит
   в самом проекте (папка «шрифты»), с чужих сайтов не подгружается —
   см. следующий раздел.
   ================================================================ */

/* ================================================================
   Шрифт игры — Onest
   ================================================================

   Зачем свой шрифт. Раньше текст рисовался тем, что стоит в телефоне
   по умолчанию: на Android это Roboto, и игра выглядела как окно
   настроек телефона, а не как игра. Свой шрифт — самая дешёвая
   вещь, которая делает вид «сделанным нарочно».

   Почему именно Onest. Он рисовался сразу с кириллицей (а не с
   латиницей, к которой русские буквы приделали потом), поэтому «д»,
   «з», «ю» у него нормальной формы, а не выморочной. Буквы широкие
   и открытые — это то, что нужно мелким подписям в 12–13 точек на
   телефоне. Лицензия свободная (OFL), файл переменный, то есть
   одним файлом даёт все степени жирности. Из ровни: Inter и Manrope
   заметно суше и ближе к тому же системному виду, от которого мы
   уходим, Golos Text — хорош, но у него более «деловой» характер,
   для карточной игры Onest дружелюбнее.

   Файлы лежат рядом с игрой, в папке «шрифты», и их четыре, а не два:
   каждое начертание разрезано на русские буквы и латинские. Так
   телефону не приходится тянуть латиницу ради русского текста —
   строка «unicode-range» говорит браузеру, какие буквы лежат в файле,
   и лишний кусок он просто не скачивает. Всего 96 килобайт, из них
   для нашей игры обычно нужны только две русские половинки (30 КБ).

   Из сети не тянется ничего: игра открывается так же быстро и
   работает без интернета.

   Пока файл ещё едет, работает запасная цепочка системных шрифтов
   (см. переменную «--шрифт»): текст виден сразу, пустоты и мигания
   нет — за это отвечает font-display: swap.
   ================================================================ */

@font-face {
  font-family: 'Onest';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('шрифты/onest-кириллица-400.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: 'Onest';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('шрифты/onest-латиница-400.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;
}

@font-face {
  font-family: 'Onest';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('шрифты/onest-кириллица-700.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: 'Onest';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('шрифты/onest-латиница-700.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;
}

:root {
  /* Шрифт игры и запасная цепочка на случай, если свой не приехал.
     Порядок такой: system-ui — то, чем телефон пишет сам, дальше
     подписаны Apple, Windows и Android поимённо, в конце — любой
     рубленый шрифт, какой найдётся. */
  --шрифт: "Onest", system-ui, -apple-system, "Segoe UI", Roboto,
           "Helvetica Neue", Arial, sans-serif;

  /* ---------- Палитра ----------
     Слева — наше название, справа — цвет Telegram и запасной вариант.
     Если Telegram цвет не прислал, берётся запасной. */
  --фон:          var(--tg-theme-bg-color, #14532d);          /* сукно стола */
  --панель:       var(--tg-theme-secondary-bg-color, #0b3a20); /* плашка итога */
  --текст:        var(--tg-theme-text-color, #f1f8f2);
  --кнопка-фон:   var(--tg-theme-button-color, #f0b32d);
  --кнопка-текст: var(--tg-theme-button-text-color, #23150a);
  --акцент:       var(--tg-theme-button-color, #ffd66b);      /* чем подсвечиваем выбор */

  /* Приглушённый текст. Своего «серого» у Telegram брать нельзя: в светлой
     теме он даёт контраст около 2 при норме 4,5 — мелкие подписи почти
     не читаются. Поэтому берём основной цвет текста и подмешиваем к нему
     фон: получается тише основного, но всё ещё хорошо читается в любой теме.

     Первая строка — страховка для браузеров старше 2023 года, которые
     не знают color-mix. Там подписи просто берут основной цвет текста:
     выглядит проще, зато читается всегда и в любой теме. Серый цвет
     Telegram в запас не годится — это ровно та бледность, от которой
     мы уходим. Кто понимает color-mix, возьмёт вторую строку.

     Доля основного цвета была 80%, стала 88% — и вот почему.
     Посреди сукна лежит мягкий белый блик (см. фон у body). Над самым
     светлым его местом фон высветляется, и подпись при 80% давала
     контраст 4,25 при норме 4,5 — то есть в самом заметном месте
     экрана она читалась хуже всего. Хуже того: если та же приглушённая
     подпись лежит ещё и на полупрозрачной плашке (строка в таблице
     рекордов, мелкая кнопка), фон под ней светлеет второй раз, и было
     уже 3,9.

     Считали так: сукно 22,91,50 плюс 10% белого от блика даёт 45,107,70;
     та же точка под плашкой — 62,111,82. При 88% подпись выходит
     215,228,218 и даёт 4,90 над бликом и 4,56 над бликом с плашкой.
     Норму прошли обе, а разница с заголовком осталась видимой: подпись
     заметно тише основного текста 241,248,242 и вдвое мельче его.
     Больше 88% не берём — вот тогда подпись и заголовок сравняются. */
  --текст-тихий:  var(--текст);
  --текст-тихий:  color-mix(in srgb, var(--текст) 88%, var(--фон));

  /* Полупрозрачные подложки специально сделаны серыми: на тёмном фоне
     они высветляют, на светлом — притемняют, и работают в любой теме. */
  --подложка:     rgba(128, 128, 128, 0.20);
  --край:         rgba(128, 128, 128, 0.45);

  /* ---------- Цвета самой карты ----------
     Бумага кремовая, как у карт набора владельца, и цвет её подогнан под
     бумагу на картинках фигур (#f6ead5): у валета, дамы и короля бумага
     нарисована прямо в картинке, и другой оттенок у цифр был бы виден
     полосой на стыке. Цвета мастей от темы Telegram не зависят вовсе —
     они всегда лежат на одной и той же бумаге.

     МАСТИ В ДВЕ КРАСКИ, как в наборе (решение штаба 10 сентября): пики
     и трефы почти чёрные, черви и бубны насыщенно-красные. Раньше колода
     была четырёхцветной (бубны синие, трефы зелёные) — её завели, когда
     в тесной руке от карты была видна полоска в десяток точек и форму
     значка было не разобрать. В новой руке полоска втрое шире, значок
     крупный, и владелец выбрал карты как в наборе. Вернуть четыре краски —
     поменять здесь две строки.

     Контраст на бумаге: красная 4,9 при норме 4,5, чёрная — больше 14.
     Цветом красится весь угол карты — и значок масти, и достоинство. */
  --карта-фон:      #f6ead5;
  --карта-край:     #98a1ac;
  --карта-текст:    #1c1a18;
  --карта-красная:  #c8102e;
  --масть-пики:     #1c1a18;
  --масть-трефы:    #1c1a18;
  --масть-черви:    #c8102e;
  --масть-бубны:    #c8102e;

  /* «Можно» и «нельзя». Зелёным «можно» теперь красится только точка
     в строке связи и образец на экране «Как играть»; в руке «можно» —
     салатовая черта под картой (см. раздел стола в конце файла).
     «Отказ» — ответ на тап по карте, которой ходить нельзя. */
  --карта-можно:    #1cc06a;
  --карта-отказ:    #e0273c;
  /* ---------- Рубашка карты ----------
     Рисунок рубашки теперь векторный (его делает js/колода-рисунок.js),
     и настоящих цветов в нём всего два — они здесь. Узор, кант и медальон
     нарисованы белым с прозрачностью, поэтому сами подстраиваются
     под любой цвет поля, менять их не нужно.

     Почему бордовый, а не прежний синий. Рубашка — самое частое, что
     видит игрок: вся колода, весь отбой, вся рука соперника. Она должна
     быть в родстве со столом, но не спорить с ним и не сливаться.
     Тёмно-зелёная рубашка на зелёном сукне пропадает (в тёмной теме сукно
     26,67,53 — рубашка была бы почти того же тона), а синяя с зелёным
     спорит: два холодных цвета рядом тянут одеяло друг у друга.
     Бордовый — старая пара зелёного сукна, та самая, что в клубах: он
     тёплый, поэтому от стола отделяется в любой теме, и при этом не
     кричит, как чистый красный.

     Кайма по краю — тёплая кремовая, а не белая: чисто белая кайма рядом
     с белой лицевой стороной карты сбивает — обе стороны выглядят
     одинаково светлыми. Кремовая отделяет рубашку от лица и заодно
     всегда обводит карту светлым контуром, поэтому рубашка не сливается
     с сукном даже там, где тона близки. */
  --рубашка-фон:    #6e2233;   /* поле рубашки — единственный её цвет */
  --рубашка-поле:   #f2ece0;   /* кремовая кайма по краю карты */

  /* ---------- Размер карты ----------
     Главный размер стола — карта в руке. На макете владельца она 85×119
     при ширине экрана 390, то есть её высота — 30,5 сотых ширины. В низком
     окне она не забирает больше 17 сотых высоты окна: руке нельзя съесть
     стол. Все остальные карты (на столе, в колоде, рубашки соперника)
     задают свой размер сами, у себя в разделе стола.
     Игра меряет готовую карту, а не считает её сама (js/game.js,
     «измеритьКарту»), поэтому других чисел для неё здесь не нужно.
     1,4 — пропорция рисунка карты (250 на 350): рисунок не растягивается. */
  --в-рука: clamp(56px, min(30.5vw, calc(var(--доступно) * 0.17)), 136px);
  --в: var(--в-рука);
  --ш: calc(var(--в) / 1.4);

  /* Высота окна. dvh — «живая» высота: не скачет, когда в Telegram
     выезжает или прячется шапка. Для старых браузеров ниже есть vh. */
  --доступно: 100vh;

  /* ---------- Безопасные поля: часы, вырез, полоса жеста ----------

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

     Полей два источника, и мы берём больший из двух:
       env(safe-area-inset-…) — знает про сам телефон (вырез, полоса),
         но не знает, сколько сверху занял Telegram своими кнопками;
       var(--безопасно-…) — их кладёт на :root js/telegram.js, и там
         уже СУММА обоих слоёв Telegram («от края экрана» и «от края
         безопасной области»). Вне Telegram и в старых его версиях
         там нули, поэтому max() спокойно берёт env().

     Дальше по файлу эти четыре переменные подставляются в отступы
     экранов. Складывать их между собой не нужно — только прибавлять
     к своему отступу. */
  --отступ-сверху: max(env(safe-area-inset-top,    0px), var(--безопасно-сверху,  0px));
  --отступ-снизу:  max(env(safe-area-inset-bottom, 0px), var(--безопасно-снизу,   0px));
  --отступ-слева:  max(env(safe-area-inset-left,   0px), var(--безопасно-слева,   0px));
  --отступ-справа: max(env(safe-area-inset-right,  0px), var(--безопасно-справа,  0px));

  /* Скругление карты-образца на экране «Как играть». У настоящих карт
     скругление считается от их ширины (см. «.карта»). */
  --скругление: 7px;
}

@supports (height: 100dvh) {
  :root { --доступно: 100dvh; }
}

* {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent; /* без серой вспышки при тапе */
}

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;            /* ничего никуда не прокручивается */
  overscroll-behavior: none;   /* и не «оттягивается» пальцем */
}

body {
  font-family: var(--шрифт);
  /* Сглаживание букв. На тёмном сукне светлый текст без этого выглядит
     жирнее, чем нарисован, и мелкие подписи слипаются. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: var(--текст);
  /* Сукно. Первая строка — чистый цвет темы, вторая подмешивает к нему
     зелёного: и в светлой теме Telegram, и в тёмной стол остаётся столом,
     а белые карты на нём хорошо видно. Старый браузер возьмёт первую строку. */
  background-color: var(--фон);
  /* Зелёного в замесе было 20%, стало 38%. Причина видна на снимке светлой
     темы: при 20% стол выходил бледно-серым, «больничным» — на стол он был
     не похож вовсе, а игра называется карточной. Промежуточные 30% дела
     не решили: в светлой теме свет и тени физически дают мало, и опираться
     приходится на насыщенность цвета, а не на светотень.
     Теперь светлая тема — (170, 204, 184) вместо прежней (210, 228, 218):
     зелёное сукно, но всё ещё светлое, под стать светлому Telegram.
     Контраст подписей от этого только вырос — тёмный текст лежит
     на чуть более тёмном фоне. */
  background-color: color-mix(in srgb, var(--фон) 62%, #1f7a45);
  /* Мягкий блик посередине — сукно перестаёт быть плоской заливкой.
     Блик белый и очень слабый, поэтому на светлой теме почти незаметен.

     Белого в нём было 10%, стало 8% — и это не косметика, а починка
     читаемости. Самое светлое место блика приходится примерно на верхнюю
     треть экрана, а там как раз живут подписи под заголовками и верхние
     строки таблицы рекордов. При 10% фон под ними высветлялся так, что
     приглушённый текст на полупрозрачной плашке давал контраст 4,43
     при норме 4,5. Лечить это можно было двумя способами: сделать
     подписи ярче — но тогда они сравняются с заголовками и порядок
     чтения пропадёт, — или убавить сам блик. Убавили блик: он и был
     причиной, а сукно на глаз почти не изменилось. */

  /* ---------- Сукно в три слоя ----------
     Плоская заливка одним цветом — главный признак старого вида: настоящий
     стол так не выглядит никогда, потому что на него падает свет и у ткани
     есть фактура. Поэтому фон собран из трёх слоёв. В CSS они записаны
     сверху вниз, то есть первым идёт самый верхний:

       1) зерно ткани — мелкий шум. Картинки-файла нет: шум рисует сам
          браузер по встроенному SVG (feTurbulence — «завихрение»,
          готовый генератор случайных точек). Матрица после него делает
          точки серыми и непрозрачными, иначе шум выходит цветным.
          Плитка 160×160 повторяется по всему экрану;
       2) блик — тон в середине стола светлее (он был и раньше);
       3) виньетка — к краям темнее. Держим её на грани заметности:
          если видно «тёмное пятно по углам», значит перебор.

     Режим смешивания у зерна — soft-light («мягкий свет»): серые точки
     чуть высветляют и чуть притемняют то, что под ними, вместо того чтобы
     лечь сверху серой пылью. Браузер, который такого не умеет, просто
     положит слабое серое зерно — тоже не страшно. */
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3'/%3E%3CfeColorMatrix values='1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.6'/%3E%3C/svg%3E"),
    radial-gradient(120% 80% at 50% 28%, rgba(255, 255, 255, 0.08), transparent 70%),
    radial-gradient(115% 95% at 50% 42%, transparent 40%, rgba(0, 0, 0, 0.30) 100%);
  background-repeat: repeat, no-repeat, no-repeat;
  background-size: 160px 160px, auto, auto;
  background-blend-mode: soft-light, normal, normal;
  touch-action: manipulation;  /* тап срабатывает сразу, без ожидания двойного */
  user-select: none;
}

#приложение {
  position: fixed;
  inset: 0;
  /* Единое число золота рейтинга. Раньше значение жило двумя отдельными
     копиями — в «#экран-рейтинга-игроков» и в «.рейтинг-панель-игр»
     (шторка выбора игры) — и при смене тона приходилось поднимать оба
     места вручную. Оба узла лежат внутри «#приложение», поэтому число
     объявлено здесь один раз, а экран и шторка ниже по файлу только
     читают его через var(). */
  --рейтинг-золото-общее: #e6b34a;
  --рейтинг-золото-край-общее: rgba(230, 179, 74, 0.45);
}

/* ================================================================
   Живой фон — пять видов на выбор
   ================================================================

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

   ЧЕМ ЭТО ОТЛИЧАЕТСЯ ОТ «ЖИВЫХ ОБОЕВ ИЗ ДВУХТЫСЯЧНЫХ». Тогда фоном
   были повторяющиеся картинки, резкие звёздочки и бегущие огоньки —
   они кричали «смотри на меня». Здесь наоборот: если человек заметил
   фон во время партии, фон плохой. Отсюда две мерки, которые я держал
   при рисовании и по которым это можно проверить:

     • ни одно пятно не отличается от сукна больше чем на восемь сотых
       по светлоте (в правилах это доли вроде 0.06–0.08);
     • полный круг движения — не быстрее полутора минут, а у тумана
       и вовсе три.

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

   ЧТО ДВИГАЕТСЯ. Только сдвиг, размер и прозрачность — то, что
   браузер рисует видеокартой. Раскладку он при этом не пересчитывает,
   поэтому телефон не греется.

   ДВА СЛУЧАЯ, КОГДА ФОН ЗАМИРАЕТ:
     1. человек попросил в телефоне «меньше движения»;
     2. страница не видна — свёрнутое мини-приложение в кармане.
   Второе игра сообщает признаком «data-страница=скрыта».
   ================================================================ */

.фон-игры {
  position: absolute;
  inset: 0;
  z-index: 0;               /* под всеми экранами */
  overflow: hidden;
  pointer-events: none;     /* сквозь фон нажимается всё, что под ним */
  /* Сила пятен — одним числом на весь фон. На странице она нарочно
     мала: восемь сотых по светлоте, ровно та мерка, по которой фон
     не должен замечаться во время партии. В образце на экране выбора
     то же число берётся крупнее (см. ниже) — иначе в окошке высотой
     в сорок шесть точек все пять фонов выглядят одинаковым зелёным
     прямоугольником, и выбрать нечего. Пятна при этом остаются теми
     же самыми: меняется только громкость, а не рисунок. */
  --сила-свет: 0.07;
  --сила-тень: 0.10;
}

/* ---------- Образец фона на экране «Оформление» ----------

   Внутри маленькой кнопки лежит ровно тот же слой «фон-игры», что
   и на странице, и признак «data-фон» стоит на самом образце. Поэтому
   правила ниже написаны через «:where(html, .образец-фона)» — они
   одинаково срабатывают и когда фон выбран для всей страницы, и когда
   он показан на кнопке.

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

   Размер образца задан здесь же: он должен быть заметно шире, чем
   высок, — фон человек видит в первую очередь как ширину экрана,
   и вытянутое окошко читается как «кусочек стола», а не как плитка. */
.образец-фона {
  position: relative;
  overflow: hidden;
  width: 100%;
  height: 46px;
  border-radius: 9px;
  background: var(--фон);
  /* Сукно с зерном рисует само тело страницы, а в окошке его нет —
     поэтому подмешиваем ту же зелень, что у стола, иначе «Сукно»
     выглядело бы серым квадратом, не похожим ни на что. */
  background: color-mix(in srgb, var(--фон) 62%, #1f7a45);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.25);
}

/* В окошке пятна крупнее по силе — иначе все пять фонов выглядят
   одинаковым зелёным прямоугольником. Рисунок тот же, громкость
   другая: так человек видит, чем «Туман» отличается от «Лампы»,
   а на самой странице оба остаются тихими. */
.образец-фона .фон-игры {
  --сила-свет: 0.38;
  --сила-тень: 0.44;
}

/* Движение в образце остановлено, и остановлено НЕ в начале: показывать
   надо середину круга, где пятна разошлись, а не исходное положение,
   в котором все фоны похожи. Отрицательная задержка как раз и значит
   «отмотай на сорок секунд вперёд и замри». Заодно это экономит
   батарею: пять кнопок не двигаются без нужды. */
.образец-фона .фон-игры::before,
.образец-фона .фон-игры::after {
  animation-delay: -40s;
  animation-play-state: paused;
}

/* Оба движущихся пятна — это псевдоэлементы слоя. Своих узлов
   в разметке они не просят: чем меньше узлов, тем дешевле страница.
   Пятна нарочно больше экрана: край размытого круга не должен
   попадать в кадр, иначе получится «шарик ползёт», а не свет. */
.фон-игры::before,
.фон-игры::after {
  content: "";
  position: absolute;
  will-change: transform, opacity;
}

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

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

/* ---------- 2. «Дыхание» ----------
   Два огромных пятна — одно светлое, другое тёмное — медленно
   расходятся и сходятся по диагонали. Круг полторы минуты. На глаз
   это не «что-то ползёт», а «картинка не мёртвая». */
:where(html[data-фон="дыхание"] #приложение, .образец-фона[data-фон="дыхание"]) > .фон-игры::before {
  width: 150%;
  height: 110%;
  left: -30%;
  top: -20%;
  background: radial-gradient(closest-side, rgba(255, 255, 255, var(--сила-свет)), transparent 100%);
  animation: фон-дыхание-светлое 96s ease-in-out infinite;
}

:where(html[data-фон="дыхание"] #приложение, .образец-фона[data-фон="дыхание"]) > .фон-игры::after {
  width: 140%;
  height: 120%;
  right: -35%;
  bottom: -25%;
  background: radial-gradient(closest-side, rgba(0, 0, 0, var(--сила-тень)), transparent 100%);
  animation: фон-дыхание-тёмное 116s ease-in-out infinite;
}

@keyframes фон-дыхание-светлое {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(6%, 5%, 0) scale(1.08); }
}

@keyframes фон-дыхание-тёмное {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1.05); }
  50%      { transform: translate3d(-7%, -4%, 0) scale(1); }
}

/* ---------- 3. «Лампа над столом» ----------
   Одно широкое пятно света сверху по центру, как от лампы над столом.
   Оно очень медленно набирает и теряет силу и чуть ходит вбок —
   будто лампа покачивается. Круг две минуты. Второе пятно — тень
   по нижним углам, она делает свет светом, а не просто белым кругом. */
:where(html[data-фон="лампа"] #приложение, .образец-фона[data-фон="лампа"]) > .фон-игры::before {
  width: 160%;
  height: 130%;
  left: -30%;
  top: -55%;
  background: radial-gradient(closest-side, rgba(255, 255, 255, calc(var(--сила-свет) + 0.01)), transparent 100%);
  animation: фон-лампа 124s ease-in-out infinite;
}

:where(html[data-фон="лампа"] #приложение, .образец-фона[data-фон="лампа"]) > .фон-игры::after {
  inset: 0;
  background: radial-gradient(120% 90% at 50% 40%, transparent 45%, rgba(0, 0, 0, 0.14) 100%);
  animation: фон-лампа-тень 124s ease-in-out infinite;
}

@keyframes фон-лампа {
  0%, 100% { transform: translate3d(-2%, 0, 0); opacity: 0.75; }
  50%      { transform: translate3d(2%, 1%, 0); opacity: 1; }
}

@keyframes фон-лампа-тень {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.8; }
}

/* ---------- 4. «Туман» ----------
   Два слоя очень мягких широких полос ползут в разные стороны
   с разной скоростью — проход около трёх минут. Работают они
   на глубину: становится видно, что стол ближе, а фон дальше.
   Полосы нарочно наклонные и без единого резкого края. */
:where(html[data-фон="туман"] #приложение, .образец-фона[data-фон="туман"]) > .фон-игры::before {
  width: 240%;
  height: 140%;
  left: -70%;
  top: -20%;
  background: linear-gradient(104deg,
    transparent 0%, rgba(255, 255, 255, calc(var(--сила-свет) * 0.8)) 18%, transparent 34%,
    transparent 58%, rgba(255, 255, 255, calc(var(--сила-свет) * 0.6)) 74%, transparent 92%);
  animation: фон-туман-вправо 186s linear infinite;
}

:where(html[data-фон="туман"] #приложение, .образец-фона[data-фон="туман"]) > .фон-игры::after {
  width: 240%;
  height: 140%;
  right: -70%;
  bottom: -20%;
  background: linear-gradient(76deg,
    transparent 0%, rgba(0, 0, 0, calc(var(--сила-тень) * 0.7)) 22%, transparent 42%,
    transparent 66%, rgba(0, 0, 0, calc(var(--сила-тень) * 0.5)) 82%, transparent 100%);
  animation: фон-туман-влево 254s linear infinite;
}

@keyframes фон-туман-вправо {
  from { transform: translate3d(-8%, 0, 0); }
  to   { transform: translate3d(8%, 0, 0); }
}

@keyframes фон-туман-влево {
  from { transform: translate3d(7%, 0, 0); }
  to   { transform: translate3d(-7%, 0, 0); }
}

/* ---------- 5. «Северный отсвет» ----------
   Вдоль верхнего края мягкое холодное свечение, медленно меняющее
   ширину. Самый нарядный из пяти — и всё равно тихий: это подсветка
   у горизонта, а не сияние с лучами. Холод даётся не цветом, а тем,
   что светлая грань стоит вверху, а тёмная внизу: так читается небо
   над столом. */
:where(html[data-фон="отсвет"] #приложение, .образец-фона[data-фон="отсвет"]) > .фон-игры::before {
  width: 180%;
  height: 70%;
  left: -40%;
  top: -28%;
  background: radial-gradient(closest-side, rgba(255, 255, 255, calc(var(--сила-свет) + 0.01)), transparent 100%);
  animation: фон-отсвет 108s ease-in-out infinite;
}

:where(html[data-фон="отсвет"] #приложение, .образец-фона[data-фон="отсвет"]) > .фон-игры::after {
  width: 100%;
  height: 60%;
  left: 0;
  bottom: 0;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.12), transparent 100%);
}

@keyframes фон-отсвет {
  0%, 100% { transform: translate3d(0, 0, 0) scaleX(1);    opacity: 0.7; }
  50%      { transform: translate3d(3%, 2%, 0) scaleX(1.15); opacity: 1; }
}

/* ---------- Когда фон замирает ----------

   Первое: страница не видна. Свёрнутое мини-приложение для самой
   страницы остаётся «видимым», поэтому признак ставит игра — и по
   браузерному событию, и по своим событиям Telegram. Мы просто
   ставим движение на паузу: вернулся человек — оно продолжится
   с того же места, а не дёрнется с начала. */
html[data-страница="скрыта"] .фон-игры::before,
html[data-страница="скрыта"] .фон-игры::after {
  animation-play-state: paused;
}

/* Второе: человек попросил в телефоне «меньше движения». Тогда фоны
   не двигаются вовсе и выглядят как спокойная картинка — пятна
   остаются, дышать перестают. */
@media (prefers-reduced-motion: reduce) {
  .фон-игры::before,
  .фон-игры::after {
    animation: none !important;
  }
}

/* ---------- Экраны ---------- */

/* Общий отступ любого экрана — восемь точек плюс безопасные поля.
   В полном экране Telegram без этого заголовок любого экрана уезжает
   под часы, а нижняя кнопка — под полосу жеста. Экраны со своими
   отступами (стол, витрина, плашки) прибавляют те же переменные
   каждый у себя — см. их правила ниже. */
.экран {
  position: absolute;
  inset: 0;
  display: none;
  flex-direction: column;
  padding: calc(8px + var(--отступ-сверху))
           calc(8px + var(--отступ-справа))
           calc(8px + var(--отступ-снизу))
           calc(8px + var(--отступ-слева));
}

.экран--виден { display: flex; }

.скрыт { display: none !important; }

/* ================================================================
   ОДНА КОЛОНКА НА ВСЕ ИГРЫ

   Владелец сказал коротко и точно: «У дурака всё так узенько,
   в нардах всё максимально широкое». Так и было: в дураке кнопки
   меню жались в 260 точек, а в нардах тянулись во всю ширину окна —
   на компьютере это полосы в полтора экрана длиной. Одна и та же
   кнопка «К выбору игры» в двух играх выглядела как две разные
   программы.

   Теперь ширина у всех одна и живёт ЗДЕСЬ, в общем файле, а не
   в файле каждой игры. Меняется в одном месте — меняется везде.

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

   Правило намеренно узкое: оно про ПРЯМЫХ детей экрана — кнопки,
   блоки выбора, подписи. Кнопки, которые лежат рядами внутри своих
   полос (кнопки под доской, ряды знаков, панель стола), оно не
   трогает вовсе — там ширину считает сама полоса.
   ================================================================ */
:root {
  --колонка: 360px;
  /* Ширина столбика кнопок на экранах меню. Раньше это число (260)
     было вписано в двенадцать разных правил дурака — от меню
     до рекордов, — и владелец справедливо назвал такую колонку
     «узенькой». Теперь оно одно на весь сборник и стоит здесь:
     300 точек — кнопка стала заметно шире, но столбик всё ещё
     читается как столбик, а не как полоса во весь экран. */
  --колонка-кнопок: 300px;
}

.экран > .кнопка,
.экран > .выбор,
.экран > .правила-текст {
  width: min(100%, var(--колонка));
  /* Поля «auto» ставят столбик посередине даже там, где экран
     растягивает детей по ширине (а так устроены экраны нард
     и шахмат). Без них колонка прилипла бы к левому краю. */
  margin-left: auto;
  margin-right: auto;
}

/* Заголовкам и подписям задаём только выравнивание, но НЕ ширину.
   Проверено на шахматах: стоило дать им ширину колонки, и строка
   «Ходят белые» — а она нарисована пилюлей по размеру текста —
   растянулась со 139 точек до 360 и превратилась в полосу.
   Пусть каждая подпись сама решает, какой ей быть шириной;
   от общего правила ей нужно одно — стоять по центру. */
.экран > .заголовок,
.экран > .подпись {
  text-align: center;
}

/* Заголовок. Буквы стоят чуть теснее обычного (отрицательный
   «letter-spacing»): у крупной надписи широкие просветы между буквами
   читаются как рыхлость, а сжатая на полточки строка выглядит как
   заголовок, набранный нарочно. Раньше здесь было наоборот — просветы
   растянуты на полточки, и это добавляло виду «сделано по умолчанию». */
.заголовок {
  margin: 0;
  font-size: 34px;
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.5px;
}

/* Подпись под заголовком. Строки чуть просторнее по высоте — так
   разница с заголовком читается не только кеглем, но и ритмом. */
.подпись {
  margin: 0;
  font-size: 15px;
  line-height: 1.35;
  color: var(--текст-тихий);
}

/* Правила старого меню дурака («#экран-меню», «#экран-бота») убраны
   11 сентября: его заменили лобби и три шага до партии, разметки меню
   больше нет. Общее правило для слова в кнопке оставлено — его берут
   «Играть с другом» и экраны шашек. */

/* ---------- Слово, которым кнопки различаются ----------

   «Играть с ботом» и «Играть с другом» отличаются одним последним
   словом, а глаз читает подпись целиком — и чтобы понять, где какая,
   приходится дочитать обе до конца. Разметка вынесла это слово
   отдельным узлом; здесь оно делается заметным без чтения.

   Только вес и размер, второго цвета нет нарочно. Цвет надписи —
   цвет текста кнопки Telegram, и любой второй оттенок на этой заливке
   либо спорит с темой, либо в одной из тем теряет контраст. Вес
   и размер работают в любой теме одинаково. Прозрачность на начале
   фразы тоже не взята: она бы съела контраст ровно там, где он
   и так на пределе — в тёмной теме на синей кнопке.

   Начало «Играть с» — 0,8 от кегля кнопки (17 при обычных 21) и вес
   500, само слово — 1,15 (24) и вес 800: разница в полтора раза
   по размеру и в два шага по весу видна с любого расстояния.

   Когда сеть переписывает начало в «Вернуться к игре с», строка
   становится длиннее ширины кнопки, и слово «другом» уходит на вторую
   строчку одно — это не поломка, а даже лучше: крупное слово стоит
   отдельной строкой. Внутри слова перенос невозможен: узел один. */
.кнопка .кнопка__начало {
  font-size: 0.8em;
  font-weight: 500;
}

.кнопка .кнопка__кого {
  font-size: 1.15em;
  font-weight: 800;
  letter-spacing: 0.2px;
}

/* ---------- Серия дней подряд ----------

   «3 дня подряд» на витрине и «День 4 подряд!» на плашке итога — один
   класс, один вид. Это крючок возвращения: строка должна попасться
   на глаза первой после заголовка, но не кричать — поэтому плашка
   на тихой подложке с тонкой рамкой цвета подсветки, кегль 14 против
   34 у заголовка. Звезда перед словами — та же, что у «★ Рекорды»:
   серия дней — из того же ряда достижений, и глаз узнаёт знак.

   Длинная строка «Вчера играли — сыграйте сегодня, чтобы не прервать
   серию из 5» на 360 точках ложится в две строки; text-wrap: balance
   делит их поровну, чтобы не было «длинная плюс одно слово». */
.серия-дней {
  display: inline-block;
  max-width: min(100%, 320px);
  margin: 0;
  padding: 5px 14px 6px;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--текст);
  background: var(--подложка);
  border: 1.5px solid var(--акцент);
  border-radius: 999px;
  text-wrap: balance;
}

.серия-дней::before {
  content: "★ ";
  color: var(--акцент);
}

/* Второй вариант — «вчера играли, сегодня ещё нет» — чуть теплее
   первого, без тревоги. Игра помечает его классом «серия-дней--вчера»
   (js/game.js, «освежитьСериюДней»). Теплее — значит подложка подкрашена
   цветом подсветки, а не рамка толще и не красный: это приглашение,
   а не предупреждение. */
.серия-дней--вчера {
  background: color-mix(in srgb, var(--акцент) 22%, var(--подложка));
}

/* =====================================================================
   ВИТРИНА — по готовому набору владельца (10 сентября, вечер)

   Цель теперь — картинка, а не описание: «эталон/0-витрина-итог.png»
   (941×1672) и вырезки его частей в «эталон/витрина-части/». Числа
   ниже сняты с этой картинки и из README набора
   («эталон/набор-витрины-README.md»), а не придуманы.

   КАК ПЕРЕВОДИТЬ КАРТИНКУ В ТОЧКИ ЭКРАНА. Картинка шириной 941,
   телефон — 390. Значит, всё на ней надо умножать на 390 / 941 ≈ 0,414.
   Пример: поле по краю на картинке 34 → на телефоне 14; промежуток
   между плитками 17 → 7. Поэтому поля и промежутки заданы в долях
   ширины экрана (vw): на 360, 390 и 430 точках экран выглядит как та же
   картинка, просто уменьшенная или увеличенная, а не «растянутая».

   ГЛАВНОЕ ОТЛИЧИЕ ОТ ПРЕЖНЕГО ПОДХОДА: плитки игр — готовые карточки
   владельца (фото, название, стрелка, затемнение и рамка уже внутри
   картинки, см. «img/витрина/»). Мы ничего не рисуем поверх второй
   раз — только ставим картинку фоном кнопки.

   Витрина не подстраивается под тему Telegram: на эталоне ровно один
   вид, тёмный. Поэтому у неё СВОИ переменные «--вт-…», объявленные
   прямо на экране, — другие экраны их не видят и как брали тему
   Telegram, так и берут.

   Один акцент — салатовый «--вт-акцент». Он красит только то, что
   выбрано или включено: активную фишку-фильтр, активную вкладку внизу
   и «вкл» у звука в листе «Ещё» (стрелки на плитках уже нарисованы
   в самих картинках тем же цветом).
   ===================================================================== */

/* ---------- Общие цвета сборника ----------
   Витрина была первой, и её цвета теперь общие: стол дурака (а потом
   шашки, шахматы и нарды) берут ровно их, чтобы сборник выглядел одним
   приложением. Числа прежние, витрина от переезда не изменилась ни на
   точку — она просто ссылается сюда. Меняете цвет — меняется везде.

   «--сб-текст» раньше объявлялась ещё раз в style-коллекция.css (тот
   файл подключён после этого и побеждал в каскаде) — семь из восьми
   страниц сборника реально видели #f4f4ed, а не число ниже. Штаб решил
   закрепить именно то, что уже видит игрок: второе объявление убрано,
   здесь теперь единственное и настоящее. */
:root {
  --сб-фон: #101416;
  --сб-поверхность: #15181b;      /* панели — на тон светлее фона */
  --сб-граница: #51575e;          /* обводка фишек и тихих плашек */
  --сб-текст: #f4f4ed;            /* тёплый белый — тот же, что видят игроки */
  --сб-текст-тихий: #858b94;
  --сб-акцент: #d2f76b;           /* салатовый — единственный акцент */
  --сб-акцент-текст: #10130a;     /* текст на салатовом — почти чёрный */
}

#экран-витрины.витрина {
  /* Цвета из README набора — сняты с макета владельца. Фон обязан
     совпадать с фоном в углах карточек: картинки прямоугольные,
     и в их скруглённых углах остался фон макета. Другой фон страницы
     проступил бы в углах тёмными уголками. */
  --вт-фон: var(--сб-фон);
  --вт-поверхность: var(--сб-поверхность);  /* панель вкладок и лист «Ещё» */
  --вт-граница: var(--сб-граница);          /* обводка фишек-фильтров */
  --вт-текст: var(--сб-текст);
  --вт-текст-тихий: var(--сб-текст-тихий);
  --вт-акцент: var(--сб-акцент);
  --вт-акцент-текст: var(--сб-акцент-текст);

  /* Поле по краю и промежуток между плитками — доли ширины экрана
     (34 и 17 из 941 на макете). На 390 это ровно 14 и 7, как в README.
     «clamp» не даёт им стать смешными на очень узком или широком окне. */
  --вт-поле: clamp(12px, 3.6vw, 18px);
  --вт-зазор: clamp(6px, 1.8vw, 9px);
  /* Между рядами на макете чуть теснее, чем между столбцами:
     15–16 из 941 против 17. На 390 это 6,4 против 7. Мелочь, но за три
     ряда набегает полторы точки, и нижний ряд заметно «съезжает». */
  --вт-зазор-рядов: clamp(5px, 1.65vw, 8px);
  /* Видимая высота фишки-фильтра: 70 из 941 на макете → 29 на 390. */
  --вт-фишка: clamp(27px, 7.45vw, 33px);
  /* Высота нижней панели вкладок без полосы жеста: на макете 135 из
     941 → 56 точек на 390. От неё же считается запас снизу под
     прокрутку. Тоже доля ширины: на 360 панель 52, на 430 — 62, как
     если бы макет просто уменьшили или увеличили. Меньше 52 нельзя —
     вкладка должна оставаться удобной пальцу. */
  --вт-панель-низ: clamp(52px, 14.36vw, 64px);

  align-items: stretch;
  gap: 0;                    /* промежутки заданы у каждого блока свои — по макету */
  /* Фон: ровный тёмный и едва заметное салатовое свечение у верхнего
     края — на макете оно стоит за шапкой «Игры с друзьями» и гаснет
     к заголовку. «local» — чтобы свечение уезжало вместе с содержимым,
     а не висело на месте при прокрутке. */
  background:
    radial-gradient(75% 120px at 50% 0, rgba(210, 247, 107, 0.07), rgba(210, 247, 107, 0) 100%) local,
    var(--вт-фон);
  color: var(--вт-текст);
  /* Сверху — вырез с часами, снизу — место под закреплённую панель
     вкладок (56) и ещё 12, как на макете между баннером и панелью,
     плюс полоса жеста. Без этого запаса баннер «Деберц» уехал бы
     под панель и его нельзя было бы нажать. */
  padding: var(--отступ-сверху)
           calc(var(--вт-поле) + var(--отступ-справа))
           calc(var(--вт-панель-низ) + 12px + var(--отступ-снизу))
           calc(var(--вт-поле) + var(--отступ-слева));
  text-align: left;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Полосу прокрутки не показываем: на телефоне её и так нет, а на
     компьютере она отъедала бы 15 точек ширины у сетки. Колесо мыши
     и палец листают как прежде. */
  scrollbar-width: none;
}

#экран-витрины.витрина::-webkit-scrollbar { display: none; }

#экран-витрины.витрина > * { flex-shrink: 0; }

/* Настоящая причина наезда среднего ряда плиток («Домино», «Морской бой»)
   на нижнюю панель вкладок на широком окне: панель — «position: fixed»,
   в поток не входит, а браузер, решая «уже видна ли плитка целиком»,
   сверяется только с высотой контейнера (clientHeight), про панель поверх
   не знает. Средний ряд (не последний в потоке — ниже ещё «Деберц»)
   при обычной прокрутке ПОЛНОСТЬЮ помещается в эту высоту даже тогда,
   когда его нижний край на самом деле спрятан под панелью — и докрутка
   до конца (scrollIntoView) его не трогает: с точки зрения браузера
   докручивать уже некуда. «scroll-margin-bottom» отодвигает эту границу
   вверх на высоту панели — тот же запас, что у padding контейнера выше
   (правило «padding» этого же селектора) и у margin последнего ряда
   ниже по файлу (@media 700×600) — так докрутка перестаёт останавливаться
   раньше времени. Playwright-проверка: tests/обход-лобби.js. */
.плитка-игры {
  scroll-margin-bottom: calc(var(--вт-панель-низ) + 12px + var(--отступ-снизу));
}

/* На компьютере содержимое собирается в колонку посередине, а не
   растягивается во весь монитор. На телефоне ограничение не срабатывает.
   Панель вкладок и лист «Ещё» лежат поверх экрана целиком — их не трогаем. */
#экран-витрины.витрина > :not(.нижние-вкладки):not(.лист-ещё) {
  width: 100%;
  max-width: 520px;
  align-self: center;
}

/* ---------- Верхняя строка: «Игры с друзьями» · ⋯ ----------

   На макете эта строка — шапка САМОГО Telegram, а не часть страницы.
   Поэтому внутри Telegram строку прячем целиком — иначе вышло бы две
   шапки подряд. Признак «открыто в Telegram» — класс «в-телеграме»
   на <html>, его ставит js/telegram.js. В обычном браузере строка
   видна: по центру название, справа «⋯» (лист «Ещё»). Своего ✕ нет —
   вкладку браузера скриптом не закрыть.

   Строка — три колонки 44 · остальное · 44: левая пустая, но держит
   название ровно по центру экрана, а не по центру оставшегося места.

   Кнопка — просто значок, без кружка и подложки, как на макете.
   Нажимаемая зона при этом 44×44. Кнопка вынесена полем к самому краю,
   чтобы значок встал там же, где на макете (центр «⋯» — в 25 точках
   от правого края). */
.витрина__панель {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) 44px;
  align-items: center;
  min-height: 44px;
  margin-bottom: 2px;
}

html.в-телеграме .витрина__панель { display: none; }

.витрина__панель-кнопка {
  grid-column: 3;
  justify-self: end;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-right: -10px;
  padding: 0;
  font: inherit;
  line-height: 1;
  color: var(--вт-текст);
  background: none;
  border: none;
  border-radius: 12px;
  cursor: pointer;
}

.витрина__панель-кнопка svg {
  display: block;
  width: 24px;
  height: 24px;
}

.витрина__панель-кнопка:active { transform: scale(0.92); opacity: 0.7; }

.витрина__панель-кнопка:focus-visible {
  outline: 2px solid var(--вт-акцент);
  outline-offset: -4px;
}

.витрина__панель-заголовок {
  grid-column: 2;
  min-width: 0;
  font-size: 16px;
  font-weight: 600;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--вт-текст);
}

/* ---------- Шапка: H1 «Во что сыграем?» + подзаголовок ----------
   На макете подзаголовок стоит вплотную под заголовком (зазор 1–2
   точки), а весь блок начинается сразу под шапкой Telegram. */
.витрина__шапка {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
  padding-top: 4px;
}

/* Плотный жирный заголовок с чуть сжатым набором. Шрифт системный
   (своих в проекте нет и из интернета мы их не берём), характер даёт
   вес и плотность. Кегль снят с макета по высоте заглавной буквы
   (сверено наложением макета на экран): 32 точки при ширине 390.
   Доля ширины (8,2vw) держит ту же пропорцию на 360 и 430. */
.витрина__заголовок {
  margin: 0;
  font-size: clamp(26px, 8.2vw, 37px);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--вт-текст);
}

/* Подзаголовок — серым и тихо, сразу под H1. На макете высота
   заглавной буквы 9,6 точки → кегль 14. */
.витрина__подзаголовок {
  margin: 0;
  font-size: clamp(13px, 3.6vw, 16px);
  line-height: 1.3;
  color: var(--вт-текст-тихий);
}

/* ---------- Ряд фишек-фильтров ----------
   «Все» / «Настольные» / «Карточные». Прокручивается вбок, если
   не влезает — переносить на вторую строку нельзя, иначе он спорит
   с плитками за высоту.

   ВИДИМАЯ фишка на макете низкая — 29 точек. А палец требует 44.
   Поэтому кнопка сама 44 в высоту и прозрачная, а фишку (заливку
   и обводку) рисует её «::before» — полоса 29 точек посередине.
   Попасть можно и чуть выше, и чуть ниже нарисованной фишки.
   Отсюда и крошечные поля у ряда: 7,5 точки невидимой зоны сверху
   и снизу уже дают тот воздух, что на макете. */
.витрина__фильтры {
  display: flex;
  align-items: center;
  /* Было clamp(7px, 2.2vw, 10px) — с ним четвёртая фишка «Головоломки»
     обрезалась на 360: четыре фишки плюс три промежутка выходили шире
     колонки. Промежуток ужат почти вдвое — фишки остаются раздельными
     на глаз, но не съедают лишнее место между собой. */
  gap: clamp(5px, 1.5vw, 8px);
  /* Поле сверху растёт с шириной экрана: чем крупнее фишка, тем меньше
     вокруг неё невидимой зоны, и без поправки на 430 фишки прилипали
     к подзаголовку. На 390 выходит ровно 1 точка, на 360 — 0. */
  margin-top: clamp(0px, 5.9vw - 22px, 6px);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.витрина__фильтры::-webkit-scrollbar { display: none; }

.витрина__фильтр {
  position: relative;
  isolation: isolate;          /* фишка «::before» ложится ПОД текст, но не под фон страницы */
  flex: 0 0 auto;
  min-height: 44px;      /* зона касания по высоте не трогаем */
  min-width: 44px;       /* зона касания не уже 44 по ширине; короткое слово
     «Все» при ужатых боковых полях иначе выходит ≈41 точка */
  /* Боковые поля были clamp(14px, 4.1vw, 18px) — на 360 сумма четырёх
     фишек с текстом и тремя промежутками выходила шире колонки витрины,
     и «Головоломки» обрезались. Поля ужаты, шрифт ниже НЕ трогаем —
     так фишки остаются такими же читаемыми, но плотнее прилегают
     к тексту. Расчёт (буква кириллицы ≈ 0,55 кегля): на 360 сумма
     всех четырёх фишек ≈ 310 точек при колонке ≈ 334 — запас есть. */
  padding: 0 clamp(9px, 2.6vw, 16px);
  font: inherit;
  /* 13 на экране 390, а не 15: на макете высота заглавной буквы в фишке
     8–8,5 точки, и «Настольные» занимает 71 точку. При 15 фишки выходили
     на десятую часть шире макета. Размер — доля ширины, как у заголовка:
     на 430 фишки растут вместе с плитками, а не остаются мелкими. */
  font-size: clamp(12px, 3.35vw, 15px);
  font-weight: 500;
  line-height: 1;
  color: rgba(248, 245, 235, 0.86);
  background: none;
  border: none;
  cursor: pointer;
}

.витрина__фильтр::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: var(--вт-фишка);
  margin-top: calc(var(--вт-фишка) / -2);
  z-index: -1;
  border: 1px solid var(--вт-граница);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.025);
  transition: transform 0.14s ease;
}

.витрина__фильтр:active::before { transform: scale(0.96); }

.витрина__фильтр:focus-visible { outline: none; }
.витрина__фильтр:focus-visible::before {
  box-shadow: 0 0 0 2px var(--вт-фон), 0 0 0 4px var(--вт-акцент);
}

/* Активная фишка — единственное салатовое пятно в этом ряду, текст
   на нём почти чёрный и чуть плотнее, как на макете. */
.витрина__фильтр--активен,
.витрина__фильтр[aria-pressed="true"] {
  color: var(--вт-акцент-текст);
  font-weight: 600;
}

.витрина__фильтр--активен::before,
.витрина__фильтр[aria-pressed="true"]::before {
  background: var(--вт-акцент);
  border-color: var(--вт-акцент);
}

/* ---------- Сетка плиток: строго два столбца ----------
   Высоты рядов на макете разные (325, 297 и 290 из 941) — так и
   должно быть: каждая карточка держит пропорцию своей картинки
   (см. «.плитка-игры»), выравнивать их нельзя, иначе картинки
   сплющатся. «minmax(0, 1fr)» — столбцы ровно пополам, даже если
   внутри что-то длинное. */
.витрина__плитки {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
  gap: var(--вт-зазор-рядов) var(--вт-зазор);
  /* Зазор от ряда фишек-фильтров до первого ряда плиток — не меньше
     8 точек на любой ширине (на 320 и 390 старая формула от ширины
     экрана давала 0–2 точки, фишки прилипали к плиткам). Не новое
     число: это тот же «--вт-зазор-рядов», что и между рядами плиток
     ниже, только не даём ему опускаться меньше своей же верхней
     границы (8px). */
  margin-top: max(8px, var(--вт-зазор-рядов));
}

/* Фишки-фильтры прячут чужие плитки классом «скрыт» (js/game.js).
   Сетка от этого не ломается: оставшиеся плитки встают по порядку,
   баннер деберца по-прежнему на всю ширину. Одинокая плитка в ряду
   остаётся в левой колонке своего размера — не растягивается. */

/* ================================================================
   Экран «Оформление» — доски, рубашки, фоны
   ================================================================

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

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

   Выбранный вариант помечен ТРЕМЯ признаками, а не цветом: обводка
   цветом темы, жирная подпись и галочка в углу. Одного цвета мало —
   на солнце экран выцветает, а каждый двенадцатый мужчина плохо
   различает оттенки.
   ================================================================ */

.оформление__раздел {
  width: 100%;
  max-width: 420px;
  margin: 0 auto 14px;
  text-align: left;
}

/* Ярлык раздела — «Доска», «Рубашка», «Фон». Тот же приём, что у
   подписей разделов в таблице рейтинга и у слова «Скоро» на витрине:
   мелкие прописные с разрядкой. Это указатель, а не заголовок. */
.оформление__подпись {
  margin: 0 0 7px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--текст-тихий);
}

/* Сетка образцов. Ширина колонки — от 92 точек: в неё помещается
   образец и имя в одну-две строки, а на узком телефоне встают три
   штуки в ряд вместо четырёх, само собой и без отдельного правила. */
.оформление__кнопки {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
  gap: 8px;
  width: 100%;
}

/* Сам образец. Класс назван дважды нарочно: у кнопки есть общий класс
   кнопок выбора, и без этого он перебил бы здешние правила и вернул
   бы залитый жёлтый прямоугольник вместо спокойной карточки. */
.оформление__выбор.оформление__выбор {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 7px;
  min-width: 0;
  min-height: 44px;              /* размер пальца, меньше нельзя */
  padding: 10px 6px 9px;
  font: inherit;
  color: var(--текст);
  background: rgba(128, 128, 128, 0.14);
  background: color-mix(in srgb, var(--текст) 8%, transparent);
  border: 1px solid rgba(128, 128, 128, 0.28);
  border: 1px solid color-mix(in srgb, var(--текст) 16%, transparent);
  border-radius: 14px;
  box-shadow: none;
  cursor: pointer;
}

.оформление__выбор.оформление__выбор:active {
  transform: translateY(1px);
}

/* Выбранный: обводка, жирная подпись и галочка в углу.

   Селектор длинный не от любви к длине: общее правило выбранной кнопки
   («кнопка + кнопка--выбор + кнопка--активная») сильнее короткого, и
   на первом снимке оно заливало образец жёлтым целиком — доски под
   краской было не разглядеть. Здесь заливка не нужна вовсе: образец
   и есть то, что выбирают, красить его нельзя. */
.кнопка.оформление__выбор.оформление__выбор.кнопка--активная {
  color: var(--текст);
  background: color-mix(in srgb, var(--акцент) 14%, transparent);
  border: 2px solid var(--акцент);
  padding: 9px 5px 8px;          /* на точку меньше — рамка стала толще */
}

.кнопка.оформление__выбор.кнопка--активная .оформление__имя {
  font-weight: 800;
  color: var(--текст);
}

.кнопка.оформление__выбор.кнопка--активная::after {
  content: "✓";
  position: absolute;
  top: 3px;
  right: 6px;
  font-size: 12px;
  font-weight: 800;
  line-height: 1;
  color: var(--акцент);
}

/* ---------- Выбранный фон отмечается сам ----------

   У досок галочку ставит игра: она вешает на кнопку признак «активная».
   У фонов такой строки в игре нет, и на экране не было отмечено ни
   одного — хотя выбран всегда какой-то, по умолчанию «Сукно».

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

   Правила ниже повторяют вид выбранной кнопки, поэтому когда игра
   начнёт ставить признак сама, ничего не изменится и не поспорит. */
:is(
  html[data-фон="сукно"]   .оформление__выбор[data-фон="сукно"],
  html:not([data-фон])     .оформление__выбор[data-фон="сукно"],
  html[data-фон="дыхание"] .оформление__выбор[data-фон="дыхание"],
  html[data-фон="лампа"]   .оформление__выбор[data-фон="лампа"],
  html[data-фон="туман"]   .оформление__выбор[data-фон="туман"],
  html[data-фон="отсвет"]  .оформление__выбор[data-фон="отсвет"]
) {
  background: color-mix(in srgb, var(--акцент) 14%, transparent);
  border: 2px solid var(--акцент);
  padding: 9px 5px 8px;
}

:is(
  html[data-фон="сукно"]   .оформление__выбор[data-фон="сукно"],
  html:not([data-фон])     .оформление__выбор[data-фон="сукно"],
  html[data-фон="дыхание"] .оформление__выбор[data-фон="дыхание"],
  html[data-фон="лампа"]   .оформление__выбор[data-фон="лампа"],
  html[data-фон="туман"]   .оформление__выбор[data-фон="туман"],
  html[data-фон="отсвет"]  .оформление__выбор[data-фон="отсвет"]
)::after {
  content: "✓";
  position: absolute;
  top: 3px;
  right: 6px;
  font-size: 12px;
  font-weight: 800;
  line-height: 1;
  color: var(--акцент);
}

:is(
  html[data-фон="сукно"]   .оформление__выбор[data-фон="сукно"],
  html:not([data-фон])     .оформление__выбор[data-фон="сукно"],
  html[data-фон="дыхание"] .оформление__выбор[data-фон="дыхание"],
  html[data-фон="лампа"]   .оформление__выбор[data-фон="лампа"],
  html[data-фон="туман"]   .оформление__выбор[data-фон="туман"],
  html[data-фон="отсвет"]  .оформление__выбор[data-фон="отсвет"]
) .оформление__имя {
  font-weight: 800;
  color: var(--текст);
}

/* Имя варианта. Переносится по словам и не растягивает колонку:
   «Холодный камень» встаёт в две строки, а не режет сетку. */
.оформление__имя {
  max-width: 100%;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  overflow-wrap: break-word;
}

/* «Фоны появятся здесь» — обычная тихая строка на всю ширину раздела,
   пока в нём нечего показывать. */
.оформление__скоро {
  grid-column: 1 / -1;
  margin: 0;
  font-size: 13px;
  line-height: 1.4;
  color: var(--текст-тихий);
}

/* Кусочек доски в образце. Размер и клетки приходят из игры (она же
   знает цвета выбранной доски), здесь — общий вид: аккуратный квадрат
   с каймой того же цвета, что у настоящей доски. Класс назван дважды
   по той же причине, что выше: правило игры вписано в начало страницы
   и иначе спорило бы с этим. */
.образец-доски.образец-доски {
  width: 52px;
  height: 52px;
  border-width: 2px;
  border-radius: 8px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.28);
}

/* =====================================================================
   ПЛИТКА ИГРЫ — готовая карточка владельца фоном кнопки

   В «img/витрина/» лежат полные карточки: фото, название, салатовая
   стрелка ↗, затемнение снизу и тонкая рамка — всё уже внутри
   картинки. README набора говорит прямо: «Не рисуй эти элементы второй
   раз». Поэтому здесь нет ни градиента, ни подписи, ни стрелки —
   только сама картинка фоном кнопки.

   Картинка растягивается ровно на кнопку («100% 100%»), а кнопка
   держит ТОЧНО ту же пропорцию, что у картинки («aspect-ratio» у
   каждой игры свой, числами из её размера). Раз пропорции равны,
   ничего не сплющивается и не обрезается. Высоты рядов от этого
   разные (325, 297, 290) — на макете так же.

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

   Текст названия в кнопке остаётся — его читает программа чтения
   с экрана и по нему находят кнопку проверки, — но глазу он не виден
   (см. ниже «только для чтения с экрана»): второе название поверх
   нарисованного было бы ровно тем, что README запрещает. */
.плитка-игры {
  position: relative;
  overflow: hidden;
  display: block;
  width: 100%;
  padding: 0;
  font: inherit;
  color: var(--вт-текст);
  text-align: left;
  /* Если картинка не приехала (плохая связь) — ровная тёмная плитка
     того же тона, что поверхность, а не цветное пятно. */
  background-color: #1a1d22;
  background-position: center;
  background-size: 100% 100%;
  background-repeat: no-repeat;
  border: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.14s ease, filter 0.14s ease;
}

/* Здесь раньше стояли восемь правил «.плитка-игры[data-игра="…"]»
   (order/aspect-ratio/border-radius/background-image по картинке
   каждой игры отдельно) — с 26.09 витрину рисуют style-витрина.css
   и style-коллекция.css: у «#экран-витрины .плитка-игры» специфичность
   выше (в селекторе есть «#id»), и её «background: #141c1e» сокращённой
   записью обнуляет background-image независимо от игры и состояния —
   картинку теперь рисует «::before» через переменную «--catalog-art».
   Убрано 26.09 (задача штаба): доказано прогоном
   tests/витрина-вид-не-изменился.js — 0 отличий вычисленного стиля
   плиток до и после удаления этого блока. */

/* Нажатие — лёгкое сжатие (масштаб 0,98 за 140 мс) и чуть темнее:
   на фотографии одно сжатие на глаз почти не видно, а игрок должен
   понять, что игра среагировала. */
.плитка-игры:active {
  transform: scale(0.98);
  filter: brightness(0.9);
}

/* Выбор с клавиатуры — салатовое кольцо, единственный акцент экрана. */
.плитка-игры:focus-visible {
  outline: 3px solid var(--вт-акцент);
  outline-offset: 2px;
}

/* Значок-рисунок на плитке больше не нужен: фото уже говорит, что за
   игра. Из разметки он убран; правило оставлено, чтобы вернувшийся
   по ошибке значок не лёг поверх карточки. */
.плитка-игры__значок { display: none; }

/* «Только для чтения с экрана»: текст есть и читается вслух, но
   занимает 1×1 точку и обрезан до нуля — глазу не виден. Классический
   приём: «display: none» не годится, его программа чтения пропускает. */
.плитка-игры__название,
.плитка-игры__описание {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- Пометка на плитке ----------
   Решение штаба (10 сентября): «играли недавно» на витрине не
   показываем — на макете её нет. Узел в разметке остаётся (его
   заполняет js/game.js), но на экран выходит только в двух случаях:
     • «не доиграна» — у дурака висит партия с другом (класс
       «плитка-игры--ждут»): друг ждёт за столом, это нужно видеть;
     • «скоро» — у выключенных плиток (см. ниже, поверх стрелки). */
.плитка-игры__пометка { display: none; }

/* «Не доиграна» — салатовая пилюля с почти чёрным текстом в левом
   верхнем углу: там она не наезжает на нарисованное внизу название.
   Салатовая нарочно — это зов действовать, как активная фишка,
   а не тихая справка. Лёгкая тень отрывает её от фотографии. */
.плитка-игры--ждут .плитка-игры__пометка {
  position: absolute;
  left: 8px;
  top: 8px;
  z-index: 2;
  display: inline-block;
  max-width: calc(100% - 16px);
  padding: 4px 10px 5px;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--вт-акцент-текст);
  background: var(--вт-акцент);
  border-radius: 999px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}

.плитка-игры--ждут .плитка-игры__пометка:empty { display: none; }

/* ---------- Плитка «скоро» (домино, морской бой, деберц) ----------
   Игры ещё нет — приглушение задано переменной ниже (два слоя поверх
   фона: полупрозрачный тёмный и серый «насыщенность»). Раньше сюда же
   дописывали и саму картинку игры (per-game url()) — семь правил
   «.плитка-игры[data-игра="…"]{--скоро,:disabled}» с одним свойством
   background-image. Убраны 26.09 (задача штаба): у той же
   «#экран-витрины .плитка-игры» из style-витрина.css специфичность
   выше и «background: #141c1e» обнуляет background-image в любом
   состоянии плитки — картинку рисует «::before» (переменная
   «--catalog-art»), эти семь правил ничего не показывали. Доказано
   прогоном tests/витрина-вид-не-изменился.js (0 отличий). Переменная
   «--вт-приглушить» и cursor/background-blend-mode ниже — НЕ трогать:
   они не привязаны к «[data-игра="…"]» и специфичностью не перебиты. */
.плитка-игры--скоро,
.плитка-игры:disabled {
  --вт-приглушить:
    linear-gradient(rgba(16, 20, 22, 0.38), rgba(16, 20, 22, 0.38)),
    linear-gradient(rgba(128, 128, 128, 0.4), rgba(128, 128, 128, 0.4));
  cursor: default;
  background-blend-mode: normal, saturation, normal;
}

.плитка-игры--скоро:active,
.плитка-игры:disabled:active {
  transform: none;
  filter: none;
}

/* Пилюля «скоро» — ровно поверх нарисованной на картинке стрелки ↗
   в правом нижнем углу: на неготовой игре вместо «перейти» написано
   «скоро». Решение штаба (10 сентября).

   Как попадаем в стрелку на любой ширине экрана. Стрелка — часть
   картинки, поэтому её место задано в долях карточки, а не в точках:
   на карточке 428×290 она кончается в 30 точках от правого края
   (7 %) и её середина — на 86 % высоты. Правый край пилюли ставим
   на 5 точек правее стрелки, середину — на середину стрелки.
   Пилюля (57×25) втрое больше стрелки (12×12 на экране 390), поэтому
   закрывает её с запасом со всех сторон — проверено под лупой на 360,
   390 и 430.

   Фон пилюли НЕПРОЗРАЧНЫЙ: сквозь полупрозрачное стекло салатовая
   стрелка просвечивала бы зелёным пятном. Тонкая светлая обводка,
   тёплый белый текст. Не салатовая: салатовым на экране крашено
   только выбранное, включённое и зовущее действовать. */
.плитка-игры--скоро .плитка-игры__пометка,
.плитка-игры:disabled .плитка-игры__пометка {
  position: absolute;
  right: calc(7% - 5px);
  top: 86.2%;
  transform: translateY(-50%);
  z-index: 2;
  display: inline-block;
  max-width: calc(100% - 16px);
  padding: 4px 10px 5px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--вт-текст);
  background: #171b1e;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 999px;
}

.плитка-игры--скоро .плитка-игры__пометка:empty,
.плитка-игры:disabled .плитка-игры__пометка:empty { display: none; }

/* На баннере 873×209 стрелка стоит иначе: кончается в 31 точке от
   правого края (3,55 %), середина — на 71 % высоты. */
.плитка-игры[data-игра="деберц"] .плитка-игры__пометка {
  right: calc(3.55% - 5px);
  top: 70.8%;
}

/* ---------- Витрина на большом экране ----------
   Игру открывают и в браузере на компьютере — колонка содержимого
   не шире 520 точек (см. правило экрана выше), плитки держат свои
   пропорции и просто становятся крупнее. Поле и промежуток на
   широком окне упираются в верхнюю границу «clamp» и дальше не растут. */

/* Кому мешает движение — плитка не сжимается совсем. */
@media (prefers-reduced-motion: reduce) {
  .плитка-игры { transition: none; }
  .плитка-игры:active { transform: none; }
}


/* =====================================================================
   НИЖНЯЯ ПАНЕЛЬ ВКЛАДОК — «Игры / Друзья / Профиль»

   По вырезке «эталон/витрина-части/bottom-nav.png»: панель на тон
   светлее фона, верхние углы скруглены (≈20 точек), по верху тонкая
   светлая линия, высота 56 точек на экране 390 (доля ширины, см.
   «--вт-панель-низ») плюс полоса жеста телефона.

   «position: fixed» — панель лежит поверх низа экрана всегда, поэтому
   у «#экран-витрины.витрина» снизу отложен запас (высота панели + 12 +
   полоса жеста, см. выше): без него баннер «Деберц» прятался бы
   под панель.

   На широком окне вкладки не разбегаются по краям монитора: боковые
   поля панели сжимают их в ту же колонку 520, что и содержимое. */
.нижние-вкладки {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 5;
  display: flex;
  align-items: stretch;
  justify-content: space-around;
  height: calc(var(--вт-панель-низ) + var(--отступ-снизу));
  /* Боковые поля 8: на макете центры вкладок стоят на 70, 195 и 320
     точках, а не на трети ширины (65, 195, 325). */
  padding: 0 max(8px, (100% - 520px) / 2) var(--отступ-снизу);
  background: var(--вт-поверхность);
  border-radius: 20px 20px 0 0;
  /* Линия по верху — внутренней тенью, а не рамкой: тень повторяет
     скругление углов и гаснет на них сама, рамка же дала бы ещё
     и вертикальные черты по бокам экрана. Вторая тень — мягкая
     наружу вверх: плитки, уезжающие под панель, темнеют. */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 -10px 24px rgba(0, 0, 0, 0.35);
}

.нижняя-вкладка {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0;
  min-height: 44px;
  padding: 0 4px 1px;
  font: inherit;
  /* На макете «Профиль» — 42 точки в ширину на 390: это 11, не 12.
     Растёт с шириной экрана вместе со всей панелью, но не мельче 10,5. */
  font-size: clamp(10.5px, 2.82vw, 13px);
  font-weight: 500;
  line-height: 1.27;
  color: var(--вт-текст-тихий);
  background: none;
  border: none;
  cursor: pointer;
}

.нижняя-вкладка__значок {
  display: flex;
  width: clamp(24px, 6.67vw, 30px);    /* 26 на 390 */
  height: clamp(24px, 6.67vw, 30px);
}

.нижняя-вкладка__значок svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* Активная — «Игры» на витрине: значок и подпись разом становятся
   салатовыми, подпись чуть плотнее — как на макете. */
.нижняя-вкладка--активна {
  color: var(--вт-акцент);
  font-weight: 600;
}

/* «Друзья» и «Профиль» пока выключены: таких экранов у нас нет.
   На макете они просто серые — такими и оставлены, без лишнего
   побледнения; нажатие на них ничего не делает и не вжимается. */
.нижняя-вкладка:disabled {
  cursor: default;
}

.нижняя-вкладка:not(:disabled):active { transform: scale(0.94); }

.нижняя-вкладка:focus-visible {
  outline: 2px solid var(--вт-акцент);
  outline-offset: -4px;
  border-radius: 12px;
}

/* Значки вкладок — из набора владельца, вписаны в разметку и красятся
   цветом кнопки (салатовый у активной, серый у остальных). Линию
   делаю чуть толще, чем в файле набора (2 вместо 1,7): на макете
   значки вкладок заметно плотнее. Правило CSS перебивает толщину,
   записанную в самом SVG, — разметку для этого трогать не нужно. */
.нижняя-вкладка__значок svg { stroke-width: 2; }

/* =====================================================================
   ЛИСТ «ЕЩЁ» — выезжает снизу по «⋯» (а в Telegram — по «Настройкам»
   в его меню)

   Та же система, что у витрины: тёмная панель на тон светлее фона,
   скруглённый верх, как у панели вкладок, строки — приподнятые
   карточки, один салатовый акцент (включённый звук). Показывает
   и прячет js/game.js классом «скрыт».

   Лист прижат к низу и не выше экрана: если строк станет много,
   он прокручивается сам, а не уезжает за верхний край. Снизу учтена
   полоса жеста — кнопка «Закрыть» не прячется под неё. */
.лист-ещё {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
}

/* Затемнение за листом: нажатие по нему закрывает лист (js/game.js). */
.лист-ещё__фон {
  position: absolute;
  inset: 0;
  background: rgba(5, 7, 8, 0.6);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  animation: лист-ещё-фон 0.2s ease-out;
}

.лист-ещё__лист {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  max-width: 520px;
  max-height: calc(100% - 24px - var(--отступ-сверху));
  overflow-y: auto;
  padding: 22px calc(var(--вт-поле) + var(--отступ-справа))
           calc(14px + var(--отступ-снизу))
           calc(var(--вт-поле) + var(--отступ-слева));
  color: var(--вт-текст);
  background: var(--вт-поверхность);
  border-radius: 20px 20px 0 0;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 -12px 32px rgba(0, 0, 0, 0.45);
  animation: лист-ещё-вверх 0.22s cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* «Ручка» сверху — привычный знак выдвижного листа. */
.лист-ещё__лист::before {
  content: "";
  position: absolute;
  top: 8px;
  left: 50%;
  width: 36px;
  height: 4px;
  margin-left: -18px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.18);
}

.лист-ещё__заголовок {
  margin: 0 0 4px;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.3;
  text-align: center;
  color: var(--вт-текст);
}

/* Строка — приподнятая карточка во всю ширину: подпись слева,
   значение или стрелка справа. Высота 52 — палец попадает уверенно. */
.лист-ещё__строка {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  min-height: 52px;
  padding: 0 16px;
  font: inherit;
  font-size: 16px;
  font-weight: 500;
  text-align: left;
  color: var(--вт-текст);
  background: #1e2226;
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 14px;
  cursor: pointer;
  transition: transform 0.12s ease, background-color 0.12s ease;
}

.лист-ещё__строка:active {
  transform: scale(0.98);
  background: #262a2f;
}

/* «Сдаться» — опасная строка листа: текст красным, тем же готовым красным,
   что у красных мастей и кнопки «Завершить» (--карта-красная). */
.лист-ещё__строка--опасно {
  color: var(--карта-красная);
}

/* Строка без значения ведёт на другой экран — справа тихая стрелка.
   Только у открытого листа: снимок доступности Playwright показывает
   нарисованный CSS текст даже у спрятанных узлов, и одинокий «›»
   на витрине сбивал бы проверки. */
.лист-ещё:not(.скрыт) .лист-ещё__строка:not([role="switch"])::after {
  content: "›";
  font-size: 22px;
  line-height: 1;
  color: var(--вт-текст-тихий);
}

/* Значение переключателя «Звук» — маленькая пилюля. Включено —
   салатовая с тёмным текстом (единственный акцент листа), выключено —
   тёмная с серой обводкой: состояние видно, не читая слова. */
.лист-ещё__значение {
  flex: 0 0 auto;
  min-width: 52px;
  padding: 5px 12px 6px;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  color: var(--вт-текст-тихий);
  border: 1px solid var(--вт-граница);
  border-radius: 999px;
}

.лист-ещё__строка[aria-checked="true"] .лист-ещё__значение {
  color: var(--вт-акцент-текст);
  background: var(--вт-акцент);
  border-color: var(--вт-акцент);
}

/* «Закрыть» — тихая, как фишки-фильтры: обводка без заливки.

   ЗАМЕЧАНИЕ ТЕСТИРОВЩИКА (11 сентября): на самом маленьком телефоне
   (320×568) в полном экране Telegram лист со строкой «Вибрация» выше
   окна, начинает прокручиваться — и «Закрыть», последняя в списке,
   уходила под полосу жеста (низ 552 при пределе 534).

   Теперь «Закрыть» прилипает к низу листа («sticky»): пока список
   прокручивается, она стоит над нижним полем листа, а в поле входит
   безопасный отступ полосы жеста. «bottom: 0» считается от края
   прокрутки за вычетом нижнего поля листа — тот же приём, что у
   «Закрыть» панели знаков (см. «#кнопка-эмоции-назад»): там поле
   уводят отрицательным отступом, чтобы полка встала вплотную к краю.
   Когда список помещается целиком, прилипание ничего не меняет.

   Под прилипшей кнопкой проезжают строки, поэтому у неё заливка цвета
   листа (на месте она выглядит так же, как без заливки), а тени того
   же цвета закрывают поле под ней до края листа и мягко гасят строку
   над ней — как у «Далее» на шагах к партии. */
.лист-ещё__закрыть {
  position: sticky;
  bottom: 0;
  z-index: 1;
  flex-shrink: 0;
  width: 100%;
  min-height: 48px;
  margin-top: 6px;
  padding: 0 16px;
  font: inherit;
  font-size: 16px;
  font-weight: 600;
  color: var(--вт-текст);
  background: var(--вт-поверхность);
  border: 1px solid var(--вт-граница);
  border-radius: 14px;
  box-shadow:
    0 -14px 14px -4px var(--вт-поверхность),
    0 calc(14px + var(--отступ-снизу)) 0 0 var(--вт-поверхность);
  cursor: pointer;
}

/* Строки тоже не сплющиваются: в прокручиваемом столбике сжатие
   испортило бы только высоту под палец. */
.лист-ещё__строка { flex-shrink: 0; }

/* Низкое окно (самый маленький телефон, особенно в полном экране
   Telegram, где сверху и снизу отнимают безопасные поля): строки чуть
   ниже — 46 вместо 52, всё ещё больше 44 под палец, — и зазоры меньше.
   Шесть строк с «Закрыть» тогда помещаются без прокрутки и на 320×568
   с полосой жеста; не поместятся — выручит прилипшая «Закрыть». */
@media (max-height: 640px) {
  .лист-ещё__лист {
    gap: 6px;
    padding-top: 18px;
  }

  .лист-ещё__заголовок { margin-bottom: 0; }

  .лист-ещё__строка { min-height: 46px; }

  .лист-ещё__закрыть { min-height: 46px; }
}

.лист-ещё__закрыть:active { transform: scale(0.98); opacity: 0.8; }

.лист-ещё__строка:focus-visible,
.лист-ещё__закрыть:focus-visible {
  outline: 2px solid var(--вт-акцент);
  outline-offset: 2px;
}

@keyframes лист-ещё-вверх {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}

@keyframes лист-ещё-фон {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .лист-ещё__лист,
  .лист-ещё__фон,
  .рейтинг-панель-игр__окно,
  .рейтинг-панель-игр__фон { animation: none; }
}

/* ---------- Сноска под кнопкой ----------

   Мелкая строчка, приписанная к кнопке сверху: она предупреждает
   о том, что человеку важно знать ДО нажатия, а не после.

   Ради чего заведена. Кнопка «Играть с другом» ничем не говорит,
   что игра вдвоём держится на включённом компьютере того, кто
   запускает игру. Человек жмёт её и упирается в объяснение —
   а правду честнее сказать заранее.

   Отчего мелкая и притянутая. В меню высота на счету: лишняя строка
   там — это два ряда текста. Поэтому сноска мелкая и подтянута вверх
   отрицательным полем: она стоит в шести точках под кнопкой, к которой
   относится, и в обычных четырнадцати от того, что идёт ниже, —
   сразу видно, к чему она приписана.
   Замерено в браузере: даже в самом тесном случае (320 на 568, да ещё
   с лишней кнопкой «Вернуться к игре с другом») обе строки помещаются
   и ничего не выдавливают за край.

   Ширина — ровно по кнопке: строка не должна быть шире того,
   что объясняет. */

.сноска {
  width: min(100%, var(--колонка-кнопок));
  margin: -6px 0 0;
  font-size: 12.5px;
  line-height: 1.25;
  color: var(--текст-тихий);
}

/* ---------- Выбор соперника ---------- */

.выбор {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: min(100%, var(--колонка-кнопок));   /* ровно по ширине кнопок меню */
}

.выбор__подпись {
  font-size: 13px;
  color: var(--текст-тихий);
}

/* Три уровня всегда в одну строку: кнопки делят ширину поровну
   и сжимаются вместе с экраном, а не переносятся вниз. */
.выбор__кнопки {
  display: flex;
  gap: 6px;
  width: 100%;
}

.кнопка.кнопка--выбор {
  flex: 1 1 0;
  width: auto;
  min-width: 0;
  min-height: 44px;
  padding: 8px 4px;
  font-size: 15px;
  font-weight: 600;
  color: var(--текст);
  background: var(--подложка);
  border: 1px solid var(--край);
  box-shadow: none;
}

/* Выбранный уровень залит цветом кнопки — видно без чтения подписи */
.кнопка.кнопка--выбор.кнопка--активная {
  color: var(--кнопка-текст);
  /* Тот же притемнённый цвет, что у обычной кнопки: подпись уровня мелкая
     (15 точек), и на чистом синем Telegram она читалась хуже нормы.
     Первая строка — запас для старых браузеров без color-mix. */
  background: var(--кнопка-фон);
  background: color-mix(in srgb, var(--кнопка-фон) 86%, #000000);
  border-color: transparent;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28);
}

/* ---------- Рекорды и звук ---------- */

/* «Рекорды» — не главное действие, поэтому только обводка:
   на экране должна выделяться одна кнопка «Играть». */
#кнопка-рекорды {
  color: var(--текст);
  background: transparent;
  border: 2px solid var(--край);
  box-shadow: none;
}

/* Звук: кружок слева залит — включён, пустой — выключен.
   Видно с одного взгляда, даже не читая надпись.

   Кнопок звука на странице две — по одной на экранах «Игра с ботом»
   и «Игра с другом», — и раньше кружок был только у первой: правило
   искало её по имени. Состояние у звука одно на всю игру, значит
   и выглядеть кнопки обязаны одинаково, иначе человек решит, что это
   две разные настройки. Теперь названы обе. */
/* Выключатель вибрации — родной брат выключателя звука: та же мелкая
   кнопка, та же надпись «включена/выключена», тот же кружок слева.
   Поэтому он просто дописан во все правила звука, а не оформлен
   по-своему: две настройки рядом обязаны выглядеть парой, иначе
   человек решит, что это разные по важности вещи. Кнопок вибрации,
   как и звука, две — по одной на экранах игры с ботом и с другом;
   ставит их js/game.js и только там, где вибрация вообще возможна. */
#кнопка-звук,
#кнопка-звук-друг,
.кнопка--вибрация {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: auto;              /* не во всю ширину: это настройка, не действие */
  color: var(--текст);
}

#кнопка-звук::before,
#кнопка-звук-друг::before,
.кнопка--вибрация::before {
  content: "";
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--акцент);
  box-shadow: 0 0 6px var(--акцент);
}

#кнопка-звук.кнопка--выключено,
#кнопка-звук-друг.кнопка--выключено,
.кнопка--вибрация.кнопка--выключено {
  color: var(--текст-тихий);
}

#кнопка-звук.кнопка--выключено::before,
#кнопка-звук-друг.кнопка--выключено::before,
.кнопка--вибрация.кнопка--выключено::before {
  background: transparent;
  border: 2px solid var(--край);
  box-shadow: none;
}

/* ---------- Кнопки ---------- */

.кнопка {
  min-height: 46px;            /* палец попадает наверняка */
  min-width: 116px;
  padding: 10px 22px;
  font: inherit;
  font-size: 17px;
  font-weight: 700;
  /* Волосок между буквами: короткое слово на кнопке («Играть», «Бито»)
     набрано жирным, и без просвета буквы слипаются в пятно. Высота
     кнопки от этого не меняется — 46 точек как были. */
  letter-spacing: 0.2px;
  color: var(--кнопка-текст);
  /* Цвет кнопки берём у Telegram, но притемняем на седьмую часть. Его
     фирменный синий под белой надписью даёт контраст 4,1 в светлой теме
     и 3,7 в тёмной, а для подписи в 17 точек норма — 4,5. После
     притемнения выходит 5,3 и 4,8: надпись читается, а кнопка остаётся
     узнаваемо «телеграмовской», не превращаясь в чёрную.
     Первая строка — для браузеров старше 2023 года, которые не знают
     color-mix: там кнопка просто чистого цвета темы. Вторая строка —
     для всех остальных, они возьмут именно её. Доля 86% та же, что
     у полосы события ниже, — кнопка и полоса одного тона. */
  background: var(--кнопка-фон);
  background: color-mix(in srgb, var(--кнопка-фон) 86%, #000000);
  border: none;
  border-radius: 12px;
  /* Три слоя вместо одной тени: короткая прижимает кнопку к сукну,
     длинная и слабая даёт ей объём, а светлая полоска внутри по верхнему
     краю — блик на выпуклой поверхности. Вместе это «кнопку можно нажать»,
     а не «прямоугольник нарисован». */
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.30),
    0 8px 18px rgba(0, 0, 0, 0.22),
    inset 0 1px 0 rgba(255, 255, 255, 0.22);
  cursor: pointer;
}

/* Нажатие: кнопка садится, длинная тень исчезает — вжалась в стол. */
.кнопка:active {
  transform: translateY(2px);
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.32),
    inset 0 1px 3px rgba(0, 0, 0, 0.20);
}

.кнопка--главная {
  font-size: 20px;
  min-width: 190px;
  min-height: 52px;
}

/* Тихая кнопка — второе, необязательное действие рядом с главным:
   «Показать ещё» под списком рейтинга, «Повторить» под сообщением
   об ошибке. Она нарочно не залита цветом и не выпуклая: тёмная
   подложка и тонкая рамка говорят «можно нажать», но взгляд к ней
   не тянут. Числа — из макета владельца («.secondary-button»),
   палец попадает: 44 точки по высоте. */
.кнопка--тихая {
  min-width: 0;
  min-height: 44px;
  padding: 10px 20px;
  font-size: 15px;
  font-weight: 600;
  color: #dfc993;
  background: #161615;
  border: 1px solid #474136;
  border-radius: 12px;
  box-shadow: none;
}

/* Нажатие — только «садится», без исчезающей тени: её тут и нет. */
.кнопка--тихая:active {
  box-shadow: none;
}

/* «Беру» нарочно НЕ приглушаем. Раньше она была пустой рамкой рядом
   с залитой «Бито», и живой игрок читал её как выключенную: «кнопка
   бледная — значит, сейчас недоступна». На деле взять карты — такое же
   полноправное действие, как отбиться, и выбор между ними делает игрок,
   а не оформление. Отдельного правила у кнопки больше нет: она выглядит
   как обычная кнопка. Спутать их нельзя — «Бито» и «Беру» никогда
   не показываются в один и тот же момент. */

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

   Высота здесь 44 — сенсорный минимум проекта (палец должен попадать
   уверенно). Кому нужно другое число — например, нарды у кнопки
   «Отменить ход» — переопределяют его сами, явно, в своём файле. */
.кнопка.кнопка--мелкая {
  min-height: 44px;
  min-width: 0;
  padding: 8px 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--текст-тихий);
  background: var(--подложка);
  border: 1px solid var(--край);
  box-shadow: none;
}

/* На странице сборника (дурак и витрина) — 44: мелкая кнопка мельче
   ПОДПИСЬЮ и тише цветом, но палец у человека тот же, и попадать в неё
   он должен так же уверенно («Как считается» на рейтинге, «Оформление»
   и «Звук» в меню). Поля по высоте не трогали — прибавка ушла в саму
   коробку, подпись осталась по центру.
   ТОЛЬКО СБОРНИК — отсюда «:has(> #экран-витрины)», тем же приёмом,
   что широкое окно. Общая прибавка задела другие игры: в нардах колонка
   меню сдвинулась на 4 точки, в шахматах выросли ряды под доской,
   и на 320×568 за край уходило пять кнопок вместо трёх. Вес правила
   тот же, что у общего («:where» веса не добавляет), поэтому все более
   точные правила ниже по файлу работают как прежде. */
:where(#приложение:has(> #экран-витрины)) .кнопка.кнопка--мелкая {
  min-height: 44px;
}

/* ---------- Раскладка игрового экрана ----------

   Стол дурака раскладывается в своём разделе в конце файла («СТОЛ ДУРАКА
   ПО ЭТАЛОНУ ВЛАДЕЛЬЦА»). Здесь осталось только общее: поля экрана
   «экран-игры» — ими пользуются нарды (у них игровой экран называется
   так же), — полоска руки и веер. */
#экран-игры {
  gap: 4px;
  padding: calc(6px + var(--отступ-сверху)) calc(8px + var(--отступ-справа))
           calc(6px + var(--отступ-снизу))  calc(8px + var(--отступ-слева));
}

.рука {
  position: relative;
  flex: 0 0 auto;
  width: 100%;
}

.веер {
  position: absolute;
  inset: 0;
}

/* Счётчики, колода с козырем, метка козыря и карты на столе живут
   в разделе стола в конце файла. Здесь осталась только коробка пары:
   её размер — карта и сдвиг накрывающей карты (рост карты объявляет
   поле пар «#стол» там же; насколько раздвинуть пару в ряду, решает
   правило «#стол > .пара» в конце файла). */
.пара {
  position: relative;
  flex: 0 0 auto;
  width: calc(var(--ш) * 1.46);
  height: calc(var(--в) + var(--сдвиг-y));
}

/* ---------- Сама карта ---------- */

/* Кремовая бумага, как у карт набора, — ровная, одним цветом: у фигур
   бумага нарисована прямо в картинке (#f6ead5), и любой перелив на карте
   рядом с ней был бы виден полосой на стыке. Объём карте дают кромка
   и тени: тонкая светлая линия внутри по краю (срез картона), полупрозрачный
   тёмный край снаружи и тень в два слоя — короткая прижимает карту к сукну,
   длинная даёт рассеянный свет вокруг. Скругление — восемь сотых ширины,
   ровно как у рисунка карты, чтобы углы рисунка и бумаги совпадали.
   Цвет текста — почти чёрный; красные масти перекрашивают его правилами
   ниже (они стоят позже нарочно — см. «Запасное правило»). */
.карта {
  position: relative;
  width: var(--ш);
  height: var(--в);
  background: var(--карта-фон);
  border: 1px solid rgba(70, 48, 22, 0.24);
  border-radius: max(3px, calc(var(--ш) * 0.08));
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.35),
    0 1px 2px rgba(0, 0, 0, 0.45),
    0 6px 14px rgba(0, 0, 0, 0.32);
  color: var(--карта-текст);
  overflow: hidden;

  /* Сколько от карты видно игроку.
     У карты на столе, у козыря и у верха колоды видна вся ширина —
     поэтому по умолчанию это вся карта. А в руке карты лежат внахлёст,
     и от каждой видна только узкая левая полоска: всё, что правее,
     накрыто соседкой. Ширину этой полоски присылает сама игра
     (см. «тесная рука» ниже), и от неё считается кегль подписи в углу:
     что не влезло в полоску, игрок просто не увидит. */
  --полоска: var(--ш);
}

/* Запасное правило. Пометку «красная» игра ставила и раньше, до того как
   научилась называть масть поимённо. Она остаётся на месте: если карта
   почему-то придёт без имени масти (например, страница откроется со старым
   сохранённым в памяти телефона js/game.js), черви и бубны всё равно будут
   красными, а не чёрными. Четыре правила ниже стоят после этого нарочно —
   вес у них одинаковый, и побеждает то, что записано позже. */
.карта--красная { color: var(--карта-красная); }

/* Четыре цвета мастей — см. подробное пояснение в начале файла */
.карта--пики  { color: var(--масть-пики); }
.карта--черви { color: var(--масть-черви); }
.карта--бубны { color: var(--масть-бубны); }
.карта--трефы { color: var(--масть-трефы); }

/* ---------- Угол карты: достоинство и под ним масть ----------

   Столбик выбран не для красоты — когда в руке много карт, от каждой
   видна полоска шириной в полтора десятка точек, и «10♦» в строчку
   туда не влезает, а «10» с «♦» под ним влезает и читается.

   ГЛАВНОЕ ПРО МАСТЬ (жалоба живого игрока: «не видно, крест это или
   пика»). В тесной руке крупная масть в середине карты не видна вовсе —
   её накрывает соседняя карта. Значит, весь разговор о мастях идёт
   в этом углу. И масть здесь — не подпись при достоинстве, а главный
   знак: достоинство узнаётся по одной цифре, а масть — по форме значка,
   и значки эти мелкие и похожие. Поэтому масть здесь крупнее
   достоинства (см. ниже) и никогда не срезается краем карты.

   С четырьмя цветами (см. начало файла) у этого угла появился второй
   способ сказать масть: цвет. Он работает даже там, где форму уже
   не разглядеть, — и красит не только значок, но и достоинство.
   В самой тесной руке из-под соседней карты торчит порой одна цифра,
   и её цвет — единственное, что остаётся от масти. */

.карта__угол {
  position: absolute;
  left: 2px;
  top: 1px;
  display: flex;
  flex-direction: column;
  /* Достоинство и масть прижаты к левому краю, а не выровнены по
     середине столбика. Разница видна на столе: карту, которой ходили,
     накрывает карта, которой отбились, и от нижней остаётся узкая
     левая полоска. Пока масть стояла по центру столбика, под широким
     «10» она уезжала вправо — ровно под накрывающую карту. */
  align-items: flex-start;
  font-weight: 800;
  line-height: 1;

  /* Кегль достоинства. Берём самое маленькое из трёх ограничений —
     что не влезло, то у игрока пропадёт:

     1) ШИРИНА ВИДИМОЙ ПОЛОСКИ. В столбике два знака — «10» и значок
        масти; самый широкий из них занимает около 1,1 кегля, ещё
        три точки уходят на отступ от края карты;
     2) ВЫСОТА КАРТЫ. Когда рука лежит в два ряда, карта вдвое ниже,
        а столбик «достоинство + масть» просит примерно 2,4 кегля
        высоты. Этого ограничения тут раньше не было, и вот чем это
        кончалось: при 35 картах на руке масть уезжала за нижний край
        карты и пропадала совсем — на экране оставались одни цифры;
     3) ПРОСТО НЕ КРУПНЕЕ ПРИЛИЧНОГО. У карты, которую видно целиком,
        угол не должен спорить с крупной мастью в середине.

     Ниже 7 точек не опускаемся: при 35 картах на экране в 280 точек
     любой кегль всё равно мал, и пусть лучше краешек знака уйдёт под
     соседнюю карту, чем подпись растает совсем.

     У этого пола есть оговорка, и она про высоту. Уехать под соседнюю
     карту вбок — не беда: там всё равно ничего не видно. А вот уехать
     под СВОЙ нижний край — беда: знак обрезается на глазах у игрока
     и выглядит сломанным. Столбик просит 2,3 кегля высоты, значит при
     карте ниже 18 точек семь точек кегля уже не помещаются: в трёх рядах
     в узкой шторке карта выходит 14 точек, столбику нужно 17, и нижняя
     треть значка масти пропадает (замер предыдущего дизайнера, поэтому
     он тогда и поднял полоску руки до 86).
     Поэтому пол не постоянный, а «семь точек, но не больше, чем влезает
     в высоту карты». На обычной карте (18 точек и выше) он равен прежним
     семи и ничего не меняет — он считается ровно там, где раньше знак
     срезался.

     Запасной строки «для старых браузеров» тут нет нарочно: min() и
     clamp() нужны игре и так — на них держится сам размер карты
     (см. «--в» в начале файла). Браузер, который их не понимает,
     не покажет вообще ничего, и подпись в углу будет наименьшей
     из бед. */
  --кегль: max(min(7px, calc((var(--в) - 2px) / 2.3)),
               min(calc((var(--полоска) - 3px) / 1.1),
                   calc(var(--в) * 0.36),
                   calc(var(--ш) * 0.38)));
}

.карта__номинал {
  font-size: var(--кегль);
  line-height: 1;
  letter-spacing: -0.02em;         /* чтобы «10» было чуть у́же */
  font-variant-numeric: tabular-nums;
}

.карта__масть-угла {
  margin-top: 1px;
  /* Значок масти крупнее достоинства в 1,3 раза. Это не украшение:
     достоинство — это цифра, её узнают с полувзгляда даже мелкой,
     а масть узнают по форме, и мелкая форма не узнаётся никак.
     Место под такой значок есть: в столбике достоинство занимает
     два знака в ширину («10»), а масть — один, и она может быть
     заметно крупнее, оставаясь в той же полоске.
     Верхний предел — 0,34 ширины карты: у карты, видной целиком,
     угол не должен спорить с крупной мастью в середине. */
  font-size: min(calc(var(--кегль) * 1.3), calc(var(--ш) * 0.34));
  line-height: 1;
  /* Начертание нарочно обычное, а не жирное, как у достоинства.
     У трефы три отдельные доли, и жирный шрифт замазывает просветы
     между ними: на мелком значке трефа превращается в такое же
     чёрное пятно, как пика, — то самое, на что жаловался игрок. */
  font-weight: 400;
  /* Просим телефон рисовать масть знаком, а не цветным эмодзи:
     на части телефонов ♥ и ♦ по умолчанию превращаются в картинку,
     и тогда пропадает и наш красный цвет, и привычная форма.
     Свойство новое — браузеры постарше просто его не заметят. */
  font-variant-emoji: text;
}

/* Крупная масть в свободной части карты. Она работает там, где карту
   видно целиком: на столе, в колоде и у карты, которую игрок поднял
   (поднятая карта лежит поверх соседок). Сдвинута вправо-вниз, чтобы
   не лезть в угол. */
.карта__масть {
  position: absolute;
  inset: 30% 4% 4% 32%;
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  font-size: calc(var(--ш) * 0.64);
  line-height: 1;
  font-variant-emoji: text;
}

/* ---------- Рубашка ----------

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

   Заливка задаётся свойством fill — это «цвет заливки» у рисованных
   фигур, то же самое, что background у обычного элемента. */
.рубашка__фон  { fill: var(--рубашка-фон); }
.рубашка__поле { fill: var(--рубашка-поле); }

/* ---------- Карты в руке ---------- */

/* Позиции карт в веере считает JS, здесь только вид */
.веер .карта {
  position: absolute;
  /* Двигает карту сама игра (она же считает, куда карта подскочит при
     выборе), поэтому плавности по «transform» здесь больше нет: она
     дублировала движение и поднятая карта ехала дважды. Плавно меняются
     только тень и цвет обводки — то, чем карта показывает, что её
     выбрали. */
  transition: box-shadow 0.12s ease, outline-color 0.12s ease;
  /* Тень влево — каждая карта отчёркивается от соседки слева; вторая,
     короткая вниз, прижимает веер к столу. */
  box-shadow:
    -3px 0 7px rgba(0, 0, 0, 0.32),
    0 2px 5px rgba(0, 0, 0, 0.35);
}

/* ---------- Тесная рука: сколько видно от каждой карты ----------

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

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

   Раньше оформление это число угадывало: считало карты в руке
   лесенкой правил «:nth-last-child» и подставляло заранее прикинутую
   долю ширины карты. Угадывание держалось на трёх допущениях сразу —
   сколько карт влезает по ширине экрана, в один ряд лежит рука или
   в два, какой из двух рядов теснее, — и на каждое допущение
   приходилось отдельное исключение: для низкого окна была написана
   вторая такая же лесенка. Теперь угадывать нечего: игра меряет
   и говорит, а оформление считает от готового числа.

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

   Запасное значение — полная ширина карты. Оно срабатывает в тот
   короткий миг, пока веер ещё не разложен. */

.веер .карта {
  --полоска: min(var(--шаг-карт, var(--ш)), var(--ш));
}

/* В тесной руке угол карты переезжает вплотную к краю: там на счету
   каждая точка ширины. Ступенька спрятана внутрь clamp — большой
   множитель превращает плавный переход в переключатель: пока от карты
   видно меньше 22 точек, отступ равен одной точке, шире — обычным
   двум. Отдельного правила «если карт больше стольких-то» для этого
   больше не нужно. */
.веер .карта__угол {
  left: clamp(1px, (var(--полоска) - 22px) * 100, 2px);
}

/* ---------- Тесная рука: масть крупным знаком ----------

   ЖАЛОБА ЖИВОГО ИГРОКА. «Когда набрал полную руку (8–9 карт), карты
   сжались в узкие полоски — видно только цифру и крошечный значок
   масти, отличал только по цвету». А цвет — подпорка, а не решение:
   его завели для тех, кто не разбирает форму значка, и опираться
   на него одного игра не должна.

   ОТЧЕГО ТАК ВЫХОДИЛО. Крупная масть нарисована в правой половине
   карты. Пока карт мало, она видна и делает всю работу: масть узнаётся
   с полувзгляда. Стоит картам лечь внахлёст — соседка накрывает правую
   половину, крупный знак пропадает, и от карты остаётся левая полоска
   с одним уголком. А уголок меряется по ширине ВСЕЙ карты (0,34 её
   ширины), а не по ширине видимой полоски. Получалась нелепость:
   на телефоне 390 точек от карты видно 35 точек в ширину и 90 в высоту,
   из них под масть отдано 21 точка в самом верху, а вся остальная
   белизна — больше половины видимого места — стоит пустой.
   Хуже того, из-под соседки торчал обрезанный край крупного знака —
   чёрный клин непонятной формы, который только мешал.

   ЧТО ДЕЛАЕМ. Как только соседка закрывает больше 12 точек, крупная
   масть в середине всё равно наполовину срезана — её убираем совсем,
   а значок в углу вырастает во всю ширину видимой полоски и во всю
   высоту, что осталась под достоинством. На телефоне 390 точек это
   27–38 точек вместо прежних 21, на 320 — 21–31 вместо 17. Форму пики,
   трефы и бубны видно, не разглядывая, и масть больше не приходится
   угадывать по цвету. Достоинство не трогаем: цифру игрок читал
   и раньше, и место ей нужнее отдать масти.

   ДВА УСЛОВИЯ, А НЕ ОДНО. Просто «карты лежат внахлёст» тут мало.
   Когда рука ложится в два ряда, карты тоже внахлёст, но они вдвое
   ниже — под достоинством свободного места нет вовсе, зато вбок его
   хватает, и крупная масть там прекрасно видна (именно два ряда игрок
   и похвалил). Поэтому знак раздувается только там, где сошлось
   и то, и другое: карта высокая (выше своей ширины — так бывает
   только в один ряд) И закрыта больше чем на 12 точек. В два ряда,
   на столе, у колоды и у поднятой карты всё остаётся как было.

   КАК ЭТО ЗАПИСАНО. Тем же приёмом, что и ступенька выше: большой
   множитель превращает clamp в переключатель. Пока хоть одно из двух
   условий не выполнено, разность отрицательная и берётся первое
   значение — прежний размер; когда выполнены оба, разность
   положительная и берётся третье — крупный знак. Порог у двух правил
   разный на одну точку нарочно: в этот волосок между ними карта
   выглядит ровно как раньше, и ни при каком стечении чисел не бывает
   так, чтобы пропали оба знака сразу. */

.веер .карта__масть-угла {
  font-size: clamp(
    /* прежний размер — когда карту видно целиком или почти целиком */
    min(calc(var(--кегль) * 1.3), calc(var(--ш) * 0.34)),
    /* переключатель: высокая карта И закрыта больше чем на 12 точек */
    calc(min(var(--в) - var(--ш) - 8px, var(--ш) - var(--полоска) - 12px) * 100),
    /* крупный знак: по ширине видимой полоски, по остатку высоты
       под достоинством и не крупнее, чем имеет смысл на самой карте */
    min(calc((var(--полоска) - 5px) * 1.05),
        calc(var(--в) - var(--кегль) - 6px),
        calc(var(--ш) * 0.62))
  );
}

/* Крупная масть в середине: когда угол взял её работу на себя, она
   тут лишняя — от неё всё равно оставался обрезанный клин под соседней
   картой. Нулевой кегль и есть «не рисуем»: отдельного «скрыть» здесь
   не нужно, а размер и так уже считается формулой. */
.веер .карта__масть {
  font-size: clamp(
    0px,
    calc(max(var(--ш) - var(--в) + 8px, var(--полоска) - var(--ш) + 11px) * 100),
    calc(var(--ш) * 0.64)
  );
}

/* ---------- Светофор в руке: чем можно ходить, а чем нельзя ----------

   Живой игрок сказал главное: «все карты выглядят одинаково белыми
   и одинаково нажимаемыми, приходится в уме вычислять, что легально».
   Считать за него умеет сама игра, а здесь её знание становится видимым:

     карта--можно   этой сейчас ходят;
     карта--нельзя  этой сейчас не сходить;
     карта--выбрана по ней попал палец;
     карта--подхват её можно бросить вне очереди;
     карта--отказ   ответ на тап по запрещённой карте.

   Как выглядят «можно», «нельзя» и «выбрана» на новом столе — в разделе
   стола в конце файла. Здесь остались подхват и отказ: их вид не менялся. */

/* ---------- Карта, которую можно бросить вне очереди ----------

   Подхват заходной: на столе лежит, скажем, семёрка, и у вас семёрка —
   её можно бросить в любой миг подхода, не дожидаясь своего хода.
   Игра ставит на такую карту свой класс ВМЕСТО «можно»/«нельзя».

   Знак — пунктирная обводка цветом подсветки, и вот почему не другой.
   Зелёная черта снизу занята: она значит «сейчас твой ход» и должна
   значить только это — старый игрок, увидев её в чужой ход, решит,
   что игра сломалась. Серая вуаль сказала бы «нельзя». Сплошная
   обводка того же цвета — «выбрана». Остаётся пунктир того же цвета:
   он читается как «можно взять, но не обязательно». После тапа игра
   добавляет «выбрана», и пунктир становится сплошным — переход
   «можно → выбрано» виден сам, ничего объяснять не надо. Ради этого
   правило стоит ВЫШЕ правила «выбрана»: при равной силе побеждает
   записанное ниже, то есть сплошная рамка.

   Карту не приподнимаем: подъём на три точки — тоже язык «твой ход».
   В чужой ход она лежит в ряду со всеми, только обведена. В тесном
   веере от карты видна левая полоска, и обводка по левому краю
   и верхнему левому углу видна всегда. */
.веер .карта--подхват,
.карта--подхват {
  outline: 2px dashed var(--акцент);
  outline-offset: 1px;
  cursor: pointer;
}

/* Та же пунктирная обводка на заходной карте стола — но только пока
   в руке есть что бросить. Так видно, ЧТО именно можно бросать:
   пунктир в руке и пунктир на столе — одно достоинство, глаз связывает
   их без чтения. Метить заходную всегда не стали: стол и так пёстрый,
   а в свой ход метка ничего не говорит — это и есть «не перегружай».
   Обводка тоньше, чем в руке: подсказка к карте, а не второй призыв.
   Если заходная одновременно и цель защиты, сплошная рамка цели
   важнее — в селекторе исключение. */
#экран-игры:has(.карта--подхват) .пара--заходная:not(.пара--цель) .карта--атака {
  outline: 2px dashed var(--акцент);
  outline-offset: 1px;
}

/* Отказ: вздрагивание ловит взгляд движением, красный ободок объясняет
   смысл. Карту поднимаем над соседями — иначе вздрагивание уедет
   под соседнюю карту, и его не заметят. */
.веер .карта--отказ,
.карта--отказ {
  z-index: 60;
  animation: карта-вздрогнула 0.7s ease-in-out, карта-вспыхнула 0.7s ease-out;
}

/* Пока карта отказывает, серую вуаль подменяем красной: видно, что
   ответила именно та карта, по которой попал палец. */
.карта--отказ::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(224, 39, 60, 0.26);
  border-radius: inherit;
  pointer-events: none;
}

@keyframes карта-вздрогнула {
  0%   { transform: translate(0, 0)     rotate(0deg); }
  12%  { transform: translate(-5px, 0)  rotate(-3deg); }
  28%  { transform: translate(5px, 0)   rotate(3deg); }
  44%  { transform: translate(-4px, 0)  rotate(-2deg); }
  60%  { transform: translate(3px, 0)   rotate(1.5deg); }
  76%  { transform: translate(-2px, 0)  rotate(0deg); }
  100% { transform: translate(0, 0)     rotate(0deg); }
}

@keyframes карта-вспыхнула {
  0%   { box-shadow: 0 0 0 3px var(--карта-отказ), 0 0 10px 2px rgba(224, 39, 60, 0.85); }
  70%  { box-shadow: 0 0 0 3px var(--карта-отказ), 0 0 9px 2px rgba(224, 39, 60, 0.55); }
  100% { box-shadow: 0 0 0 3px rgba(224, 39, 60, 0); }
}

/* Если в телефоне выключены анимации, вздрагивание не показываем.
   Но без ответа игрока оставлять нельзя, поэтому вспышка остаётся. */
@media (prefers-reduced-motion: reduce) {
  .веер .карта--отказ,
  .карта--отказ {
    animation: карта-вспыхнула 0.7s ease-out;
  }
}

/* ---------- Подсказка ----------

   Строка внизу экрана, которой игра говорит, что случилось и что делать.
   Устроена она из двух частей, и это разделение — главное здесь:

     КОРОБКА (#подсказка) — место на экране. Высота у неё неподвижная,
        и коробка эту высоту держит, что бы игра ни написала;
     ТЕКСТ (вложенный «подсказка__текст») — сами слова. Вся раскраска —
        подложка, рамка, кружок-огонёк — рисуется на нём, поэтому плашка
        обтягивает слова, а не всю коробку.

   ПОЧЕМУ ТАК. Когда коробка облегала текст, одно событие дёргало стол
   дважды: длинное сообщение раздвигало коробку, через три секунды
   остывало и складывалось обратно — стол прыгал вверх и вниз
   (тестировщик описал это как «текст переписался сам»). Отсюда два
   правила, и они в силе:

   1. Коробка неподвижна — 44 точки. Это две строки текста (самая
      длинная фраза игры, 78 знаков, при этом кегле встаёт в две строки
      даже на 360) и немного воздуха; заодно это высота под палец —
      по строке нажимают, чтобы открыть «Что было».

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

   НОВЫЙ ВИД (стол по эталону владельца). На макете это тихая серая
   строка под строкой «Вы»: главное «кто что делает» говорит плашка
   статуса в строке «Вы», поэтому подсказке больше не нужна крупная
   цветная плашка. Ждём соперника — строка серая; ждут вас — белая,
   с салатовой точкой; свежая новость — белая, с коротким всплеском. */

#подсказка {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Именно height, а не min/max: коробка не должна ни расти, ни сжиматься */
  height: 44px;
  padding: 0 6px;
  font-size: clamp(13px, 3.6vw, 15px);
  font-weight: 500;
  line-height: 1.25;
  text-align: center;
  /* Ждём соперника — строка спокойная, приглушённая */
  color: var(--текст-тихий);
  /* Скругление нужно запасному пути (см. ниже): там плашка — сама коробка */
  border-radius: 10px;
  overflow: hidden;
}

/* Сами слова. Плашка рисуется здесь, поэтому она облегает текст:
   под коротким сообщением не остаётся пустого цветного прямоугольника
   в три строки высотой.

   Поля заданы всегда, даже когда плашки не видно. Так ширина, в которую
   ложатся слова, одна и та же во всех состояниях, и перенос слов не
   меняется от того, подсвечено сообщение или уже остыло.

   Два ограничения по краям — страховка: шире коробки плашка не станет
   (max-width), выше коробки не вырастет (max-height). Если игра когда-то
   покажет сообщение длиннее трёх строк, лишнее срежется снизу, как
   у книжной страницы, а не сверху и снизу разом, как было, когда
   текст стоял по центру жёсткой коробки. */
#подсказка .подсказка__текст {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  max-width: 100%;
  max-height: 100%;
  padding: 0 4px;
  border-radius: 10px;
  overflow: hidden;
}

/* Ждут вас: строка белеет, слева салатовая точка-огонёк.
   Селектор «#подсказка .класс» нарочно тяжёлый: цвет строки задан выше
   у «#подсказка», и правило из одного класса ему проиграло бы. */
#подсказка .подсказка--ваш-ход {
  color: var(--текст);
}

#подсказка .подсказка--ваш-ход::before {
  content: "";
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  margin-right: 7px;
  border-radius: 50%;
  background: var(--акцент);
  box-shadow: 0 0 6px color-mix(in srgb, var(--акцент) 60%, transparent);
}

/* Рассказ о том, что только что случилось («Соперник подкинул Д♦»).
   Висит три секунды: белым и с коротким всплеском при появлении — иначе
   игрок событие не замечает. Правило идёт после «вашего хода» и
   перебивает его: пока висит событие, важнее оно. Начертание нарочно
   не жирнее обычного — жирные буквы шире, и слова перекладывались бы
   на другое число строк, стоило событию остыть. */
#подсказка .подсказка--событие {
  color: var(--текст);
  animation: всплеск 0.3s ease-out;
}

/* На плашке события огонёк не нужен: там и так всё подсвечено.
   Но убираем его именно из вида, а не из строки: «visibility» прячет
   кружок, оставляя за ним место, и слова стоят там же, где будут стоять
   через три секунды, когда огонёк вернётся. Со старым «display: none»
   строка при остывании становилась на 16 точек у́же и текст переносился
   заново. */
#подсказка .подсказка--событие::before { visibility: hidden; }

@keyframes всплеск {
  from { transform: scale(0.92); opacity: 0.25; }
  to   { transform: scale(1);    opacity: 1; }
}

/* ---------- Подсказка: запасной путь для старых страниц ----------

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

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

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

#подсказка.подсказка--ваш-ход {
  color: var(--текст);
}

#подсказка.подсказка--ваш-ход::before {
  content: "";
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  margin-right: 7px;
  border-radius: 50%;
  background: var(--акцент);
}

#подсказка.подсказка--событие {
  color: var(--текст);
  animation: всплеск 0.3s ease-out;
}

/* Тот же случай, что и выше: огонёк прячем, место за ним оставляем,
   иначе при остывании слова перенесутся заново. */
#подсказка.подсказка--событие::before { visibility: hidden; }

/* Кнопки хода («Взять», «Бито», «Сказать») — в разделе стола в конце
   файла («Панель действий»). */

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

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

/* ---------- Кто ловит касания, когда показан итог ----------

   ПОЛОМКА, КОТОРУЮ ВИДЕЛ ВЛАДЕЛЕЦ: «кнопка назад не всегда работает».
   Пока партия шла — всё нажималось; кончилась — нижний ряд кнопок под
   доской переставал отвечать, хотя кнопки видны. Проверка спрашивала
   у страницы, что лежит в точке под пальцем, и отвечала: «экран-итога».
   То есть касание доставалось не кнопке, а самому слою итога.

   Сначала я снял касания только с вуали (она тянется от плашки вверх
   на весь экран) — этого не хватило: ловила сама секция.

   Теперь так, как и надо было:
     • слой итога касаний НЕ принимает вовсе — мимо плашки палец
       проходит насквозь, к кнопкам игры под ним;
     • сама плашка принимает — за это отвечает подложка «::after»
       ниже: она ровно по размеру плашки и лежит под её содержимым.
       Поэтому промах мимо кнопки, но в плашку, никуда не проваливается,
       как было раньше;
     • заголовок, подписи и кнопки внутри принимают тоже.

   Класс общий, значит починка разом действует на все игры сборника. */
.экран--поверх,
#экран-результата {
  pointer-events: none;
  inset: auto 0 0 0;           /* прижат к низу, высота — по содержимому */
  height: auto;
  /* Плашка обязана быть выше всего, что есть на игровом экране. Без этой
     строки приподнятая карта из руки (у неё своя высота слоя) вылезала
     поверх плашки и закрывала вопрос — видно на проверке плашки выхода. */
  z-index: 100;
  /* Строки текста — во всю ширину, а две кнопки встают рядом:
     плашка ниже, и из-под неё видно свою руку. */
  flex-flow: row wrap;
  align-items: center;
  justify-content: center;
  gap: 10px;
  /* Плашка прижата к низу, поэтому безопасное поле ей нужно только
     снизу: в полном экране Telegram под ней проходит полоса жеста,
     и без отступа нижняя кнопка оказывается прямо на ней. */
  padding: 18px calc(14px + var(--отступ-справа))
           calc(18px + var(--отступ-снизу)) calc(14px + var(--отступ-слева));
  text-align: center;
  background: var(--панель);
  border-top: 1px solid var(--край);
  border-radius: 18px 18px 0 0;
  box-shadow: 0 -12px 32px rgba(0, 0, 0, 0.45);
}

/* ---------- Вуаль над плашкой ----------

   Всё, что выше плашки, слегка притемнено — так видно, что игра
   остановлена, но стол по-прежнему можно рассмотреть.

   ПОЧИНКА, КОТОРУЮ ВИДЕЛ ВЛАДЕЛЕЦ: «кнопка назад не всегда работает».
   Вуаль тянется от плашки до верха экрана и раньше ловила нажатия.
   Пока партия шла, плашки не было и всё работало; кончилась — и нижний
   ряд кнопок под доской (в шашках это «В меню», «Звук», «Как играть»,
   «Рекорды») оказывался ПОД вуалью: кнопки видны сквозь неё, человек
   в них тычет, а касание достаётся вуали. Отсюда и «не всегда».

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

   Почему не наоборот — не «слой не ловит, содержимое ловит»: тогда
   перестала бы ловить и площадь самой плашки между кнопками, и тап
   мимо кнопки проходил бы на стол под ней вслепую. */
.экран--поверх.экран--виден::before,
#экран-результата.экран--виден::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: 100vh;
  background: rgba(0, 0, 0, 0.34);
  pointer-events: none;
}

/* ---------- Плашка итога приподнята над рядом кнопок ----------

   Последняя половина той же поломки. Собственная кнопка плашки
   («Другая игра», «Играть ещё») приходилась ровно на то место, где
   под доской стоят «В меню» и «Рекорды». Перекрытие тут честное —
   это настоящая видимая кнопка, и нажатия она ловит по праву;
   касаниями такое не лечится, только раскладкой. Прятать «В меню»
   нельзя: без неё человек заперт на экране итога — это уже проверено
   и получено красным.

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

   Раз плашка больше не касается краёв — у неё скруглены все углы
   и появились поля по бокам: теперь это карточка, лежащая поверх
   стола, а не полка, приклеенная к низу экрана.

   Правило нарочно только для плашек ИТОГА, а не для всего, что
   «поверх»: тем же общим классом пользуются лента новостей и панель
   знаков у карт, и их поднимать нельзя — у панели знаков «Закрыть»
   рассчитана ровно на то, что панель прижата к низу. */
#экран-результата.экран--поверх,
#экран-результата,
#экран-итога.экран--поверх {
  inset: auto 8px calc(62px + var(--отступ-снизу)) 8px;
  padding-bottom: 18px;
  border: 1px solid var(--край);
  border-radius: 18px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.45);
}

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

/* Подложка плашки: невидимая, ровно по её размеру, лежит под всем
   содержимым. Она и возвращает плашке способность ловить касания —
   включая просветы между кнопками. Без неё промах на пару точек мимо
   кнопки уходил бы вслепую на стол под плашкой. */
.экран--поверх::after,
#экран-результата::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: auto;
}

/* Всё, что лежит в плашке — заголовок, подписи, кнопки, — касания
   принимает. Правило одно на всех детей: перечислять кнопки поимённо
   значило бы забыть новую, как только её добавят. */
.экран--поверх > *,
#экран-результата > * {
  pointer-events: auto;
}

#экран-результата .заголовок { font-size: 27px; }

/* Серия побед — главная цифра итога. Ставим её сразу под заголовок
   (порядком, а не в разметке — см. раздел о порядке ниже) и обводим
   рамкой цвета подсветки: взгляд попадает на неё первой. Текст обычного
   цвета — так он читается в любой теме, а рамка делает всю работу
   по вниманию. */
.серия {
  margin: 0;
  padding: 5px 14px;
  font-size: 18px;
  font-weight: 800;
  line-height: 1.25;
  color: var(--текст);
  background: var(--подложка);
  border: 2px solid var(--акцент);
  border-radius: 12px;
}

/* ---------- Порядок строк и кнопок на плашке итога ----------

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

   Здесь была настоящая беда, и вот в чём она. Порядок раньше стоял
   только у тех, кого переставляли: у объяснения и у кнопок. А любой,
   кому порядок не задан, считается нулевым — то есть встаёт ВПЕРЕДИ
   всех, кому задали первый и второй. Про ответ сервера на «Собрать
   стол заново» просто забыли, и он уезжал наверх: в разметке он стоит
   под своей кнопкой, а на экране вклинивался между заголовком
   и объяснением. Выходило так:

       Вы выиграли!
       Вы вышли из этой партии — чтобы играть дальше, начните новую
       Дурак — Константин: карты остались у него…

   Первые две строки спорят друг с другом, и к какой из двух кнопок
   относится ответ — угадать нельзя. А ответ приходит на каждый отказ
   сервера: «Стол собирает тот, кто создал комнату», «Связь пропала».

   Чиним не одну строку, а саму причину. Порядок теперь расписан
   поимённо для КАЖДОГО, кто есть на плашке, а сверху лежит запасное
   правило: всё, про что забудут дальше, встаёт в конец. Уехать в конец
   не страшно — заметят и поправят. Уехать наверх и разорвать заголовок
   с объяснением — беда, которую видит живой игрок.

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

/* Запасной путь: элемент, про который забыли, встаёт последним, а не первым */
#экран-результата > * { order: 90; }

#экран-результата > .заголовок           { order: 10; }  /* «Вы выиграли!»   */
#экран-результата > .серия               { order: 20; }  /* побед подряд     */
#экран-результата > #пояснение-результата { order: 30; }  /* чем кончилось    */
#экран-результата > #кнопка-ещё          { order: 40; }  /* «Играть ещё»     */
#экран-результата > #кнопка-пересобрать  { order: 50; }  /* «Собрать заново» */
/* «Рекорды» приехали на итог позже остальных и порядка не получили,
   а без порядка кнопка встаёт последней — то есть ПОД «В меню». Уход
   обязан быть последним всегда: это край плашки, дальше ничего нет.
   Ставим рекорды перед ним. */
#экран-результата > #кнопка-рекорды-итог { order: 65; }  /* посмотреть серии */
#экран-результата > #кнопка-в-меню-итог  { order: 70; }  /* уход             */

/* Три строки, которые появились на плашке позже и без порядка уехали бы
   в самый конец — под «В меню». Серия дней — сразу за серией побед:
   это два достижения рядом. Итог раздачи дня и сравнение с остальными —
   сразу за объяснением «чем кончилось»: они про ту же партию. */
#экран-результата > #серия-дней-итога    { order: 25; }  /* «День 4 подряд!» */
#экран-результата > #итог-дня            { order: 32; }  /* «Раздача дня: …» */
#экран-результата > #сравнение-дня       { order: 34; }  /* «…выиграли N из M» */
/* «+2 к рейтингу» (или отказ сервера про дневной лимит на ботов) — тоже
   про итог этой партии, а не про следующий шаг. Без своего порядка строка
   попадала под запасное правило и уезжала в конец, под все три кнопки —
   человек видел её последней и не понимал, к чему она относится. Ставим
   сразу за сравнением дня и перед первой кнопкой. */
#экран-результата > #итог-рейтинга       { order: 36; }  /* «+2 к рейтингу» */

/* ---------- Звёздочка у «Рекордов» ----------

   На плашке итога «Рекорды» встали вплотную к «В меню», и обе — мелкие
   тихие кнопки с тонкой серой каймой. Различались они только надписью
   в 13 точек, а цена ошибки разная: одна показывает таблицу и её можно
   закрыть, вторая бросает партию и уводит из игры. Ровно тот же разговор,
   что был про «Собрать стол заново» и «В меню» ниже.

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

   Ту же звёздочку получает и «Рекорды» на экране игры с ботом: одна
   и та же кнопка должна выглядеть одинаково, где бы её ни встретили. */
#кнопка-рекорды,
#кнопка-рекорды-итог {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
}

#кнопка-рекорды::before,
#кнопка-рекорды-итог::before {
  content: "★";
  font-size: 1.05em;
  line-height: 1;
  color: var(--акцент);
  color: color-mix(in srgb, var(--акцент) 60%, var(--текст));
}

/* ---------- Ответ сервера под кнопкой «Собрать стол заново» ----------

   Место. Ответ встаёт сразу под своей кнопкой — там же, где стоит
   в разметке (порядок 60, между пересбором и «В меню»). Он широкий,
   поэтому «В меню» само уходит на следующую строку, и между кнопкой
   и её ответом уже ничего не вклинивается.

   Вид. Сюда игра пишет только отказы: «Комната уже закрыта», «Связь
   с сервером пропала — попробуйте нажать ещё раз», «Так сейчас нельзя».
   Раньше эта строка выглядела в точности как объяснение итога — тот же
   кегль, тот же тихий цвет, — и два разных сообщения сливались в один
   абзац. Теперь у неё тот же вид, каким игра отвечает в прихожей:
   серая плашка с полоской цвета подсветки слева (см. «.сеть-сообщение»).
   Одинаковый вид в двух местах — это уже язык игры: полоска слева
   значит «так ответил сервер», а не «так кончилась партия».

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

   Сверху прижимаем плотнее, чем снизу (6 точек против 10): так с одного
   взгляда видно, что ответ относится к кнопке НАД ним, а не к «В меню»
   под ним.

   Про ширину. Ниже стоит общее правило «строки итога — во всю ширину»,
   и оно ЭТУ строку не тронет: у правила ниже вес меньше (класс против
   идентификатора), а не «оно позже, значит сильнее». Кегль, наоборот,
   нарочно не задаём — пусть остаётся общий, включая уменьшенный
   в низком окне. */
#экран-результата > #сообщение-пересбора {
  order: 60;
  width: min(100%, 330px);
  margin-top: -4px;
  padding: 9px 12px;
  line-height: 1.4;
  text-align: left;
  overflow-wrap: anywhere;
  color: var(--текст);
  background: var(--подложка);
  border-left: 4px solid var(--акцент);
  border-radius: 4px 10px 10px 4px;
}

#экран-результата > .заголовок,
#экран-результата > .подпись,
#экран-результата > .серия { width: 100%; }

/* Серия дней на плашке — плашка-таблетка по ширине слов, как на витрине,
   а не строка во всю ширину: правило выше её растянуло бы. */
#экран-результата > .серия-дней {
  width: auto;
  align-self: center;
}

/* «Раздача дня: победа за 14 ходов» — это итог соревнования, а не ещё одно
   объяснение, поэтому не тихая подпись, а обычный цвет текста и вес 600.
   Сравнение с остальными («выиграли N из M») остаётся тихим — это
   уточнение к итогу. Обе строки прижаты друг к другу и к объяснению
   отрицательным полем: они про одно и то же. */
#экран-результата > #итог-дня {
  margin-top: -4px;
  font-weight: 600;
  color: var(--текст);
}

#экран-результата > #сравнение-дня {
  margin-top: -6px;
  font-size: 13px;
  line-height: 1.35;
  /* На 320 точках строка переносится; без баланса выходило
     «…вы на 3-м» и одинокое «месте» — место отрывалось от числа. */
  text-wrap: balance;
}

/* «+2 к рейтингу» — хорошая новость, и должна читаться как хорошая
   новость: не тихая серая подпись, а жирный текст цвета подсветки.
   Тот же текст иногда приходит от сервера как отказ («На сегодня очки
   за ботов кончились…») — своего класса под этот случай нет, а
   выдумывать вид под два разных сообщения не задача оформителя. Цвет
   подмешанный (60% подсветки к обычному тексту), а не чистый — та же
   мера, что у значков на этой плашке (звёздочка «Рекордов», стрелка
   «Собрать заново»): чистый акцент на тёмной панели даёт контраст ниже
   нормы. Первая строка — запасной путь для браузеров без color-mix. */
#экран-результата > #итог-рейтинга {
  margin-top: -4px;
  font-weight: 700;
  color: var(--акцент);
  color: color-mix(in srgb, var(--акцент) 60%, var(--текст));
}

/* Сравнение приходит с задержкой — после ответа сервера. Если до ответа
   строки нет вовсе, плашка при её появлении подпрыгивает вместе
   с кнопками, и палец, уже занесённый над «Играть ещё», попадает
   в другое. Поэтому пока итог раздачи дня на плашке, а сравнения ещё
   нет, место под него держится заранее: строка есть, но невидима.
   Две строки, а не одна: «Сегодня эту раздачу выиграли 7 из 12, вы
   на 3-м месте» на 320 точках переносится, и резерв в одну строку
   всё равно давал бы прыжок. В обычной партии (без итога дня) строки
   нет и места она не занимает. Правило сильнее общего «скрыт»
   и потому с !important — иначе его не перебить. */
#экран-результата:has(#итог-дня:not(.скрыт)) > #сравнение-дня.скрыт {
  display: block !important;
  visibility: hidden;
  min-height: calc(2 * 1.35em);
}

/* ---------- Две мелкие кнопки под итогом: пересбор и уход ----------

   У хозяина сетевого стола под итогом стоят рядом «Собрать стол заново»
   и «В меню». Пришли они с одним и тем же видом — тот же серый фон,
   та же тонкая рамка, тот же кегль, — и различались только шириной
   и местом. На узком телефоне обе встают в одну строку, и вот тут
   их путают. Цена ошибки при этом разная: первая собирает стол заново
   с тем же кодом, вторая уводит из партии, и обратно человек попадёт
   только по коду, который придётся заново спрашивать у друзей.

   Разводим их по смыслу, а не по ширине. За столом три вещи, и они
   разного веса:
     «Ещё партию»          — главное действие, залито целиком;
     «Собрать стол заново» — тоже действие с игрой, но второе по счёту:
                             рамка цветом подсветки, обычный цвет текста
                             и круговая стрелка впереди. Ровно так же
                             в прихожей выглядят «Посадить бота»
                             и «Убрать бота» — это уже язык игры;
     «В меню»              — не действие, а уход: тише всех, без заливки
                             вовсе, тонкая серая рамка и тихий текст.

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

#кнопка-пересобрать {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  /* 44 точки — та высота, в которую палец попадает не целясь.
     У «В меню» их по-прежнему 40: промахнуться мимо ухода не жалко. */
  min-height: 44px;
  padding: 9px 14px;
  font-size: 14px;
  font-weight: 700;
  color: var(--текст);
  background: var(--подложка);
  border: 2px solid var(--акцент);
  box-shadow: none;
}

/* Круговая стрелка — единственный значок на этой плашке, и он говорит
   «то же самое, только сначала». Рисуем знаком, а не картинкой: стрелки
   есть в системных шрифтах всех телефонов (они распространены шире, чем
   масти, которыми игра пользуется с первого дня).
   Цвет — тот же смешанный, что у номеров правил: чистый цвет подсветки
   на этой плашке даёт контраст ниже нормы, а подмешанный к нему цвет
   текста вытягивает его в любой теме. Первая строка — для браузеров
   без color-mix. */
#кнопка-пересобрать::before {
  content: "↻";
  font-size: 17px;
  line-height: 1;
  color: var(--акцент);
  color: color-mix(in srgb, var(--акцент) 60%, var(--текст));
}

/* Уход — самое тихое, что есть на плашке: заливку убираем совсем,
   остаётся только тонкий контур. Рядом с рамкой цвета подсветки
   эта кнопка честно читается как «выйти отсюда», а не как действие. */
#экран-результата #кнопка-в-меню-итог {
  background: transparent;
}

/* Оговорка к правилу ниже. Когда реванша нет, игра прячет «Ещё партию»,
   и правило ниже поднимает оставшиеся мелкие кнопки до полноценных —
   затем, чтобы единственный выход не выглядел выключенным. Но у хозяина
   сетевого стола рядом стоит ещё и «Собрать стол заново», и тогда обе
   кнопки снова становились одинаковыми — как раз в том случае, где
   спутать их дороже всего: партия кончилась насовсем, и человек выбирает
   между «собрать стол заново» и «уйти из партии».

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

   Оба условия написаны в одном селекторе нарочно: в обычном итоге,
   где «Ещё партию» на месте, это правило молчит, и «В меню» живёт
   по общим правилам мелкой кнопки — включая её размеры на узком
   телефоне, которые заданы отдельно, в самом низу файла. */
#экран-результата:has(#кнопка-ещё.скрыт):has(#кнопка-пересобрать:not(.скрыт))
  #кнопка-в-меню-итог {
  min-height: 44px;     /* палец тот же, что и у главной кнопки */
  min-width: 0;
  padding: 8px 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--текст-тихий);
  background: transparent;
  border: 1px solid var(--край);
}

/* Итог без реванша — «В меню» остаётся единственным выходом.
   Так кончаются сетевые партии: друг вышел, связь пропала совсем,
   комната закрылась. Кнопку «Ещё партию» игра в этих случаях прячет,
   и внизу плашки оставалась одна мелкая тусклая кнопка в 40 точек —
   ровно та, которую по всей игре нарочно делают незаметной, чтобы
   на неё не нажимали случайно. Получалось наоборот: единственное
   действие на экране выглядело как «сюда не надо».

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

   Как игра сообщает, что реванша не будет: вешает на кнопку
   «Ещё партию» класс «скрыт». Пока кнопка видна, правило молчит
   и плашка выглядит как раньше. Старый браузер без «:has» просто
   покажет прежнюю мелкую кнопку — выход останется на месте.

   Из-под этого правила выведены две кнопки. «В меню» рядом с видимым
   пересбором (см. оговорку выше): уход не должен вырастать до размера
   действия только потому, что действие рядом изменилось. И «Рекорды»:
   они на этой плашке — не выход из тупика, а «посмотреть, что было
   раньше». Выросши до размера действия, они спорили бы за внимание
   ровно с тем единственным выходом, ради которого правило и написано. */
#экран-результата:has(#кнопка-ещё.скрыт)
  .кнопка.кнопка--мелкая:not(#кнопка-рекорды-итог) {
  min-height: 46px;
  min-width: 160px;
  padding: 10px 20px;
  font-size: 16px;
  font-weight: 700;
  color: var(--текст);
  background: var(--подложка);
  border: 2px solid var(--акцент);
}

/* Пока висит плашка итога, игровой экран остаётся на месте и не
   реагирует на нажатия. Строка нужна до тех пор, пока игра прячет
   игровой экран сама; когда перестанет — она просто ничего не изменит.
   Стол не приподнимаем: плашка итога закрывает только руку и кнопки,
   и стол над ней виден целиком. Поле снизу — прежнее, с полосой жеста. */
#приложение:has(#экран-результата.экран--виден) #экран-игры {
  display: flex;
  pointer-events: none;
  padding-bottom: calc(8px + var(--отступ-снизу));
}

/* Кнопки хода на итоге не нужны: «Бито» и «Беру» уже спрятаны, а «В меню»
   есть на самой плашке. Место за собой оставляют, чтобы стол не прыгал. */
#приложение:has(#экран-результата.экран--виден) #панель-кнопок {
  visibility: hidden;
}

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

   Главной сделана та кнопка, которая оставляет игрока в партии:
   она во всю ширину, залита цветом и стоит первой. «Выйти в меню» —
   мелкая и ниже: уйти можно, но для этого надо прицелиться. */

#экран-выхода .заголовок { font-size: 24px; }

#экран-выхода > .заголовок,
#экран-выхода > .подпись,
#экран-выхода > .кнопка {
  width: 100%;
}

#экран-выхода .кнопка--главная {
  max-width: 300px;
}

/* «Выйти в меню» не растягиваем во всю строку, но и не делаем крохотной:
   140 точек ширины и 40 высоты — палец попадает спокойно. */
#экран-выхода .кнопка--мелкая {
  width: auto;
  min-width: 140px;
}

/* ================================================================
   ПЛАШКА «ЧТО БЫЛО» — последние новости стола

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

   Плашка собрана на чужих классах: «таблица» одолжила прокрутку,
   «таблица__строка» — саму строку. Но таблица рекордов — список
   достижений, у неё три привычки, которые здесь прямо вредят:

     1) текст в строке обрезается многоточием. В рекордах обрезать
        нечего (там короткое «12 побед подряд»), а тут в строке живая
        фраза, и на 390 точках от неё оставалось «У вас младший
        козырь 2♦ — вы ход…» — то есть пропадало главное;
     2) первая строка обведена как чемпион. Здесь первая — самая
        СТАРАЯ новость, и золотая рамка звала взгляд ровно не туда;
     3) текст стоит по центру. Восемь центрированных строк разной
        длины читать сверху вниз тяжело: глаз каждый раз ищет,
        откуда начинается фраза.

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

/* Сама плашка. Лежит поверх стола, поэтому вид ей задаёт общий
   «экран--поверх»; здесь только раскладка столбиком и потолок высоты.

   Потолок нужен вот зачем: плашка открывается ПОСРЕДИ ПАРТИИ, соперники
   в это время ходят и список пополняется на глазах. Если дать плашке
   вырасти во весь экран, она станет стеной, и человеку покажется, что
   игра встала. 86% — это полоска стола, которая всегда остаётся видна
   сверху: на высоком телефоне из-под плашки видно соперников и колоду,
   а в шторке высотой 420 точек — хотя бы верхний ряд соперников. */
#экран-ленты {
  flex-flow: column nowrap;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  max-height: 86%;
  /* Плашка прижата к низу, поэтому безопасное поле нужно только снизу. */
  padding: 12px calc(10px + var(--отступ-справа))
           calc(12px + var(--отступ-снизу)) calc(10px + var(--отступ-слева));
}

/* Заголовок здесь служебный: человек и так знает, что открыл. Крупные
   34 точки отбирали у списка две строки новостей — отдаём их списку. */
#экран-ленты .заголовок {
  flex: none;
  font-size: 23px;
}

#кнопка-лента-назад {
  flex: none;
  width: min(100%, var(--колонка-кнопок));
}

/* ---------- Список ----------
   Ширину и прокрутку даёт «таблица». Здесь — подсказка о том, что
   список прокручивается: у верхнего края лежит тень, а к первой строке
   приклеена «крышка» цвета плашки. Пока список прокручен вниз, тень
   видна и говорит «выше есть ещё»; вернулись наверх — крышка наехала
   на тень, и та пропала. Тот же приём, что в прихожей, только зеркальный:
   там прятались новые строки внизу, а тут вниз смотреть не нужно —
   самая свежая новость и так приклеена к нижнему краю (см. ниже). */
#лента-событий {
  gap: 5px;
  padding-right: 2px;      /* полоска прокрутки не наезжает на текст */
  background:
    linear-gradient(var(--панель), transparent) top / 100% 12px local no-repeat,
    radial-gradient(farthest-side at 50% 0, rgba(0, 0, 0, 0.40), transparent)
      top / 100% 8px scroll no-repeat;
}

/* ---------- Строка новости ----------
   Две колонки: слева порядковый номер, справа сама новость. Номер
   тихий и узкий — он лишь помогает не потерять место в списке;
   главное в строке — фраза, поэтому она читается слева направо
   обычным текстом и переносится на вторую строку, а не обрезается. */
#лента-событий .таблица__строка {
  grid-template-columns: 1.7em minmax(0, 1fr);
  align-items: start;
  gap: 2px 8px;
  padding: 7px 10px 8px;
  text-align: left;
  background: rgba(128, 128, 128, 0.14);
  border-radius: 10px;
  /* Отменяем «чемпионскую» обводку первой строки: старая новость
     ничем не заслужила золотую рамку. */
  box-shadow: none;
}

#лента-событий .таблица__место {
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.6;                      /* цифра на одной линии с текстом */
  color: var(--текст-тихий);
  font-variant-numeric: tabular-nums;    /* цифры одной ширины — столбик ровный */
}

#лента-событий .таблица__очки {
  font-size: 15px;
  font-weight: 600;
  line-height: 1.35;
  text-align: left;
  /* Главная починка: длинную новость переносим, а не режем многоточием */
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
}

/* ---------- Что случилось давно ----------
   Четвёртая с конца новость и дальше — это уже «было когда-то»:
   заливка бледнее, текст тише и легче. Совсем гасить его нельзя —
   человек пришёл сюда именно читать, — поэтому берём тот же
   приглушённый цвет, что у подписей: он тише основного, но контраст
   с фоном держит с запасом. */
#лента-событий .таблица__строка:nth-last-child(n+4) {
  background: rgba(128, 128, 128, 0.08);
}

#лента-событий .таблица__строка:nth-last-child(n+4) .таблица__очки {
  /* Кегль на точку мельче, чем у недавних, и на две — чем у свежей.
     Получается лесенка 14 — 15 — 16: список будто уходит вдаль, и
     возраст новости виден раньше, чем человек прочтёт её номер.
     Гасить старое прозрачностью нельзя: в светлой теме Telegram
     бледный текст на бледной плашке перестаёт читаться, — поэтому
     возраст показан размером и весом букв, а не яркостью. */
  font-size: 14px;
  font-weight: 500;
  color: var(--текст-тихий);
}

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

     1) полоса цвета подсветки слева;
     2) заливка с примесью того же цвета — строка теплее соседних;
     3) текст крупнее и жирнее остальных;
     4) метка «только что» словами — самая честная из четырёх.

   И главное: строка ПРИЛИПАЕТ к нижнему краю списка. Новости идут
   сверху вниз по времени, свежая — последняя, и в низком окне она
   оказывалась за нижним краем: человек открывал плашку и видел то,
   что было восемь ходов назад, а самое важное приходилось искать
   прокруткой. Теперь она всегда на виду, а старые новости проезжают
   под ней. Пока список помещается целиком, прилипание ничего не
   меняет — строка и так стоит на своём месте. */
#лента-событий .таблица__строка--свежая {
  position: sticky;
  bottom: 0;
  z-index: 2;
  padding-left: 6px;                 /* минус ширина полосы — текст в колонку */
  border-left: 4px solid var(--акцент);
  /* Заливка обязана быть НЕПРОЗРАЧНОЙ: под приклеенной строкой проезжают
     соседние, и сквозь полупрозрачную было бы видно чужие буквы.
     Первая строка — запасная для браузеров старше 2023 года. */
  background: var(--панель);
  background: color-mix(in srgb, var(--акцент) 18%, var(--панель));
  box-shadow: 0 -6px 12px rgba(0, 0, 0, 0.28);
}

#лента-событий .таблица__строка--свежая .таблица__место {
  color: var(--текст);
}

#лента-событий .таблица__строка--свежая .таблица__очки {
  font-size: 16px;
  font-weight: 800;
  color: var(--текст);
}

/* Метка «только что». Встаёт под текстом отдельной строчкой, а не сбоку:
   сбоку она отняла бы у новости треть ширины, а на 280 точках это
   три-четыре слова. Рисуется оформлением, потому что это не новость,
   а пометка о её свежести. */
#лента-событий .таблица__строка--свежая::after {
  content: "только что";
  grid-column: 2;
  justify-self: start;
  margin-top: 3px;
  padding: 1px 8px 2px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.3px;
  color: var(--кнопка-текст);
  background: var(--акцент);
  border-radius: 999px;
}

/* Пока новостей нет вовсе. Общая плашка «пусто» подходит, ей нужен
   только левый край текста как у строк — по центру короткая фраза
   в широком окне выглядит потерянной. */
#лента-событий .таблица__пусто {
  text-align: left;
}

/* ---------- Экран рекордов ----------
   Список самых длинных серий побед. Десять строк должны помещаться
   целиком на обычном телефоне; на маленьком экране список прокручивается,
   а заголовок и кнопка «Назад» остаются на месте. */

#экран-рекордов {
  align-items: center;
  gap: 10px;
  padding: calc(14px + var(--отступ-сверху)) calc(10px + var(--отступ-справа))
           calc(10px + var(--отступ-снизу))  calc(10px + var(--отступ-слева));
}

#экран-рекордов .заголовок { font-size: 28px; }

#лучший-рекорд {
  font-size: 15px;
  font-weight: 600;
  color: var(--текст-тихий);
  text-align: center;
}

.таблица {
  flex: 0 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: min(100%, 420px);
}

/* Строка: место, серия, дата, уровень — в одну линию */
.таблица__строка {
  display: grid;
  grid-template-columns: 1.9em minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 0 10px;
  padding: 7px 10px;
  background: var(--подложка);
  border-radius: 10px;
}

.таблица__место {
  font-size: 14px;
  font-weight: 700;
  color: var(--текст-тихий);
}

.таблица__очки {
  font-size: 15px;
  font-weight: 700;
  color: var(--текст);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.таблица__дата,
.таблица__сложность {
  font-size: 12px;
  color: var(--текст-тихий);
  white-space: nowrap;
}

/* ---------- Строка рекорда: число побед — на своей строке ----------

   Пока подпись была короткой («сложный»), все четыре ячейки стояли
   в одну линию и всё помещалось. Потом к уровню добавился стол
   («сложный · вшестером» — 19 знаков вместо 7), и линия перестала
   влезать. Отъедала место при этом не подпись: она стоит с шириной
   по содержимому и не сжимается, поэтому ужималась соседняя колонка —
   и обрезалось главное. На 390 точках человек видел «12 побед под…»,
   на 280 — «12 по…», то есть ровно то число, ради которого он таблицу
   и открыл.

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

   Все правила нарочно привязаны к #таблица-рекордов: те же классы
   одолжил себе список мест в прихожей (js/сеть.js), а там строки
   короткие и должны остаться в одну линию. */
#таблица-рекордов .таблица__строка {
  /* Место | дата | подпись стола. Число побед ляжет поверх двух
     последних колонок — во всю ширину строки. */
  grid-template-columns: 1.9em auto minmax(0, 1fr);
  /* Просвет между колонками тесный нарочно: дату и подпись стола
     разделяет ещё и точка, а лишние точки ширины на узком телефоне
     дороже — из них складывается буква, которая не уехала на перенос. */
  gap: 1px 6px;
  padding: 6px 10px 7px;
}

#таблица-рекордов .таблица__место {
  grid-area: 1 / 1 / 3 / 2;   /* номер — слева, по центру обеих строчек */
  align-self: center;
  font-variant-numeric: tabular-nums;   /* цифры одной ширины: столбик ровный */
}

#таблица-рекордов .таблица__очки {
  grid-area: 1 / 2 / 2 / 4;
  font-size: 16px;            /* главное в строке — и кегль у него самый крупный */
  line-height: 1.25;
  /* Многоточие здесь запрещено. Места теперь хватает с запасом, но если
     у человека в системе стоит крупный шрифт, пусть строка лучше
     перенесётся на вторую, чем от числа побед останется «12 по…». */
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
}

#таблица-рекордов .таблица__дата {
  grid-area: 2 / 2 / 3 / 3;
  font-variant-numeric: tabular-nums;
}

#таблица-рекордов .таблица__сложность {
  grid-area: 2 / 3 / 3 / 4;
  justify-self: start;
  white-space: normal;        /* длинной подписи разрешено перенестись */
  line-height: 1.25;
}

/* Точка между датой и подписью. Рисуем её оформлением, а не текстом:
   у старых записей подпись пустая, и тогда точка не появляется вовсе. */
#таблица-рекордов .таблица__сложность:not(:empty)::before {
  content: "· ";
  opacity: 0.7;
}

/* Первое место чуть заметнее остальных */
.таблица__строка:first-child {
  box-shadow: inset 0 0 0 2px var(--акцент);
}

.таблица__пусто {
  margin: 0;
  padding: 14px 12px;
  font-size: 14px;
  line-height: 1.4;
  text-align: center;
  color: var(--текст-тихий);
  background: var(--подложка);
  border-radius: 12px;
}

#кнопка-рекорды-назад {
  margin-top: auto;      /* прижата к низу — большой палец достаёт */
  width: min(100%, var(--колонка-кнопок));
}

/* ================================================================
   Экран «Как я играю» — личный счёт игрока

   Читается он сверху вниз и ровно один раз: крупное число — доля
   побед, под ним строка словами, и только потом подробности.
   Из этого выведено всё остальное.

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

#экран-рейтинга {
  align-items: center;
  gap: 8px;
  padding: calc(14px + var(--отступ-сверху)) calc(10px + var(--отступ-справа))
           calc(10px + var(--отступ-снизу))  calc(10px + var(--отступ-слева));
}

#экран-рейтинга .заголовок { font-size: 26px; }

/* ---------- Крупное число ----------

   Ради него сюда и заходят: «Побед 53%». Рамку даёт общий класс
   «серия» (та же, что у главного числа на плашке итога), здесь только
   размер и поведение длинной строки.

   Размер задан вилкой, а не числом: в этом же месте бывает не число,
   а фраза — «Пока ни одной партии», «Счёт не прочитался», «Минутку…».
   На узком телефоне такая фраза набором в 34 точки заняла бы три
   строки высотой в треть экрана, поэтому кегль сам съезжает к 26.
   Перенос по словам разрешён и уравновешен (text-wrap: balance):
   фраза ложится двумя ровными строчками, а не «длинная плюс одно
   слово-сирота».

   Цифры одной ширины (tabular-nums) — чтобы число не дёргалось,
   когда счёт меняется с 9% на 53%. */
#рейтинг-главное {
  max-width: min(100%, 340px);
  padding: 7px 18px 8px;
  font-size: clamp(26px, 8.4vw, 34px);
  line-height: 1.12;
  text-align: center;
  text-wrap: balance;
  font-variant-numeric: tabular-nums;
}

/* ---------- Строка словами ----------

   «105 из 200 партий · сейчас 2 подряд · лучшая серия 7». Она
   объясняет крупное число, поэтому стоит вплотную под ним и заметно
   тише его.

   Кегль 13,5, а не обычные 15, — ради того, чтобы строка помещалась
   в один ряд. При 14 точках она рвалась пополам, и разрыв приходился
   на середину куска: «105 из 200 партий · сейчас» и ниже «2 подряд ·
   лучшая серия 7». Прочесть такое можно, но спотыкаешься: части
   разделены точками, а перенос делит их не по точкам. */
#рейтинг-подпись {
  max-width: min(100%, 360px);
  margin-top: -2px;
  font-size: 13.5px;
  line-height: 1.4;
  text-align: center;
  text-wrap: balance;
  font-variant-numeric: tabular-nums;
}

/* ---------- Строка сравнения «а как в последнее время» ----------

   Под крупным числом — две отметки: доля побед за последние партии
   (двадцать и пятьдесят; в подписи игра пишет, сколько учтено на самом
   деле). Разметку кладёт js/game.js («нарисоватьДинамику») в блок
   #рейтинг-динамика: плитка «рейтинг__окно» с подписью и числом,
   пометка «--лучше» или «--хуже», если разница с общим счётом заметна.

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

   Отметок ровно две и они мелкие: это уточнение к главному числу,
   а не второе главное число. Кегль числа 15 против 34 у главного —
   разница больше чем вдвое, спутать их нельзя.

   Пустой блок прячем совсем (:empty). Игра опустошает его, когда
   сравнивать нечего — у новичка без партий или когда в журнале не
   больше партий, чем в счёте целиком, — и без этого правила посреди
   экрана висела бы полоса воздуха ни за чем: ровно то, отчего экран
   выглядит недогруженным. Общий класс «скрыт» тоже сработает, если
   игра когда-нибудь повесит его вместо опустошения: :empty перестаёт
   срабатывать от одного пробела внутри, и запасной путь не лишний.

   Отметки заворачиваются на вторую строчку (flex-wrap), если не влезли:
   на 320 точках «последние 20» и «последние 50» рядом уже тесно, а рвать
   надпись переносом внутри плитки нельзя — число оторвётся от подписи. */
#рейтинг-динамика {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  max-width: min(100%, 360px);
  margin-top: 2px;
}

#рейтинг-динамика:empty { display: none; }

/* Одна отметка: подпись словами и число рядом, в тихой плашке —
   такой же, как у доли побед в строке таблицы. Так глаз сразу видит,
   что это родня: «название и его отметка». */
.рейтинг__окно {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 4px 11px 5px;
  background: var(--подложка);
  border-radius: 999px;
  white-space: nowrap;
}

.рейтинг__окно-подпись {
  font-size: 12px;
  color: var(--текст-тихий);
}

/* Цифры одной ширины: доля за последние партии скачет чаще всех
   остальных чисел на экране, и плитка не должна от этого дёргаться. */
.рейтинг__окно-число {
  font-size: 15px;
  font-weight: 700;
  color: var(--текст);
  font-variant-numeric: tabular-nums;
}

/* Стало лучше или хуже — показываем стрелкой, а не цветом.
   Цвет здесь не годится по двум причинам сразу: зелёное и красное
   должны читаться в обеих темах Telegram (а тема бывает какая угодно),
   и каждый двенадцатый мужчина эти два цвета путает. Стрелка понятна
   всем и в любой теме. Плитке «стало лучше» вдобавок даём ободок
   цветом подсветки — это единственная хорошая новость на экране,
   пусть её замечают. Плохую новость не подсвечиваем нарочно. */
.рейтинг__окно--лучше { box-shadow: inset 0 0 0 1.5px var(--акцент); }
.рейтинг__окно--лучше .рейтинг__окно-число::after { content: "\00a0↑"; }
.рейтинг__окно--хуже  .рейтинг__окно-число::after { content: "\00a0↓"; }

/* Для справки, как выглядит одна плитка в разметке:
     <span class="рейтинг__окно рейтинг__окно--лучше">
       <span class="рейтинг__окно-подпись">последние 20</span>
       <span class="рейтинг__окно-число">60%</span>
     </span>
   Без пометки — когда разница с общим счётом меньше пяти пунктов:
   это шум, а не новость, и стрелки на такой плитке нет. */

/* ---------- Заголовок раздела ----------

   «С кем играли», «Против каких ботов», «За какими столами».
   Тихий и мелкий: он не сообщение, а указатель. Черта под ним
   отделяет разделы друг от друга — без неё три группы плиток
   сливаются в одну длинную простыню. */
.таблица__раздел {
  margin: 12px 0 2px;
  padding: 0 2px 4px;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.3px;
  color: var(--текст-тихий);
  border-bottom: 1px solid var(--край);
}

/* Первому разделу верхний отступ не нужен: над ним и так строка
   словами, а лишний просвет отрывает таблицу от неё. */
#таблица-рейтинга .таблица__раздел:first-child { margin-top: 0; }

/* ---------- Строка счёта ----------

   Три ячейки: за что играли, сколько партий, доля побед.

   Ширины двух правых колонок заданы точно, а не «по содержимому», —
   и это главное здесь. Каждая строка таблицы сама себе сетка, между
   собой строки колонками не связаны: у «13 партий» и «128 партий»
   ширина разная, и при колонках «по содержимому» число процентов
   в каждой строке начиналось бы со своего места. Столбик от этого
   пляшет, и сравнить строки глазом нельзя — а таблицу открывают
   ровно затем, чтобы сравнивать.

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

   5,4em — это «128 партий» с запасом на пробел, 6,5em — «100% побед»
   вместе с плашкой вокруг доли: сначала под неё было отдано 5,9em,
   и на снимке плашка упиралась в край строки — в колонке надо считать
   не только цифры, но и поля плашки вокруг них. */
#таблица-рейтинга .таблица__строка {
  grid-template-columns: minmax(0, 1fr) 5.4em 6.5em;
  gap: 2px 8px;
  padding: 8px 12px;
  font-size: 12.5px;
}

/* Первая строка на экране рекордов обведена рамкой — там это «первое
   место». Здесь порядок строк ничего не значит (разделы идут подряд),
   и такая рамка обещала бы значение, которого нет. */
#таблица-рейтинга .таблица__строка:first-child { box-shadow: none; }

/* Название — главное в строке, поэтому оно крупнее чисел рядом.
   Многоточие запрещено: длинные названия («вшестером, парами»)
   должны читаться целиком, а не превращаться в «вшестером, па…».
   Не поместилось — пусть перенесётся на вторую строчку. */
#таблица-рейтинга .рейтинг__название {
  font-size: 15px;
  line-height: 1.25;
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
}

/* Сколько партий — самая тихая часть строки: она объясняет, насколько
   доле побед можно верить (4 партии и 128 партий — разный разговор). */
#таблица-рейтинга .рейтинг__партий {
  justify-self: end;
  align-self: center;
  font-size: 12.5px;
  white-space: nowrap;
  color: var(--текст-тихий);
  font-variant-numeric: tabular-nums;
}

/* Доля побед — то, ради чего строку читают. Она в маленькой плашке:
   так строка перестаёт быть строкой отчёта и читается как «название
   и его отметка». Цифры одной ширины — столбик стоит ровно. */
#таблица-рейтинга .рейтинг__доля {
  justify-self: end;
  align-self: center;
  padding: 2px 7px 3px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--текст);
  white-space: nowrap;
  background: var(--подложка);
  border-radius: 999px;
  font-variant-numeric: tabular-nums;
}

/* ---------- Сноска под таблицей ----------

   «Счёт ведётся с 01.06.2026.» Это приписка, а не сообщение, поэтому
   плашки под ней быть не должно — иначе она весит столько же, сколько
   строки счёта. Узнаём её по соседству: перед ней есть хотя бы одна
   строка счёта, значит это не пустой экран, а подпись под таблицей.

   Вторая строка правила — про человека, который сыграл две-три партии.
   Разрезов у него ещё нет (разрез из одной строки игра не показывает),
   поэтому строк счёта на экране ноль, а абзаца два: «сыграйте против
   другого соперника» и та же приписка с датой. По первому правилу
   приписка не ловилась, и дата вставала в такую же плашку, как
   сообщение над ней, — на снимке 390×844 это выглядело как два
   одинаковых по важности сообщения подряд.

   Отличаем по строке словами под крупным числом. Если счёта нет вовсе,
   игра её прячет («скрыт»), и тогда второй абзац — настоящее сообщение,
   плашку у него забирать нельзя. Если строка на месте, счёт есть,
   и второй абзац — приписка. */
#таблица-рейтинга .таблица__строка ~ .таблица__пусто,
#экран-рейтинга:not(:has(#рейтинг-подпись.скрыт)) #таблица-рейтинга .таблица__пусто + .таблица__пусто {
  padding: 8px 12px 0;
  font-size: 12.5px;
  background: none;
}

/* ---------- Пустой счёт у новичка ----------

   Партий нет ни одной, и на экране вместо чисел два предложения.
   Это самое опасное место экрана: пустая страница читается как
   поломка, а не как «вы ещё не играли».

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

   Селектор нарочно узкий: «первая плашка из ровно двух». Ровно два
   абзаца бывают только там, где счёта ещё нет. У сообщения о беде
   с хранилищем и у «Считаем партии…» плашка одна — на них масти
   не попадут: подмигивать посреди неполадки нельзя. */
#таблица-рейтинга .таблица__пусто:first-child:nth-last-child(2) {
  padding-top: 10px;
  font-size: 15px;
  color: var(--текст);
}

/* Полоска мастей — только на странице дурака. Экран «Как я играю»
   общий на весь сборник, и без этой оговорки масти всплывали на
   страницах шашек и нард, где карт нет вовсе. Страницу дурака узнаём
   по витрине (#экран-витрины есть только в index.html) — тем же
   приёмом, что и другие правила этого файла. «:where» не добавляет
   веса: правило остаётся ровно той же силы, что и раньше. */
:where(:root:has(#экран-витрины)) #таблица-рейтинга .таблица__пусто:first-child:nth-last-child(2)::before {
  content: "♠ ♥ ♦ ♣";
  display: block;
  margin-bottom: 8px;
  font-size: 22px;
  letter-spacing: 4px;
  color: var(--текст-тихий);
}

/* Второй абзац — уточнение к первому: он тише и мельче. */
#таблица-рейтинга .таблица__пусто:first-child + .таблица__пусто:last-child {
  margin-top: 6px;
  font-size: 13px;
}

/* Когда строк счёта нет вовсе, текст ставим по середине свободного места,
   а не оставляем прижатым к верху.

   Зачем. На снимке 390×844 два абзаца кончались на трети экрана, и ниже
   до самой кнопки лежало 420 точек пустоты. Такой экран читается как
   недогруженная страница: человек ждёт, что там вот-вот что-то появится.
   Ровно этого мы и не хотим — счёта у новичка нет, и это не поломка,
   а нормальное начало.

   Сделано пустыми полями сверху и снизу, а не выравниванием всего
   столбца: заголовок должен остаться наверху, а кнопка внизу — там, где
   их ищут на всех остальных экранах. Двигается только середина.

   Правило работает во всех трёх случаях без строк: у новичка, при
   «Считаем партии…» и при сообщении о неполадке. Браузер, который
   не знает :has (старее 2023 года), просто оставит текст сверху —
   как было; ничего не сломается. */
#экран-рейтинга:not(:has(.таблица__строка)) #рейтинг-главное {
  margin-top: auto;
}

#таблица-рейтинга:not(:has(.таблица__строка)) {
  margin-bottom: auto;
}

#кнопка-рейтинг-назад {
  margin-top: auto;      /* прижата к низу, как «Назад» на рекордах */
  width: min(100%, var(--колонка-кнопок));
}

/* ---------- «Стереть счёт партий» — с переспросом ----------

   Необратимое действие, поэтому кнопка выглядит «осторожно»: надпись
   и тонкая кайма красноватые, но не чистым красным — чистый красный
   на сукне и в тёмной теме не дотягивает по контрасту, а на весь
   экран кричать здесь нечего. Красный подмешан к цвету текста: в светлой
   теме выходит тёмно-красный, в тёмной и на сукне — розоватый, и читается
   везде. Первая строка каждого правила — для браузеров без color-mix.

   Первое нажатие ничего не стирает: игра показывает строку-вопрос,
   меняет подпись на «Да, стереть» и вешает на кнопку класс
   «кнопка--стереть-точно». В этом состоянии кнопка заметнее: кайма
   толще и чистого красного цвета, подложка подкрашена. Узнаём его
   по классу, а не по видимой строке вопроса нарочно: та же строка потом
   говорит «Счёт стёрт», и по ней кнопка на миг выглядела бы
   переспрашивающей, хотя стирать уже нечего.

   Кнопка и вопрос стоят внизу, над «Назад к рекордам»: стирать счёт
   человек приходит редко, и место этому — у края, а не под таблицей.
   Пустое поле поэтому берёт на себя кнопка (или вопрос, когда он
   виден), а «Назад» под ними уже ни к чему тянуться. */
#кнопка-стереть-счёт {
  margin-top: auto;
  color: var(--карта-отказ);
  color: color-mix(in srgb, var(--карта-отказ) 70%, var(--текст));
  background: var(--подложка);
  border: 1px solid var(--край);
  border-color: color-mix(in srgb, var(--карта-отказ) 45%, var(--край));
  box-shadow: none;
}

#вопрос-стирания {
  margin-top: auto;
  max-width: min(100%, 330px);
  font-size: 13px;
  line-height: 1.35;
  text-align: center;
}

/* Пока виден вопрос, пустое поле держит он, а не кнопка, — иначе они
   разъедутся: вопрос под таблицей, кнопка внизу. */
#экран-рейтинга:has(#вопрос-стирания:not(.скрыт)) #кнопка-стереть-счёт {
  margin-top: 0;
}

#кнопка-стереть-счёт.кнопка--стереть-точно {
  font-weight: 700;
  color: var(--текст);
  background: var(--подложка);
  background: color-mix(in srgb, var(--карта-отказ) 18%, var(--подложка));
  border: 2px solid var(--карта-отказ);
}

#экран-рейтинга:has(#кнопка-стереть-счёт:not(.скрыт)) #кнопка-рейтинг-назад {
  margin-top: 0;
}

/* Шторка Telegram открыта не во весь рост. Высота здесь дороже всего:
   в окне 360×600 заголовок с рамкой съедали 110 точек из 600, и до
   таблицы оставалась половина экрана. Ужимаем всё, что над таблицей, —
   тогда в списке видно на две строки больше. Сами строки не трогаем:
   их всё равно читать. */
@media (max-height: 620px) {
  #экран-рейтинга {
    gap: 6px;
    padding: calc(9px + var(--отступ-сверху)) calc(8px + var(--отступ-справа))
             calc(8px + var(--отступ-снизу))  calc(8px + var(--отступ-слева));
  }
  #экран-рейтинга .заголовок { font-size: 21px; }
  #рейтинг-главное { padding: 5px 14px 6px; font-size: clamp(22px, 7vw, 27px); }
  #рейтинг-подпись { font-size: 13px; }
  #рейтинг-динамика { gap: 5px; margin-top: 1px; }
  .рейтинг__окно { padding: 3px 9px 4px; }
  .рейтинг__окно-число { font-size: 14px; }
  .таблица__раздел { margin-top: 9px; }
}

/* Телефон поуже 390 точек. Отдаём названию всё, что можно отобрать
   у чисел: на 360 точках «вшестером, парами» переносилось на вторую
   строчку, а строка счёта должна читаться одним взглядом. Числа
   от этого не страдают — им и так хватало с запасом. */
@media (max-width: 380px) {
  #таблица-рейтинга .таблица__строка {
    grid-template-columns: minmax(0, 1fr) 5em 6.2em;
    gap: 2px 6px;
    padding: 8px 10px;
  }
  #таблица-рейтинга .рейтинг__название { font-size: 14px; }
}

/* ---------- Кнопка «Как играть» в меню ----------

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

   Поэтому здесь рамка вместо заливки — та же, что у «Играть с другом».
   Кнопку по-прежнему прекрасно видно (а новичку она и нужна заметной,
   он за ней сюда и пришёл), но спорить с «Играть» она перестала.
   Серую рамку «Рекордов» ей не даём нарочно: рекорды человек ищет сам,
   когда захочет, а правила должны попасться на глаза тому, кто их
   не искал. */
#кнопка-как-играть {
  color: var(--текст);
  background: var(--подложка);
  border: 2px solid var(--акцент);
  box-shadow: none;
}

/* ---------- Кнопка «Раздача дня» ----------

   Одна и та же раздача всем игрокам в этот день — соревнование,
   а не ещё одна партия. Стоит сразу под «Играть», и спорить с ней
   не должна: «Играть» — главная, залитая. Но и теряться в ряду
   «Как играть / Рекорды / Звук» ей нельзя — те рамочные и тихие.

   Поэтому рамка та же, что у «Как играть» (это тоже вход, а не
   действие в партии), а надпись — цветом подсветки и с искрой «✦»
   впереди: «сегодняшнее, особенное». Цвет подсветки на подложке
   читается в любой теме: это цвет кнопок Telegram, а на своей теме —
   золото на сукне. Так кнопка заметнее рамочных соседей, но не залита,
   как главная. */
.кнопка.кнопка--раздача-дня {
  color: var(--акцент);
  background: var(--подложка);
  border: 2px solid var(--акцент);
  box-shadow: none;
}

.кнопка.кнопка--раздача-дня::before {
  content: "✦ ";
}

/* Сыграли — та же кнопка до полуночи показывает итог: «Сегодня: победа
   за 14 ходов» — и не нажимается. Общий вид выключенной кнопки здесь
   не годится: серая заглушка говорит «нельзя», а сказать надо
   «сделано, вот результат». Поэтому тихая плашка: подложка, тонкая
   серая кайма вместо цветной, надпись обычным цветом текста, галочка
   впереди цветом подсветки. Кегль чуть меньше и перенос разрешён:
   «Сегодня: поражение за 23 хода» длиннее любой кнопки в ряду.
   Три класса в селекторе — чтобы перебить общее правило «:disabled». */
.кнопка.кнопка--раздача-дня.кнопка--раздача-сыграна,
.кнопка.кнопка--раздача-дня.кнопка--раздача-сыграна:disabled {
  padding: 8px 14px;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.25;
  white-space: normal;
  /* Две строки делятся поровну: без этого на 360 точках выходило
     «Сегодня: поражение за 23» и одинокое «хода» строкой ниже. */
  text-wrap: balance;
  color: var(--текст);
  background: var(--подложка);
  border: 1.5px solid var(--край);
  box-shadow: none;
  cursor: default;
}

.кнопка.кнопка--раздача-дня.кнопка--раздача-сыграна::before {
  content: "✓ ";
  color: var(--акцент);
}

/* ================================================================
   ЭКРАН «КАК ИГРАТЬ»

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

   Всё ниже действует только внутри «.правила». Класс «подпись» стоит
   ещё на десятке экранов, и общий его вид не тронут ни на точку.
   ================================================================ */

#экран-правил {
  align-items: center;
  gap: 10px;
  padding: calc(14px + var(--отступ-сверху)) calc(10px + var(--отступ-справа))
           calc(10px + var(--отступ-снизу))  calc(10px + var(--отступ-слева));
}

/* Заголовок как у рекордов: 34 точки на этом экране лишние — под ним
   идёт длинный текст, и крупная шапка отбирает у него строки. */
#экран-правил .заголовок { font-size: 28px; }

.правила {
  gap: 8px;
  text-align: left;
  counter-reset: правило;

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

     Первая строка — для браузеров старше 2023 года, они не знают
     color-mix и возьмут просто цвет темы. Вторая — точный цвет сукна. */
  background:
    linear-gradient(transparent, var(--фон)) bottom / 100% 16px local no-repeat,
    radial-gradient(farthest-side at 50% 100%, rgba(0, 0, 0, 0.42), transparent)
      bottom / 100% 9px scroll no-repeat;
  background:
    linear-gradient(transparent, color-mix(in srgb, var(--фон) 80%, #1f7a45))
      bottom / 100% 16px local no-repeat,
    radial-gradient(farthest-side at 50% 100%, rgba(0, 0, 0, 0.42), transparent)
      bottom / 100% 9px scroll no-repeat;
}

/* Одно правило — одна плашка.

   Про кегль и цвет. Было 15 точек тихим серым — так в игре выглядят
   приписки, которые можно и не читать. Здесь наоборот: это единственное,
   ради чего человек открыл экран. Поэтому цвет обычный, полный, кегль
   15,5 и строки просторнее (1,45) — текст читают подряд, а не выхватывают
   взглядом, и тесные строки в таком чтении сбивают.

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

   Про отступ слева. Поле в 34 точки и отрицательный «text-indent»
   дают висячий номер: цифра стоит слева, а все строки правила —
   ровным столбиком правее неё. Без этого вторая строка заезжала
   бы под номер, и шесть правил читались бы как одна каша. */
.правила .подпись {
  display: list-item;
  list-style: decimal inside;
  counter-increment: правило;
  margin: 0;
  padding: 10px 12px 11px 34px;
  text-indent: -22px;
  font-size: 15.5px;
  line-height: 1.45;
  color: var(--текст);
  background: var(--подложка);
  border-radius: 12px;
}

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

   Про цвет. Чистый цвет подсветки на плашке даёт контраст 4,2 при норме
   4,5 — цифра в полтора десятка точек на грани читаемости. Поэтому к нему
   подмешаны две пятых цвета основного текста: тот по определению хорошо виден
   на своей теме, и подмешивание всегда тянет цифру в сторону читаемости —
   в тёмной теме высветляет, в светлой притемняет. Замерено: 4,6 в тёмной
   теме и 5,7 в светлой, а цвет по-прежнему узнаётся как «тот самый,
   которым игра подсвечивает выбор». Первая строка — запас для браузеров
   без color-mix. */
.правила .подпись::marker {
  content: counter(правило) ".\00a0\00a0";
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--акцент);
  color: color-mix(in srgb, var(--акцент) 60%, var(--текст));
}

/* Образцы карт «можно / нельзя» к правилу про подсветку живут теперь
   в разделе «КАК ИГРАТЬ, РЕКОРДЫ, ОФОРМЛЕНИЕ ДУРАКА» в конце файла.
   Раньше они цеплялись к ПОСЛЕДНЕМУ правилу, а правил стало одиннадцать,
   и последнее — про игру парами: карты стояли не под тем текстом. */

/* «Назад» — единственная кнопка экрана, поэтому обычная, залитая,
   и прижата к низу: большой палец достаёт до неё, не перехватывая
   телефон. Ширина как у кнопок меню — во всю ширину экрана кнопка
   выглядела бы полосой, а не кнопкой. */
#кнопка-правила-назад {
  margin-top: auto;
  width: min(100%, var(--колонка-кнопок));
}

/* ================================================================
   ИГРА ВДВОЁМ: код комнаты, ожидание друга и строка связи

   Здесь всё держится на одной мысли: главный предмет этого режима —
   четыре знака кода. Их диктуют другу по телефону, глядя в свой
   экран, поэтому код оформлен как записка на бумаге: белая плашка,
   чёрные знаки, моноширинный шрифт (у него все буквы одной ширины
   и не сливаются), крупные просветы между знаками. Всё остальное
   на этих экранах нарочно спокойное — чтобы взгляд шёл к коду.
   ================================================================ */

/* ---------- Обведённые кнопки: «Войти по коду» и соседи ----------
   Правило простое: на одном экране залита одна кнопка — та, ради
   которой на экран пришли. Всё остальное, что тоже нажимается, берёт
   рамку цветом подсветки: видно и понятно, что кнопка, но за внимание
   она не спорит.

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

   Кнопки «Играть с другом» здесь больше нет, и это нарочно. На первом
   экране она стоит рядом с «Играть с ботом», и эти двое равны — там
   залиты обе (см. «Две кнопки первого экрана» выше). Единственное место,
   где две залитые кнопки подряд не мешают, — развилка из двух ответов
   на один вопрос.

   «Скопировать код» — из той же породы, что «Войти по коду». Залитая
   кнопка на экране кода перетягивала бы взгляд с самого кода, а он тут
   главный. Рамка вместо заливки: кнопку видно и по ней понятно, что она
   нажимается, но первым в глаза бросается код. */
#кнопка-войти-по-коду,
#кнопка-копировать-код,
/* «Проверить» стоит в самом техническом слое, рядом с «Сохранить адрес».
   Залитыми они выглядели как два одинаково важных действия подряд,
   хотя проверка — это примерка, а сохранение — дело. Оставляем залитым
   только сохранение. */
#кнопка-проверить-адрес {
  color: var(--текст);
  background: var(--подложка);
  border: 2px solid var(--акцент);
  box-shadow: none;
}

/* ---------- Пока висит «играть с другом сейчас нельзя» ----------

   На этом экране две крупные залитые кнопки оказывались рядом:
   «Создать игру» и «Играть с ботом». Обе кричали «нажми меня», причём
   первая только что отказала — и человек не понимал, какая из них
   теперь настоящая.

   Расставляем по правде. Прямо сейчас игра вдвоём не работает, и жать
   «Создать игру» второй раз бессмысленно, пока не включён нужный
   компьютер, — поэтому кнопка становится обведённой, как «Войти
   по коду»: место, размер и нажимаемость те же, громкость меньше.
   Залитой остаётся одна кнопка на экране — «Играть с ботом», то есть
   ровно то, что сейчас действительно можно сделать.

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

   Правило держится на соседстве: «:has» смотрит, висит ли на экране
   блок беды. Браузеры старше 2023 года «:has» не знают — у них
   останется прежний вид с двумя залитыми кнопками, то есть ровно то,
   что было до этой правки, и ничего не ломается. */
#экран-друга:has(#нет-сервера-главное:not(.скрыт)) #кнопка-создать-игру {
  color: var(--текст);
  background: var(--подложка);
  border: 2px solid var(--акцент);
  box-shadow: none;
}

/* ---------- «Вернуться к игре с другом» ----------

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

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

   Высота не задана намертво, только наименьшая: подпись длинная,
   на узком телефоне встаёт в две строки — кнопка от этого просто
   вырастет, а не обрежет буквы. */
#кнопка-вернуться-в-игру.кнопка--возврат {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 56px;
  font-size: 19px;
  line-height: 1.2;
}

#кнопка-вернуться-в-игру.кнопка--возврат::before {
  content: "↻";
  font-size: 20px;
  line-height: 1;
}

/* А «Создать игру» на это время уступает: пока брошенная партия жива,
   главное действие экрана — вернуться в неё, а не начать ещё одну.
   Кнопка остаётся на месте и работает — она только тише.
   Старый браузер без «:has» покажет обе залитыми, как было раньше. */
#экран-друга:has(#кнопка-вернуться-в-игру:not(.скрыт)) #кнопка-создать-игру {
  color: var(--текст);
  background: var(--подложка);
  border: 2px solid var(--акцент);
  box-shadow: none;
}

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

   Своего фона у тройки не было вовсе: класс «.экран» фон не красит
   (правило «.экран» в начале файла), сквозь него было видно «--фон»
   по умолчанию — зелёное сукно стола, а кнопки красились цветом
   кнопки Telegram, а не салатовым акцентом сборника. Ровно та беда,
   что уже чинили у лобби, шагов, «Найти игру» и «Ищем соперника» —
   тот же приём: свои переменные из общей палитры сборника «--сб-*»
   (см. «Общие цвета сборника» в начале файла). Это касается и
   запасного вида комнаты («#комната-старая»): свежий вид комнаты
   («#комната.комната») красит себя ещё раз сам, отдельным более
   точным правилом ниже по файлу — он не пострадает.

   «Друзья» и «Добавить друга» добавлены сюда же — той же бедой страдали,
   своих строк в style.css у них не было вовсе.

   Фон здесь — тёмный графит сборника, одинаковый у всех игр (решение
   владельца 22.09: служебные экраны дурака выглядят как у шашек,
   шахмат и нард). Сукно живёт только внутри стола и рамы, на фон
   экранов не выходит. */
#экран-друга,
#экран-комнаты,
#экран-входа,
#экран-друзей,
#экран-добавить-друга {
  --фон: var(--сб-фон);
  --панель: var(--сб-поверхность);
  --текст: var(--сб-текст);
  --текст-тихий: var(--сб-текст-тихий);
  --кнопка-фон: var(--сб-акцент);
  --кнопка-текст: var(--сб-акцент-текст);
  --акцент: var(--сб-акцент);
  --подложка: rgba(248, 245, 235, 0.06);
  --край: rgba(248, 245, 235, 0.14);
  /* «--плитка»/«--плитка-кромка» здесь раньше не было: их просит общий
     класс «.код-игры» (плашка с кодом) и «.поле-кода» (ввод кода), а без
     объявления в области видимости «var(--плитка)» ничего не значит —
     подложка откатывается на светлый цвет темы, и код читается на ярком
     бежевом поле вместо тёмного. Те же самые значения уже объявлены
     у экрана «Найти игру» (см. ниже по файлу) — переносим их сюда. */
  --плитка: #1e2226;
  --плитка-кромка: rgba(248, 245, 235, 0.12);

  align-items: center;
  gap: 14px;
  padding: calc(16px + var(--отступ-сверху)) calc(12px + var(--отступ-справа))
           calc(16px + var(--отступ-снизу))  calc(12px + var(--отступ-слева));
  text-align: center;
  color: var(--сб-текст);
  /* Тот же фон, что у лобби и «Найти игру»: ровный тёмный и едва
     заметное салатовое свечение у верхнего края. «local» — чтобы
     свечение уходило вместе с текстом при прокрутке длинного
     объяснения, а не висело поверх него. */
  background:
    radial-gradient(75% 120px at 50% 0, rgba(210, 247, 107, 0.07), rgba(210, 247, 107, 0) 100%) local,
    var(--сб-фон);
  /* Длинное объяснение (например, про http и https) на маленьком
     экране не помещается — тогда столбик прокручивается.
     Вбок не прокручивается никогда. */
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Смотритель нашёл (снимок «тёмный-экран-друга-390x844.png»): когда
     сервер недоступен, объяснение обрывается ровно на нижнем краю
     кадра, посреди фразы, и ничего не подсказывает, что дальше есть
     ещё текст и можно прокрутить.

     Раньше здесь стояла mask-image тем же приёмом, что у списка
     лидеров («#рейтинг-таблица»), — и не сработала: там маска висит
     на ОТДЕЛЬНОМ внутреннем блоке (высота через flex: 1 1 auto внутри
     неподвижного экрана), а здесь маску пришлось бы вешать на сам
     «.экран» — он и прокручивается (overflow-y выше), и одновременно
     растянут на весь экран через «position: absolute; inset: 0»
     (высота не через flex, а через «резину» до краёв родителя). Эта
     смесь браузер не потянул: край гас по высоте содержимого, а не
     по высоте того, что реально видно, — снимок остался обрубленным.
     Разбирать «.экран» на два вложенных блока — это уже разметка,
     не моя зона.

     Решение без новых узлов: вместо маски — отдельная лёгкая накладка
     «::after» у нижнего края (правило ниже). Она не читает высоту
     содержимого вовсе, просто рисует свою узкую полоску того же
     цвета, что фон экрана, ровно там, где кончается экран физически.
     «pointer-events: none» — чтобы накладка не мешала нажимать то,
     что случайно окажется под ней. */
}

/* Строка-выключатель «Друзья видят, что вы в игре» (js/друзья-экран.js)
   взяла готовые классы листа «⋯» — «.лист-ещё__строка» и пилюлю
   «.лист-ещё__значение», — а те красятся переменными «--вт-…» (см.
   «Витрина» в начале файла). У «#экран-друзей» их не было вовсе:
   пилюля «вкл/выкл» выходила простым текстом без капсулы и без цвета.
   Заводим свой набор — тем же приёмом, что у рейтинга, профиля и лобби
   (у каждого он свой, объявлен на самом экране): акцент здесь обычный
   салатовый сборника, без золота — этот экран не особенный. */
#экран-друзей {
  --вт-поверхность: var(--сб-поверхность);
  --вт-граница: var(--сб-граница);
  --вт-текст: var(--сб-текст);
  --вт-текст-тихий: var(--сб-текст-тихий);
  --вт-акцент: var(--сб-акцент);
  --вт-акцент-текст: var(--сб-акцент-текст);
}

/* Полоска-затухание у нижнего края. Отдельным слоем, а не маской —
   см. комментарий выше про то, почему маска здесь не удалась. Полоска
   всегда на месте; когда текста мало и низ и так пустой, она ложится
   на пустой фон и не видна — не мешает.

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

   Высота и градиент — замечание смотрителя по снимку 22.09: на тёмном
   бордовом сукне прежние 24px были почти не видны, полоска не давала
   догадаться, что ниже есть ещё текст. Сделано заметнее: полоска выше
   (60px) и доходит до 60% цвета фона на середине, полный цвет — у самого
   нижнего края — на глаз это читается как явное затухание, а
   не как тонкая кайма. Выше делать нельзя: у всех пяти экранов внизу
   стоит кнопка «Назад» (высота от 44px, отступ снизу — padding самого
   экрана, 8px плюс безопасное поле), и полоска не должна закрывать её
   собой при прокрутке до упора — 60px оставляет кнопке достаточно
   места под полоской, чтобы её было видно и можно было нажать. */
#экран-друга::after,
#экран-комнаты::after,
#экран-входа::after,
#экран-друзей::after,
#экран-добавить-друга::after {
  content: "";
  /* «absolute» здесь не подходит: «.экран» одновременно растянут через
     «position: absolute; inset: 0» и сам прокручивается (overflow-y выше),
     поэтому абсолютный потомок отсчитывается от НИЗА ВСЕГО СОДЕРЖИМОГО
     и уезжает вместе с прокруткой — на длинном тексте накладка повисает
     за пределами видимого кадра и никогда не видна (проверено браузером).
     «fixed» держит накладку у нижнего края ОКНА независимо от прокрутки:
     ни у html/body, ни у «#приложение», ни у самого «.экран» нет
     transform/filter/perspective/backdrop-filter/will-change/contain,
     которые превратили бы кого-то из них в свою точку отсчёта для fixed,
     а «#приложение» и так занимает весь видимый прямоугольник
     (position: fixed; inset: 0) — значит от окна и от него разницы нет. */
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 60px;
  /* Цвет — тёмный графит сборника, тот же, которым залит сам экран.
     Первая строка — простой двухцветный переход, запасной вариант для
     браузеров без color-mix. Вторая строка его перебивает: цвет фона
     набирает 60% непрозрачности уже на середине высоты полоски, а не
     только у самого низа — так затухание видно на глаз, а не только
     там, где полоска почти сливается с фоном. */
  background: linear-gradient(180deg, transparent, var(--сб-фон));
  background: linear-gradient(180deg,
    transparent,
    color-mix(in srgb, var(--сб-фон) 60%, transparent) 50%,
    var(--сб-фон));
  pointer-events: none;
}

/* Салатовая обводка с клавиатуры — как у лобби и комнаты, а не синяя
   системная: тот же приём переезда на тёмный вид, только для фокуса. */
:is(#экран-друга, #экран-комнаты, #экран-входа) button:focus-visible {
  outline: 2px solid var(--сб-акцент);
  outline-offset: 2px;
}

/* Центрируем столбик пустыми полями сверху и снизу, а не привычным
   justify-content: center. Разница видна, когда содержимое выше
   экрана: justify-content срезал бы заголовок сверху и до него было
   бы уже не докрутить, а пустые поля в этом случае просто сжимаются
   до нуля, и виден весь текст. */
#экран-друга    > :first-child,
#экран-комнаты  > :first-child,
#экран-входа    > :first-child { margin-top: auto; }

#экран-друга    > :last-child,
#экран-комнаты  > :last-child,
#экран-входа    > :last-child { margin-bottom: auto; }

#экран-друга   .заголовок,
#экран-комнаты .заголовок,
#экран-входа   .заголовок { font-size: 28px; }

#экран-друга   > .подпись,
#экран-комнаты > .подпись,
#экран-входа   > .подпись {
  max-width: 330px;
  line-height: 1.35;
}

#экран-друга   .кнопка,
#экран-комнаты .кнопка,
#экран-входа   .кнопка { width: min(100%, var(--колонка-кнопок)); }

/* «Назад» и «Отменить игру» — уводящие кнопки, поэтому они мельче
   и тусклее. Но по высоте всё равно 44 точки: мимо пальцем не
   промахнуться, места на этих экранах хватает. */
#экран-друга   .кнопка.кнопка--мелкая,
#экран-комнаты .кнопка.кнопка--мелкая,
#экран-входа   .кнопка.кнопка--мелкая {
  width: auto;
  min-width: 150px;
  min-height: 44px;
  margin-top: 2px;
}

/* ---------- Две мелкие кнопки внизу комнаты — в один ряд ----------

   Внизу комнаты стоят «Как играть» и «Отменить игру», обёрнутые
   в «кнопки-комнаты». Пока обёртки не было и они были двумя
   отдельными детьми столбика, они вставали одна под другой и съедали
   97 точек (44 + 9 + 44). На снимке 320×568 у хозяина стола ровно
   на столько ужимался список мест: из шести строк видно три, остальное
   прокруткой. Это то самое место, которое отвоёвывали под список.

   В один ряд две кнопки занимают 44, и списку возвращаются полторы
   строки (на снимке 320×568 список вырос со 106 до 159 точек, видно
   пять мест из шести). В столбике два соседних элемента в ряд
   не поставить честно — потому и обёртка.

   Хак с отрицательным полем (вторую кнопку подтянуть на высоту первой
   и развести их по краям) нарочно не взят: он держится на том, что
   обе кнопки ровно 44 точки ростом, а при крупном системном шрифте
   «Отменить игру» переносится в две строки — и ряд разъезжается.

   Ширина у кнопок своя, не половина ряда: «Как играть» и «Отменить
   игру» разной длины, и растянутые до равной ширины они выглядели бы
   одной плашкой с чертой. На 320 точках ряд — 130 + 8 + 130 = 268
   из 300 доступных. У́же 280 точек ряд переносится сам (flex-wrap),
   и это не поломка: кнопки просто встанут как сейчас. */
.кнопки-комнаты {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  width: 100%;
  margin-top: 2px;
}

#экран-комнаты .кнопки-комнаты .кнопка.кнопка--мелкая {
  flex: 0 1 auto;
  margin-top: 0;
}

/* ---------- Знакомые: с кем уже играли и кто сейчас за столом ----------

   Блок стоит на экране «Игра с другом» под «Войти по коду». Открывают
   его ради одного: увидеть, кто из знакомых играет прямо сейчас, —
   к нему и можно зайти. Поэтому играющие сверху (их так ставит игра)
   и помечены так, чтобы читаться с первого взгляда, а остальные тише.

   Блок обведён тонкой рамкой и стоит одним куском: без неё заголовок
   «С кем вы играли», строки и подпись расползались по столбику экрана
   между кнопками и сноской и читались как три разные вещи. */
.знакомые {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  width: min(100%, 360px);
  padding: 8px 8px 9px;
  border: 1px solid var(--край);
  border-radius: 14px;
  text-align: left;
}

/* Заголовок раздела здесь первый в рамке — верхний отступ ему не нужен. */
.знакомые .таблица__раздел { margin-top: 0; }

.знакомые .таблица {
  width: 100%;
  gap: 4px;
}

/* Строка: метка · имя · «сейчас за столом». Четвёртая ячейка приходит
   пустой (она нужна сетке таблицы рекордов) — прячем, иначе сетка
   отведёт ей колонку и просвет. Три колонки: узкая под точку, имя
   во всю ширину, пометка по содержимому.

   «position: relative» здесь не для этой строки самой по себе, а как
   точка отсчёта для кнопки «Позвать» — см. ниже: разработчик кладёт её
   внутрь ячейки имени (сетка строки трёхколоночная, менять разметку
   ему нельзя), а нам нужно вытащить её визуально в свой, четвёртый
   угол справа. */
.знакомые .таблица__строка {
  grid-template-columns: 1.1em minmax(0, 1fr) auto;
  gap: 0 8px;
  padding: 7px 10px;
  border: 1px solid transparent;
  text-align: left;
  position: relative;
}

.знакомые .таблица__строка .таблица__сложность:empty { display: none; }

/* Рамка чемпиона у первой строки здесь не про то: первый в списке —
   не лучший, а просто играющий сейчас, и у него своя пометка. */
.знакомые .таблица__строка:first-child { box-shadow: none; }

/* ---------- Кнопка «Позвать» — своя, четвёртая колонка справа ----------

   js/game.js кладёт кнопку ПОСЛЕДНИМ ребёнком в ячейку имени (класс
   «знакомые__позвать» у кнопки, комментарий в game.js объясняет
   почему — трёхколоночная сетка строки). Если ничего не делать, кнопка
   встаёт прямо в текст имени: при длинном имени «overflow: hidden» на
   ячейке (см. «.таблица__очки») обрезает её вместе с многоточием —
   кнопка просто пропадает, а при коротком имени она наезжает на
   пометку «где» и на соседей снизу-сверху (проверено вживую).

   Лечим не переносом кнопки в разметке (её кладёт чужой файл), а тем,
   что у строки уже есть — «position: relative» выше. Резервируем
   справа полосу шириной под кнопку (четвёртый, фиксированный трек
   сетки — он пустой, реальный грид-элемент в нём не стоит, но место
   держит), из-за чего имя и пометка «где» сами сдвигаются левее
   и укорачивается имя многоточием, а саму кнопку вытаскиваем в эту
   полосу «position: absolute» — так она всегда лежит в правом углу
   строки, поверх какой бы ширины ни оказалось имя.

   84 точки — по факту хватает трём подписям кнопки («Позвать»,
   «Зовём…», «Позвали») с полями 8×12 и кеглем 13 без переноса.
   Высоту строки поднимаем до 56: кнопка 44 плюс по 6 сверху и снизу,
   иначе бы она соседей задевала при просвете строк в 4 точки. */
.знакомые .таблица__строка:has(.знакомые__позвать) {
  grid-template-columns: 1.1em minmax(0, 1fr) auto 84px;
  min-height: 56px;
}

/* Специфичность через id — иначе «#экран-друга .кнопка.кнопка--мелкая»
   (широкая, min-width 150, для «Назад»/«Отменить игру» на этом же
   экране) перетянет на себя и кнопку «Позвать»: у нас тут ровно
   столько же классов плюс тот же id, и мы называем на один класс
   больше — превосходим по правилам каскада, не трогая исходное
   правило. */
#экран-друга .кнопка.кнопка--мелкая.знакомые__позвать,
#лист-места .кнопка.кнопка--мелкая.знакомые__позвать {
  /* Кнопка лежит поверх имени знакомого в его строке,
     в старом экране-друга и в листе места-в-комнате */
  position: absolute;
  top: 50%;
  right: 10px;
  transform: translateY(-50%);
  width: auto;
  min-width: 0;
  min-height: 44px;
  margin-top: 0;
  padding: 8px 12px;
}

/* Нажатие — то же «садится и темнеет», что у остальных кнопок
   (см. «.кнопка:active» в общем разделе), но со своим смещением:
   там переезд на 2 точки вниз, здесь кнопка уже сдвинута по вертикали
   на -50% ради центровки в строке — складываем оба сдвига через
   calc(), иначе один «transform» затирал бы другой. */
#экран-друга .кнопка.кнопка--мелкая.знакомые__позвать:active,
#лист-места .кнопка.кнопка--мелкая.знакомые__позвать:active {
  /* Сдвиг при нажатии, совместимый с центровкой по вертикали */
  transform: translateY(calc(-50% + 2px));
}

.знакомые__имя {
  font-size: 15px;
  text-align: left;
}

/* Кто не за столом — тише: имя обычным весом и приглушённым цветом.
   Так играющие выделяются не только пометкой, но и самим именем. */
.знакомые__строка:not(.знакомые__строка--за-столом) .знакомые__имя {
  font-weight: 600;
  color: var(--текст-тихий);
}

/* ---------- Сейчас за столом ----------

   Три отличия разом, каждое работает на своём расстоянии:
     • строка обведена цветом подсветки и чуть подкрашена — та же
       краска, что у «это вы» в прихожей: «здесь кто-то живой»;
     • слева зелёная точка — та зелень, которой в игре помечено
       «можно ходить»; её видно боковым зрением раньше слов;
     • справа пометка словами в плашке цвета кнопки Telegram: белым
       по цвету темы, как кнопка, — читается в любой теме и с первого
       взгляда, потому что это единственное залитое пятно в блоке. */
.знакомые__строка--за-столом {
  border-color: var(--акцент);
  background: color-mix(in srgb, var(--акцент) 16%, var(--подложка));
}

.знакомые__метка {
  font-size: 18px;
  line-height: 1;
  color: var(--карта-можно);
  text-align: center;
}

.знакомые__где {
  padding: 2px 9px 3px;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.3;
  white-space: nowrap;
  color: var(--кнопка-текст);
  background: var(--кнопка-фон);
  border-radius: 999px;
}

/* У того, кто не за столом, пометка пустая — плашки быть не должно. */
.знакомые__где:empty { display: none; }

/* «Пока никого» у новичка и «Минутку…» — общая плашка «пусто»:
   тихая, с подложкой, читается как объяснение, а не как ошибка.
   Здесь только кегль поменьше: блок второстепенный. */
.знакомые .таблица__пусто {
  padding: 10px 12px;
  font-size: 13.5px;
}

/* Подпись под списком — сноска: «Видно только тех, кто сейчас играет
   на этом сервере». */
#знакомые-подпись {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.35;
  text-align: center;
}

/* Причина, почему список не свежий: «Сервер игры не ответил. Кто из
   знакомых сейчас за столом — неизвестно». Игра ставит её своим узлом
   перед общей подписью. Заметно, но не тревожно: своя строка, обычный
   цвет текста и вес 600 против тихой сноски — глаз её не пропустит;
   а красного и восклицаний нет — это не поломка, список просто старый. */
.знакомые__причина {
  display: block;
  margin-bottom: 3px;
  font-weight: 600;
  color: var(--текст);
}

/* ---------- Код комнаты — главный предмет этого экрана ----------

   Раньше плашка была белой в любой теме — той же кремовой бумагой,
   что и карты: чёрное на светлом читается лучше всего и не зависит
   от того, какие цвета пришлют из Telegram. Смотритель нашёл в этом
   нарушение: кремовый рядом с салатовым — уже два ярких цвета,
   а правило владельца — акцент один. Заменили на тёмную подложку
   сборника (--плитка) с салатовой рамкой (--акцент) и светлым текстом
   (--сб-текст): контраст у пары «почти белый на очень тёмном» не ниже,
   чем был у «почти чёрный на кремовом» (посчитан отдельно, около 16:1 —
   даже выше многих обычных тёмных панелей), так что читаемость код
   не потерял, а второй яркий цвет со страницы ушёл. Код здесь
   не «текст на странице», а вещь, которую переписывают на бумажку
   и диктуют вслух, — ему нужна максимальная разборчивость.

   Шрифт моноширинный: в нём у знаков одинаковая ширина и более
   строгое начертание, поэтому «S» не путается с «5», а «Q» — с «G».
   Сами похожие знаки из кода убраны на сервере (нет нуля и буквы O,
   нет единицы, I и L), шрифт добивает остальное.

   Просветы между знаками (letter-spacing) нужны, чтобы четыре знака
   читались как четыре отдельных, а не как слово. Просвет добавляется
   и после последнего знака, из-за чего строка кажется сдвинутой
   влево, — text-indent ровно на ту же величину возвращает её
   на середину. */

.код-игры {
  max-width: 100%;
  padding: 10px 16px;
  /* Только системные шрифты: ничего не скачивается, работает без сети */
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", "Courier New", monospace;
  /* Кегль растёт вместе с экраном: на узком телефоне 42–53 точки,
     на обычном около 74. Больше 76 не даём — на широком экране
     код и так виден с вытянутой руки. */
  font-size: clamp(42px, 19vw, 76px);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: 0.16em;
  text-indent: 0.16em;
  text-align: center;
  /* Перенос нарочно не запрещаем: код всегда из четырёх знаков и в
     строку помещается с запасом, но если он когда-нибудь станет
     длиннее, плашка перенесёт его на две строки, а не вылезет
     за край экрана. */
  color: var(--сб-текст);
  background: var(--плитка);
  border: 3px solid var(--сб-акцент);
  border-radius: 16px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.38);
  /* По всей игре выделение текста выключено, чтобы карты не
     подсвечивались при долгом нажатии. Коду выделение возвращаем:
     его удобно скопировать и переслать другу сообщением. */
  -webkit-user-select: text;
  user-select: text;
}

/* Кода ещё нет — плашка стоит пустая, с точками. Точки нарочно бледные
   (полупрозрачный светлый текст на тёмной плитке), рамка тихая
   (--плитка-кромка) вместо салатовой, тени нет: видно, что это не
   значение, а место под него, и диктовать пока нечего. Как только код
   приходит, игра снимает этот класс, и плашка загорается в полную
   силу — сама эта перемена и говорит «код готов». Читаемость тут
   нарочно ниже нормы: норма — про текст, который надо прочитать,
   а эти точки читать не нужно и нельзя. */
.код-игры--ждём {
  color: rgba(248, 245, 235, 0.45);
  border-color: var(--плитка-кромка);
  box-shadow: none;
}

/* ---------- «Ждём, когда друг войдёт…» ----------
   К словам добавлено вращающееся колечко: без него непонятно,
   ждёт игра чего-то или просто зависла.

   Колечко стоит прямо в строке текста, как буква, — и это не мелочь,
   а починка. Раньше строка была «рядом из двух ячеек»: слева колечко,
   справа текст. Пока надпись помещалась в одну строку, всё выглядело
   верно. Но на узком телефоне (280 точек) надпись переносится на две
   строки, ячейка с текстом при этом остаётся во всю оставшуюся ширину,
   а строки внутри неё встают по центру — и колечко оказывалось у самого
   левого края экрана, в стороне от своих слов, как случайное пятно.
   Теперь колечко — часть первой строки: куда уезжает текст, туда и оно,
   при любой ширине экрана. */

.сеть-ожидание {
  max-width: 330px;
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.35;
  text-align: center;
  color: var(--текст);
}

.сеть-ожидание::before {
  content: "";
  display: inline-block;
  /* Чуть ниже базовой линии — так кружок приходится ровно на высоту
     заглавной буквы и не «висит» над строкой. */
  vertical-align: -3px;
  width: 16px;
  height: 16px;
  margin-right: 8px;
  border: 3px solid var(--край);
  border-top-color: var(--акцент);
  border-radius: 50%;
  animation: колечко-ожидания 1.1s linear infinite;
}

@keyframes колечко-ожидания {
  to { transform: rotate(360deg); }
}

/* ---------- Кружок ожидания на подсказке стола и на плашке итога ----------
   Та же вертушка, что у «сеть-ожидания» (тот же keyframes, второй не заводим),
   только цвет берём из текста строки (currentColor), а не из своих переменных:
   класс ставится то на приглушённую подсказку, то на белую строку итога,
   и кольцо должно подстраиваться под обе. Разрыв кольца рисуем прозрачным
   верхним краем — на однотонном currentColor иначе вращения не увидеть.
   Класс вешает js/game.js на тот узел, где стоит текст «Ждём…»: спан
   подсказки, саму коробку подсказки (запасной путь) или плашку «серия-итога». */
.ожидание-крутится::before {
  content: "";
  display: inline-block;
  flex: 0 0 auto;
  vertical-align: -0.12em;
  width: 1em;
  height: 1em;
  margin-right: 8px;
  border: 0.15em solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: колечко-ожидания 1.1s linear infinite;
}

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

.сеть-сообщение {
  width: min(100%, 330px);
  margin: 0;
  padding: 10px 12px;
  font-size: 14px;
  line-height: 1.4;
  text-align: left;
  /* В этих сообщениях игра называет адрес сервера целиком, а адрес —
     это одно длинное слово без пробелов. Обычные правила переноса
     такое слово не разрывают: оно вылезло бы за плашку и утащило
     за собой весь экран вбок. Разрешаем перенести его в любом месте —
     лучше адрес в две строки, чем прокрутка вбок. */
  overflow-wrap: anywhere;
  /* Цвет обычного текста на серой подложке: оба берутся из одной
     пары «фон — текст», поэтому читаются и в светлой теме,
     и в тёмной. Смешивать цвет текста с цветом кнопки нельзя —
     на этом в игре уже обжигались. */
  color: var(--текст);
  background: var(--подложка);
  border-left: 4px solid var(--акцент);
  border-radius: 4px 10px 10px 4px;
}

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

.поле-кода {
  width: min(100%, var(--колонка-кнопок));
  min-height: 62px;
  padding: 6px 10px;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", "Courier New", monospace;
  font-size: 34px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: 0.16em;
  text-indent: 0.16em;
  text-align: center;
  text-transform: uppercase;
  color: var(--сб-текст);
  background: var(--плитка);
  border: 2px solid var(--сб-акцент);
  border-radius: 12px;
  caret-color: var(--сб-акцент);
  -webkit-appearance: none;
  appearance: none;
  /* Обязательно: по всей игре выделение текста выключено, а без
     разрешения на выделение поле ввода на iPhone не даёт печатать. */
  -webkit-user-select: text;
  user-select: text;
}

.поле-кода::placeholder {
  font-weight: 400;
  /* Тихий текст сборника, а не отдельный серый «от себя»: на тёмной
     плитке даёт контраст около 5,5 — подсказку видно, и при этом
     её не спутаешь с набранным кодом (он жирный и светлый). Строка
     opacity нужна Firefox: он сам делает подсказку полупрозрачной. */
  color: var(--сб-текст-тихий);
  opacity: 1;
}

.поле-кода:focus {
  outline: 3px solid var(--сб-акцент);
  outline-offset: 2px;
  border-color: transparent;
}

/* ---------- Поле для адреса сервера ----------

   ЖАЛОБА ЖИВОГО ИГРОКА: «вылезло поле, в котором огромными буквами
   видно только "HTTP://127", остальное не помещается».

   Отчего так вышло. Поле адреса и поле кода — это один и тот же вид
   в разметке: у поля адреса стоят оба класса. Для кода из четырёх
   знаков всё правильно: 34 точки, заглавные, вразрядку, по центру —
   код диктуют вслух и переписывают на бумажку. Но адрес сервера
   не диктуют, а вставляют или правят, и он длинный: в
   «https://johnny-dense-shield.trycloudflare.com» сорок пять знаков.
   При кегле 34 с разрядкой в поле помещалось десять — то есть человек
   не видел даже, тот это адрес или чужой.

   Что делаем. Адрес — обычная строчка, поэтому: кегль 16 вместо 34,
   без заглавных, без разрядки, по левому краю. Теперь на телефоне
   в 390 точек видно больше тридцати знаков вместо десяти, на 320 —
   около тридцати: имя сервера читается целиком, и понятно, что за
   адрес в поле стоит.

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

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

   ПОЧЕМУ СЕЛЕКТОР С «input». Ниже, в правилах для низкого и узкого
   экрана, поле кода ужимается до 30 точек — и эти правила стоят
   в файле позже. Обычный класс они бы перебили, и на маленьком
   телефоне адрес снова стал бы огромным. Имя элемента в селекторе
   делает это правило тяжелее, и оно побеждает везде.

   Всё остальное — тёмная подложка, салатовая рамка, свечение при
   наборе, разрешение печатать на iPhone — берётся у «поле-кода»:
   оба класса на поле стоят нарочно, и второй раз то же самое
   не пишем. */

input.поле-адреса {
  /* Та же ширина, что у объяснений на этом экране, — поле встаёт
     с ними в один столбик, а не выпирает из него. */
  width: min(100%, 330px);
  min-height: 46px;          /* палец попадает: столько же, сколько у кнопки */
  padding: 9px 12px;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: normal;
  text-indent: 0;
  text-align: left;
  text-transform: none;
  /* Что не поместилось — многоточием. Пока в поле не печатают, браузер
     показывает его сам, и обрыв адреса не выглядит опечаткой. */
  text-overflow: ellipsis;
  border-radius: 10px;
}

/* ---------- Строка связи над столом ----------

   Одна полоска отвечает на вопрос «а друг вообще там?». У неё три
   состояния, и они должны различаться до чтения текста:

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

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

   Высота у полоски постоянная, на две строки текста: длинное
   сообщение о потерянной связи в одну строку не помещается,
   а прыгающая полоска сдвигала бы стол под руками у игрока. */

.связь {
  flex: 0 0 auto;
  align-self: center;
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: 100%;
  height: 34px;
  padding: 0 12px;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  color: var(--текст);
  background: var(--подложка);
  border-radius: 10px;
  overflow: hidden;
}

.связь::before {
  content: "";
  flex: 0 0 auto;
  width: 10px;
  height: 10px;
  margin-right: 8px;
  border-radius: 50%;
  /* Тот же зелёный, что у карты, которой можно ходить: в этой игре
     зелёный везде значит «всё в порядке». */
  background: var(--карта-можно);
}

/* Ожидание: плашка темнеет, кайма и точка янтарные. Свои цвета,
   не из темы: «ждём» должно выглядеть одинаково при любой теме.
   Первая строка фона — для браузеров без color-mix. */
.связь.связь--ожидание {
  color: #ffffff;
  background: rgba(20, 24, 30, 0.88);
  background: color-mix(in srgb, #f0b32d 20%, #10151b);
  box-shadow: inset 0 0 0 2px #f0b32d;
}

.связь--ожидание::before {
  background: #f0b32d;
  animation: связь-дышит 1.4s ease-in-out infinite;
}

/* Тревога: красная плашка и мигающий треугольник. Белый текст
   на этом красном даёт контраст 8,2 — читается при любой теме. */
.связь.связь--тревога {
  color: #ffffff;
  background: rgba(155, 26, 40, 0.94);
  background: color-mix(in srgb, var(--карта-отказ) 62%, #2a0409);
  box-shadow: inset 0 0 0 2px var(--карта-отказ);
}

/* Треугольник нарисован рамками — картинок в проекте нет */
.связь--тревога::before {
  width: 0;
  height: 0;
  border-radius: 0;
  background: transparent;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-bottom: 11px solid #ffffff;
  animation: связь-мигает 1.3s ease-in-out infinite;
}

@keyframes связь-дышит {
  0%, 100% { transform: scale(1);    opacity: 1; }
  50%      { transform: scale(0.55); opacity: 0.45; }
}

@keyframes связь-мигает {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.3; }
}

/* Если в телефоне выключены анимации, всё остаётся на месте:
   состояния и без движения различаются цветом и фигурой. */
@media (prefers-reduced-motion: reduce) {
  .сеть-ожидание::before,
  .связь--ожидание::before,
  .связь--тревога::before,
  .ожидание-крутится::before,
  #комната > .комната__начать.комната__ожидает::before {
    animation: none;
  }
}

/* Пока строка связи видна, она забирает свою высоту у стола: стол
   занимает остаток экрана и просто становится ниже. Вычитать её вручную
   больше не нужно. */

/* ================================================================
   ИГРА КОМПАНИЕЙ: выбор стола, прихожая и полоса соперников

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

     чей сейчас ход   — плашка соперника залита цветом, как
                        нажатая кнопка: она одна такая на полосе;
     кто отбивается   — плашка обведена той же краской, но
                        не залита, и слово состояния лежит
                        на цветной подложке с колечком-щитом;
     кто мой напарник — белая полоска у левого края плашки
                        и белый значок «напарник».

   Всё остальное — «выбыл», «ушёл», «нет связи» — нарочно тише:
   это справка, а не событие. Тише они не цветом (цвет пришлёт
   Telegram, и какой он будет — неизвестно), а отсутствием
   заливки: у выбывшего плашка пустая, с пунктирной каймой.
   ================================================================ */

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

.настройка-стола {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Девять точек, а не двенадцать: три ряда настроек стоят на самом
     длинном экране игры («Игра с ботом»), и в полном экране Telegram
     каждые сэкономленные три точки — это часть последней кнопки,
     которая иначе уходит под полосу жеста. */
  gap: 9px;
  width: 100%;
}

/* Ряд «2 3 4 5 6» — пять кнопок вместо привычных трёх. Кнопка выбора
   и так делит ширину поровну, но подпись у неё рассчитана на слово;
   здесь это одна цифра, поэтому боковые поля убираем, а саму цифру
   делаем крупнее — по ней целится палец, и её же читают глазами.
   Ширина одной кнопки выходит около 47 точек при высоте 44 — палец
   попадает свободно.

   Ряд — на экране «Игра с другом» («#выбор-мест»). Второй такой ряд
   был в старом меню дурака; меню убрано, правило осталось одно. */
#выбор-мест .кнопка.кнопка--выбор {
  padding: 8px 2px;
  font-size: 18px;
  font-variant-numeric: tabular-nums;
}

/* Строка «что получится при таком выборе». Место под неё отложено
   заранее: без этого кнопки прыгали вверх-вниз каждый раз, когда
   текст менялся с одной строки на три, и палец промахивался.
   Отложено четыре строки — столько занимает почти любой ответ.
   Самое длинное объяснение (парами и переводной разом) всё-таки
   длиннее и растянет плашку: обрезать его нельзя — это как раз
   те правила, ради которых человек сюда и смотрит.

   Строка — на экране «Игра с другом». */
#пояснение-стола {
  box-sizing: border-box;
  width: min(100%, 340px);
  /* Резерв под самое длинное пояснение — три строки: при кегле 13,5
     и междустрочии 1,35 это 55 точек, плюс поля 16. Кнопки от смены
     текста не прыгают: резерв держит самый длинный вариант. */
  min-height: 70px;
  margin: 0;
  padding: 8px 11px;
  font-size: 13.5px;
  line-height: 1.35;
  text-align: left;
  color: var(--текст-тихий);
  background: var(--подложка);
  border-radius: 10px;
}

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

.прихожая {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: 100%;
  max-width: 360px;
  padding: 10px 9px 11px;
  border: 1px solid var(--край);
  border-radius: 14px;
  /* Разрешаем прихожей сжиматься. Без этой строчки блок упирается
     в высоту своего содержимого и растёт вниз, сколько бы мест
     за столом ни было, — а вместе с ним уезжают за край экрана
     кнопки «Начать игру» и «Отменить игру», которые стоят ниже.
     Ужимается при этом только список мест (см. ниже): он длинный,
     но однообразный, и человеку достаточно видеть его часть.
     У кнопок такого запаса нет — их либо видно, либо нет. */
  min-height: 0;
}

/* Какой получился стол: «Играют шестеро, каждый сам за себя».
   Это заголовок прихожей, а не подпись, поэтому цвет обычный,
   не приглушённый: по этой строке человек проверяет, что создал
   именно то, что хотел. */
#прихожая-правила {
  margin: 0;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.3;
  text-align: center;
  color: var(--текст);
}

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

.список-мест {
  gap: 5px;
  width: 100%;
  /* Прокручиваться список уже умеет — это ему досталось от таблицы
     рекордов. Здесь только пол: ужать список меньше чем до двух
     строк нельзя, иначе от него не останется смысла. Если и после
     этого содержимое не помещается (совсем низкое окно), прокрутится
     весь экран, как и раньше. */
  min-height: 74px;

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

     Первая строка — для браузеров старше 2023 года, которые не знают
     color-mix: крышка там просто цвета темы, чуть отличного от сукна.
     Вторая — точный цвет сукна, тот же, что у поля игры. */
  background:
    linear-gradient(transparent, var(--фон)) bottom / 100% 14px local no-repeat,
    radial-gradient(farthest-side at 50% 100%, rgba(0, 0, 0, 0.42), transparent)
      bottom / 100% 9px scroll no-repeat;
  background:
    linear-gradient(transparent, color-mix(in srgb, var(--фон) 80%, #1f7a45))
      bottom / 100% 14px local no-repeat,
    radial-gradient(farthest-side at 50% 100%, rgba(0, 0, 0, 0.42), transparent)
      bottom / 100% 9px scroll no-repeat;
}

.список-мест .место-за-столом {
  grid-template-columns: 1.6em minmax(0, 1fr) auto auto;
  gap: 0 8px;
  padding: 7px 9px;
  border: 1px solid transparent;
  text-align: left;
}

/* Отменяем переезд колонок на вторую строку, который таблица
   рекордов включает на узком экране: здесь всё влезает в строку. */
.список-мест .место-за-столом__номер,
.список-мест .место-за-столом__имя,
.список-мест .место-за-столом__роль,
.список-мест .место-за-столом__связь {
  grid-area: auto;
}

.список-мест .место-за-столом__номер {
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.список-мест .место-за-столом__имя {
  font-size: 14px;
  text-align: left;
}

/* «хозяин», «бот» — кто это за столом; «на связи», «ждём» — как у него
   дела. Обе подписи мелкие и тихие: главное в строке — имя. */
.список-мест .место-за-столом__роль,
.список-мест .место-за-столом__связь {
  font-size: 11.5px;
  text-align: right;
}

/* Первую строку таблица рекордов обводит как чемпиона. В прихожей
   обводкой отмечено другое — «это вы»: своё место человек должен
   находить мгновенно, и оно далеко не всегда первое. */
.список-мест .место-за-столом:first-child {
  box-shadow: none;
}

.список-мест .место-за-столом--я {
  box-shadow: none;
  border-color: var(--акцент);
  background: color-mix(in srgb, var(--акцент) 16%, var(--подложка));
}

/* Свободное место — это дырка в столе, а не игрок. Поэтому заливки
   у него нет вовсе, кайма пунктирная, а подпись обычного веса:
   строка видна, но взгляд по ней скользит мимо. */
.список-мест .место-за-столом--пусто {
  background: transparent;
  border-style: dashed;
  border-color: var(--край);
}

.список-мест .место-за-столом--пусто .место-за-столом__имя {
  font-weight: 600;
  color: var(--текст-тихий);
}

/* ---------- Кто с кем в паре ----------

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

   Полосы РАЗНЫЕ НЕ ЦВЕТОМ, а рисунком: у первой пары она сплошная,
   у второй — из штрихов. Так сделано по двум причинам. Цвет пришлось
   бы выдумывать свой (тема Telegram присылает один акцент, и он уже
   занят пометкой «это вы»), а главное — каждый двенадцатый мужчина
   путает цвета, и для него две цветные полосы были бы одинаковыми.
   Сплошную и штриховую не спутать никому и ни в какой теме.

   Цвет у обеих один — цвет текста: он приходит из темы вместе с фоном
   и всегда на нём виден. Полоса лежит в собственном левом поле строки
   (девять точек, из них полоса занимает пять) — значит, ни высоты,
   ни ширины она у строки не отнимает и номер места не задевает. */

.список-мест .место-за-столом--пара-1,
.список-мест .место-за-столом--пара-2 {
  position: relative;
}

.список-мест .место-за-столом--пара-1::before,
.список-мест .место-за-столом--пара-2::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 5px;
  border-radius: 10px 0 0 10px;
  background: var(--текст);
}

/* Вторая пара — та же полоса, но из штрихов: четыре точки краски,
   четыре пустых. */
.список-мест .место-за-столом--пара-2::before {
  background: repeating-linear-gradient(
    var(--текст) 0 4px, transparent 4px 8px);
}

/* Сама подпись «пара 1» — тихая: она подтверждает полосу словами,
   а не спорит с именем. Стоит внутри ячейки имени, поэтому кегль
   задан долей от него. */
.список-мест .место-за-столом__пара {
  margin-left: 4px;
  padding: 1px 5px;
  font-size: 0.8em;
  font-weight: 700;
  white-space: nowrap;
  color: inherit;
  background: rgba(128, 128, 128, 0.3);
  background: color-mix(in srgb, currentColor 16%, transparent);
  border-radius: 6px;
}

/* ---------- Места, которые можно поменять местами ----------

   Хозяин стола нажимает на два места по очереди, и игроки меняются.
   Отсюда два требования, и оба про «понятно, что нажалось»:

   1) видно, что строка вообще нажимается. У хозяина строка чуть выше
      обычной и отзывается на нажатие; у остальных игроков она
      не меняется вовсе — обещать нажатие, которого не будет, нельзя;

   2) видно, какое место выбрано первым. Пока второе не нажато, игра
      ждёт, и человек должен понимать, что первое нажатие засчиталось.

   Выбранное место помечено не так, как «это вы»: там кайма цвета
   акцента и лёгкая заливка, а тут — толстая рамка внутрь, крупная
   заливка и номер, вывернутый наизнанку (белая цифра на цветном
   кружке). Эти две пометки могут стоять на одной строке разом
   (хозяин выбирает своё же место), и различить их надо с одного
   взгляда. */

.список-мест .место-за-столом--нажимается {
  cursor: pointer;
  /* Нажатие должно попадать пальцем. Полных сорока четырёх точек тут
     нет: тогда шесть мест не поместятся на экран целиком, а увидеть
     весь стол важнее (см. «Прихожая: место отдаём списку»). Строка
     при этом во всю ширину экрана — промахнуться вбок нельзя,
     а сверху и снизу её отделяет просвет. Там, где высоты вдоволь,
     строка подрастает — правило ниже, в разделе про высокий экран. */
  min-height: 30px;
}

/* Палец на строке: она темнеет и слегка вжимается. Отклик короткий —
   он должен успеть показаться до того, как игра перерисует список. */
.список-мест .место-за-столом--нажимается:active {
  background: color-mix(in srgb, var(--акцент) 26%, var(--подложка));
  transform: scale(0.985);
}

/* Два класса в селекторе нарочно. Первую строку списка таблица рекордов
   обводит как чемпиона, а прихожая эту обводку снимает — правилом
   «.место-за-столом:first-child { box-shadow: none }». Оно тяжелее
   обычного класса, и напиши мы здесь просто «выбрано», у ПЕРВОГО места
   рамка выбора не появилась бы вовсе. А хозяин чаще всего первым
   и нажимает на себя, чтобы выбрать напарника. */
.список-мест .место-за-столом.место-за-столом--выбрано {
  box-shadow: inset 0 0 0 2px var(--акцент);
  background: color-mix(in srgb, var(--акцент) 30%, var(--подложка));
}

/* Номер выбранного места — белая цифра на цветном кружке. Кружок
   рисуется полями внутри своей же колонки, поэтому строка от него
   не становится ни выше, ни шире. */
.список-мест .место-за-столом--выбрано .место-за-столом__номер {
  color: var(--кнопка-текст);
  background: var(--акцент);
  border-radius: 999px;
  text-align: center;
  font-weight: 800;
}

/* ---------- Кнопки хозяина стола ----------
   Их три, и раньше все три были одинаково залиты — глаз не находил
   главную. Теперь старшинство видно: «Начать игру» залита и лежит
   отдельной строкой во всю ширину, а «Посадить бота» и «Убрать бота»
   стоят парой над ней и только обведены. Это те же кнопки-обводки,
   что «Играть с другом» в меню, — в игре они уже значат «действие
   есть, но оно не главное». */

.кнопки-хозяина {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  width: 100%;
}

#экран-комнаты .кнопки-хозяина .кнопка {
  flex: 1 1 0;
  width: auto;
  min-width: 0;
  padding: 10px 8px;
  font-size: 15px;
}

#экран-комнаты .кнопки-хозяина #кнопка-посадить-бота,
#экран-комнаты .кнопки-хозяина #кнопка-убрать-бота {
  color: var(--текст);
  background: var(--подложка);
  border: 2px solid var(--акцент);
  box-shadow: none;
}

#экран-комнаты .кнопки-хозяина .кнопка--главная {
  flex: 1 0 100%;
  font-size: 18px;
}

/* ---------- Прихожая: место отдаём списку мест ----------

   ЖАЛОБА ЖИВОГО ВЛАДЕЛЬЦА: «смотри, я не вижу всех 4-х мест, а тем
   более не увижу 6-ти». На его снимке из Telegram видно код, две
   кнопки, строку «Играют четверо, парами, 2 на 2» — и два с половиной
   места из четырёх. Остальные лежали за краем окошка списка.

   Отчего так вышло. Экран кода собран из семи блоков подряд: заголовок,
   объяснение, огромный код, «Позвать друга», «Скопировать код», сама
   прихожая, строка ожидания и «Отменить игру». Каждый из них взял
   столько, сколько просил, а прихожая стоит предпоследней — ей достался
   остаток. Остатка не хватило, список ужался до своего пола и
   прокрутился. В браузере на 844 точках это было почти незаметно
   (влезало пять мест из шести), а в Telegram окно ниже, да ещё и
   появляется кнопка «Позвать друга», которой в браузере нет.

   Что делаем. Отбираем понемногу у всех, кто стоит вокруг списка,
   и отдаём это списку. Считано по замеру на 390×844 с шестью местами:

     промежутки между блоками   14 → 8 точек   (восемь штук — 48)
     код игры                   74 → 49 точек кегля            (35)
     заголовок «Код игры»       28 → 22                         (7)
     объяснение под ним         15 → 13                         (2)
     обе кнопки под кодом       52 и 46 → по 44                (10)
     поля самой прихожей        10/11 → 8/9, просвет 8 → 6      (6)
     строки списка              7 → 5 точек поля, просвет 5 → 4 (29)
     кнопки хозяина             46/52 → 44/48, просвет 8 → 6   (10)

   Итого около полутора сотен точек — при том что шестому месту
   не хватало двадцати семи.

   КОД ПРИ ЭТОМ ОСТАЁТСЯ КРУПНЫМ, и это не переговорная позиция:
   его работа — быть продиктованным вслух и переписанным на бумажку.
   Сорок девять точек на телефоне 390 — это всё ещё вдвое крупнее
   заголовка экрана и втрое крупнее любой подписи; на снимке он
   по-прежнему первое, что видит глаз. Мельче 34 не даём никогда.

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

#экран-комнаты:has(#прихожая:not(.скрыт)) {
  gap: 8px;
  padding: calc(10px + var(--отступ-сверху)) calc(12px + var(--отступ-справа))
           calc(10px + var(--отступ-снизу))  calc(12px + var(--отступ-слева));
}

#экран-комнаты:has(#прихожая:not(.скрыт)) .заголовок { font-size: 22px; }

#экран-комнаты:has(#прихожая:not(.скрыт)) > .подпись { font-size: 13px; }

#экран-комнаты:has(#прихожая:not(.скрыт)) .код-игры {
  font-size: clamp(34px, 12.5vw, 50px);
  padding: 7px 14px;
}

/* Кнопки под кодом. Сорок четыре точки — нижний предел, ниже которого
   в кнопку не попадают пальцем; «Позвать друга» была главной и просила
   пятьдесят две. Здесь ей хватает общей высоты: она и так стоит первой
   и залита цветом, а лишние восемь точек нужнее списку. */
#экран-комнаты:has(#прихожая:not(.скрыт)) #кнопка-позвать-друга,
#экран-комнаты:has(#прихожая:not(.скрыт)) #кнопка-копировать-код {
  min-height: 44px;
  padding: 9px 16px;
  font-size: 16px;
}

#экран-комнаты:has(#прихожая:not(.скрыт)) .прихожая {
  gap: 6px;
  padding: 8px 8px 9px;
}

#экран-комнаты:has(#прихожая:not(.скрыт)) #прихожая-правила {
  font-size: 13.5px;
}

/* Пять точек поля сверху и снизу вместо семи оставляют строке около
   тридцати точек: имя в 14 точек стоит в ней свободно, и строки
   не слипаются. Хозяин по строкам ещё и нажимает (пересадка игроков),
   и там, где высоты хватает, они подрастают до сорока — см. раздел
   «Места, которые можно поменять местами». */
#экран-комнаты:has(#прихожая:not(.скрыт)) .список-мест { gap: 4px; }

#экран-комнаты:has(#прихожая:not(.скрыт)) .место-за-столом {
  padding: 5px 9px;
}

/* А вот кнопки хозяина остаются кнопками: 44 точки — это то,
   во что попадает палец. Убавлен только просвет между ними. */
#экран-комнаты:has(#прихожая:not(.скрыт)) .кнопки-хозяина { gap: 6px; }

#экран-комнаты:has(#прихожая:not(.скрыт)) .кнопки-хозяина .кнопка {
  min-height: 44px;
}

#экран-комнаты:has(#прихожая:not(.скрыт)) .кнопки-хозяина .кнопка--главная {
  min-height: 48px;
  font-size: 17px;
}

/* Строка ожидания под прихожей выросла втрое: к «Скажите друзьям код»
   добавилось объяснение про пересадку игроков. Три строки по 15 точек
   занимают 83 точки — почти три места в списке. Кегль 12,5 оставляет
   те же три строки, но забирает у них 34 точки. Это подпись-объяснение,
   а не то, что читают каждую секунду, и мельче она читается спокойно. */
#экран-комнаты:has(#прихожая:not(.скрыт)) .сеть-ожидание {
  font-size: 12.5px;
  line-height: 1.3;
}

/* ---------- Прихожая, когда окно ниже 780 точек ----------

   Внутри Telegram окно игры всегда ниже, чем экран телефона: сверху
   лежит шапка приложения. На телефоне 390×844 игре достаётся около
   760 точек — и ровно в этой полосе (от 700 до 780) прихожая с шестью
   местами переставала помещаться, хотя по всем правилам выше она уже
   ужата.

   Убираем объяснение «Продиктуйте или перешлите этот код другу»:
   с ним рядом стоят две кнопки — «Позвать друга» и «Скопировать код», —
   которые говорят то же самое и делом. На высоком экране объяснение
   остаётся: там за него не платят местом. */

@media (max-height: 780px) {
  #экран-комнаты:has(#прихожая:not(.скрыт)) > .подпись {
    display: none;
  }
}

/* А на высоком экране, наоборот, отдаём лишнюю высоту строкам списка:
   у хозяина они нажимаются (пересадка игроков), и чем крупнее цель,
   тем меньше он промахнётся. Сорок точек вместо тридцати — это ещё
   шестьдесят точек на шесть мест, и на экране в 844 точки они есть
   с запасом. Ниже 781 этого запаса нет, и там строки остаются
   тесными: увидеть все шесть мест важнее. */
@media (min-height: 781px) {
  #экран-комнаты:has(#прихожая:not(.скрыт)) .место-за-столом--нажимается {
    min-height: 40px;
  }
}

/* ---------- Прихожая на невысоком экране ----------

   Находка тестировщика: окно 320×568, стол на шестерых — кнопка
   «Начать игру» обрезана нижним краем экрана, а «Отменить игру»
   висит совсем за ним. Прокрутка была, но человек про неё
   не догадывался: список мест выглядел законченным.

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

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

   1) объяснение «Продиктуйте или перешлите этот код другу». Ровно то же
      самое сказано рядом двумя кнопками — «Позвать друга» и
      «Скопировать код», — а под кодом уже стоит список мест, и человек
      занят им, а не чтением. На высоком экране объяснение остаётся.

   2) строку «Скажите друзьям код. Все собрались — нажмите „Начать
      игру“» — но только у хозяина стола. У него прямо под списком
      лежит сама кнопка «Начать игру», и строка повторяет её словами.
      Гостю, у которого кнопок нет, строка остаётся: для него это
      единственный ответ на вопрос «чего мы ждём», и колечко в ней —
      единственный признак, что игра жива.

   Правила включаются только тогда, когда прихожая на экране
   (в обычной игре вдвоём её нет вовсе) и только на невысоком
   экране: на большом телефоне всё и так помещается свободно. */

@media (max-height: 700px) {
  #экран-комнаты:has(#прихожая:not(.скрыт)) {
    gap: 7px;
    padding: calc(8px + var(--отступ-сверху)) calc(10px + var(--отступ-справа))
             calc(8px + var(--отступ-снизу))  calc(10px + var(--отступ-слева));
  }

  /* Код остаётся самым крупным на экране, но в прихожей ему хватает
     сорока с небольшим точек: его диктуют, а не читают через стол. */
  #экран-комнаты:has(#прихожая:not(.скрыт)) .код-игры {
    font-size: clamp(30px, 11vw, 46px);
    padding: 6px 14px;
  }

  #экран-комнаты:has(#прихожая:not(.скрыт)) > .подпись {
    display: none;
  }

  /* Хозяину строку ожидания не показываем: у него есть кнопка. */
  #экран-комнаты:has(#прихожая:not(.скрыт)):has(.кнопки-хозяина:not(.скрыт))
    .сеть-ожидание {
    display: none;
  }

  #экран-комнаты:has(#прихожая:not(.скрыт)) .прихожая {
    gap: 5px;
    padding: 7px 8px 8px;
  }

  /* Строки списка ещё теснее: здесь важнее увидеть все шесть мест,
     чем дать каждому по сорок четыре точки под палец. */
  #экран-комнаты:has(#прихожая:not(.скрыт)) .список-мест { gap: 4px; }

  #экран-комнаты:has(#прихожая:not(.скрыт)) .место-за-столом {
    padding: 4px 8px;
  }

  #экран-комнаты:has(#прихожая:not(.скрыт)) .кнопки-хозяина { gap: 6px; }

  /* А вот кнопки остаются кнопками: 44 точки высоты — это то,
     во что попадает палец, и отнимать у них высоту нельзя. */
  #экран-комнаты:has(#прихожая:not(.скрыт)) .кнопки-хозяина .кнопка {
    min-height: 44px;
  }

  #экран-комнаты:has(#прихожая:not(.скрыт)) .кнопки-хозяина .кнопка--главная {
    min-height: 48px;
  }

  /* Строку ожидания здесь не трогаем: кегль ей уже убавлен разделом
     выше, а у хозяина её и вовсе нет. */

  /* ---------- Правила на невысоком экране ----------

     Сейчас это правила шашек: у дурака свой тёмный экран правил
     со своими правилами для низкого окна (раздел «КАК ИГРАТЬ, РЕКОРДЫ,
     ОФОРМЛЕНИЕ ДУРАКА» в конце файла).

     Невысоких телефонов полно, а в шторке Telegram высоты ещё меньше,
     поэтому ужимаем всё, что вокруг текста, — шапку, поля, просветы
     между плашками. Сам текст оставляем крупным: мельче 15 точек его читать
     неприятно, а читают тут именно его. Прокрутка остаётся только
     на совсем маленьких экранах — обрезанная плашка сама говорит,
     что список продолжается. */
  #экран-правил {
    gap: 8px;
    padding: calc(10px + var(--отступ-сверху)) calc(10px + var(--отступ-справа))
             calc(10px + var(--отступ-снизу))  calc(10px + var(--отступ-слева));
  }
  #экран-правил .заголовок { font-size: 22px; }
  .правила { gap: 6px; }
  .правила .подпись {
    padding: 8px 10px 9px 30px;
    text-indent: -20px;
    font-size: 15px;
    line-height: 1.4;
  }
}

/* ---------- Кнопка, которую сейчас нажимать нечем ----------
   «Начать игру» не работает, пока за столом один человек, а кнопки
   прихожей выключаются на время, пока сервер отвечает. Своего вида
   у выключенной кнопки в игре не было вовсе: она выглядела точно
   как рабочая, человек жал её и решал, что игра зависла.
   Гасим её не прозрачностью (от неё подпись становится нечитаемой),
   а снятием заливки: остаётся спокойная серая плашка — видно, что
   кнопка есть, но сейчас она молчит. */
.кнопка:disabled {
  color: var(--текст-тихий);
  background: var(--подложка);
  border: 1px solid var(--край);
  box-shadow: none;
  cursor: default;
}

.кнопка:disabled:active {
  transform: none;
}

/* ---------- Полоса соперников над столом (компания) ----------
   Компанией чужие карты не рисуем: пять вееров рубашек не помещаются
   на телефон и ничего не сообщают. Вместо них — места: аватар, имя,
   сколько карт и что с человеком происходит.

   Как выглядят места на новом столе — в разделе стола в конце файла
   («Компания: соперники над столом»). Здесь только основа, общая для
   любой раскладки: полоса в ряд, и место — мерка для своих надписей
   («container-type»: кегли внутри считаются от ширины самого места,
   а не экрана — тесно бывает месту, а не телефону). */
.соперники {
  flex: 0 0 auto;
  display: flex;
  width: 100%;
}

.соперник {
  position: relative;
  box-sizing: border-box;
  min-width: 0;
  container-type: inline-size;
}

/* ПРОБЕЛ МЕЖДУ ЧИСЛОМ И СЛОВОМ («6 карт») РИСУЕМ САМИ. В разметке между
   ними стоит настоящий пробел отдельным узлом, но «флекс» пробельные узлы
   выбрасывает молча — на снимке стояло «6карт» слитно. Доля кегля,
   а не точки: на узком месте просвет ужимается вместе с надписью. */
.соперник__число + .соперник__слово { margin-left: 0.35em; }

/* Уровень бота и слово состояния («ходит», «отбивается») стоят в одной
   строке места, и вместе они не влезают: пока соперник ходит, отбивается
   или потерял связь, уровень уступает строку и не показывается вовсе.
   Уровень — справка на всю партию, он одинаков у всех ботов за столом;
   состояние меняется каждый ход, и видно должно быть его. */
.соперник:has(.соперник__метка) .соперник__роль {
  display: none;
}

/* Уровень у выбывшего и ушедшего не показываем совсем: он уже не играет,
   а читать на его месте надо другое — кто теперь ходит с его места
   («играет Бот 4»). */
.соперник--выбыл .соперник__роль,
.соперник--ушёл .соперник__роль {
  display: none;
}

/* Значки перед словом состояния — чтобы два состояния не спутать даже
   краем глаза: у защитника колечко-щит, у того, кто ходит, — стрелка.
   Оба меряются долями кегля («em»): слово то крупнее, то мельче (от
   ширины места), и значок растёт вместе с ним. Нарисованы средствами
   CSS, а не буквой: значки-стрелки на части телефонов подменяются
   цветным эмодзи. В самом узком месте значки убираются (см. раздел
   стола в конце файла) — там слово важнее. */
.соперник--отбивается .соперник__метка::before {
  content: "";
  display: inline-block;
  vertical-align: -0.08em;
  width: 0.72em;
  height: 0.72em;
  margin-right: 0.35em;
  border: 0.16em solid currentColor;
  border-radius: 50%;
}

/* Защитник, чей сейчас черёд (у него обе пометки разом), остаётся
   с колечком-щитом: стрелка на защитнике читалась бы как «он ходит».
   Значок говорит, ЧТО человек делает, салатовый — ЧЕЙ сейчас черёд. */
.соперник--ходит:not(.соперник--отбивается) .соперник__метка::before {
  content: "";
  display: inline-block;
  vertical-align: -0.05em;
  width: 0;
  height: 0;
  margin-right: 0.35em;
  border: 0.38em solid transparent;
  border-right: 0;
  border-left: 0.55em solid currentColor;
}

/* Кнопки хода компанией («Пас», «Перевести», «Бросить») — в разделе
   стола в конце файла («Панель действий»): там у всех кнопок хода
   один вид, а различает их значок перед словом. */

/* ---------- Невысокое окно (шторка Telegram) ---------- */

@media (max-height: 620px) {
  .заголовок { font-size: 26px; }
  #экран-результата .заголовок { font-size: 23px; }

  /* Просветы в низком окне и так сжаты до девяти точек, поэтому сноску
     подтягиваем к своей кнопке слабее — иначе она к ней прилипнет. */
  .сноска { margin-top: -3px; font-size: 12px; }
  #экран-рекордов .заголовок { font-size: 22px; }

  /* Плашка «Что было» в шторке. Собираем высоту по мелочи — с полей,
     просветов и заголовка, — чтобы в список поместилось на новость
     больше. Кегль самих новостей не трогаем: читать их всё равно
     придётся, а мелкий текст в шторке читается хуже всего.
     Заголовок назван с идентификатором нарочно — по той же причине,
     что и у меню тремя строками выше. */
  #экран-ленты {
    gap: 6px;
    padding: 9px calc(8px + var(--отступ-справа))
             calc(9px + var(--отступ-снизу)) calc(8px + var(--отступ-слева));
  }
  #экран-ленты .заголовок { font-size: 20px; }
  #лента-событий { gap: 4px; }
  #лента-событий .таблица__строка { padding: 6px 9px 7px; }
  /* Свежей строке левое поле уменьшено на ширину её полосы — иначе
     текст в ней встанет правее, чем у соседей, и столбик поедет. */
  #лента-событий .таблица__строка--свежая { padding-left: 5px; }

  /* Плашка итога не должна съесть пол-экрана: подписи мельче и теснее */
  #экран-результата {
    gap: 8px 10px;
    padding: 12px calc(12px + var(--отступ-справа))
             calc(12px + var(--отступ-снизу)) calc(12px + var(--отступ-слева));
  }
  #экран-результата .подпись { font-size: 13px; }
  .серия { font-size: 16px; padding: 4px 12px; }
  #экран-результата .кнопка--главная { min-height: 46px; font-size: 18px; }

  /* Плашка «точно выйти?» ужимается так же, как итог: вопрос из двух
     строк и две кнопки должны помещаться в шторку Telegram. */
  #экран-выхода {
    gap: 8px 10px;
    padding: calc(12px + var(--отступ-сверху)) calc(12px + var(--отступ-справа))
             calc(12px + var(--отступ-снизу))  calc(12px + var(--отступ-слева));
  }
  #экран-выхода .заголовок { font-size: 21px; }
  #экран-выхода .подпись { font-size: 13px; }
  #экран-выхода .кнопка--главная { min-height: 46px; font-size: 18px; }

  /* Экраны игры вдвоём в шторке: заголовки и просветы ужимаются,
     чтобы столбик целиком помещался без прокрутки. Селекторы
     повторены с идентификатором — иначе правила выше, у которых
     идентификатор есть, окажутся сильнее и ничего не изменится. */
  #экран-друга,
  #экран-комнаты,
  #экран-входа {
    gap: 10px;
    padding: calc(10px + var(--отступ-сверху)) calc(12px + var(--отступ-справа))
             calc(10px + var(--отступ-снизу))  calc(12px + var(--отступ-слева));
  }

  #экран-друга   .заголовок,
  #экран-комнаты .заголовок,
  #экран-входа   .заголовок { font-size: 22px; }

  #экран-друга   > .подпись,
  #экран-комнаты > .подпись,
  #экран-входа   > .подпись { font-size: 14px; }

  /* Код остаётся самым крупным на экране, но в низком окне ему
     хватает 60 точек: рядом должны поместиться заголовок,
     объяснение и кнопка отмены. */
  .код-игры { font-size: clamp(38px, 16vw, 60px); padding: 8px 14px; }

  .поле-кода { min-height: 54px; font-size: 30px; }

  /* Полоска связи тоже ниже. Две строки по 12,5 точки просят ровно 30,
     но даём 32: у разных телефонов шрифты чуть выше или ниже, и на
     впритык подогнанной полоске второй строке срезало бы нижние хвостики
     букв. Стол под неё подстраивается сам — он забирает остаток высоты. */
  .связь { height: 32px; font-size: 12.5px; }

  /* Прихожая и выбор стола в шторке: просветы и место под пояснение
     ужимаются, иначе список из шести мест не помещается вместе
     с кодом и кнопками. */
  .настройка-стола { gap: 8px; }
  #пояснение-стола { min-height: 68px; font-size: 12.5px; padding: 6px 9px; }
  .прихожая { gap: 6px; padding: 8px 8px 9px; }
  .список-мест .место-за-столом { padding: 5px 8px; }
  .список-мест .место-за-столом__имя { font-size: 13px; }

  /* Стол дурака в низком окне (соперники, стол, рука, подсказка)
     ужимается в своём разделе в конце файла. */
}

/* ---------- Узкий экран ---------- */

@media (max-width: 330px) {
  /* Стол дурака на узком экране ужимается сам — его размеры считаются
     от ширины экрана и стола (см. раздел стола в конце файла). */

  .кнопка { min-width: 100px; padding: 10px 14px; font-size: 16px; }
  .кнопка--главная { min-width: 160px; }
  .кнопка.кнопка--мелкая { padding: 8px 9px; font-size: 12px; }
  .кнопка.кнопка--выбор { font-size: 13px; padding: 8px 2px; }

  /* Плашка выхода: кнопка «Продолжить партию» длинная, на 280 точках
     ей нужен весь ряд, поэтому подпись на ней мельче. */
  #экран-выхода .кнопка--главная { font-size: 17px; }

  /* Экраны игры вдвоём на узком телефоне. Код по-прежнему считается
     от ширины экрана (19vw), поэтому сам ужимается; поджимаем всё
     вокруг него, чтобы ничего не выходило за край. */
  #экран-друга,
  #экран-комнаты,
  #экран-входа {
    padding-left: calc(10px + var(--отступ-слева));
    padding-right: calc(10px + var(--отступ-справа));
  }

  #экран-друга   .кнопка.кнопка--мелкая,
  #экран-комнаты .кнопка.кнопка--мелкая,
  #экран-входа   .кнопка.кнопка--мелкая { min-width: 130px; }

  .код-игры { padding: 8px 12px; border-width: 2px; }
  .поле-кода { font-size: 30px; }
  .сеть-сообщение { font-size: 13px; padding: 9px 10px; }
  .сеть-ожидание { font-size: 14px; }
  .связь { font-size: 12px; padding: 0 8px; }

  /* Правила на узком телефоне. Строка тут короче на пять-шесть букв,
     поэтому поля у плашки и висячий отступ номера чуть теснее —
     каждая отвоёванная точка это буква, которая не уехала на новую
     строку. Кегль 15: ниже него текст правил уже не читается спокойно. */
  #экран-правил { padding-left: 8px; padding-right: 8px; }
  .правила .подпись {
    padding: 9px 10px 10px 30px;
    text-indent: -20px;
    font-size: 15px;
  }

  /* В таблице рекордов на узком телефоне сжимаем только поля и мелкий
     текст. Раскладка в две строчки у неё теперь всегда — она задана
     выше, отдельно повторять её здесь не нужно. */
  #таблица-рекордов .таблица__строка { gap: 1px 5px; padding: 6px 8px 7px; }
  #таблица-рекордов .таблица__очки   { font-size: 15px; }
  #таблица-рекордов .таблица__дата,
  #таблица-рекордов .таблица__сложность { font-size: 11.5px; }

  /* Плашка «Что было» на узком телефоне. Ужимаем только поля и колонку
     с номером: каждая отвоёванная точка ширины — это буква новости,
     которая не уехала на вторую строку. Сам текст остаётся прежнего
     размера, читать его придётся в любом окне. */
  #экран-ленты { padding-left: 8px; padding-right: 8px; }
  #лента-событий .таблица__строка {
    grid-template-columns: 1.5em minmax(0, 1fr);
    gap: 2px 7px;
    padding: 7px 8px 8px;
  }
  #лента-событий .таблица__строка--свежая { padding-left: 4px; }

  /* Выбор стола на узком телефоне. Пояснению нужно больше строк —
     строка короче, а текст тот же, — поэтому место под него больше. */
  #пояснение-стола { min-height: 96px; font-size: 13px; padding: 7px 9px; }
  #выбор-мест .кнопка.кнопка--выбор { font-size: 16px; }

  /* Прихожая: поля теснее, подписи мельче. Строка места остаётся
     в одну линию — «Игрок 1 — вы · хозяин · на связи» на 280 точках
     ещё помещается, а длинное имя обрежется многоточием. */
  .прихожая { padding: 9px 7px 10px; }
  .список-мест .место-за-столом { gap: 0 6px; padding: 6px 7px; }
  .список-мест .место-за-столом__имя { font-size: 13px; }
  .список-мест .место-за-столом__роль,
  .список-мест .место-за-столом__связь { font-size: 10.5px; }
  #экран-комнаты .кнопки-хозяина .кнопка { font-size: 13px; padding: 10px 4px; }
  #экран-комнаты .кнопки-хозяина .кнопка--главная { font-size: 17px; }
}

/* ---------- Узкий и невысокий разом ----------
   Такое окно бывает чаще, чем кажется: шторка Telegram на маленьком
   телефоне. Правила для узкого экрана записаны в файле ниже правил для
   низкого окна, поэтому при равном весе побеждают они — и строке
   объяснения под выбором стола доставалось место под четыре строки
   (96 точек), рассчитанное на высокий экран. В окне 320×568 эти
   96 точек и выталкивали кнопку «Играть» за нижний край.

   Здесь возвращаем ей шторочный размер. Строка не обрезается:
   при таком кегле в неё помещается любое обычное объяснение,
   а самое длинное (парами и переводной разом) по-прежнему растянет
   плашку само, ничего не потеряв. */

@media (max-width: 330px) and (max-height: 620px) {
  #пояснение-стола { min-height: 68px; font-size: 12.5px; padding: 6px 9px; }
}

/* =====================================================================
   ЗНАКИ ВНИМАНИЯ: смайлики и готовые фразы

   ЖАЛОБА ЖИВОГО ВЛАДЕЛЬЦА: «смайлики работают, но их плохо видно, пусть
   всплывают по центру экрана справа крупно и через 2 сек медленно
   исчезают».

   Как было. Знак висел маленьким тёмным облачком у плашки того, кто его
   сказал: смайлик в 24 точки, вся плашка около 50 точек на 36 — вчетверо
   мельче игральной карты. Стояло облачко у самого края руки и вдобавок
   наезжало на строку подсказки. Замысел был правильный (видно, КТО
   сказал), но на телефоне это читалось как случайное пятнышко.

   Как стало. Знак всплывает у правого края, ровно по середине высоты
   экрана, и он крупный: смайлик — полсотни точек (это ширина игральной
   карты), фраза — жирной строкой на плашке с каймой и тенью. Полторы
   секунды висит, потом тает — рывком не пропадает.

   ЧЕГО ЗНАК НЕ ЗАКРЫВАЕТ. Это главное ограничение, и оно проверено
   замером на обоих телефонах:
     колода и метка козыря  — стоят у ЛЕВОГО края, знак у правого;
     своя рука              — она в нижней четверти, знак по середине;
     «Беру», «Бито», «Пас»  — нижняя полоса, туда знак не достаёт;
     строка подсказки       — она над кнопками, знак кончается выше.
   Стол знак накрывает, и по-другому не выйдет: середина экрана — это
   и есть стол. Но накрывает он правый край поля и всего на две секунды,
   а взамен человек видит, что ему сказали.

   ===================================================================== */

/* ---------- Полка: где висят знаки ----------

   Игра складывает облачка в столбик («знаки-внимания») и кладёт его
   на игровой экран. Место столбика — здесь, и оно ровно такое, как
   просил владелец: правый край, середина высоты.

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

   Столбик растёт от середины в обе стороны: одно облачко стоит точно
   по центру, три (больше игра не показывает) расходятся вверх и вниз
   поровну. Прижат он к правому краю — «align-items: flex-end», —
   поэтому короткий смайлик и длинная фраза выстраиваются по одной
   линии справа, а не пляшут серединами. */
.знаки-внимания {
  position: fixed;
  right: max(10px, var(--отступ-справа));
  top: 50%;
  transform: translateY(-50%);
  /* Выше стола, карт и полосы плашек, но ниже плашки итога и панели
     выбора знаков (у тех 100): пока человек выбирает, что сказать,
     его прошлое облачко не должно лезть поверх кнопок. */
  z-index: 70;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  /* Сквозь полку нажимается то, что под ней: она висит над столом
     и не должна съедать тычки по картам. */
  pointer-events: none;
}

/* ---------- Само облачко ---------- */

.знак-внимания {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  /* Длинная фраза не растягивается на весь экран: «Спасибо за игру»
     занимает 168 точек из отведённых 230 и встаёт в одну строку,
     а на узком телефоне переносится на две. Шире брать нельзя —
     знак закроет весь стол вместо его края. */
  max-width: min(60vw, 230px);
  padding: 8px 14px 9px;
  text-align: center;
  /* Слово переносим по-живому, а слишком длинное ломаем, но за край
     плашки не выпускаем. */
  overflow-wrap: anywhere;

  color: var(--текст);
  background: var(--панель);
  /* Кайма цветом темы — то самое «бросается в глаза». Своей краски
     не берём: акцент приходит из Telegram и в любой теме контрастен
     и к сукну, и к плашке. */
  border: 2px solid var(--акцент);
  border-radius: 16px;
  /* Тень крупная и мягкая: знак висит над картами, и без тени он
     выглядел бы наклейкой, приклеенной к столу. */
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.5);

  /* Как знак ПОЯВЛЯЕТСЯ — коротким всплытием справа (см. ниже).
     «backwards» вместо «both» выбрано нарочно: «both» оставил бы
     на облачке последний кадр анимации навсегда, а кадр сильнее
     обычного правила — и затухание, которое рисуется переходом,
     просто не сработало бы. */
  animation: знак-всплыл 240ms ease-out backwards;

  /* Как знак ИСЧЕЗАЕТ. Само затухание включает игра, вешая пометку
     «гаснет» (см. ниже); здесь только сказано, за сколько и как.
     Срок вынесен в отдельную строку нарочно: он должен совпадать
     с числом «ЗНАК_ТАЕТ» в js/game.js, и менять его придётся сразу
     в двух местах — пусть в этом файле оно будет одно и на виду. */
  --знак-тает: 400ms;
  transition: opacity var(--знак-тает) linear,
              transform var(--знак-тает) ease-in;
}

/* Кто сказал. Строчка тихая и мелкая: она отвечает на вопрос «чьё это»,
   а читать в облачке нужно не её. Раньше вопроса не было вовсе —
   облачко висело у плашки говорящего, — но у края экрана без имени
   знак превращается в возглас из ниоткуда. */
.знак-внимания__кто {
  font-size: 11.5px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: 0.02em;
  opacity: 0.75;
}

/* Что сказали. Фраза — жирной строкой; читается с одного взгляда. */
.знак-внимания__что {
  font-size: clamp(15px, 4.6vw, 19px);
  font-weight: 700;
  line-height: 1.25;
}

/* Смайлик — это картинка, а не текст, и читать в нём нечего: даём ему
   вырасти во всю ладонь. Полсотни точек — это примерно ширина игральной
   карты на телефоне 390; крупнее делать некуда, знак начнёт спорить
   со столом. */
.знак-внимания--смайлик {
  max-width: none;
  padding: 5px 14px 7px;
}

.знак-внимания--смайлик .знак-внимания__что {
  font-size: clamp(40px, 13vw, 54px);
  line-height: 1.1;
}

/* Своё слово человек уже знает — оно тише чужого: кайма обычная,
   тень мельче. Кричать должен тот знак, который сказали ТЕБЕ. */
.знак-внимания--свой {
  border-color: var(--край);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4);
}

/* ---------- Когда заговорили трое разом ----------

   Больше трёх знаков игра не показывает, и это её потолок. Но три
   смайлика в полный рост — это 250 точек столбиком, и на телефоне
   в 640 точек такой столбик достаёт до строки подсказки. Случай редкий
   (три голоса за две секунды бывают только за столом компанией), но
   именно в нём знаки мешали бы игре, а не помогали.

   Поэтому когда на полке третье облачко, смайлики мельчают, а просвет
   между ними ужимается: столбик садится с 263 точек до 223 и снова
   умещается между столом и подсказкой. Фраз это не касается — они
   и втроём занимают меньше.

   «:has(> :nth-child(3))» читается как «у полки есть третий ребёнок».
   Браузеры старше 2023 года этого не поймут: там три смайлика разом
   останутся крупными, то есть будет ровно как сейчас. */
.знаки-внимания:has(> :nth-child(3)) {
  gap: 6px;
}

.знаки-внимания:has(> :nth-child(3)) .знак-внимания--смайлик .знак-внимания__что {
  font-size: clamp(32px, 10vw, 44px);
}

/* ---------- Как знак всплывает ----------
   Четверть секунды: вылетает справа, чуть перерастая себя, и встаёт
   на место. Это и есть «всплывает» — короткое движение с краю,
   от которого глаз сам поворачивается в нужную сторону. */
@keyframes знак-всплыл {
  from {
    opacity: 0;
    transform: translateX(26px) scale(0.84);
  }
  70% {
    opacity: 1;
    transform: translateX(0) scale(1.05);
  }
  to {
    opacity: 1;
    transform: translateX(0) scale(1);
  }
}

/* ---------- Как знак тает ----------

   Пометку «гаснет» вешает игра ровно за 400 миллисекунд до того, как
   снимет облачко со стола («ЗНАК_ТАЕТ» в js/game.js). ЭТИ ЧИСЛА ОБЯЗАНЫ
   СОВПАДАТЬ с длиной перехода выше: сделаем переход длиннее — знак
   оборвётся на полуслове, короче — постоит прозрачным пустым местом.
   Меняете там — поменяйте и здесь, это одно число в двух файлах.

   Тает знак не только прозрачностью, но и движением: уезжает вправо,
   откуда пришёл, и слегка уменьшается. Так понятнее, что он ушёл сам,
   а не мигнул экран. */
.знак-внимания--гаснет {
  opacity: 0;
  transform: translateX(14px) scale(0.96);
}

/* У кого в телефоне выключены движения, тот не должен видеть ни полёта,
   ни таяния: знак просто появляется и пропадает. Прозрачность при этом
   меняется мгновенно — это не движение, а включение и выключение. */
@media (prefers-reduced-motion: reduce) {
  .знак-внимания {
    animation: none;
    transition: none;
  }

  .знак-внимания--гаснет {
    transform: none;
  }
}

/* ---------- Живой смайлик ----------

   Владелец просил «анимированные смайлы». Библиотек и картинок в игре
   нет, поэтому живым делаем обычный символ: он покачивается и чуть
   подпрыгивает, как будто его показывают рукой. Живым бывает только
   смайлик — фразу не трогаем ни при каком классе: качающийся текст
   не прочесть. Пометку «живой» ставит игра; здесь она работает лишь
   на облачке-смайлике.

   Качание мягкое и несимметричное (два подскока разной высоты на цикл):
   ровное маятниковое движение через пару секунд начинает раздражать,
   а неровное читается как живое. Полтора оборота в секунду — медленно,
   взгляд не дёргает. Точка вращения у нижнего края знака: так он
   «стоит» на плашке и покачивается, а не крутится вокруг центра. */
.знак-внимания--смайлик.знак-внимания--живой .знак-внимания__что {
  display: inline-block;   /* строчному узлу transform не задать */
  transform-origin: 50% 85%;
  animation: смайлик-живой 1.5s ease-in-out infinite;
}

@keyframes смайлик-живой {
  0%, 100% { transform: translateY(0)    rotate(-7deg) scale(1); }
  30%      { transform: translateY(-5px) rotate(5deg)  scale(1.06); }
  60%      { transform: translateY(0)    rotate(7deg)  scale(1); }
  80%      { transform: translateY(-3px) rotate(-3deg) scale(1.03); }
}

/* =====================================================================
   ЛЕТЯЩИЙ ПРЕДМЕТ: кинуть смайликом в соперника

   Владелец просил «кинуть какашкой в соперника». Предмет — один символ
   (💩, 🍅, 🥚, 👞, ❤️, 🌹), который летит от плашки бросившего к плашке
   цели над всем столом, шлёпается и тает. Игра кладёт узел на игровой
   экран и пишет ему четыре переменные: --от-x, --от-y, --до-x, --до-y —
   точки относительно игрового экрана. Больше от игры ничего не нужно:
   куда лететь — знает CSS.

   Как устроен полёт. Движение разложено на два свойства, и это главное
   решение здесь. «translate» везёт предмет по прямой от точки к точке.
   «transform» — независимо от него — подбрасывает вверх и опускает
   (дуга) и крутит. Сумма двух — бросок по дуге. В одном свойстве так
   не сделать: прямая и дуга слились бы в одну кривую, которую пришлось
   бы считать заново для каждой пары точек — а точек игра не знает
   заранее.

   Дуга не выше 110 точек и не выше верхнего края экрана: если оба конца
   у самого верха (плашки соперников стоят там), подъём урезается, чтобы
   предмет не улетал за край и не обрезался. Для броска снизу вверх —
   от своей руки к плашке — вертикальная дуга почти нулевая, и бросок
   показывает глубина: предмет вырастает в середине пути и уменьшается
   к цели, как будто пролетает мимо зрителя.

   Сквозь предмет нажимается всё, что под ним (pointer-events: none),
   и висит он не дольше полёта: после шлепка тает и остаётся невидимым
   до тех пор, пока игра его не уберёт. Руку и кнопки он не закрывает
   ничем, кроме себя самого, и то на секунду.
   ===================================================================== */

.летящий-предмет {
  position: absolute;
  left: 0;
  top: 0;
  /* Над столом, полосой плашек и облачками (у тех 70), но под плашкой
     итога и панелью выбора знаков (у тех 100). */
  z-index: 80;
  pointer-events: none;
  user-select: none;
  margin: -0.5em 0 0 -0.5em;   /* точка — центр символа, а не его угол */
  font-size: 40px;
  line-height: 1;
  will-change: translate, transform, opacity;

  /* Подъём дуги: не больше --дуга (по умолчанию 110), и не выше,
     чем 24 точки от верха экрана над самой верхней из двух точек. */
  --подъём: max(0px, min(var(--дуга, 110px),
                         calc(min(var(--от-y, 0px), var(--до-y, 0px)) - 24px)));

  translate: var(--от-x, 50%) var(--от-y, 50%);
  animation:
    предмет-летит var(--полёт, 700ms) linear forwards,
    предмет-дуга  var(--полёт, 700ms) linear forwards;
}

@keyframes предмет-летит {
  from { translate: var(--от-x) var(--от-y); }
  to   { translate: var(--до-x) var(--до-y); }
}

/* Вверх — с замедлением, вниз — с ускорением: так летит брошенное.
   Оборот ровно один: в конце угол снова ноль, и шлепок начинается
   без рывка. Вырастает в середине пути — это «глубина» броска. */
@keyframes предмет-дуга {
  0%   { transform: translateY(0) rotate(0deg) scale(0.75);
         animation-timing-function: ease-out; }
  50%  { transform: translateY(calc(-1 * var(--подъём))) rotate(180deg) scale(1.3);
         animation-timing-function: ease-in; }
  100% { transform: translateY(0) rotate(360deg) scale(1); }
}

/* Попал. Игра вешает пометку в момент прибытия; предмет стоит в точке
   цели (translate задан явно — иначе, потеряв анимацию полёта, он
   отскочил бы к началу), коротко раздувается и тает. Тень под ним
   пропадает вместе с ним. */
.летящий-предмет--попал {
  translate: var(--до-x) var(--до-y);
  animation: предмет-шлёп 300ms ease-out forwards;
}

@keyframes предмет-шлёп {
  0%   { transform: scale(1)   rotate(0deg);   opacity: 1; }
  35%  { transform: scale(1.5) rotate(-12deg); opacity: 1; }
  100% { transform: scale(1.2) rotate(0deg);   opacity: 0; }
}

/* ---------- В плашку попали ----------

   Полсекунды плашка цели вздрагивает: несколько сдвигов по четыре
   точки с лёгким наклоном, затухающих к концу. Заметно — но не мультяшно:
   ни подскока, ни вращения. Движение задано отдельными свойствами
   «translate» и «rotate», а не «transform»: у плашки того, кто ходит,
   transform уже занят увеличением, и тряска не должна его сбивать. */
.плашка--попали {
  animation: плашку-тряхнуло 500ms ease-in-out;
}

@keyframes плашку-тряхнуло {
  0%, 100% { translate: 0 0;    rotate: 0deg; }
  15%      { translate: -4px 0; rotate: -1.5deg; }
  35%      { translate: 4px 1px; rotate: 1.5deg; }
  55%      { translate: -3px 0; rotate: -1deg; }
  75%      { translate: 2px 0;  rotate: 0.6deg; }
}

/* Кому мешает движение — без полёта: предмет появляется у цели,
   тает без раздувания, плашка не трясётся, смайлик не качается.
   Сам предмет при этом виден — человек должен узнать, что в него
   кинули; просто без спецэффектов. */
@media (prefers-reduced-motion: reduce) {
  .летящий-предмет {
    animation: none;
    translate: var(--до-x) var(--до-y);
    transform: none;
  }

  .летящий-предмет--попал {
    animation: предмет-тает 300ms ease-out forwards;
  }

  .плашка--попали { animation: none; }

  .знак-внимания--смайлик.знак-внимания--живой .знак-внимания__что {
    animation: none;
  }
}

@keyframes предмет-тает {
  from { opacity: 1; }
  to   { opacity: 0; }
}

/* ---------- Знаки в невысоком окне (шторка Telegram) ----------
   Высоты мало: три облачка прежнего роста заняли бы почти весь стол
   и достали бы до строки подсказки. Ужимаем и сами знаки, и просвет
   между ними. */
@media (max-height: 620px) {
  .знаки-внимания { gap: 6px; }

  .знак-внимания {
    padding: 6px 12px 7px;
    border-radius: 14px;
  }

  .знак-внимания__кто { font-size: 10.5px; }
  .знак-внимания__что { font-size: clamp(14px, 4.2vw, 17px); }

  .знак-внимания--смайлик { padding: 4px 12px 5px; }
  .знак-внимания--смайлик .знак-внимания__что {
    font-size: clamp(34px, 11vw, 44px);
  }
}

/* ---------- Панель «сказать за столом» ----------
   Четырнадцать кнопок: шесть смайликов рядом и восемь готовых фраз.
   Правила переехали сюда из index.html — там их временно положил
   разработчик, потому что у знаков не было своего оформления. */

/* ---------- Сама панель: потолок высоты и прокрутка внутри ----------

   ЧТО БЫЛО СЛОМАНО. Знаков со временем стало много — 12 смайликов,
   11 фраз и 8 предметов для броска, всего 32 кнопки. Панель — плашка,
   прижатая к нижнему краю, а высота у неё была «сколько попросит
   содержимое». На телефоне 320×568 содержимое попросило 682 точки,
   плашка выросла выше экрана, и её верх — заголовок и десять кнопок —
   оказался ЗА краем. Прокрутки при этом не было никакой: до тех знаков
   нельзя было добраться вовсе.

   Это не про полный экран. Даже без полей под часы верх срезало
   на 62 точки; полный экран лишь делал хуже.

   КАК ПОЧИНЕНО. Три вещи сразу:

   1. У панели появился потолок — она никогда не выше окна за вычетом
      верхнего безопасного поля. Что не поместилось, то прокручивается
      внутри неё, а не уезжает за экран.
   2. Содержимое встаёт столбиком (у общей плашки раскладка «в строку
      с переносом» — она для двух кнопок итога, а не для четырёх рядов).
   3. Кнопка «Закрыть» прилипает к нижнему краю панели и остаётся
      на месте, сколько бы мы ни прокручивали. Без этого закрыть панель
      можно было бы, только домотав до конца, — а это ровно та ловушка,
      из которой мы человека и вытаскиваем.

   Ужатие кнопок на узких и невысоких экранах — ниже, отдельными
   правилами: прокрутка спасает всегда, но чем реже она нужна,
   тем лучше. */
#экран-эмоций {
  flex-flow: column nowrap;
  align-items: center;
  justify-content: flex-start;
  /* Потолок: вся высота окна минус верхнее безопасное поле и небольшой
     зазор, чтобы из-под панели была видна полоска стола — иначе она
     читается как отдельный экран, а не как плашка поверх игры. */
  max-height: calc(var(--доступно) - var(--отступ-сверху) - 10px);
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
}

/* Ничего не сплющивается по высоте: в столбике с прокруткой сжатие
   только испортило бы кнопки. */
#экран-эмоций > * { flex-shrink: 0; }

/* «Закрыть» видна всегда, даже когда список знаков прокручен наверх.

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

   Нижнее поле уводит полку под нижний отступ панели: тогда прилипшая
   кнопка стоит вплотную к краю, а безопасное поле полного экрана
   отдано её собственному нижнему полю — палец не попадает на полосу
   жеста. */
#экран-эмоций #кнопка-эмоции-назад {
  position: sticky;
  bottom: calc(-1 * var(--отступ-снизу) - 18px);
  z-index: 2;
  width: auto;
  align-self: stretch;
  min-width: 0;
  margin: 2px -14px calc(-1 * var(--отступ-снизу) - 18px);
  padding: 12px 14px calc(12px + var(--отступ-снизу) + 18px);
  background: var(--панель);
  border: none;
  border-top: 1px solid var(--край);
  border-radius: 0;
  box-shadow: none;
}

/* ---------- Вкладки над рядами знаков: «Смайлики», «Фразы», «Кинуть» ----------

   ЗАЧЕМ ОНИ ЗДЕСЬ. Знаков тридцать два, и тремя рядами подряд они на узкий
   телефон не помещались: панель просила 494 точки и приходилось прокручивать.
   Разложили по вкладкам — стало 227 точек без прокрутки. Полоска вкладок
   в эти 227 уже входит, поэтому главное требование к ней — быть скромной
   по высоте: 44 точки (палец) и ни точкой больше.

   ПОЧЕМУ У НИХ СВОИ ПРАВИЛА. Кнопкам вкладок код даёт классы
   «кнопка кнопка--выбор панель-знаков__вкладка». Без здешних правил им
   доставалось единственное подходящее — оформление кнопок выбора сложности
   (см. «.кнопка.кнопка--выбор» выше). Оно рассчитано на гибкую строку,
   а полоска вкладок гибкой не была вовсе: вкладки вставали впритык, разной
   ширины и могли перенестись на две строки. Хуже того — правь потом кнопки
   сложности, и молча поедут вкладки знаков. Теперь связи нет.

   ПОЧЕМУ ВЕЗДЕ «#экран-эмоций». Тот же приём и те же имена классов есть
   на панели знаков в шашках, а шашки грузят этот файл первым и свой
   («style-шашки.css») вторым. Напиши я правила просто по классу — и они
   перебили бы шашечные, потому что здешние сильнее. Приставка по имени
   экрана держит их строго внутри панели знаков дурака: этого имени нет
   ни в шашках, ни в нардах, ни в шахматах. */

/* Полоска: три вкладки в ряд, каждая занимает треть — так они читаются
   как один переключатель, а не как три отдельные кнопки.

   Своего просвета снизу у полоски нет нарочно: между частями панели уже
   стоит общий просвет в 10 точек, и собственное поле сложилось бы с ним
   вдвое — панель выросла бы ровно там, где высота на счету.

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

   Цвет дорожки — из цвета текста темы, а не из «--край». Первый раз
   я взял именно край (серый с прозрачностью 0,45) и толщину в точку —
   на снимке живой игры такой линии не было видно вовсе: на тёмно-зелёном
   сукне она давала контраст около 1,2. Цвет текста всегда контрастен
   фону в любой теме, поэтому пятая его часть видна и на тёмном, и на
   светлом; вместе с толщиной в две точки линия наконец читается
   (контраст к панели 1,9 — для служебной черты в самый раз: видно,
   но она не спорит с жёлтой чертой выбранной вкладки).
   Первая строка — запас для браузеров старше 2023 года. */
#экран-эмоций .панель-знаков__вкладки {
  display: flex;
  gap: 6px;
  width: 100%;
  box-shadow: inset 0 -2px 0 var(--край);
  box-shadow: inset 0 -2px 0 color-mix(in srgb, var(--текст) 22%, transparent);
}

/* Сама вкладка. Высота 44 точки — размер пальца, меньше нельзя; черта
   снизу считается внутрь этих 44, поэтому полоска от неё не растёт.
   Подпись в одну строку всегда: перенос на две строки съел бы высоту
   и разъехался бы с соседками. Скругление только сверху — низ у вкладки
   прямой, он лежит на дорожке. */
#экран-эмоций .панель-знаков__вкладка {
  flex: 1 1 0;
  width: auto;
  min-width: 0;
  min-height: 44px;
  padding: 8px 6px;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0;
  /* Подпись в одну строку, а если у человека в системе включён крупный
     шрифт и слово всё-таки не влезло — оно обрезается многоточием, а не
     наезжает на соседнюю вкладку. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--текст-тихий);
  background: transparent;
  border: none;
  border-radius: 10px 10px 0 0;
  box-shadow: none;
  /* Место под черту выбранной вкладки занято всегда — иначе при
     переключении подписи прыгали бы на три точки вверх-вниз. */
  border-bottom: 3px solid transparent;
}

/* ВЫБРАННАЯ ВКЛАДКА ОТЛИЧАЕТСЯ ЧЕТЫРЬМЯ ПРИЗНАКАМИ СРАЗУ, и это не запас
   ради красоты. Цвет пропадает первым: на солнце экран выцветает, а каждый
   двенадцатый мужчина плохо различает оттенки. Поэтому работают ещё три:
   толстая черта снизу (она же показывает, что ряд знаков под ней принадлежит
   именно этой вкладке), жирная подпись (видна и в чёрно-белом) и мягкая
   заливка.

   ПОСЧИТАННЫЙ КОНТРАСТ. Главный признак — черта. Меряем её против того,
   что на этом месте у невыбранной вкладки, то есть против фона панели:
     — запасная тёмная тема (панель 11,58,32, черта 255,220,131) — 9,6;
     — светлая тема Telegram (панель 241,241,241, черта 42,118,193) — 4,2;
     — тёмная тема Telegram (панель 24,24,24, черта 157,141,230) — 6,2.
   Худшее из трёх — 4,2 при нашем пороге 3,0.
   Заливка сама по себе слабее (1,5) — она четвёртый признак, а не первый.

   ПОЧЕМУ ЧЕРТА НЕ ЧИСТЫМ ЦВЕТОМ ТЕМЫ. Так сделано в шашках, и на белом
   фоне светлой темы синий Telegram даёт всего 2,9 — ниже порога. Подмешиваем
   к нему пятую часть цвета текста: текст в теме всегда контрастен фону,
   поэтому примесь всегда двигает черту в сторону контраста — в тёмной теме
   светлее, в светлой темнее. Первые строки в обеих парах — запас для
   браузеров старше 2023 года, которые не умеют смешивать цвета: там черта
   будет цвета текста (контраст наибольший, вид скромнее). */
#экран-эмоций .панель-знаков__вкладка.кнопка--активная {
  color: var(--текст);
  font-weight: 800;
  background: var(--подложка);
  background: color-mix(in srgb, var(--акцент) 18%, transparent);
  border-bottom-color: var(--текст);
  border-bottom-color: color-mix(in srgb, var(--акцент) 82%, var(--текст));
}

/* Нажатие. Обычная кнопка при нажатии садится на две точки вниз — вкладке
   это ни к чему: полоска дёргалась бы целиком. Вместо движения — заливка
   под пальцем, ответ виден сразу. */
#экран-эмоций .панель-знаков__вкладка:active {
  transform: none;
  background: var(--подложка);
  box-shadow: none;
}

/* Узкий телефон (320 точек). Считаем вслух: панель оставляет под полоску
   300 точек, два просвета по 5 забирают 10, значит вкладке достаётся 96.
   Подпись «Смайлики» при кегле 13 занимает около 58 плюс поля — влезает
   с запасом и не режется. */
@media (max-width: 360px) {
  #экран-эмоций .панель-знаков__вкладки { gap: 5px; }

  #экран-эмоций .панель-знаков__вкладка {
    padding: 8px 3px;
    font-size: 13px;
  }
}

/* Ряд кнопок переносится сам, если не влез. Просвет тесноват нарочно:
   шесть смайликов должны вставать в один ряд на телефоне в 360 точек.
   При просвете в 8 шестой переносился на новую строку, и ряд читался
   как «пять и один». */
.ряд-знаков {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  width: 100%;
}

/* Класс в селекторе назван дважды нарочно — тем же приёмом, что и
   «.кнопка.кнопка--мелкая» выше: иначе общее правило кнопок окажется
   сильнее, и четырнадцать кнопок шириной по 116 точек займут две трети
   экрана (замер разработчика: панель выросла до 489 точек).

   Смайлик крупный — по нему целятся пальцем, а читать в нём нечего.
   Фраза мельче: в ней слова, и кнопка растёт от их длины. Высота
   у обеих 44 точки: это то, во что попадает палец. */
.кнопка.кнопка--смайлик {
  min-width: 0;
  min-height: 44px;
  padding: 4px 7px;
  font-size: 26px;
  line-height: 1;
}

.кнопка.кнопка--фраза {
  min-width: 0;
  min-height: 44px;
  padding: 8px 12px;
  font-size: 14px;
  font-weight: 600;
}

/* Кнопка «Сказать» живёт в панели действий стола — узкая третья справа
   (см. «Панель действий» в разделе стола в конце файла). */

/* ---------- Панель знаков на узком или невысоком телефоне ----------

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

   Что даёт ужатие: смайлик у́же на восемь точек, и двенадцать смайликов
   встают в два ряда вместо трёх, восемь предметов — в один вместо двух,
   фразы мельче на точку и садятся плотнее. Вместе с полями и просветами
   набегает около 165 точек — примерно четверть панели. */
@media (max-width: 360px), (max-height: 620px) {
  #экран-эмоций {
    gap: 8px;
    padding-top: 12px;
    padding-left: calc(10px + var(--отступ-слева));
    padding-right: calc(10px + var(--отступ-справа));
  }

  #экран-эмоций .ряд-знаков { gap: 5px; }

  #экран-эмоций .кнопка.кнопка--смайлик {
    padding: 4px 5px;
    font-size: 22px;
  }

  #экран-эмоций .кнопка.кнопка--фраза {
    padding: 7px 9px;
    font-size: 13px;
  }

  /* Поля у прилипшей кнопки считаются от полей панели — раз те стали
     у́же, пересчитываем и здесь, иначе её фон не дотянется до краёв. */
  #экран-эмоций #кнопка-эмоции-назад { margin-left: -10px; margin-right: -10px; }
}


/* ---------- Две двери про себя на экране рекордов ----------

   «Как я играю» и «Рейтинг игроков» отвечают на два соседних вопроса —
   «каков я» и «где я среди остальных», — и по важности равны. Поэтому
   выглядят они одинаково: одна ширина на обе (иначе кнопки по своему
   содержимому встают лесенкой и читаются как разные по весу) и обводка
   вместо заливки. Заливка на этом экране остаётся у одной кнопки —
   «Назад»: когда залито всё подряд, глазу не за что зацепиться. */
#кнопка-мой-счёт,
.кнопка.кнопка--рейтинг {
  width: min(100%, var(--колонка-кнопок));
  color: var(--текст);
  background: transparent;
  border: 2px solid var(--край);
  box-shadow: none;
}

/* ================================================================
   Рейтинг игроков — таблица «кто впереди»
   ================================================================

   Экран собирает js/рейтинг-экран.js, оформления у него не было вовсе:
   место, имя, очки и победы шли простым текстом в столбик, и своя
   строка ничем не отличалась от чужих. Здесь всё это раскладывается
   по четырём колонкам.

   Главное правило этого экрана: человек открывает рейтинг, чтобы
   найти себя. Поэтому своя строка выделена сразу тремя признаками —
   заливкой, обводкой цветом темы и жирным именем: любого одного
   признака мало, если у человека сбита цветопередача или он смотрит
   на экран под солнцем.
   ================================================================ */

/* Весь экран столбиком, с воздухом между частями.
   Штаб, «экран рейтинга выше окна» (22.09.2026): у «Дурака» строк над
   списком много (шапка, кнопка игры, подпись, круг, меры, два ряда
   фильтров, карточка «Моё место») — на 390×844 и на 1280×800 (там
   окно ниже, 800, а резерв под полосу вкладок больше) сумма зазоров
   между ними — одна из причин, почему карточка «Моё место» съезжает
   за низ окна. Было 10px; до карточки шесть переходов — лишних 24
   точки только на них. Стало 6px (см. ещё точечный срез самой карточки
   ниже, «#рейтинг-моё-место»). Сами ряды фильтров («.переключатель__
   вариант») не трогаем — их судьба ждёт отдельного решения владельца. */
#экран-рейтинга-игроков {
  gap: 6px;
  align-items: center;
  text-align: center;
}

/* Переключатель «Дурак / Шашки» — два одинаковых по ширине кнопки в ряд. */
.рейтинг-выбор {
  display: flex;
  gap: 8px;
  width: min(100%, 420px);
}

/* ---------- Вторая полоска: какая мера показана ----------

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

   У шашек вкладки в панели знаков устроены иначе (чертой снизу), и это
   тоже нарочно: там вкладки стоят внутри плашки поверх доски, а здесь
   переключатель лежит на экране сам по себе — ему идёт обойма. */
.рейтинг-меры {
  display: flex;
  gap: 4px;
  width: min(100%, 420px);
  padding: 4px;
  background: var(--подложка);
  border-radius: 999px;
}

/* Класс назван дважды нарочно: у кнопки есть общий класс кнопок выбора,
   и без этого он перебил бы здешние правила. */
.рейтинг-меры .кнопка.кнопка--выбор {
  flex: 1 1 0;
  min-width: 0;
  min-height: 44px;                 /* размер пальца, меньше нельзя */
  padding: 8px 6px;
  font-size: 14px;
  font-weight: 600;
  color: var(--текст-тихий);
  background: transparent;
  border: none;
  border-radius: 999px;
  box-shadow: none;
}

/* Выбранная мера отличается не только цветом: она залита пилюлей
   (форма видна и в чёрно-белом), подпись жирнее, и лежит она будто
   приподнятой над дорожкой. */
.рейтинг-меры .кнопка.кнопка--выбор.кнопка--активная {
  color: var(--текст);
  font-weight: 800;
  background: color-mix(in srgb, var(--акцент) 30%, var(--панель));
  box-shadow:
    inset 0 0 0 1px color-mix(in srgb, var(--акцент) 55%, transparent),
    0 1px 3px rgba(0, 0, 0, 0.22);
}

/* Своё место словами — под переключателем. Строка бывает крупной
   («7 место») и обычной («Вас в таблице пока нет»); крупную рисует
   класс «серия», ей ничего добавлять не нужно. */
#рейтинг-моё-место { text-align: center; }

/* Пояснение внутри таблицы («Всего в таблице 40 игроков…») — мельче
   строк, оно справочное, а не главное. */
/* Пояснение внутри таблицы. Выровнено по левому краю нарочно: коротким
   строкам центр не мешает, но когда игру открыли мимо Telegram, здесь
   лежит абзац в шесть строк («рейтинг ведётся по учётной записи…»),
   а длинный текст с рваными краями читается заметно хуже — глазу негде
   зацепиться в начале каждой строки. */
#рейтинг-таблица > .подпись:first-child {
  font-size: 13px;
  line-height: 1.35;
  margin-bottom: 2px;
  text-align: left;
}

/* ---------- Ярлык раздела и обычные фразы — разные вещи ----------

   Мелкие прописные хороши для КОРОТКОГО ЯРЛЫКА: «ВЫ И СОСЕДИ ПО СИЛЕ»,
   «ИГРОК», «СИЛА». Но предложение прописными читается заметно медленнее:
   слова теряют форму, и глаз разбирает их по букве. А ещё это звучит
   как повышенный голос.

   Раньше правило ловило «вторую подпись подряд» — и было верным, пока
   подписей было ровно две. Потом сервер начал присылать в таблицу целые
   фразы («4 место в таблице силы», «сыграно 601 партия…»), и прописными
   стало набрано пять предложений кряду.

   Теперь ярлык узнаётся по своему месту, а не по счёту: это подпись,
   сразу за которой начинается шапка таблицы. Так оно и есть по смыслу —
   ярлык подписывает то, что под ним. Браузер старше 2023 года такого
   не умеет: там ярлык останется обычными буквами. Это не беда —
   предложения важнее, а они правильны везде. */
#рейтинг-таблица > .подпись:has(+ .рейтинг-строка--шапка) {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  text-align: left;
  margin-top: 4px;
}

/* Обычные фразы в таблице — те самые предложения от сервера. Они
   читаются подряд, поэтому набраны как текст: обычные буквы, ровный
   левый край, строки чуть просторнее. Кегль мельче общей подписи —
   это подробности под главным числом, а не заголовок. */
#рейтинг-таблица > .подпись {
  font-size: 13px;
  line-height: 1.4;
  text-align: left;
}

/* ---------- Готовая фраза сервера под главным числом ----------

   Ради неё всё и затевалось. Число силы человек видит сразу, но само
   по себе оно молчит: упало — и непонятно, наказали тебя или так вышло.
   Фраза объясняет: «измерена уверенно» или «ещё приблизительная,
   сыграйте ещё двенадцать партий».

   Поэтому она оформлена не как подпись, а как маленькая карточка:
   своя подложка, полоска цвета темы слева и кегль крупнее обычной
   подписи. Полоска слева — тот приём, которым в тексте отмечают
   выделенное: глаз цепляется за неё раньше, чем начинает читать.
   Селектор нарочно длинный: правило для первого абзаца в таблице
   (см. выше) сильнее короткого и иначе оставило бы фразу мелкой. */
#рейтинг-таблица > .подпись.рейтинг-пояснение {
  margin: 2px 0 6px;
  padding: 9px 12px 9px 11px;
  font-size: 14px;
  line-height: 1.4;
  text-align: left;
  color: var(--текст);
  background: color-mix(in srgb, var(--акцент) 14%, var(--подложка));
  border-left: 3px solid var(--акцент);
  border-radius: 4px 10px 10px 4px;
}

/* ---------- Соперники последней партии ----------

   Три строки вида «Пётр — играл сильнее вас (сила 1240)». Цветом здесь
   злоупотреблять нельзя: красное «слабее» читается как насмешка над
   живым человеком, а «сильнее» красным — как упрёк себе. Поэтому все
   три строки одного спокойного тона, а различает их знак слева:
   стрелка вверх, стрелка вниз или равенство. Знак — признак формы,
   он работает и в чёрно-белом, и у того, кто оттенки различает плохо.

   Подложка у всех трёх одинаковая и очень слабая: строки складываются
   в аккуратный список, но ни одна не выделена как «плохая». */
#рейтинг-таблица > .подпись.рейтинг-соперник {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin: 0;
  padding: 6px 10px;
  font-size: 13px;
  line-height: 1.35;
  text-align: left;
  color: var(--текст);
  background: color-mix(in srgb, var(--текст) 7%, transparent);
  border-radius: 8px;
}

/* Знак перед строкой. Он же держит левый край ровным: ширина у всех
   трёх одна, поэтому имена начинаются на одной вертикали. */
.рейтинг-соперник::before {
  flex: 0 0 auto;
  width: 1.1em;
  font-weight: 700;
  text-align: center;
  color: var(--текст-тихий);
}

.рейтинг-соперник--сильнее::before { content: "↑"; }
.рейтинг-соперник--слабее::before  { content: "↓"; }
.рейтинг-соперник--вровень::before { content: "="; }

/* ---------- Строка таблицы ----------

   Четыре колонки: номер места, имя, очки, победы. Имя занимает всё
   свободное место и обрезается многоточием — длинное имя из Telegram
   («Александр Константинопольский») не должно раздвигать столбцы
   и утаскивать очки за край экрана. Цифры набраны моноширинными
   (tabular-nums): столбик цифр стоит ровно, как в бумажной ведомости. */
.рейтинг-строка {
  display: grid;
  /* Столбец с числом умеет подрасти. Приблизительная сила пишется
     со знаком «≈» впереди, а он шире цифры и в жёсткие 3,4 знака
     не помещался — число ужималось или переносилось. Теперь ширина
     считается по содержимому, но не меньше прежней: столбец не скачет
     от строки к строке, а знак влезает. Имя рядом ужмётся само,
     у него на этот случай многоточие. */
  grid-template-columns: 28px minmax(0, 1fr) minmax(3.4em, auto) 3.6em;
  align-items: center;
  gap: 0 8px;
  min-height: 40px;
  padding: 6px 10px;
  background: var(--подложка);
  border-radius: 10px;
  text-align: left;
}

/* Мера «очки» по макету владельца показывает только МЕСТО/ИГРОК/ОЧКИ —
   js/рейтинг-экран.js для неё больше не строит ячейку «.рейтинг-победы»
   (столбец «Побед» остался только у меры «сила игры», см. «Партий»
   ниже). Без четвёртой ячейки прежняя сетка в четыре колонки оставляла
   бы пустой хвост справа — трёхколоночная сетка отдаёт это место
   ячейке очков, и число стоит у самого края строки, как в макете. */
.рейтинг-строка:not(:has(> .рейтинг-победы)) {
  grid-template-columns: 28px minmax(0, 1fr) auto;
}

.рейтинг-место {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--подложка);
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--текст-тихий);
}

/* Ячейка имени — теперь флекс-строка из двух span'ов («ячейкаИмени» в
   js/рейтинг-экран.js): «.рейтинг-имя__текст» с самим именем и, у своей
   строки, «.рейтинг-имя__вы» с пилюлей рядом. Раньше обрезку многоточием
   вешали на саму ячейку — на длинном имени резало не только лишний
   текст, но и пилюлю «Вы» вместе с ним (она лежала внутри того же
   обрезаемого блока). Теперь ужимается только «__текст» (правило ниже),
   а пилюля — обычный сосед с «flex-shrink: 0», её не тронет никогда. */
.рейтинг-имя {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 15px;
  line-height: 1.2;
  /* Ячейка — элемент грид-строки («grid-area: имя», см. ниже): без
     явного «0» у грид-элемента минимальная ширина по умолчанию тянется
     под содержимое (текст имени), и на длинном имени вся строка
     раздувалась и выезжала за экран. «min-width: 0» разрешает ячейке
     сжаться до колонки, дальше уже обрезается «__текст» внутри. */
  min-width: 0;
}

/* Общий узел текста имени — один и тот же класс у строки таблицы,
   карточки «Моё место» и подиума («ячейкаИмени» строит их одинаково),
   поэтому и обрезка многоточием у него одна на все три места. */
.рейтинг-имя__текст {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.рейтинг-очки {
  font-size: 16px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

/* Побед из партий — справочное число, поэтому тише и мельче очков. */
.рейтинг-победы {
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--текст-тихий);
  text-align: right;
  white-space: nowrap;
}

/* ---------- Шапка ----------
   Не строка, а подписи к столбцам: без плашки, мелко и тихо.

   Она приклеена к верху списка, и это не украшение, а починка. На узком
   телефоне таблица не помещается целиком, человек её прокручивает — и на
   снимке 320 точек было видно, как ярлык «ВЫ И СОСЕДИ ПО СИЛЕ» режется
   верхним краем ровно посередине букв: выглядит как поломка вёрстки.
   Теперь всё, что уезжает вверх, прячется ПОД шапкой, а сама шапка
   стоит на месте — заодно видно, что за столбцы, до какой бы строки
   ни домотал.

   Фон у неё непрозрачный и в тон сукну: сквозь прозрачный просвечивали
   бы уезжающие строки. Первая строка — запас для браузеров без
   color-mix, там шапка будет просто цвета темы. */
.рейтинг-строка.рейтинг-строка--шапка {
  position: sticky;
  top: 0;
  z-index: 2;
  min-height: 0;
  padding: 4px 10px 3px;
  background: var(--фон);
  background: color-mix(in srgb, var(--фон) 62%, #1f7a45);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--текст-тихий);
}

.рейтинг-строка--шапка .рейтинг-место {
  width: 24px;
  height: auto;
  background: none;
  font-size: 11px;
  color: inherit;
}

.рейтинг-строка--шапка .рейтинг-имя,
.рейтинг-строка--шапка .рейтинг-очки,
.рейтинг-строка--шапка .рейтинг-победы {
  font-size: 11px;
  font-weight: 700;
  color: inherit;
}

/* ---------- Своя строка ----------
   Её ищут глазами первой, поэтому она отличается от соседей заливкой,
   рамкой цветом темы и жирным именем разом. */
.рейтинг-строка.рейтинг-строка--я {
  background: var(--подложка);
  background: color-mix(in srgb, var(--акцент) 24%, var(--подложка));
  box-shadow:
    inset 0 0 0 2px var(--акцент),
    0 2px 8px rgba(0, 0, 0, 0.22);
  min-height: 44px;
}

.рейтинг-строка--я .рейтинг-имя {
  font-weight: 700;
  color: var(--текст);
}

.рейтинг-строка--я .рейтинг-очки { font-size: 17px; }

.рейтинг-строка--я .рейтинг-место {
  color: var(--текст);
  background: color-mix(in srgb, var(--акцент) 45%, transparent);
}

.рейтинг-строка--я .рейтинг-победы { color: var(--текст); }

/* ---------- Тройка сильнейших ----------

   Первое, второе и третье место помечены кружком цвета медали. Работает
   это по атрибуту «data-место» на строке, который проставляет игра:
   из самого оформления номер места не виден (он лежит текстом внутри
   ячейки), а считать «первые три строки сверху» нельзя — в разделе
   «Вы и соседи» сверху стоят соседи, скажем, седьмое место.
   Пока атрибута нет, кружки просто одинаковые, ничего не ломается. */
.рейтинг-строка[data-место="1"] .рейтинг-место {
  color: #3a2a05;
  background: linear-gradient(160deg, #ffdc73, #e0a516);
}

.рейтинг-строка[data-место="2"] .рейтинг-место {
  color: #2b2f33;
  background: linear-gradient(160deg, #eef2f6, #b7c1cb);
}

.рейтинг-строка[data-место="3"] .рейтинг-место {
  color: #3a2410;
  background: linear-gradient(160deg, #eab989, #c07f45);
}

/* Верхняя строка списка стоит чуть просторнее — у таблицы появляется
   «шапка списка», а не сплошная лента одинаковых полосок. */
.рейтинг-строка--шапка + .рейтинг-строка { min-height: 44px; }

/* Объяснение «как считаются очки» — обычный текст, а не таблица. */
#рейтинг-объяснение {
  gap: 6px;
  text-align: left;
}

#рейтинг-объяснение .подпись { font-size: 13px; line-height: 1.4; }

/* ---------- Рейтинг на узком телефоне ----------
   На 320 точках колонка побед забирает слишком много: ужимаем кегли
   и просветы, но высоту строки не трогаем — по ней попадают пальцем. */
@media (max-width: 360px) {
  .рейтинг-строка {
    grid-template-columns: 24px minmax(0, 1fr) minmax(3.2em, auto) 3.4em;
    gap: 0 6px;
    padding: 6px 8px;
  }

  /* Тот же приём, что в базовом правиле выше: без ячейки «Побед»
     (мера «очки») сетка — в три колонки, не в четыре. */
  .рейтинг-строка:not(:has(> .рейтинг-победы)) {
    grid-template-columns: 24px minmax(0, 1fr) auto;
  }

  .рейтинг-место { width: 22px; height: 22px; font-size: 12px; }
  .рейтинг-имя { font-size: 14px; }
  .рейтинг-очки { font-size: 15px; }
  .рейтинг-победы { font-size: 11px; }
}

/* =====================================================================
   СТОЛ ДУРАКА ПО ЭТАЛОНУ ВЛАДЕЛЬЦА (10 сентября, вечер)

   Цель — картинка «эталон/9-дурак-стол-итог.png» (941×1672). Владелец
   сказал: «не один в один, а как концепт, как витрину». Поэтому с неё
   берём устройство и материалы, а цвета — общие цвета сборника
   («--сб-…», см. раздел витрины), а не числа из README набора.

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

   КАК ПЕРЕВОДИТЬ КАРТИНКУ В ТОЧКИ — как у витрины: ширина 941 → 390,
   всё умножаем на 0,414. Поэтому высоты рядов заданы долями ширины
   экрана (vw): на 360, 390 и 430 экран выглядит той же картинкой.

   КАК УСТРОЕН ЭКРАН. Столбик рядов сверху вниз: (шапка), соперник,
   стол, (строка «Вы»), подсказка, своя рука, кнопки. У всех рядов,
   кроме стола, высота постоянная. Стол забирает остаток, а карты на нём
   и колода меряются ОТ РАЗМЕРА САМОГО СТОЛА — единицами cqw и cqh,
   «сотая доля ширины и высоты моей коробки». Отсюда главное свойство:
   что бы ни случилось с высотой окна, стол не может наехать на соседей,
   он просто становится меньше — и карты на нём вместе с ним.

   Прежняя арифметика «служебной высоты» (--служебное, --свобода,
   --рука-прибавка) ушла из файла вместе со старыми правилами стола:
   двух наборов правил на одно и то же больше нет. Выше по файлу от
   прежнего стола остались только общие вещи — поля экрана «экран-игры»
   (ими пользуются нарды), бумага и углы карты, подсказка, подхват
   и отказ в руке; каждое помечено там, где живёт.
   ===================================================================== */

:root {
  /* Бумага карты, две краски мастей и размер карты в руке — в начале
     файла, в общем списке цветов и размеров. */

  /* ---------- Значки из набора владельца ----------
     Это копии файлов «img/дурак/значки/*.svg» (аватар, «Взять», «Бито»,
     чат), вписанные прямо сюда. Почему копии, а не ссылки
     на файлы: значок рисуется маской, а маску браузер берёт только
     у файла, который сервер назвал картинкой. Проверочный сервер
     проекта называет .svg «неизвестными данными» — и все значки молча
     пропадали. Вписанный значок от сервера не зависит вовсе и не стоит
     ни одного лишнего запроса. Цвет у маски не важен (важна форма),
     поэтому линии здесь просто чёрные — красит их цвет текста кнопки.
     Четыре последних значка («Пас», «Готово», «Перевести», «Бросить»)
     в наборе не нашлись и нарисованы здесь тем же пером: сетка 24,
     линия 1,7–1,8, круглые концы. */
  --значок-аватар: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Ccircle cx='12' cy='9' r='3' fill='black' stroke='none'/%3E%3Cpath d='M6 19v-2c0-5 12-5 12 0v2c-4 2-8 2-12 0Z' fill='black' stroke='none'/%3E%3C/svg%3E");
  --значок-взять: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='5' y='3' width='12' height='18' rx='2' transform='rotate(-12 11 12)'/%3E%3Cpath d='M19 4h2v15h-2'/%3E%3C/svg%3E");
  --значок-бито: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 3 4 2 12 14M3 4l2 4 14 12M20 3l-4 2L4 19M21 4l-2 4L5 20M3 15l6 6M15 21l6-6'/%3E%3C/svg%3E");
  --значок-чат: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 3h14a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3h-8l-6 4v-4a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3Z'/%3E%3Cpath d='M7 11h.01M12 11h.01M17 11h.01'/%3E%3C/svg%3E");
  --значок-пас: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12h12M12 7l5 5-5 5M20 5v14'/%3E%3C/svg%3E");
  --значок-готово: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.2 4.2L19 7'/%3E%3C/svg%3E");
  --значок-перевести: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 8h14M14 4l4 4-4 4M20 16H6M10 12l-4 4 4 4'/%3E%3C/svg%3E");
  --значок-бросить: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3v8M9 6l3-3 3 3'/%3E%3Crect x='6.5' y='11.5' width='11' height='9.5' rx='2'/%3E%3C/svg%3E");
}

/* «:has(> #зона-стола)» — не лишнее. Игровой экран нард называется
   так же, «экран-игры» (нарды.html), и тоже подключает этот файл. Без
   уточнения тёмный фон, поля и салатовые кнопки стола дурака ложились
   и на нарды: их доска становилась у́же, а «Бросить кубики» — салатовой.
   Стол дурака — единственный «экран-игры», внутри которого лежит
   «зона-стола», поэтому правило держится ровно за него. */
#экран-игры:has(> #зона-стола) {
  /* Свои цвета поверх цветов темы — только внутри стола. Все прежние
     правила игры, которые берут «--текст», «--подложка», «--акцент»,
     сами переходят на тёмный вид с салатовым акцентом. Другие экраны
     этих значений не видят и остаются как были. */
  --фон: var(--сб-фон);
  --панель: var(--сб-поверхность);
  --текст: var(--сб-текст);
  --текст-тихий: var(--сб-текст-тихий);
  --кнопка-фон: var(--сб-акцент);
  --кнопка-текст: var(--сб-акцент-текст);
  --акцент: var(--сб-акцент);
  --подложка: rgba(248, 245, 235, 0.06);
  --край: rgba(248, 245, 235, 0.14);
  --граница-тихая: rgba(248, 245, 235, 0.09);

  /* Поля и промежутки — как у витрины: 14 и 8 точек на экране 390. */
  --поле: clamp(12px, 3.6vw, 18px);
  --зазор-рядов: clamp(6px, 2vw, 10px);
  /* Высоты рядов сняты с макета: панель соперника 142 из 1672 → 59
     точек на 390, ряд кнопок 116 → 48. */
  --ряд-соперника: clamp(52px, 15vw, 64px);
  --ряд-кнопок: clamp(46px, 12.3vw, 54px);

  gap: var(--зазор-рядов);
  padding: calc(6px + var(--отступ-сверху)) calc(var(--поле) + var(--отступ-справа))
           calc(8px + var(--отступ-снизу))  calc(var(--поле) + var(--отступ-слева));
  color: var(--сб-текст);
  /* Тот же фон, что у витрины: ровный тёмный и едва заметное салатовое
     свечение у верхнего края. */
  background:
    radial-gradient(75% 120px at 50% 0, rgba(210, 247, 107, 0.07), rgba(210, 247, 107, 0) 100%),
    var(--сб-фон);
}

/* На компьютере столбик не шире, чем у витрины (520 точек), и стоит
   посередине. На телефоне ограничение не срабатывает. */
#экран-игры > .верх-игры,
#экран-игры > .шапка-игры,
#экран-игры > #соперники,
#экран-игры > #рука-бота,
#экран-игры > #строка-меня,
#экран-игры > #подсказка,
#экран-игры > #рука-человека,
#экран-игры > #панель-кнопок {
  width: 100%;
  max-width: 520px;
  align-self: center;
}

/* Пока висит итог партии, стол больше не приподнимается: считать
   «свободное место» по-старому здесь нечем, а плашка итога и так
   закрывает только руку и кнопки — стол над ней виден целиком. */
#приложение:has(#экран-результата.экран--виден) #экран-игры {
  padding-bottom: calc(8px + var(--отступ-снизу));
}

/* ---------- Верхняя строка «‹ · ⋯» — только в браузере ----------
   Внутри Telegram такую строку рисует он сам (его стрелка «Назад»
   и меню «⋯»), поэтому там наша прячется целиком — как у витрины.
   В браузере — две кнопки-значка без подложки по краям, каждая 44×44
   под палец; поля отрицательные, чтобы значки встали у самого края,
   как «⋯» на витрине. */
.верх-игры {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 44px;
  /* Поля экрана по бокам — 8px плюс безопасный отступ (var(--отступ-слева/справа),
     см. начало файла), а не 10px: раньше здесь стояло круглое число,
     и полоса выезжала на 2px за оба края окна на любой ширине. */
  margin: -4px calc(-8px - var(--отступ-справа)) -8px calc(-8px - var(--отступ-слева));
}

html.в-телеграме .верх-игры { display: none; }

#экран-игры > .верх-игры {
  width: calc(100% + 16px + var(--отступ-слева) + var(--отступ-справа));
  max-width: 536px;
}

.верх-игры__кнопка {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  font: inherit;
  line-height: 1;
  color: var(--сб-текст);
  background: none;
  border: none;
  border-radius: 12px;
  cursor: pointer;
}

.верх-игры__кнопка svg {
  display: block;
  width: 24px;
  height: 24px;
}

.верх-игры__кнопка:active { transform: scale(0.92); opacity: 0.7; }

.верх-игры__кнопка:focus-visible {
  outline: 2px solid var(--сб-акцент);
  outline-offset: -4px;
}

/* Лист «Ещё» — тот же, что у витрины, но у стола свой узел. Цвета
   витрины («--вт-…») объявлены только на самой витрине, поэтому листу
   даём их здесь же: он выглядит одинаково, где бы его ни открыли. */
/* Лист стола открывается и поверх итога партии — значит, лежит выше
   плашек итога и вопроса о выходе (у тех слой 100). */
#лист-игры { z-index: 110; }

/* Пока показан итог, игровой экран касаний не ловит (см. «Кто ловит
   касания, когда показан итог») — а верхняя строка «‹ ⋯» и лист стола
   лежат внутри него. Без этого правила в браузере на итоге не нажимались
   ни «‹», ни «⋯» (проверено: касание уходило мимо), то есть дорога
   к «Как играть», «Звуку» и «Рекордам» была закрыта. Возвращаем касания
   только им двоим; стол под плашкой по-прежнему не нажимается. */
#приложение:has(#экран-результата.экран--виден) #экран-игры .верх-игры,
#приложение:has(#экран-результата.экран--виден) #лист-игры {
  pointer-events: auto;
}

.лист-ещё {
  --вт-поле: clamp(12px, 3.6vw, 18px);
  --вт-поверхность: var(--сб-поверхность);
  --вт-граница: var(--сб-граница);
  --вт-текст: var(--сб-текст);
  --вт-текст-тихий: var(--сб-текст-тихий);
  --вт-акцент: var(--сб-акцент);
  --вт-акцент-текст: var(--сб-акцент-текст);
}

/* ---------- Шапка: «Дурак» и строка режима ----------
   Та же пара, что «Во что сыграем?» на витрине: жирный заголовок
   и серая строка под ним. В низком окне шапка сжимается в одну мелкую
   строку (см. ниже): стол и рука важнее крупного названия, но режим
   партии («Подкидной · 52 карты») человек должен видеть всегда. */
.шапка-игры {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.шапка-игры__заголовок {
  margin: 0;
  font-size: clamp(26px, 8.2vw, 37px);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--сб-текст);
}

.шапка-игры__подзаголовок {
  margin: 0;
  font-size: clamp(13px, 3.6vw, 16px);
  line-height: 1.3;
  color: var(--сб-текст-тихий);
}

/* ---------- Шапка в низком окне — одна строка ----------
   Раньше при высоте до 700 шапка пряталась целиком. Но в Telegram без
   полного экрана окно часто ниже 700, и режим партии («Переводной ·
   52 карты») не было видно нигде — человек садился за стол, не зная,
   во что играет. Теперь шапка сжимается в одну строку высотой 24 точки:
   «Дурак · Подкидной · 36 карт», по центру, название белым, режим серым.
   Не влезает по ширине — режим обрезается многоточием, название остаётся.

   Где стоит строка:
     • в браузере — в строке «‹ ⋯», между кнопками, где всё равно пусто.
       Высоты она там не отнимает вовсе: всё ниже стоит, где стояло;
     • в Telegram нашей строки «‹ ⋯» нет — там одна строка над столом,
       это 24 точки плюс обычный просвет.
   Касаний строка не ловит: над ней кнопки «‹» и «⋯», и её коробка
   не должна их перекрывать. */
@media (max-height: 700px) {
  .шапка-игры {
    flex-direction: row;
    align-items: baseline;
    justify-content: center;
    gap: 0.35em;
    box-sizing: border-box;
    height: 24px;
    padding: 0 40px;
    overflow: hidden;
    white-space: nowrap;
    pointer-events: none;
  }

  .шапка-игры__заголовок {
    flex: 0 0 auto;
    font-size: 15px;
    font-weight: 700;
    line-height: 24px;
    letter-spacing: 0;
  }

  .шапка-игры__подзаголовок {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 13px;
    line-height: 24px;
  }

  /* Точка между названием и режимом — только когда режим уже написан. */
  .шапка-игры__подзаголовок:not(:empty)::before {
    content: "· ";
  }

  /* Строка «‹ ⋯» видна (в браузере и в старом Telegram — см. «без-настроек»):
     шапка поднимается в неё. «‹ ⋯» занимает в столбике 32 точки (44 минус
     поля), значит шапка встаёт на 24 точки выше своего места плюс просвет
     между рядами — и следующая за ней полоса остаётся ровно там же. */
  html:not(.в-телеграме) #экран-игры > .верх-игры + .шапка-игры,
  html.в-телеграме.без-настроек #экран-игры > .верх-игры + .шапка-игры {
    margin-top: calc(-24px - var(--зазор-рядов));
  }
}

/* ---------- Старый Telegram (до 7.0): нет пункта «Настройки» ----------
   В новом Telegram лист «Ещё» стола открывается пунктом «Настройки»
   в его меню, поэтому нашу строку «‹ ⋯» мы там прячем. В старом такого
   пункта нет — и лист со звуком, правилами и рекордами было бы открыть
   нечем. Признак ставит игра на <html> (класс «без-настроек»): тогда
   строка снова видна, но только с «⋯» — стрелку «Назад» Telegram рисует
   сам. «‹» не убираем из строки, а делаем невидимой: так «⋯» остаётся
   справа, где её ищут. Витрина — так же: её строка видна, но без
   названия (его пишет шапка Telegram) — только «⋯». */
html.в-телеграме.без-настроек .верх-игры { display: flex; }

/* «‹» — первая кнопка строки: на столе, в лобби и на шагах до партии. */
html.в-телеграме.без-настроек .верх-игры > .верх-игры__кнопка:first-child { visibility: hidden; }

html.в-телеграме.без-настроек .витрина__панель { display: grid; }

html.в-телеграме.без-настроек .витрина__панель-заголовок { visibility: hidden; }

/* ---------- Аватар ----------
   Кружок с человечком — значок «avatar.svg» из набора. Рисуется маской:
   форму даёт значок, цвет — цвет текста. Поэтому один и тот же значок
   бывает серым (ждёт) и салатовым (сейчас его ход) без второй картинки.
   Пока в строке соперника нет настоящего узла «аватар», кружок рисует
   сама строка (::before); появится узел — строка рисовать перестанет. */
.аватар,
#рука-бота:not(:has(> .аватар))::before {
  content: "";
  flex: 0 0 auto;
  display: block;
  width: var(--аватар, 40px);
  height: var(--аватар, 40px);
  color: #8a9199;
  background-color: currentColor;
  -webkit-mask: var(--значок-аватар) center / contain no-repeat;
  mask: var(--значок-аватар) center / contain no-repeat;
}

/* Настоящее фото вместо нарисованного значка: js кладёт готовый адрес
   (уже вида url("…")) в переменную «--фото-аватара» и добавляет этот
   класс. Маска-человечек гаснет, кружок остаётся тем же размером —
   просто вместо значка теперь фотография, подрезанная по кругу без
   искажения пропорций («cover»: лицо не растягивается, лишние края
   обрезаются). Нет фото — класса нет, кружок как был. */
.аватар--фото {
  -webkit-mask: none;
  mask: none;
  background-color: transparent;
  background-image: var(--фото-аватара);
  background-position: center;
  background-size: cover;
  border-radius: 50%;
}

/* ---------- Строка игрока: соперник вдвоём и «Вы» ----------
   Тёмная панель на тон светлее страницы, тонкая светлая кромка и мягкая
   тень — как панель «Соперник» на макете. Класс общий: такую же строку
   получат шашки, шахматы и нарды. Пока разработчик не поставил класс
   на ряд соперника, правило держится за его идентификатор. */
.строка-игрока,
#экран-игры > #рука-бота {
  --аватар: clamp(34px, 10.5vw, 46px);
  position: relative;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: clamp(9px, 3vw, 14px);
  height: var(--ряд-соперника, 58px);
  max-height: none;
  padding: 0 clamp(8px, 2.6vw, 12px);
  color: var(--сб-текст);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0) 70%),
    var(--сб-поверхность);
  border: 1px solid var(--граница-тихая, rgba(248, 245, 235, 0.09));
  border-radius: 14px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    0 6px 16px rgba(0, 0, 0, 0.28);
}

/* Чей ход — салатовое кольцо у аватара, как у «Вы» на макете. Кольцо
   одно на весь экран, и оно всегда у того, кто сейчас ходит. */
.строка-игрока--ходит .аватар,
#рука-бота.строка-игрока--ходит:not(:has(> .аватар))::before {
  color: var(--сб-акцент);
}

.строка-игрока--ходит {
  border-color: rgba(210, 247, 107, 0.32);
}

/* Строка «Вы» ниже строки соперника (на макете 39 точек против 59):
   в ней нет веера, только имя и плашка статуса справа. */
.строка-игрока--я {
  --аватар: clamp(28px, 8.5vw, 36px);
  height: clamp(40px, 11.3vw, 50px);
  gap: clamp(8px, 2.6vw, 12px);
  padding: 0 5px 0 clamp(6px, 2vw, 9px);
}

.строка-игрока__имя {
  flex: 0 0 auto;
  font-size: clamp(15px, 4.3vw, 18px);
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
  color: var(--сб-текст);
}

/* ---------- Плашка статуса («пилюля») ----------
   Круглая плашка по размеру слов у правого края строки: «Вы отбиваетесь»,
   «Ваш ход», «Ход соперника». Когда ход ваш — салатовая с почти чёрным
   текстом, как на макете; когда ждём — тихая, только контур. Пустая
   плашка не рисуется вовсе. Класс общий для всех игр. */
.пилюля {
  flex: 0 1 auto;
  min-width: 0;
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  height: calc(100% - 10px);
  max-height: 34px;
  padding: 0 clamp(12px, 3.6vw, 16px);
  font-size: clamp(13px, 3.8vw, 16px);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--сб-текст-тихий);
  border: 1px solid var(--сб-граница);
  border-radius: 999px;
}

.пилюля:empty { display: none; }

.пилюля--акцент {
  font-weight: 700;
  color: var(--сб-акцент-текст);
  background: var(--сб-акцент);
  border-color: var(--сб-акцент);
}

/* ---------- Таймер-пилюля: секунды на ход (план «время на ход») ----------
   Форма — общая «.пилюля», активный ход красит уже готовый «.пилюля--акцент»
   (та же салатовая заливка, что у статуса «Ваш ход») — своего цвета не
   заводим. Свой класс нужен только для места в строке и моноширинных цифр,
   чтобы секунды не «прыгали» на ходу. Пилюля скрыта классом «скрыт», пока
   у партии нет лимита на ход, — стол выглядит ровно как без правила. */
.таймер-хода {
  font-variant-numeric: tabular-nums;
  order: 3;
  flex: 0 0 auto;
  margin-left: 6px;
}

/* Подпись соперника: имя крупно и белым, «6 карт» — серым под ним.
   Раньше это была пилюля под веером; теперь это текст панели. */
#рука-бота #счётчик-бота {
  position: static;
  order: 1;
  flex: 1 1 auto;
  min-width: 0;
  max-width: none;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 0.3em;
  padding: 0;
  font-size: clamp(13px, 3.6vw, 15px);
  font-weight: 500;
  line-height: 1.3;
  text-align: left;
  white-space: nowrap;
  color: var(--сб-текст-тихий);
  background: none;
  border-radius: 0;
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  overflow: hidden;
}

#рука-бота #счётчик-бота .счётчик__имя {
  flex: 0 0 100%;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: clamp(14px, 4.1vw, 17px);
  font-weight: 700;
  color: var(--сб-текст);
}

/* Веер рубашек справа: карты внахлёст, прижаты к правому краю, как на
   макете. Рубашка — 12,5 сотых ширины экрана (49 точек на 390; на макете
   51, но у нас имя длиннее — «Обычный соперник», — и ему нужна ширина).
   Позиции карт внутри веера считает игра; ширину веера задаём по числу
   рубашек, чтобы короткий веер стоял у правого края, а не посередине. */
#рука-бота > #карты-бота {
  --рубашка-в: clamp(40px, 12.5vw, 54px);
  --в: var(--рубашка-в);
  --ш: calc(var(--рубашка-в) / 1.4);
  --рубашек: 6;
  position: relative;
  inset: auto;
  order: 2;
  flex: 0 0 auto;
  width: min(40%, calc(var(--ш) * (1 + (var(--карт-в-веере, var(--рубашек)) - 1) * 0.5)));
  height: calc(var(--в) + 4px);
}

#карты-бота:not(:has(> :nth-child(2)))                        { --рубашек: 1; }
#карты-бота:has(> :nth-child(2)):not(:has(> :nth-child(3)))   { --рубашек: 2; }
#карты-бота:has(> :nth-child(3)):not(:has(> :nth-child(4)))   { --рубашек: 3; }
#карты-бота:has(> :nth-child(4)):not(:has(> :nth-child(5)))   { --рубашек: 4; }
#карты-бота:has(> :nth-child(5)):not(:has(> :nth-child(6)))   { --рубашек: 5; }

/* ---------- Стол: деревянная рама и бордовое сукно ----------
   Картинок нет: всё рисуется слоями.
     сукно — тёмно-бордовый, светлее к середине и темнее к краям,
             поверх мелкое зерно ткани (тот же шум, что был у зелёного
             стола) и тень от рамы внутрь;
     рама  — рамка элемента, залитая деревом: сверху светлее, снизу
             темнее (свет падает сверху), поверх продольные волокна,
             по внешнему краю фаска — светлая кромка сверху и тёмная
             снизу (её рисует ::before).
   Стол почти касается краёв экрана — на макете рама шире панелей.
   Класс общий («стол-игры»): шашки и нарды получат ту же раму, со своим
   сукном — цвета сукна вынесены в переменные. */
#зона-стола,
.стол-игры {
  --рама: clamp(7px, 2.3vw, 11px);
  --сукно-свет: #6e181c;
  --сукно: #4f0d10;
  --сукно-тень: #2a0507;
  --дерево-свет: #9a6841;
  --дерево: #75492b;
  --дерево-тень: #4a2b17;

  /* Стол — мерка для всего, что на нём лежит (см. начало раздела). */
  container: стол / size;
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  /* Выше этого столу расти незачем: два ряда пар в полный рост уже
     помещаются. Лишняя высота уходит воздухом над столом и под ним. */
  max-height: min(95vw, 480px);
  align-self: center;
  width: min(calc(100% + 2 * (var(--поле, 14px) - 4px)), 540px);
  margin: auto 0;
  border: var(--рама) solid transparent;
  border-radius: calc(var(--рама) + 16px);
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3'/%3E%3CfeColorMatrix values='1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E") padding-box,
    radial-gradient(120% 95% at 50% 32%, var(--сукно-свет) 0%, var(--сукно) 50%, var(--сукно-тень) 100%) padding-box,
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='60'%3E%3Cfilter id='d'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.012 0.5' numOctaves='2'/%3E%3CfeColorMatrix values='1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1'/%3E%3C/filter%3E%3Crect width='240' height='60' filter='url(%23d)' opacity='0.7'/%3E%3C/svg%3E") border-box,
    linear-gradient(180deg, var(--дерево-свет) 0%, var(--дерево) 40%, var(--дерево-тень) 100%) border-box;
  background-size: 160px 160px, auto, 240px 60px, auto;
  background-repeat: repeat, no-repeat, repeat, no-repeat;
  background-blend-mode: soft-light, normal, soft-light, normal;
  box-shadow:
    inset 0 0 0 1px rgba(0, 0, 0, 0.55),      /* шов между рамой и сукном */
    inset 0 10px 26px rgba(0, 0, 0, 0.50),    /* тень от верхнего борта */
    inset 0 -8px 20px rgba(0, 0, 0, 0.35),    /* и от нижнего */
    0 0 0 1px rgba(0, 0, 0, 0.60),            /* тёмный край рамы */
    0 14px 30px rgba(0, 0, 0, 0.55);          /* стол отбрасывает тень */
}

/* Фаска рамы: светлая кромка по верхнему внешнему краю, тёмная — по
   нижнему. Лежит под картами и касаний не ловит. */
#зона-стола::before,
.стол-игры::before {
  content: "";
  position: absolute;
  inset: calc(-1 * var(--рама));
  border-radius: inherit;
  pointer-events: none;
  box-shadow:
    inset 0 1.5px 0 rgba(255, 222, 184, 0.34),
    inset 0 -1.5px 0 rgba(0, 0, 0, 0.45),
    inset 1px 0 0 rgba(255, 222, 184, 0.10),
    inset -1px 0 0 rgba(0, 0, 0, 0.25);
}

/* ---------- Колода с козырем и подпись ----------
   Колода — стопка в левом верхнем углу сукна.

   ЖАЛОБА ВЛАДЕЛЬЦА (11 сентября): «колода карт в дураке сильно маленькая
   и плохо видно карту, которая под колодой». Было: рост колоды — 17,5
   сотых ширины ОКНА, не больше 80 точек. На телефоне это 68 точек,
   а на планшете окно широкое, и колода упиралась в свои 80 — на
   увеличенном столе она выглядела спичечным коробком.

   Стало: рост колоды считается от самого сукна — 24 сотых его ширины
   (87 точек на 390), но не больше 36 сотых его высоты и не больше 100
   точек. Почему именно так: каждая точка колоды отнимается у полосы пар
   под ней. При шести парах (два ряда) на 390×844 карта на столе выходит
   91 точку вместо 99 — всё ещё крупная, угол читается. Дальше растить
   колоду — значит мельчить пары, а они важнее: по ним отбиваются.

   Козырь лежит ПОПЕРЁК, под колодой, как кладут в настоящей игре,
   и выглядывает справа торцом на полкарты («--выгляд»). */
#зона-стола {
  /* Потолок роста колоды. На планшете и мониторе он растёт вместе
     с картой в руке (раздел «ШИРОКОЕ ОКНО» в конце файла). */
  --колода-потолок: 100px;
  --колода-в: min(24cqw, 36cqh, var(--колода-потолок));
  --колода-ш: calc(var(--колода-в) / 1.4);
  --колода-x: clamp(8px, 3vw, 14px);
  --колода-y: clamp(8px, 2.6vw, 12px);
  --выгляд: calc(var(--колода-ш) * 0.5);
  --до-подписи: clamp(10px, 3.4vw, 16px);
}

#зона-стола > #колода {
  --в: var(--колода-в);
  --ш: var(--колода-ш);
  position: absolute;
  left: var(--колода-x);
  top: var(--колода-y);
  width: calc(var(--колода-ш) + var(--выгляд));
  height: calc(var(--колода-в) + 6px);
}

/* Стопка: под верхней рубашкой видны кромки ещё нескольких карт —
   тонкие светлые и тёмные полоски снизу, как на макете. */
#колода #верх-колоды .карта {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 2;
  box-shadow:
    0 1px 0 #d8cfbb, 0 2px 0 #7f735d,
    0 3px 0 #ddd4c0, 0 4px 0 #7f735d,
    0 5px 0 #d4cab5, 0 6px 0 #6f6450,
    0 8px 12px rgba(0, 0, 0, 0.55);
}

/* Козырь поперёк. Сама карта размечена стоймя, как любая, а на бок её
   кладёт «rotate: 90deg» — поворот по часовой вокруг середины. Именно
   «rotate», а не «transform»: полёт карт пользуется «transform», и так
   они друг другу не мешают (как у пар на столе).
   Где лежит: середина козыря — на середине колоды по высоте, правый
   торец выходит из-под колоды на «--выгляд». Отсюда «left»: правый край
   лежачей карты (ширина колоды + выгляд) минус половина её длины (--в / 2)
   минус половина её ширины (--ш / 2) — потому что «left» считается
   от карты, ещё не повёрнутой.
   Тень задана вбок («2px 0»): после поворота на 90° она ложится вниз. */
#колода #козырная-карта .карта {
  position: absolute;
  left: calc(var(--колода-ш) + var(--выгляд) - var(--колода-в) / 2 - var(--колода-ш) / 2);
  top: 2px;
  z-index: 1;
  transform: none;
  rotate: 90deg;
  box-shadow: 2px 0 4px rgba(0, 0, 0, 0.45), 6px 0 12px rgba(0, 0, 0, 0.30);
}

/* Что видно в торце. У лежачей карты углы с достоинством стоят боком —
   читать их пришлось бы, наклонив голову. Поэтому в торце показываем
   третий угол рисунка («угол-козыря», js/колода-рисунок.js): у каждой
   карты он есть, но скрыт. Здесь он разворачивается обратно прямо
   («rotate(-90deg)» гасит поворот карты) и встаёт посередине торца,
   увеличенный так, чтобы занять всю видимую полоску (см. ниже, откуда
   взялись два разных числа масштаба).
   Числа — в точках рисунка карты (он 250 на 350): угол стоит у правого
   края, его середина около x = 219; середина торца — на 125 по x и на
   четверти ширины карты от её верха. Сдвиг «-94» переносит угол с края
   на середину торца.
   Последнюю карту колоды сдают в руку, и там она сама становится
   обычной — правила действуют только под колодой.

   УВЕЛИЧЕНИЕ (11 сентября): было видно плохо — мелкая надпись терялась
   рядом с колодой. У поворота на 90° оси меняются местами, поэтому два
   числа scale() отвечают за разное: первое (по бывшей ширине буквы)
   определяет, насколько знак растянется В ГЛУБИНУ, под колоду, а второе
   (по бывшей высоте столбика «достоинство над мастью») — насколько он
   заполнит полоску ПО ВЫСОТЕ. Полоска узкая (около трети ширины карты),
   а двузначная «10» и без того широкая — тяни оба числа поровну, и «10»
   упёрлась бы в колоду раньше, чем достоинство с мастью заполнили бы
   высоту. Раздельный масштаб снимает этот компромисс: 1,5 — с запасом
   даже для «10», 2 — почти во всю высоту полоски. Проверено расчётом
   по формуле поворота и снимками на 390, 360×640 и 820×1180. */
#колода #козырная-карта .карта-рисунок__угол-козыря {
  visibility: visible;
  transform-box: fill-box;
  transform-origin: center;
  transform: translate(-94px, 4px) rotate(-90deg) scale(1.5, 2);
}

/* Пока на козыре лежат рубашки, в торце — только этот угол. Значки
   середины и картинка фигуры торчали бы из-под него и путали надпись,
   а обычные углы стояли бы боком рядом с прямым. */
#колода:not(:has(#верх-колоды:empty)) #козырная-карта .карта-рисунок > g > :not(.карта-рисунок__угол-козыря) {
  visibility: hidden;
}

/* В колоде остался один козырь — рубашки над ним нет, карта видна
   целиком, со своими углами и значками. Добавочный угол был бы лишним
   и лёг бы поверх значков. Прячем. */
#колода:has(#верх-колоды:empty) #козырная-карта .карта-рисунок__угол-козыря {
  visibility: hidden;
}

/* Подпись справа от колоды: «Козырь ♥» белым, под ним серым «В колоде:
   21». Обе части уже есть в разметке, их просто переставили. По метке
   козыря нажимают (игра объясняет, что это такое), поэтому её коробка —
   44 точки в высоту, хотя буквы занимают меньше. */
#зона-стола > #метка-козыря {
  position: absolute;
  left: calc(var(--колода-x) + var(--колода-ш) + var(--выгляд) + var(--до-подписи));
  top: calc(var(--колода-y) - 2px);
  width: auto;
  max-width: calc(100% - var(--колода-x) - var(--колода-ш) - var(--выгляд) - var(--до-подписи) - 8px);
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.35em;
  padding: 0;
  font-size: clamp(14px, 4vw, 17px);
  font-weight: 600;
  color: var(--сб-текст);
  background: none;
  border: none;
  border-radius: 8px;
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  align-content: center;
}

#метка-козыря .метка__слово {
  font-size: 1em;
  line-height: 1;
  letter-spacing: 0;
  color: var(--сб-текст);
}

/* Знак масти — как на самой карте (чёрный у пик и треф, красный у червей
   и бубён: цвет берётся из тех же классов «карта--…», ничего своего тут
   не красим). На тёмном сукне чёрный значок один потерялся бы, поэтому
   под него — маленькая кремовая плашка цвета лица карты, с той же тонкой
   окантовкой и тенью, что у карт на столе. Так масть узнаётся с одного
   взгляда, на любом из пяти сукон. */
#метка-козыря .метка__масть {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.05em;
  line-height: 1;
  padding: 0.16em 0.4em;
  background: var(--карта-фон);
  border: 1px solid rgba(70, 48, 22, 0.28);
  border-radius: 5px;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.35),
    0 1px 2px rgba(0, 0, 0, 0.45),
    0 2px 5px rgba(0, 0, 0, 0.3);
}

#метка-козыря:active {
  transform: translateY(1px);
  box-shadow: none;
  opacity: 0.8;
}

#зона-стола #колода #счётчик-колоды {
  position: absolute;
  left: calc(100% + var(--до-подписи));
  top: clamp(26px, 7.6vw, 34px);
  width: auto;
  height: auto;
  max-width: none;
  max-height: none;
  padding: 0;
  font-size: clamp(12px, 3.5vw, 15px);
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  text-align: left;
  /* Серый на бордовом: тёплый белый с прозрачностью — контраст около 6 */
  color: rgba(248, 245, 235, 0.62);
  background: none;
  border-radius: 0;
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  overflow: visible;
}

/* ---------- Карты на столе ----------
   Поле пар — под колодой (или справа от неё), во всю оставшуюся ширину
   сукна. Оно — мерка: размер карты считается от его ширины и высоты.

   ЖАЛОБА ВЛАДЕЛЬЦА (11 сентября): «когда больше трёх карт на столе,
   карты становятся сильно маленькими!». Причина была в арифметике:
   поле пар всегда считалось на ТРИ пары в ряд, даже когда пара одна,
   а с четвёртой пары колода уходила в столбик, отнимала ширину — и
   карта падала скачком на треть (на 390×740 — с 99 до 66 точек,
   на 390×844 с полной рукой — до 60).

   Стало — три ступени, по порядку:
     1) РЯДЫ. Для своего числа пар пробуем раскладки в один ряд, в два
        и в три и берём ту, где карта крупнее. Четыре пары — это два
        ряда по две, а не ряд на три пары и одна внизу.
     2) НАЛОЖЕНИЕ. Отбивающая карта сдвинута вправо на 46 сотых карты,
        когда места хватает, и до 30 сотых — когда тесно. Угол побитой
        карты с достоинством и мастью виден и при 30. Решает сама
        раскладка: ряд собирается по плотной ширине пары, а свободное
        место в ряду раздаётся парам обратно — до свободного наложения
        (см. «.пара» ниже).
     3) И только потом карта уменьшается — ровно настолько, насколько
        не хватает места, без скачков.
   Потолок прежний — девять десятых карты в руке: карта на столе
   не крупнее своей.

   Числа в формулах:
     0,989 — ширина пары на единицу роста карты при плотном наложении,
       с запасом на поворот: (1 + 0,30) / 1,4 × 1,065;
     1,13 — рост пары на единицу роста карты: карта, сдвиг отбивающей
       вниз на 7 сотых и запас на поворот.
   Сотые доли «cqw» и «cqh» здесь — от самого поля пар: переменные
   считаются там, где их берут пары и карты, а их мерка — это поле. */
#зона-стола > #стол {
  container-type: size;
  --пары-зазор: clamp(8px, 3vw, 14px);
  /* Предел роста карты, когда в ряду 1…6 пар (по ширине поля)… */
  --по-ширине-1: calc(100cqw / 0.989);
  --по-ширине-2: calc((100cqw - 1 * var(--пары-зазор)) / 1.978);
  --по-ширине-3: calc((100cqw - 2 * var(--пары-зазор)) / 2.967);
  --по-ширине-4: calc((100cqw - 3 * var(--пары-зазор)) / 3.956);
  --по-ширине-5: calc((100cqw - 4 * var(--пары-зазор)) / 4.945);
  --по-ширине-6: calc((100cqw - 5 * var(--пары-зазор)) / 5.934);
  /* …и когда рядов 1, 2 или 3 (по высоте поля). */
  --по-высоте-1: calc(100cqh / 1.13);
  --по-высоте-2: calc((100cqh - 1 * var(--пары-зазор)) / 2.26);
  --по-высоте-3: calc((100cqh - 2 * var(--пары-зазор)) / 3.39);
  --потолок-стола: calc(var(--в-рука) * 0.9);
  /* Одна пара: один ряд. */
  --в: min(var(--потолок-стола), var(--по-ширине-1), var(--по-высоте-1));
  --ш: calc(var(--в) / 1.4);
  --сдвиг-y: calc(var(--в) * 0.07);
  position: absolute;
  left: 6px;
  right: 6px;
  top: calc(var(--колода-y) + var(--колода-в) + 14px);
  bottom: 6px;
  display: flex;
  flex-wrap: wrap;
  align-content: center;
  justify-content: center;
  gap: var(--пары-зазор);
}

/* Две пары и больше: из раскладок «в один ряд», «в два», «в три» —
   та, где карта крупнее. Правила идут по возрастанию числа пар, вес
   у них одинаковый — срабатывает последнее подходящее. */
#зона-стола > #стол:has(> .пара:nth-child(2)) {
  --в: min(var(--потолок-стола),
           max(min(var(--по-ширине-2), var(--по-высоте-1)),
               min(var(--по-ширине-1), var(--по-высоте-2))));
}

#зона-стола > #стол:has(> .пара:nth-child(3)) {
  --в: min(var(--потолок-стола),
           max(min(var(--по-ширине-3), var(--по-высоте-1)),
               min(var(--по-ширине-2), var(--по-высоте-2))));
}

#зона-стола > #стол:has(> .пара:nth-child(4)) {
  --в: min(var(--потолок-стола),
           max(min(var(--по-ширине-4), var(--по-высоте-1)),
               min(var(--по-ширине-2), var(--по-высоте-2))));
}

#зона-стола > #стол:has(> .пара:nth-child(5)) {
  --в: min(var(--потолок-стола),
           max(min(var(--по-ширине-5), var(--по-высоте-1)),
               min(var(--по-ширине-3), var(--по-высоте-2)),
               min(var(--по-ширине-2), var(--по-высоте-3))));
}

#зона-стола > #стол:has(> .пара:nth-child(6)) {
  --в: min(var(--потолок-стола),
           max(min(var(--по-ширине-6), var(--по-высоте-1)),
               min(var(--по-ширине-3), var(--по-высоте-2)),
               min(var(--по-ширине-2), var(--по-высоте-3))));
}

/* Больше шести пар в дураке не бывает, но если правила когда-нибудь
   позволят — два ряда по четыре или три по три, а не обрыв. */
#зона-стола > #стол:has(> .пара:nth-child(7)) {
  --в: min(var(--потолок-стола),
           max(min(var(--по-ширине-4), var(--по-высоте-2)),
               min(var(--по-ширине-3), var(--по-высоте-3))));
}

/* Пара на столе. Ряд собирается по ПЛОТНОЙ ширине пары (отбивающая
   сдвинута на 30 сотых карты), потом свободное место ряда раздаётся
   парам обратно — каждая раздвигается до свободных 46 сотых. Так
   наложение становится плотнее только там и тогда, где тесно.
   Отбивающая карта прижата к правому краю пары — её сдвиг и есть
   «ширина пары минус карта». */
#зона-стола > #стол > .пара {
  flex: 1 1 calc(var(--ш) * 1.3);
  max-width: calc(var(--ш) * 1.46);
}

/* ---------- Колода кончилась ----------
   Стопки больше нет, и подпись («Козырь ♣ / Колода пуста») встаёт
   в левый верхний угол сукна, а поле пар поднимается на освободившееся
   место: в конце партии карт на столе как раз больше всего. */
#зона-стола:has(#верх-колоды:empty):has(#козырная-карта:empty) > #метка-козыря {
  left: var(--колода-x);
  top: calc(var(--колода-y) - 6px);
  height: 36px;
}

#зона-стола:has(#верх-колоды:empty):has(#козырная-карта:empty) #колода #счётчик-колоды {
  left: 0;
  top: 24px;
}

#зона-стола:has(#верх-колоды:empty):has(#козырная-карта:empty) > #стол {
  top: calc(var(--колода-y) + 48px);
}

/* ---------- Низкий и широкий стол: колода встаёт столбиком слева ----------
   Полоса с колодой сверху съедает у стола почти сотню точек высоты.
   Пока стол высокий, это не жалко. В низком окне (или когда пар четыре
   и больше и нужны два ряда) выгоднее поставить колоду с подписью
   столбиком у левого края, а пары — справа во всю высоту: карты на
   столе выходят крупнее. Решает форма стола, а не размер окна:
     • пар до трёх — столбик, если сукно шире своей высоты больше чем
       вдвое;
     • пар четыре и больше — если сукно просто шире своей высоты
       (до 11 сентября порог был «шире на треть»).
   Пороги посчитаны так, чтобы из двух раскладок всегда бралась та,
   где карта на столе крупнее. Сверено замером в окне 390×568: сукно
   364×179 (в 2,03 раза шире), полосой карта выходила 72 точки, столбиком —
   73; ниже этого окна столбик выигрывает всё заметнее.
   Почему порог для четырёх пар опустился. Раньше поле пар всегда
   считалось на три пары в ряд, и столбик колоды, отнимая ширину, почти
   никогда не окупался. Теперь четыре пары — это два ряда по две, и им
   ширины у столбика хватает: на 390×844 (сукно 364×340) карта выходит
   107 точек столбиком против 93 полосой. При шести парах на том же
   сукне полоса была бы чуть крупнее (93 против 90), но колода, которая
   на пятой паре прыгает обратно наверх, путает сильнее трёх точек. */
@container стол (min-aspect-ratio: 2 / 1) {
  /* В низком столе колода стоит столбиком и пары под собой не теснит,
     поэтому её рост ограничен не 36, а 42 сотыми высоты сукна — как
     было до 11 сентября, чтобы в низком окне колода не стала мельче
     прежней. Ширину и выгляд объявляем заново здесь же: переменная
     считается там, где объявлена, и прежние унаследовались бы готовыми. */
  #зона-стола > :is(#колода, #метка-козыря, #стол) {
    --колода-в: min(24cqw, 42cqh, var(--колода-потолок));
    --колода-ш: calc(var(--колода-в) / 1.4);
    --выгляд: calc(var(--колода-ш) * 0.5);
  }

  #зона-стола > #стол {
    left: calc(var(--колода-x) + max(calc(var(--колода-ш) + var(--выгляд)), 74px) + 10px);
    top: 6px;
  }

  #зона-стола > #метка-козыря {
    left: var(--колода-x);
    top: calc(var(--колода-y) + var(--колода-в) + 4px);
    height: 32px;
    max-width: none;
    font-size: clamp(12px, 3.4vw, 14px);
  }

  #зона-стола #колода #счётчик-колоды {
    left: 0;
    top: calc(100% + 34px);
    font-size: clamp(11px, 3.1vw, 13px);
  }

  /* Колода кончилась, а стол низкий: пары остаются справа во всю высоту,
     подпись — в углу слева. */
  #зона-стола:has(#верх-колоды:empty):has(#козырная-карта:empty) > #стол {
    top: 6px;
  }
}

/* Столбик для четырёх пар и больше — только пока колода на столе
   (в «верх-колоды» или «козырная-карта» что-то лежит). Колода кончилась —
   столбик пустой, и отступ под него (около 107 точек) пропадал зря:
   шесть пар полосой на 390×844 выходят 107 точек, в оставшейся справа
   ширине — 90. Тогда пары встают полосой под подписью «Колода пуста»
   (см. «Колода кончилась» выше). */
@container стол (min-aspect-ratio: 1 / 1) {
  #зона-стола:has(> #стол > .пара:nth-child(4)):has(:is(#верх-колоды, #козырная-карта):not(:empty)) > #стол {
    left: calc(var(--колода-x) + max(calc(var(--колода-ш) + var(--выгляд)), 74px) + 10px);
    top: 6px;
  }

  #зона-стола:has(> #стол > .пара:nth-child(4)):has(:is(#верх-колоды, #козырная-карта):not(:empty)) > #метка-козыря {
    left: var(--колода-x);
    top: calc(var(--колода-y) + var(--колода-в) + 4px);
    height: 32px;
    max-width: none;
    font-size: clamp(12px, 3.4vw, 14px);
  }

  #зона-стола:has(> #стол > .пара:nth-child(4)):has(:is(#верх-колоды, #козырная-карта):not(:empty)) #колода #счётчик-колоды {
    left: 0;
    top: calc(100% + 34px);
    font-size: clamp(11px, 3.1vw, 13px);
  }
}

/* Пара: побитая карта чуть повёрнута влево, накрывающая — вправо,
   как кладут рукой. Повороты у пар немного разные, чтобы стол не
   выглядел отпечатанным штампом. Поворот задан свойством «rotate»,
   а не «transform»: движение карт пользуется «transform», и они
   друг другу не мешают. */
#стол .пара .карта--атака {
  position: absolute;
  left: 0;
  top: 0;
  rotate: -2deg;
}

#стол .пара .карта--защита {
  position: absolute;
  left: auto;
  right: 0;
  top: var(--сдвиг-y);
  transform: none;
  rotate: 6deg;
  box-shadow:
    -3px -1px 6px rgba(0, 0, 0, 0.35),
    3px 6px 12px rgba(0, 0, 0, 0.45);
}

#стол .пара:nth-child(3n + 2) .карта--атака  { rotate: 1.5deg; }
#стол .пара:nth-child(3n + 2) .карта--защита { rotate: 4deg; }
#стол .пара:nth-child(3n) .карта--атака      { rotate: -0.5deg; }
#стол .пара:nth-child(3n) .карта--защита     { rotate: 7deg; }

/* Неотбитая карта — тихая белая рамка вокруг: «эту ещё надо крыть».
   Оформление само видит пару без накрывающей карты, разметки не нужно. */
#стол .пара:not(:has(> .карта--защита)) > .карта--атака {
  outline: 1.5px solid rgba(248, 245, 235, 0.5);
  outline-offset: 4px;
}

/* Куда можно положить выбранную карту — салатовая рамка с отступом,
   как у десятки пик на макете, и мягкое свечение. Салатовый здесь
   значит то же, что у выбранной карты в руке: «вот сюда». */
#стол .пара.пара--цель:not(:has(> .карта--защита)) > .карта--атака {
  outline: 2px solid var(--сб-акцент);
  outline-offset: 5px;
  box-shadow:
    0 2px 4px rgba(0, 0, 0, 0.45),
    0 6px 14px rgba(0, 0, 0, 0.32),
    0 0 22px 3px rgba(210, 247, 107, 0.35);
}

/* Бумага, кромка и тени карты — в самом правиле «.карта» (раздел «Сама
   карта» выше по файлу), одним местом.

   ВНИМАНИЕ тому, кто захочет задать карте вид здесь, в конце файла:
   ЦВЕТ КАРТЕ НИЖЕ ПРАВИЛ МАСТЕЙ НЕ ЗАДАВАТЬ. Цвет карты — это цвет её
   масти («карта--черви», «карта--красная» и прочие), и рисунок красит им
   и номинал, и значки. Правило «.карта { color: … }» с тем же весом, но
   ниже по файлу, перебивает их все: так 10 сентября черви и бубны стали
   чёрными, и владелец написал «красные и тёмные сливаются». */

/* ---------- Своя рука ----------
   Карта в руке — самая крупная на экране (85×119 на телефоне 390).
   Полоска руки — рост карты и 24 точки запаса: 14 сверху, чтобы
   выбранной карте было куда подняться, и 10 снизу — под салатовую
   черту «этой можно ходить».

   Когда карт дюжина и больше, игра кладёт руку в два ряда, и полоска
   забирает у стола высоту на второй ряд (карта в ряду — 78 сотых
   обычной), но не больше четверти окна. Решает, класть ли ряды, сама
   игра — по высоте, которую ей здесь дали. Полы 70 и 86 точек — прежние:
   ниже них ряды не включаются вовсе (см. «Наименьшая высота руки»). */
#приложение #экран-игры #рука-человека {
  height: calc(var(--в) + 24px);
  max-height: calc(var(--в) + 24px);
}

#приложение #экран-игры #рука-человека:has(#карты-человека > :nth-child(12)) {
  height: max(70px, min(calc(var(--в) * 1.56 + 26px), calc(var(--доступно) * 0.26)));
  max-height: max(70px, min(calc(var(--в) * 1.56 + 26px), calc(var(--доступно) * 0.26)));
}

#приложение #экран-игры #рука-человека:has(#карты-человека > :nth-child(18)) {
  height: max(86px, min(calc(var(--в) * 1.56 + 26px), calc(var(--доступно) * 0.26)));
  max-height: max(86px, min(calc(var(--в) * 1.56 + 26px), calc(var(--доступно) * 0.26)));
}

/* Обрезку по краю с карты руки снимаем: под картой рисуется черта
   «можно ходить», а рисунок карты и так не выходит за скруглённые углы.
   (Тень, которой карта отчёркивается от соседки, — в «.веер .карта»
   выше по файлу.) */
#карты-человека > .карта {
  overflow: visible;
}

/* Лёгкая дуга, как веер в руке на макете: крайние карты наклонены
   (не больше чем на 5 градусов) и чуть опущены. Номер карты и число
   карт присылает игра («--номер-в-веере», «--карт-в-веере»); пока их
   нет, рука лежит ровным рядом. Когда карт дюжина и больше, дуги нет:
   там рука может лечь рядами, а в рядах наклон только мешает. */
#карты-человека > .карта {
  --от-середины: calc(var(--номер-в-веере, 0) - (var(--карт-в-веере, 1) - 1) / 2);
  transform-origin: 50% 100%;
  rotate: calc(var(--от-середины) * min(2deg, 10deg / max(1, var(--карт-в-веере, 1) - 1)));
  translate: 0 calc(var(--от-середины) * var(--от-середины) * 6px
                    / max(1, (var(--карт-в-веере, 1) - 1) * (var(--карт-в-веере, 1) - 1) / 4));
}

#карты-человека:has(> :nth-child(12)) > .карта {
  rotate: none;
  translate: none;
  /* В рядах игра делает карту ниже (пишет ей свою высоту), а ширину
     не трогает — и рисунок сплющивался: король выходил вдвое шире,
     чем выше. Ширину считаем от высоты ряда, пропорция остаётся
     карточной. Пока рука лежит одним рядом, высота обычная, и это
     правило ничего не меняет. */
  width: calc(var(--в) / 1.4);
}

/* Можно ходить — короткая салатовая черта под картой, ровно под той
   полоской, которую от неё видно (её ширину присылает игра). Черта
   снаружи карты, а не на бумаге: салатовый на кремовом почти не виден. */
.веер .карта--можно,
.карта--можно {
  transform: translateY(-3px);
  box-shadow:
    -3px 0 7px rgba(0, 0, 0, 0.32),
    0 4px 8px rgba(0, 0, 0, 0.40);
  cursor: pointer;
}

/* Отступ и толщина черты вместе не должны вылезать за 6 точек: столько
   (ЗАЗОР_РЯДОВ в js/game.js, менять нельзя) свободного места оставлено
   между рядами руки, когда карт дюжина и больше. Раньше черта уходила
   на 8 точек (5 отступ + 3 толщина) — 2 лишние точки проваливались
   под карты второго ряда, и подсветку верхнего ряда было не видно. */
#карты-человека > .карта--можно::before {
  content: "";
  position: absolute;
  left: 5px;
  top: calc(100% + 2px);
  width: max(10px, calc(var(--полоска) - 10px));
  height: 3px;
  border-radius: 2px;
  background: var(--сб-акцент);
  box-shadow: 0 0 6px rgba(210, 247, 107, 0.55);
  pointer-events: none;
}

/* Нельзя ходить — карта притушена и чуть осела. На тёмной странице
   притушенная карта сама читается как «сейчас не она», а номинал
   и масть на ней всё ещё видны. Прежняя серая плёнка больше не нужна.
   Притушаем ТОЛЬКО яркостью, цвет не трогаем: обесцвеченная черва
   становится бурой и сливается с пикой, а красное обязано отличаться
   от чёрного с первого взгляда на любой карте, в том числе на этой. */
.веер .карта--нельзя,
.карта--нельзя {
  filter: brightness(0.74);
  transform: translateY(2px);
  box-shadow: -2px 0 4px rgba(0, 0, 0, 0.30);
}

.карта--нельзя::after { background: transparent; }

/* Выбрана — поднята над соседками, обведена салатовым и светится,
   как валет на макете. Без этого игрок не понимает, среагировала ли
   игра на палец. */
.веер .карта--выбрана,
.карта--выбрана {
  transform: translateY(-14px);
  outline: 2.5px solid var(--сб-акцент);
  outline-offset: 2px;
  box-shadow:
    0 8px 18px rgba(0, 0, 0, 0.55),
    0 0 18px rgba(210, 247, 107, 0.55);
  z-index: 50;
  --полоска: var(--ш);
}

/* Подсказка (тихая серая строка под строкой «Вы») — в разделе «Подсказка»
   выше по файлу, одним местом: её коробка, цвета и запасной путь. */

/* ---------- Панель действий: «Взять», «Бито», «Сказать» ----------
   Как на макете: две равные кнопки и узкая третья справа. Тёмные,
   с тонкой светлой обводкой и значком перед словом. Недоступная —
   серая, без обводки: видно, что кнопка есть, но сейчас молчит.
   Значки — из набора владельца («img/дурак/значки/»), рисуются маской
   цветом текста. Для «Пас», «Готово», «Перевести» и «Бросить» в наборе
   значков нет — они нарисованы здесь же, тем же пером.

   Какой значок у кнопки, решает её «data-действие» (его ставит игра),
   а пока его нет — сам идентификатор кнопки. */
#панель-кнопок,
.панель-действий {
  position: relative;
  flex: 0 0 auto;
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: clamp(6px, 1.8vw, 9px);
  height: var(--ряд-кнопок, 48px);
  padding: 0;
}

#экран-игры #панель-кнопок > .кнопка,
.панель-действий > .кнопка {
  position: relative;
  order: 2;
  flex: 1 1 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-width: 0;
  min-height: 0;
  height: 100%;
  padding: 0 10px;
  font-size: clamp(15px, 4.2vw, 18px);
  font-weight: 600;
  letter-spacing: 0;
  white-space: nowrap;
  color: var(--сб-текст);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0) 60%),
    #171b1e;
  border: 1.5px solid rgba(248, 245, 235, 0.55);
  border-radius: 14px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.05),
    0 4px 12px rgba(0, 0, 0, 0.30);
}

/* Место под значок есть у каждой кнопки панели, но показывается он
   только у тех, для кого значок выбран (список ниже): у незнакомой
   кнопки пустого квадрата перед словом не будет. */
#экран-игры #панель-кнопок > .кнопка::before,
.панель-действий > .кнопка::before {
  content: "";
  display: none;
  flex: 0 0 auto;
  width: 1.3em;
  height: 1.3em;
  background-color: currentColor;
  -webkit-mask: var(--значок) center / contain no-repeat;
  mask: var(--значок) center / contain no-repeat;
}

#экран-игры #панель-кнопок > :is(#кнопка-беру, #кнопка-завершить, #кнопка-перевести,
                                  #кнопка-бросить, #кнопка-эмоции,
                                  [data-действие])::before {
  display: block;
}

#экран-игры #панель-кнопок > .кнопка:active {
  transform: translateY(1px);
  background: #121518;
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.35);
}

#экран-игры #панель-кнопок > .кнопка:disabled,
.панель-действий > .кнопка:disabled {
  color: #5f656c;
  background: #14171a;
  border-color: rgba(248, 245, 235, 0.10);
  box-shadow: none;
  cursor: default;
}

#экран-игры #панель-кнопок > .кнопка:disabled:active { transform: none; }

/* Порядок как на макете: «Взять» слева, «Бито» (или то, что встаёт
   на его место) посередине, «Сказать» справа. */
#панель-кнопок > #кнопка-беру                 { order: 1; --значок: var(--значок-взять); }
#панель-кнопок > #кнопка-завершить            { --значок: var(--значок-бито); }
#панель-кнопок > #кнопка-завершить.кнопка--пас { --значок: var(--значок-пас); }
#панель-кнопок > #кнопка-перевести            { --значок: var(--значок-перевести); }
#панель-кнопок > #кнопка-бросить              { --значок: var(--значок-бросить); }

/* Метка игры сильнее имени кнопки: одна и та же кнопка бывает «Бито»,
   «Пас», «Готово», «Перевести» и «Бросить», и значок идёт за ней. */
#экран-игры #панель-кнопок > .кнопка[data-действие="взять"]     { --значок: var(--значок-взять); }
#экран-игры #панель-кнопок > .кнопка[data-действие="сказать"]   { --значок: var(--значок-чат); }
#экран-игры #панель-кнопок > .кнопка[data-действие="бито"]      { --значок: var(--значок-бито); }
#экран-игры #панель-кнопок > .кнопка[data-действие="пас"]       { --значок: var(--значок-пас); }
#экран-игры #панель-кнопок > .кнопка[data-действие="готово"]    { --значок: var(--значок-готово); }
#экран-игры #панель-кнопок > .кнопка[data-действие="перевести"] { --значок: var(--значок-перевести); }
#экран-игры #панель-кнопок > .кнопка[data-действие="бросить"]   { --значок: var(--значок-бросить); }

/* «Бросить» — пара к поднятой карте: та же салатовая обводка, что
   у карты над ней. Видно без чтения: «вот эта карта, вот её кнопка». */
#экран-игры #панель-кнопок > #кнопка-бросить,
#экран-игры #панель-кнопок > .кнопка[data-действие="бросить"] {
  border-color: var(--сб-акцент);
  box-shadow: 0 0 12px rgba(210, 247, 107, 0.30);
}

/* Узкая кнопка знаков справа — место «Чата» на макете. */
#экран-игры #панель-кнопок > #кнопка-эмоции {
  --значок: var(--значок-чат);
  position: relative;
  right: auto;
  order: 3;
  flex: 0 0 auto;
  padding: 0 clamp(10px, 3.4vw, 16px);
  font-size: clamp(13px, 3.6vw, 15px);
  gap: 7px;
}

/* «В меню» из панели ушла: в Telegram это его стрелка «Назад», в браузере —
   «‹» в верхней строке, а служебные кнопки — в листе «⋯» (решение штаба). */

/* ---------- Компания: соперники над столом ----------
   Та же тёмная панель, что у соперника вдвоём, только поделена на места.
     • Двое соперников — два широких места, в каждом аватар слева, справа
       имя, «6 карт» и плашка состояния («ходит», «отбивается», «пас»).
     • Трое и больше — места поуже: аватар и число карт рядом (перед
       числом маленькая рубашка — чтобы число читалось как «карт»),
       под ними имя и плашка состояния во всю ширину места. Широкая
       раскладка на троих не помещалась: на экране 390 месту остаётся
       117 точек, тексту из них — 54, и «отбивается» обрезалось до «от…»
       (видно на снимке 390×844, стол на четверых).
   Кто ходит — салатовое кольцо у аватара и салатовая плашка «ходит»;
   это тот же знак, что у «Вы». Отбивается — белая обводка места
   и плашка с колечком-щитом. Выбывший — место гаснет.
   Высота полосы постоянная при любом числе соперников — стол под ней
   не прыгает, когда состояние переходит от одного к другому. */
#соперники {
  flex-wrap: nowrap;
  align-content: stretch;
  gap: clamp(5px, 1.6vw, 8px);
}

#соперники .соперник {
  --аватар: clamp(30px, 9.5vw, 40px);
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  max-width: none;
  min-height: 0;
  height: clamp(58px, 16.5vw, 70px);
  display: grid;
  grid-template-columns: var(--аватар) minmax(0, 1fr);
  grid-template-rows: auto auto auto;
  align-content: center;
  align-items: center;
  justify-items: start;
  column-gap: clamp(7px, 2.2vw, 10px);
  row-gap: 1px;
  padding: 0 clamp(7px, 2.2vw, 10px);
  color: var(--сб-текст);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0) 70%),
    var(--сб-поверхность);
  border: 1px solid var(--граница-тихая);
  border-radius: 14px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    0 6px 16px rgba(0, 0, 0, 0.28);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  transform: none;
  overflow: hidden;
}

#соперники .соперник::before {
  content: "";
  position: static;
  inset: auto;
  grid-column: 1;
  grid-row: 1 / -1;
  width: var(--аватар);
  height: var(--аватар);
  color: #8a9199;
  background: currentColor;
  -webkit-mask: var(--значок-аватар) center / contain no-repeat;
  mask: var(--значок-аватар) center / contain no-repeat;
}

#соперники .соперник__имя {
  grid-column: 2;
  grid-row: 1;
  display: block;
  max-width: 100%;
  -webkit-line-clamp: unset;
  font-size: clamp(13px, 3.8vw, 16px);
  font-weight: 700;
  line-height: 1.2;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

#соперники .соперник__карт {
  grid-column: 2;
  grid-row: 2;
  display: flex;
  align-items: baseline;
  justify-content: flex-start;
  height: auto;
  font-size: clamp(12px, 3.4vw, 14px);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0;
  color: var(--сб-текст-тихий);
  white-space: nowrap;
}

#соперники .соперник__число {
  font-size: 1.2em;
  font-weight: 700;
  line-height: 1;
  color: var(--сб-текст);
}

#соперники .соперник__слово { font-size: 1em; }
#соперники .соперник__слово:only-child { font-size: 1em; }

#соперники .соперник__метка,
#соперники .соперник__роль {
  grid-column: 2;
  grid-row: 3;
  justify-self: start;
  max-width: 100%;
  margin-top: 2px;
  padding: 1px 7px;
  font-size: clamp(10px, 2.9vw, 12px);
  font-weight: 600;
  line-height: 1.3;
  border-radius: 999px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

#соперники .соперник__метка {
  color: var(--сб-текст);
  background: rgba(248, 245, 235, 0.10);
}

#соперники .соперник__роль {
  color: var(--сб-текст-тихий);
  background: transparent;
  box-shadow: inset 0 0 0 1px rgba(248, 245, 235, 0.22);
  opacity: 1;
}

/* Напарник — вывернутая плашка «свой»: светлая с тёмными буквами.
   Прежняя полоса у левого края больше не нужна — там теперь аватар. */
#соперники .соперник--напарник .соперник__роль {
  color: var(--сб-фон);
  background: var(--сб-текст);
  box-shadow: none;
}

/* Ходит — салатовое кольцо у аватара и салатовая плашка «ходит». */
#соперники .соперник--ходит {
  color: var(--сб-текст);
  background:
    linear-gradient(180deg, rgba(210, 247, 107, 0.08), rgba(210, 247, 107, 0) 70%),
    var(--сб-поверхность);
  border: 1px solid rgba(210, 247, 107, 0.45);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.30);
  transform: none;
}

#соперники .соперник--ходит::before { color: var(--сб-акцент); }

#соперники .соперник--ходит .соперник__метка,
#соперники .соперник--ходит.соперник--отбивается .соперник__метка {
  color: var(--сб-акцент-текст);
  background: var(--сб-акцент);
  box-shadow: none;
}

/* Отбивается — белая обводка места и контурная плашка с колечком. */
#соперники .соперник--отбивается {
  border: 1px solid rgba(248, 245, 235, 0.40);
}

#соперники .соперник--отбивается .соперник__метка {
  color: var(--сб-текст);
  background: transparent;
  box-shadow: inset 0 0 0 1px rgba(248, 245, 235, 0.55);
}

/* Если отбивающийся одновременно и ходит — главнее «ходит». */
#соперники .соперник--ходит.соперник--отбивается {
  border-color: rgba(210, 247, 107, 0.45);
}

/* Выбыл или ушёл — место гаснет, кайма пунктиром. */
#соперники .соперник--выбыл,
#соперники .соперник--ушёл {
  background: transparent;
  border-style: dashed;
  border-color: rgba(248, 245, 235, 0.16);
  box-shadow: none;
}

#соперники .соперник--выбыл::before,
#соперники .соперник--ушёл::before { color: #4f555c; }

#соперники .соперник--выбыл .соперник__метка {
  color: var(--сб-текст-тихий);
  background: rgba(248, 245, 235, 0.08);
}

#соперники .соперник--нет-связи::before { opacity: 0.45; }

/* Сосед уснул (страница молчит), за него играет бот: аватар притушен,
   метка «играет бот» спокойная. Размеры и раскладку не трогаем — метка
   уже в своей ячейке с обрезкой, поэтому на 320 карточка не раздвигается.
   Отличия: от бота — притушенный аватар, значок сна и холодная метка;
   от ушедшего — нет пунктира; от «чей ход» — нет салатового. */
#соперники .соперник--спит::before {
  opacity: 0.2;
  filter: grayscale(1);
}
/* Холодная кайма (сплошная, не пунктир) отличает спящего от обычного и от ушедшего. */
#соперники .соперник.соперник--спит {
  border-color: rgba(140, 165, 220, 0.4);
}
/* Значок сна в углу у аватара, крупный и с воздухом от края; поверх сетки, раскладку не двигает. */
#соперники .соперник--спит::after {
  content: "z z";
  position: absolute;
  top: 3px;
  left: 4px;
  font-size: 16px;
  font-weight: 700;
  font-style: italic;
  line-height: 1;
  letter-spacing: 0.1em;
  color: #a9bde0;
  pointer-events: none;
}
/* Класс метки повторён нарочно: за столом на троих и больше её кегль
   задаёт правило с :has() и той же силой, а мельче 10 точек метка сна быть не должна. */
#соперники .соперник.соперник--спит .соперник__метка.соперник__метка {
  color: #a9bde0;
  background: rgba(140, 165, 220, 0.16);
  font-size: clamp(11px, 9cqw, 11.5px);
  font-style: italic;
}

#соперники .соперник--проиграл {
  border: 1px solid var(--карта-отказ);
}

/* Трое и больше: места поуже, аватар и число карт в одну строку. */
#соперники:has(> .соперник:nth-child(3)) .соперник {
  --аватар: clamp(26px, 8vw, 34px);
  grid-template-columns: auto auto;
  grid-template-rows: auto auto auto;
  justify-content: center;
  justify-items: center;
  column-gap: 5px;
  row-gap: 2px;
  height: clamp(66px, 19vw, 80px);
  padding: 0 4px;
}

#соперники:has(> .соперник:nth-child(3)) .соперник::before {
  grid-column: 1;
  grid-row: 1;
}

#соперники:has(> .соперник:nth-child(3)) .соперник__карт {
  grid-column: 2;
  grid-row: 1;
  align-items: center;
  font-size: clamp(14px, 4.2vw, 17px);
}

/* Маленькая рубашка перед числом: «▯ 6» читается как «шесть карт». */
#соперники:has(> .соперник:nth-child(3)) .соперник__карт::before {
  content: "";
  flex: 0 0 auto;
  width: 0.62em;
  height: 0.86em;
  margin-right: 0.28em;
  border: 1.5px solid var(--рубашка-поле);
  border-radius: 2px;
  background: var(--рубашка-фон);
}

#соперники:has(> .соперник:nth-child(3)) .соперник__число { font-size: 1em; }
#соперники:has(> .соперник:nth-child(3)) .соперник__слово { display: none; }

/* «Всё на столе» — числа нет, слово остаётся одно и мельче. */
#соперники:has(> .соперник:nth-child(3)) .соперник__слово:only-child {
  display: inline;
  font-size: 0.62em;
  white-space: normal;
  line-height: 1.1;
}

#соперники:has(> .соперник:nth-child(3)) .соперник__имя {
  grid-column: 1 / -1;
  grid-row: 2;
  font-size: clamp(11px, 3.3vw, 13px);
  text-align: center;
}

#соперники:has(> .соперник:nth-child(3)) .соперник__метка,
#соперники:has(> .соперник:nth-child(3)) .соперник__роль {
  grid-column: 1 / -1;
  grid-row: 3;
  justify-self: center;
  margin-top: 1px;
  padding: 0 5px;
  /* Кегль — от ширины самого места: на троих место 117 точек и слово
     «отбивается» с колечком встаёт крупно, на шестерых — 62 и мельче,
     но всё ещё целиком. */
  font-size: clamp(9px, 9cqw, 11.5px);
}

#соперники:has(> .соперник:nth-child(3)) .соперник__имя {
  font-size: clamp(10.5px, 10.5cqw, 13px);
}

/* Выбывший: число карт у него всегда ноль, а что с его местом — говорит
   надпись («отыграл», «играет Бот 4»). Число убираем, аватар меньше —
   и длинная надпись («играет Александра-Мария») встаёт в две строки,
   не вылезая за место. Высота места при этом та же, что у соседей:
   полоса не дёргается в тот миг, когда кто-то выходит из игры. */
#соперники:has(> .соперник:nth-child(3)) .соперник--выбыл .соперник__карт { display: none; }
#соперники:has(> .соперник:nth-child(3)) .соперник--выбыл { --аватар: clamp(20px, 6vw, 26px); }

#соперники .соперник--выбыл .соперник__метка {
  white-space: normal;
  overflow-wrap: anywhere;
  text-align: center;
  line-height: 1.15;
  border-radius: 8px;
}

/* Самое узкое место (шестеро за столом, 60–70 точек): слово состояния
   важнее значка перед ним. Колечко-щит и стрелку убираем, поля плашки
   сужаем — и «отбивается» встаёт целиком, а не обрезается до «отбив…».
   Что это защитник, по-прежнему видно по белой обводке места, что ходит —
   по салатовой плашке и кольцу у аватара. «@container» меряет ширину
   самого места, а не экрана: тесно бывает месту, а не телефону. */
@container (max-width: 84px) {
  #соперники .соперник__метка::before { display: none; }
  #соперники .соперник__метка,
  #соперники .соперник__роль {
    max-width: 100%;
    padding: 0 3px;
    letter-spacing: -0.02em;
  }
}

/* Поля самого места в этом случае тоже минимальные: на экране 360
   при шестерых месту достаётся 62 точки, и каждая точка — это буква
   слова «отбивается». */
#соперники:has(> .соперник:nth-child(5)) { gap: 4px; }
#соперники:has(> .соперник:nth-child(5)) .соперник { padding: 0 2px; }
#соперники:has(> .соперник:nth-child(5)) .соперник__метка,
#соперники:has(> .соперник:nth-child(5)) .соперник__роль { padding: 0 2px; }

/* ---------- Низкое окно (шторка Telegram, маленький телефон) ----------
   Ряды ужимаются по мелочи, чтобы стол не стал крошечным: панель
   соперника ниже, кнопки — ровно по пальцу (44), подсказка мельче,
   промежутки теснее. Карты в руке уменьшаются сами (см. «--в-рука»). */
@media (max-height: 620px) {
  #экран-игры:has(> #зона-стола) {
    --ряд-соперника: clamp(46px, 12.5vw, 54px);
    --ряд-кнопок: 44px;
    --зазор-рядов: 5px;
  }

  #экран-игры > #рука-бота { --аватар: clamp(30px, 9vw, 38px); }

  /* Кегль мельче, но коробка прежние 44 точки: по подсказке нажимают
     (открывается «Что было»), и ниже пальца её делать нельзя. */
  #подсказка { font-size: 13px; }

  #соперники .соперник { height: 54px; }
  #соперники:has(> .соперник:nth-child(3)) .соперник { height: 64px; }
}

/* =====================================================================
   ПЛАШКИ ПОВЕРХ СТОЛА: итог партии, «Выйти в меню?», «Что было»
   и панель знаков («Сказать»)

   Все четыре ложатся поверх нового тёмного стола, а были зелёными
   с золотыми кнопками — игрок видел два разных приложения на одном
   экране. Своего макета у владельца для них нет, поэтому они собраны
   из того, что уже есть в системе витрины и стола:
     • тёмная карточка на тон светлее фона, тонкая светлая кромка, тень;
     • крупный жирный заголовок, как «Дурак» и «Во что сыграем?»;
     • ОДНА салатовая кнопка — главное действие плашки («Играть ещё»,
       «Продолжить партию»), остальные тихие: тёмные с тонким контуром;
     • панель знаков — лист снизу, как лист «Ещё» на витрине, вкладки —
       пилюли, как фишки-фильтры витрины: выбранная залита салатовым.

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

   Цвета: внутри плашек объявлены те же переменные, что внутри стола.
   Все прежние правила плашек, которые берут «--текст», «--подложка»,
   «--акцент», сами переходят на тёмный вид — переписывать каждое
   не нужно. */
#экран-результата,
#экран-выхода,
#экран-ленты,
#экран-эмоций {
  --фон: var(--сб-фон);
  --панель: var(--сб-поверхность);
  --текст: var(--сб-текст);
  --текст-тихий: var(--сб-текст-тихий);
  --кнопка-фон: var(--сб-акцент);
  --кнопка-текст: var(--сб-акцент-текст);
  --акцент: var(--сб-акцент);
  --подложка: rgba(248, 245, 235, 0.06);
  --край: rgba(248, 245, 235, 0.14);
  --поле: clamp(12px, 3.6vw, 18px);
  /* Плитка внутри тёмной плашки — на тон светлее её самой, как строки
     листа «Ещё» на витрине. */
  --плитка: #1e2226;
  --плитка-нажата: #262a2f;
  color: var(--сб-текст);
}

/* Вуаль над плашкой — плотнее прежней: на тёмной странице лёгкая вуаль
   почти не видна, и плашка терялась на фоне стола. */
#экран-результата.экран--виден::before,
#экран-выхода.экран--поверх.экран--виден::before,
#экран-ленты.экран--поверх.экран--виден::before,
#экран-эмоций.экран--поверх.экран--виден::before {
  background: rgba(5, 7, 8, 0.55);
}

/* Карточка итога и вопроса о выходе у́же экрана и не касается низа,
   а прежняя вуаль рисовалась только НАД плашкой и по её ширине: по бокам
   и под карточкой из-под неё выглядывала рука. Здесь вуаль — это широкая
   тень самой карточки (см. её правило ниже): она затемняет весь экран
   вокруг, а касаний, как и прежняя вуаль, не ловит — тень не бывает
   целью нажатия. */
#экран-результата.экран--виден::before,
#экран-выхода.экран--поверх.экран--виден::before,
#экран-эмоций.экран--поверх.экран--виден::before {
  background: transparent;
}

/* ---------- Карточка итога и вопроса «Выйти в меню?» ----------
   Тёмная карточка у нижнего края, со скруглением со всех сторон и полями
   по бокам — лежит поверх стола, а не приклеена к экрану. Над ней вуаль,
   стол сквозь неё виден: чем кончилось, рассмотреть можно. Ряд кнопок
   стола под карточкой на итоге спрятан (см. правило игры), поэтому
   поднимать её над ним, как раньше, больше не нужно. */
#экран-результата,
#экран-результата.экран--поверх,
#экран-выхода.экран--поверх {
  left: 0;
  right: 0;
  bottom: calc(12px + var(--отступ-снизу));
  top: auto;
  width: min(calc(100% - 2 * var(--поле) - var(--отступ-слева) - var(--отступ-справа)), 520px);
  margin: 0 auto;
  gap: 10px 8px;
  padding: 22px 16px 16px;
  text-align: center;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0) 45%),
    var(--сб-поверхность);
  border: 1px solid rgba(248, 245, 235, 0.10);
  border-radius: 22px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 18px 44px rgba(0, 0, 0, 0.60),
    0 0 0 100vmax rgba(5, 7, 8, 0.55);      /* вуаль на весь экран вокруг */
}

/* Итог — самое крупное на карточке: «Вы выиграли!», «Вы — дурак».
   Тот же плотный жирный набор, что у «Дурак» над столом. */
#экран-результата .заголовок {
  font-size: clamp(26px, 7.4vw, 32px);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--сб-текст);
}

#экран-выхода .заголовок {
  font-size: clamp(22px, 6.2vw, 26px);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--сб-текст);
}

#экран-результата > .подпись,
#экран-выхода > .подпись {
  font-size: clamp(13.5px, 3.7vw, 15px);
  line-height: 1.35;
  color: var(--сб-текст-тихий);
}

/* Серия побед и серия дней — тихие пилюли по размеру слов: это
   достижение, но не кнопка, и спорить с главной кнопкой за салатовый цвет
   оно не должно. Звёздочки перед строкой нет нарочно: в эту же строку
   игра пишет и приглашения («Остальные зовут сыграть ещё»), а звезда
   перед ними читалась бы как награда. */
#экран-результата > .серия {
  width: auto;
  max-width: 100%;
  padding: 6px 14px 7px;
  font-size: clamp(14px, 3.8vw, 16px);
  font-weight: 700;
  line-height: 1.25;
  color: var(--сб-текст);
  background: rgba(248, 245, 235, 0.06);
  border: 1px solid rgba(248, 245, 235, 0.16);
  border-radius: 999px;
}

#экран-результата > .серия-дней {
  background: rgba(248, 245, 235, 0.06);
  border: 1px solid rgba(248, 245, 235, 0.16);
}

/* Главная кнопка — единственная салатовая: «Играть ещё», «Сыграть
   с ботом», «Продолжить партию», «Назад к столу». Во всю ширину
   карточки, 52 точки в высоту. */
#экран-результата .кнопка.кнопка--главная,
#экран-выхода .кнопка.кнопка--главная,
#экран-ленты .кнопка.кнопка--главная {
  width: 100%;
  max-width: none;
  min-width: 0;
  min-height: 52px;
  padding: 10px 16px;
  font-size: clamp(16px, 4.6vw, 18px);
  font-weight: 700;
  letter-spacing: 0;
  color: var(--сб-акцент-текст);
  background: var(--сб-акцент);
  border: none;
  border-radius: 14px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    0 6px 18px rgba(210, 247, 107, 0.16);
}

#экран-результата .кнопка.кнопка--главная:active,
#экран-выхода .кнопка.кнопка--главная:active,
#экран-ленты .кнопка.кнопка--главная:active {
  transform: translateY(1px);
  filter: brightness(0.94);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.18);
}

/* Остальные — тихие: тёмная плитка с тонким контуром, как строки листа
   «Ещё». Встают в ряд и делят его поровну; не влезают — переносятся. */
#экран-результата .кнопка.кнопка--мелкая,
#экран-выхода .кнопка.кнопка--мелкая {
  flex: 1 1 0;
  min-width: min(100%, 118px);
  min-height: 46px;
  padding: 0 12px;
  font-size: 15px;
  font-weight: 600;
  color: var(--сб-текст);
  background: var(--плитка);
  border: 1px solid rgba(248, 245, 235, 0.14);
  border-radius: 14px;
  box-shadow: none;
}

#экран-результата .кнопка.кнопка--мелкая:active,
#экран-выхода .кнопка.кнопка--мелкая:active {
  transform: translateY(1px);
  background: var(--плитка-нажата);
  box-shadow: none;
}

/* Уход — тише всех: без заливки, только контур. */
#экран-результата #кнопка-в-меню-итог,
#экран-выхода #кнопка-выход-да {
  background: transparent;
}

/* Реванша не будет — «В меню» остаётся единственным выходом и не должна
   выглядеть выключенной: контур салатовый, подпись белая. */
#экран-результата:has(#кнопка-ещё.скрыт) .кнопка.кнопка--мелкая:not(#кнопка-рекорды-итог) {
  min-height: 48px;
  font-size: 16px;
  color: var(--сб-текст);
  background: transparent;
  border: 1.5px solid var(--сб-акцент);
}

@media (max-height: 620px) {
  #экран-результата,
  #экран-результата.экран--поверх,
  #экран-выхода.экран--поверх {
    gap: 8px;
    padding: 16px 14px 12px;
  }
}

/* ---------- Плашка «Завершить партию?» ----------
   Общее подтверждение для всех игр сборника (Э2, штаб/план-выход-из-партии.md):
   рисует её не разметка игры, а js/лист-ещё.js — один узел на всё
   приложение, добавленный в конец <body>. У плашки нет id, только классы:
   «плашка-завершить» (корень, прячется классом «скрыт»),
   «плашка-завершить__фон», «плашка-завершить__окно»,
   «плашка-завершить__заголовок», «плашка-завершить__текст»,
   «плашка-завершить__кнопки»; кнопки внутри — обычные «.кнопка.кнопка--главная»
   и новая «.кнопка.кнопка--опасная».

   Вид — тот же, что у плашки выхода «Выйти в меню?» чуть выше (тёмная
   карточка у нижнего края, вуаль на весь стол, колонка той же ширины,
   что и весь сборник). Открывается ИЗ листа «Ещё», а у листа стола слой
   110 (см. «#лист-игры» выше в файле) — значит эта плашка обязана лежать
   ещё выше, иначе легла бы под лист. */
.плашка-завершить {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  padding: 0 0 calc(12px + var(--отступ-снизу));
}

.плашка-завершить.скрыт { display: none; }

/* Вуаль — как у листа «Ещё»: клик по ней возвращает в игру (ловит
   js/лист-ещё.js), значит обязана закрывать весь экран, а не только
   место под карточкой. */
.плашка-завершить__фон {
  position: absolute;
  inset: 0;
  background: rgba(5, 7, 8, 0.6);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}

/* «position: relative» обязательна: без неё вуаль (она «position:
   absolute») по правилам отрисовки легла бы поверх карточки, хотя
   в разметке карточка идёт позже — тот же приём, что у «.лист-ещё__лист». */
.плашка-завершить__окно {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: min(calc(100% - 32px - var(--отступ-слева) - var(--отступ-справа)), 520px);
  padding: 22px 16px 16px;
  text-align: center;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0) 45%),
    var(--сб-поверхность);
  border: 1px solid rgba(248, 245, 235, 0.10);
  border-radius: 22px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 18px 44px rgba(0, 0, 0, 0.60);
}

.плашка-завершить__заголовок {
  margin: 0;
  font-size: clamp(22px, 6.2vw, 26px);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--сб-текст);
}

.плашка-завершить__текст {
  margin: 0;
  font-size: clamp(13.5px, 3.7vw, 15px);
  line-height: 1.35;
  color: var(--сб-текст-тихий);
}

/* Кнопки друг под другом, не в ряд: «Вернуться» сверху и шире, «Завершить»
   снизу и тише — тот же порядок «безопасный выбор впереди», что у плашки
   выхода («Продолжить партию» перед «Выйти в меню»). */
.плашка-завершить__кнопки {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  margin-top: 4px;
}

/* «Вернуться к игре» — безопасный выбор, поэтому единственная салатовая
   кнопка плашки: тот же вид, что у главной кнопки итога и выхода выше. */
.плашка-завершить .кнопка.кнопка--главная {
  width: 100%;
  max-width: none;
  min-width: 0;
  min-height: 52px;
  padding: 10px 16px;
  font-size: clamp(16px, 4.6vw, 18px);
  font-weight: 700;
  letter-spacing: 0;
  color: var(--сб-акцент-текст);
  background: var(--сб-акцент);
  border: none;
  border-radius: 14px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    0 6px 18px rgba(210, 247, 107, 0.16);
}

.плашка-завершить .кнопка.кнопка--главная:active {
  transform: translateY(1px);
  filter: brightness(0.94);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.18);
}

/* «Завершить» — опасное действие, единственная НЕ салатовая кнопка
   сборника: красный берём готовый, тот же, что красит красные масти
   карты («--карта-красная»), новый цвет не выдумываем. Заливки нет
   нарочно — ровный красный тон выглядел бы тревожнее, чем нужно для
   «согласиться уйти»; глаз цепляется за слово, а не за пятно. */
.плашка-завершить .кнопка.кнопка--опасная {
  width: 100%;
  min-width: 0;
  min-height: 46px;
  padding: 0 16px;
  font-size: 15px;
  font-weight: 600;
  color: var(--карта-красная);
  background: rgba(248, 245, 235, 0.06);
  border: 1px solid rgba(200, 16, 46, 0.4);   /* тот же красный, что «--карта-красная», с прозрачностью */
  border-radius: 14px;
  box-shadow: none;
}

.плашка-завершить .кнопка.кнопка--опасная:active {
  transform: translateY(1px);
  background: rgba(200, 16, 46, 0.16);
  box-shadow: none;
}

@media (max-height: 620px) {
  .плашка-завершить__окно {
    gap: 8px;
    padding: 16px 14px 12px;
  }
}

/* ---------- Плашка голосования «закончить партию по согласию» ----------
   Этап 7 штаб/план-сдача-голосованием.md. Узел строит js/лист-ещё.js
   (ЛистЕщё.досрочно), классы перечислены там у ID_ПЛАШКИ_ДОСРОЧНО.

   НЕ модальная: партия под ней идёт, поэтому ни вуали, ни затемнения —
   только карточка. Стоит вверху, сразу под строкой «‹ ⋯» (44 точки
   строки + её поля ≈ 50 от безопасного верха): так она закрывает
   соперников, а не руку игрока и не кнопки хода внизу. Ширина — общая
   колонка сборника: те же поля, что у лобби и листа «⋯» («--поле»,
   clamp(12px, 3.6vw, 18px); на :root этой переменной нет — она своя
   у каждого экрана, поэтому число повторено здесь), и не шире 520.
   Вид — карточка лобби (общий класс «плитка»: #1e2226 и светлая кромка).
   Раньше здесь была «--сб-поверхность» — почти цвет страницы: тонкая
   полоска над заголовком лобби не читалась карточкой, и смотрителю
   казалось, что сквозь неё просвечивает страница. Заливка сплошная,
   без прозрачности. «--плитка» объявлена у каждого экрана, а плашка
   лежит в body, вне экранов, — поэтому те же числа объявлены и здесь
   (как у «#экран-друга» и соседей); новых цветов нет. На страницах
   со style-коллекция.css карточки рисуются её градиентом
   («--коллекция-панель», кромка «--коллекция-кромка») — плашка берёт
   его же, но кладёт поверх сплошной «--плитки»: сам градиент слегка
   прозрачный, а страница сквозь плашку просвечивать не должна.

   Слой: плашка лежит в body, а стол, итог и лист «⋯» — внутри
   «#приложение», у которого («position: fixed») свой отдельный слой.
   Поэтому любое положительное число ставит плашку над всем приложением
   (голосование важнее итога), а под лист её уводит только отрицательное
   (см. правило ниже). Подтверждение «Завершить партию?» тоже в body,
   у него 120 — выше. */
.плашка-досрочно {
  position: fixed;
  /* Плашка начинается ниже верхней строки «‹ ⋯», чтобы стрелка «назад» и «⋯»
     нажимались, пока игрок спит или идёт голосование. Общей переменной
     высоты строки в файле нет: у дурака, шашек, нард строка кончается на
     46px, у монополии — на 59px (её кнопки по 46px и поле сверху 13px),
     поэтому берём 64px с запасом. Проверка: tests/плашка-досрочно-верх.js. */
  top: calc(var(--отступ-сверху) + 64px);
  left: calc(clamp(12px, 3.6vw, 18px) + var(--отступ-слева));
  right: calc(clamp(12px, 3.6vw, 18px) + var(--отступ-справа));
  z-index: 105;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: 520px;
  margin: 0 auto;
  padding: 10px 12px;
  --плитка: #1e2226;
  --плитка-кромка: rgba(248, 245, 235, 0.12);
  color: var(--сб-текст);
  background-color: var(--плитка);
  background-image: var(--коллекция-панель, none);
  border: 1px solid var(--коллекция-кромка, var(--плитка-кромка));
  border-radius: 16px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 12px 32px rgba(0, 0, 0, 0.55);
}

/* Внутри Telegram нашу строку «‹ ⋯» заменяет сам Telegram — но только если
   она сделана классом «.верх-игры» (его в Telegram прячет правило выше).
   Тогда плашка встаёт к безопасному верху. У домино, монополии, морского
   боя и катана на столе своя строка без этого класса: Telegram её не
   прячет, и плашка остаётся под ней (общие 64px). Условие «на видимом
   экране есть .верх-игры» держит это различие; без поддержки :has()
   правило не сработает, и плашка встанет на 64px — безопасно. Где Telegram
   «Настроек» не умеет, строка возвращается (класс «без-настроек»), и плашка
   тоже остаётся под ней. */
html.в-телеграме:not(.без-настроек):has(.экран--виден .верх-игры) .плашка-досрочно {
  top: calc(var(--отступ-сверху) + 8px);
}

/* Лист «⋯» или подтверждение открыты — плашка уходит под их вуаль:
   их игрок открыл сам, они должны лежать сверху. Отрицательный слой —
   единственный, что ниже «#приложение» (см. пояснение выше); фон
   страницы рисуется ещё ниже, так что плашка не пропадает, а лишь
   темнеет под вуалью. */
html:has(.лист-ещё:not(.скрыт)) .плашка-досрочно,
html:has(.плашка-завершить:not(.скрыт)) .плашка-досрочно {
  z-index: -1;
}

/* Одна строка-абзац: «Аня предлагает закончить партию · за 2 из 3 ·
   ещё 25 сек.». Счёт и отсчёт — внутри абзаца, а не своими строками:
   на 320 точках так плашка остаётся ниже 110 даже с длинным именем. */
.плашка-досрочно__строка {
  margin: 0;
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

.плашка-досрочно__счёт,
.плашка-досрочно__отсчёт {
  margin-left: 6px;
  white-space: nowrap;
}

.плашка-досрочно__счёт { font-weight: 800; }

.плашка-досрочно__отсчёт {
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--сб-текст-тихий);
}

.плашка-досрочно__отсчёт:empty,
.плашка-досрочно__счёт:empty { display: none; }

/* Две кнопки в ряд, поровну: «Согласен» — салатовая (единственный
   акцент плашки), «Играть дальше» — тихая, без заливки. 44 точки — палец. */
.плашка-досрочно__кнопки {
  display: flex;
  gap: 8px;
}

.плашка-досрочно .кнопка {
  flex: 1 1 0;
  min-width: 0;
  min-height: 44px;
  padding: 0 10px;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0;
  white-space: nowrap;
  border-radius: 12px;
}

.плашка-досрочно .кнопка.кнопка--главная {
  color: var(--сб-акцент-текст);
  background: var(--сб-акцент);
  border: none;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    0 6px 18px rgba(210, 247, 107, 0.16);
}

.плашка-досрочно .кнопка.кнопка--тихая {
  font-weight: 600;
  color: var(--сб-текст);
  background: rgba(248, 245, 235, 0.06);
  border: 1px solid var(--сб-граница);
  box-shadow: none;
}

.плашка-досрочно .кнопка:active {
  transform: translateY(1px);
  filter: brightness(0.94);
}

/* Запрос в пути — кнопки гаснут (js/лист-ещё.js ставит disabled). */
.плашка-досрочно .кнопка:disabled,
#кнопка-лист-игры-досрочно:disabled {
  opacity: 0.5;
  cursor: default;
  transform: none;
  filter: none;
}

/* Неактивная кнопка без стрелки. */
#кнопка-лист-игры-досрочно:disabled::after {
  content: "";
}

/* Строка вместо кнопок («Вы согласны»). */
.плашка-досрочно__подпись {
  margin: 0;
  font-size: 13px;
  line-height: 1.3;
  color: var(--сб-текст-тихий);
}

/* Отказ сервера («не получилось») — тем же приёмом, что тревога в строке
   связи над столом («.связь--тревога»): красная полоса с красной каймой,
   белый текст и белый треугольник. Цвета — ровно её, новых нет. Треугольник
   не мигает: причина и так гаснет сама через несколько секунд.
   Высота — как у кнопок голосования (44), поэтому плашка с одной причиной
   не сжимается в тонкую полоску: поля у неё те же, что у плашки голосования. */
.плашка-досрочно__причина {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  margin: 0;
  padding: 8px 12px;
  box-sizing: border-box;
  font-size: 13.5px;
  font-weight: 700;
  line-height: 1.3;
  overflow-wrap: anywhere;
  color: #ffffff;
  background: rgba(155, 26, 40, 0.94);
  background: color-mix(in srgb, var(--карта-отказ) 62%, #2a0409);
  box-shadow: inset 0 0 0 2px var(--карта-отказ);
  border-radius: 12px;
}

/* Треугольник нарисован рамками, как у «.связь--тревога::before». */
.плашка-досрочно__причина::before {
  content: "";
  flex: 0 0 auto;
  width: 0;
  height: 0;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-bottom: 11px solid #ffffff;
}

/* Строка сна («Вы долго не ходили — за вас играет бот» и «Я здесь») — в том
   же корне, выше голосования (js/лист-ещё.js, ЛистЕщё.сон). Обёртка прячется
   классом «скрыт». Когда под ней есть ещё голосование или причина, корень
   получает класс «--сон-и-другое» — тогда между ними тонкая линия. */
.плашка-досрочно__сон-блок {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.плашка-досрочно--сон-и-другое .плашка-досрочно__сон-блок {
  padding-bottom: 10px;
  border-bottom: 1px solid var(--сб-граница);
}

.плашка-досрочно__сон {
  margin: 0;
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

/* Слова сбоя — отдельной строкой под строкой сна (блок в колонке всегда
   начинается с новой строки). Пустой узел прячется классом «скрыт». */
.плашка-досрочно__сон-сбой {
  display: block;
  margin: 0;
  font-size: 13px;
  line-height: 1.3;
  color: var(--сб-текст-тихий);
  overflow-wrap: anywhere;
}

/* Кнопка на всю ширину плашки, не ниже 44; слова могут переноситься,
   чтобы на 320 не вылезти за край, — поля сверху и снизу, чтобы две строки
   не упирались в края. */
.плашка-досрочно .плашка-досрочно__я-здесь {
  flex: 0 0 auto;
  width: 100%;
  min-height: 44px;
  padding-block: 10px;
  white-space: normal;
}

/* ---------- «Что было» — лист снизу ----------
   Список новостей стола — лист, выезжающий снизу, как «Ещё» на витрине:
   скруглён только верх, прижат к низу, не шире колонки сборника. */
#экран-ленты.экран--поверх {
  left: 0;
  right: 0;
  width: 100%;
  max-width: 520px;
  margin: 0 auto;
  background: var(--сб-поверхность);
  border: none;
  border-radius: 20px 20px 0 0;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 -12px 32px rgba(0, 0, 0, 0.45),
    0 0 0 100vmax rgba(5, 7, 8, 0.55);     /* вуаль над столом */
}

#экран-ленты.экран--поверх.экран--виден::before { background: transparent; }

#экран-ленты .заголовок {
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

#лента-событий .таблица__строка {
  background: var(--плитка);
  border: 1px solid rgba(255, 255, 255, 0.05);
}

#лента-событий .таблица__строка:nth-last-child(n+4) {
  background: rgba(30, 34, 38, 0.6);
}

/* ---------- Панель знаков — лист «Сказать» ----------
   Лист снизу, как «Ещё» на витрине: тёмная панель, скруглённый верх,
   «ручка» сверху (знак выдвижного листа), не шире колонки сборника. */
#экран-эмоций.экран--поверх {
  left: 0;
  right: 0;
  width: 100%;
  max-width: 520px;
  margin: 0 auto;
  gap: 12px;
  padding: 24px calc(var(--поле) + var(--отступ-справа))
           calc(18px + var(--отступ-снизу)) calc(var(--поле) + var(--отступ-слева));
  background:
    linear-gradient(rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.18)) top 9px center / 36px 4px no-repeat,
    var(--сб-поверхность);
  border: none;
  border-radius: 20px 20px 0 0;
  /* Последняя тень — вуаль над столом. Прежняя вуаль рисовалась над
     листом отдельным слоем, но лист прокручивается внутри себя и обрезал
     её: стол над листом оставался ярким. Тень лист не обрезает, а касаний
     она не ловит. */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 -12px 32px rgba(0, 0, 0, 0.45),
    0 0 0 100vmax rgba(5, 7, 8, 0.55);
}

/* Вкладки «Смайлики / Фразы / Кинуть» — пилюли, как фишки-фильтры на
   витрине. Кнопка вкладки сама 44 точки в высоту (палец), а видимая
   пилюля внутри неё ниже — 34 точки; попасть можно и чуть выше, и чуть
   ниже нарисованной. Выбранная залита салатовым, текст почти чёрный. */
#экран-эмоций .панель-знаков__вкладки {
  justify-content: flex-start;
  gap: clamp(7px, 2.2vw, 10px);
  box-shadow: none;
}

#экран-эмоций .кнопка.панель-знаков__вкладка {
  position: relative;
  isolation: isolate;
  flex: 0 0 auto;
  min-height: 44px;
  padding: 0 clamp(14px, 4.1vw, 18px);
  font-size: clamp(14px, 3.8vw, 16px);
  font-weight: 600;
  color: rgba(248, 245, 235, 0.86);
  background: none;
  border: none;
  border-radius: 999px;
  box-shadow: none;
}

#экран-эмоций .кнопка.панель-знаков__вкладка::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 5px;
  bottom: 5px;
  z-index: -1;
  border: 1px solid var(--сб-граница);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.025);
  transition: transform 0.14s ease;
}

#экран-эмоций .кнопка.панель-знаков__вкладка:active { transform: none; background: none; }
#экран-эмоций .кнопка.панель-знаков__вкладка:active::before { transform: scale(0.96); }

#экран-эмоций .кнопка.панель-знаков__вкладка.кнопка--активная {
  color: var(--сб-акцент-текст);
  font-weight: 700;
  background: none;
}

#экран-эмоций .кнопка.панель-знаков__вкладка.кнопка--активная::before {
  background: var(--сб-акцент);
  border-color: var(--сб-акцент);
}

/* Ряды знаков — сетки из тёмных плиток. Смайлики — по шесть в ряд
   (двенадцать встают в два ряда), каждая плитка квадратная и не меньше
   44 точек: на экране 360 выходит 50. */
#экран-эмоций .ряд-знаков {
  display: grid;
  gap: 6px;
  width: 100%;
}

#экран-эмоций #ряд-эмоций {
  grid-template-columns: repeat(6, minmax(44px, 1fr));
}

#экран-эмоций .кнопка.кнопка--смайлик,
#экран-эмоций .кнопка.кнопка--фраза,
#экран-эмоций .кнопка.кнопка--цель {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  min-height: 44px;
  color: var(--сб-текст);
  background: var(--плитка);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 14px;
  box-shadow: none;
}

#экран-эмоций .кнопка.кнопка--смайлик {
  aspect-ratio: 1 / 1;
  padding: 0;
  font-size: clamp(24px, 7vw, 30px);
  line-height: 1;
}

#экран-эмоций .кнопка.кнопка--смайлик:active,
#экран-эмоций .кнопка.кнопка--фраза:active,
#экран-эмоций .кнопка.кнопка--цель:active {
  transform: scale(0.96);
  background: var(--плитка-нажата);
  box-shadow: none;
}

/* Фразы — пилюли по длине слов, переносятся рядами. */
#экран-эмоций #ряд-фраз {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
}

#экран-эмоций .кнопка.кнопка--фраза {
  padding: 8px 14px;
  font-size: clamp(13.5px, 3.7vw, 15px);
  font-weight: 600;
  line-height: 1.2;
  border-radius: 999px;
}

/* ---------- «Кинуть»: пятнадцать предметов картинками, сетка 5×3 ----------
   Владелец прислал свои рисунки предметов (img/бросок/*.webp, 200×200,
   прозрачный фон). Пока бросаются значки телефона — они стоят в тех же
   клетках, крупным знаком. Когда разработчик положит в кнопку картинку
   («img.предмет-броска»), она встанет в клетку сама: на три четверти
   клетки, по центру, не растягиваясь.
   Клетка квадратная: на экране 390 — 64 точки, на 360 — 58, в самом
   узком случае не меньше 44. */
#экран-эмоций #ряд-бросков {
  grid-template-columns: repeat(5, minmax(44px, 1fr));
}

#экран-эмоций .кнопка.кнопка--бросок-предмет {
  aspect-ratio: 1 / 1;
  font-size: clamp(26px, 7.6vw, 32px);
}

#экран-эмоций .кнопка--бросок-предмет > .предмет-броска {
  display: block;
  width: 76%;
  height: 76%;
  object-fit: contain;
  pointer-events: none;
  /* Лёгкая тень — предмет «лежит» в клетке, а не наклеен на неё */
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.45));
}

/* Предмет выбран, игра спрашивает «в кого кинуть?» — клетка обведена
   салатовым и светится, как выбранная карта в руке: видно, чем сейчас
   будут кидать. */
#экран-эмоций .кнопка.кнопка--бросок-предмет.кнопка--выбрана {
  background: var(--плитка-нажата);
  border-color: var(--сб-акцент);
  box-shadow:
    0 0 0 1.5px var(--сб-акцент),
    0 0 14px rgba(210, 247, 107, 0.35);
}

/* Картинка предмета в облачке над игроком растёт от кегля облачка, как
   смайлик рядом. Запасной размер 48 у неё стоит атрибутами — это правило
   его перебивает. */
.знак-внимания__что > .предмет-броска {
  display: inline-block;
  width: 1em;
  height: 1em;
  object-fit: contain;
  vertical-align: middle;
}

/* Летящий предмет картинкой: размер берётся от кегля полёта (1em), поэтому
   все правила полёта — дуга, вращение, шлепок — работают как со значком. */
.летящий-предмет > .летящий-предмет__картинка {
  display: block;
  width: 1em;
  height: 1em;
  object-fit: contain;
}

/* ---------- Рисунок предмета не доехал: название словом ----------
   Если картинка предмета не загрузилась, игра ставит на её место слово —
   «Помидор», «Шарик с водой» (span.название-предмета): в клетку панели
   «Кинуть», в летящий предмет и в облачко над игроком. Везде у слова
   одна задача — читаться и не вылезать за край своей коробки. Кегль
   у всех трёх мест задан для значков (26–54 точки), слову он не годится,
   поэтому у слова свой. */

/* В клетке панели: мелкий жирный текст по центру, не больше трёх строк.
   «Перчатка» встаёт в одну строку уже в клетке 58 точек (экран 360),
   «Шарик с водой» — в две. В самой узкой клетке (44) длинное слово
   переносится, а не торчит за край.

   Правило общее для панелей дурака и шашек (замечание ревьюера,
   11 сентября: у шашек его не было, и слово вставало кеглем смайлика —
   18 точек). У шашек кнопка предмета — «.панель-знаков__знак--бросок»
   (js/шашки-экран.js), сама кнопка и её цвета — в style-шашки.css. */
#экран-эмоций .кнопка--бросок-предмет > .название-предмета,
.панель-знаков__знак--бросок > .название-предмета {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  box-sizing: border-box;
  max-width: 100%;
  padding: 0 3px;
  overflow: hidden;
  font-size: clamp(10px, 2.9vw, 12px);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: 0;
  text-align: center;
  hyphens: auto;
  overflow-wrap: anywhere;
  color: var(--сб-текст);
  pointer-events: none;
}

/* У шашек клетка не задана сеткой, как у дурака: кнопка растёт под
   содержимое. Без потолка «Шарик с водой» вытянул бы её в полосу
   на весь ряд. Потолок — 5,5 кегля (66 точек при 12): «Перчатка» ещё
   в одну строку, «Шарик с водой» — в две; кнопка остаётся плиткой
   рядом с рисунками. Цвет — от самой кнопки: у шашек своя тема. */
.панель-знаков__знак--бросок > .название-предмета {
  max-width: 5.5em;
  color: inherit;
}

/* В облачке над игроком — как фраза: жирная строка обычного кегля,
   облачко не шире, чем у фраз, длинное название переносится по словам.
   Качать слово нельзя: качающиеся буквы не прочесть (смайлик и рисунок
   в облачке покачиваются — слово стоит). */
.знак-внимания--бросок:has(.название-предмета) {
  max-width: min(60vw, 230px);
  padding: 8px 14px 9px;
}

.знак-внимания--смайлик.знак-внимания--живой .знак-внимания__что:has(> .название-предмета) {
  animation: none;
  transform: none;
}

.знак-внимания__что > .название-предмета {
  display: block;
  font-size: clamp(15px, 4.6vw, 19px);
  font-weight: 700;
  line-height: 1.25;
}

/* Летит слово: тёмная пилюля, как плашки стола, белый жирный текст
   в одну строку. Центр пилюли — в точке полёта: у значка это делает
   поле «-0.5em» (значок квадратный, в 1em), у слова ширина своя, поэтому
   поле снимаем, а пилюлю сдвигаем на половину её собственного размера.
   Точка вращения и роста — та же точка, иначе в середине пути, где
   предмет растёт, слово съезжало бы вбок. */
.летящий-предмет:has(> .название-предмета) {
  margin: 0;
  transform-origin: 0 0;
}

.летящий-предмет > .название-предмета {
  display: block;
  translate: -50% -50%;
  padding: 5px 11px 6px;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
  color: var(--сб-текст);
  background: var(--сб-поверхность);
  border: 1px solid rgba(248, 245, 235, 0.18);
  border-radius: 999px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.5);
}

/* Слово в полёте не крутится — крутящееся слово не прочесть. Дуга,
   рост в середине пути и шлепок в конце — прежние. Только для тех, у кого
   движения не выключены: у остальных полёта нет вовсе. */
@media (prefers-reduced-motion: no-preference) {
  .летящий-предмет:not(.летящий-предмет--попал):has(> .название-предмета) {
    animation-name: предмет-летит, предмет-дуга-слово;
  }
}

@keyframes предмет-дуга-слово {
  0%   { transform: translateY(0) scale(0.75);
         animation-timing-function: ease-out; }
  50%  { transform: translateY(calc(-1 * var(--подъём))) scale(1.3);
         animation-timing-function: ease-in; }
  100% { transform: translateY(0) scale(1); }
}

/* Второй шаг броска за столом компанией: «В кого кинуть?» — имена
   соперников плитками в два столбца, чтобы длинное имя не обрезалось. */
#экран-эмоций .выбор-цели {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
}

#экран-эмоций .выбор-цели > .подпись {
  font-size: 15px;
  font-weight: 600;
  text-align: left;
  color: var(--сб-текст);
}

#экран-эмоций .ряд-знаков.ряд-знаков--цели {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

#экран-эмоций .кнопка.кнопка--цель {
  padding: 8px 12px;
  font-size: 15px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* «Закрыть» — полка по низу листа, как «Закрыть» у листа «Ещё»:
   тихая, с тонкой чертой сверху. Прилипание к низу — прежнее. */
#экран-эмоций #кнопка-эмоции-назад {
  font-size: 16px;
  font-weight: 600;
  color: var(--сб-текст);
  background: var(--сб-поверхность);
  border-top: 1px solid rgba(248, 245, 235, 0.08);
}

@media (max-width: 360px), (max-height: 620px) {
  #экран-эмоций.экран--поверх {
    gap: 10px;
    padding-top: 22px;
  }

  #экран-эмоций .ряд-знаков { gap: 5px; }
}

/* =====================================================================
   «КАК ИГРАТЬ», «РЕКОРДЫ», «ОФОРМЛЕНИЕ» ДУРАКА — В ТЁМНОЙ СИСТЕМЕ

   Все три открываются из листа «Ещё» прямо посреди партии, а были
   зелёными: с тёмного стола человек попадал на зелёное сукно и обратно —
   два разных приложения за одну минуту. Своего макета у владельца для них
   нет, поэтому они собраны из того, что уже есть на витрине и за столом:
     • ровный тёмный фон с едва заметным салатовым свечением сверху;
     • «‹» в левом верхнем углу — как у стола. Внутри Telegram стрелку
       «Назад» рисует он сам в своей шапке, и наша прячется — тоже как
       у стола;
     • крупный жирный заголовок слева — как «Дурак» над столом;
     • строки — тёмные плитки на тон светлее фона, как в листе «Ещё»;
     • салатовый — одно место на экране: лучший рекорд, выбранный фон,
       черта под картой, которой можно ходить.

   Большой залитой кнопки «Назад» внизу больше нет — её работу делает «‹».
   Это та же самая кнопка из разметки: оформление переносит её в угол
   и рисует стрелкой, а слово «Назад» остаётся для чтеца экрана.

   ТОЛЬКО СТРАНИЦА СБОРНИКА — отсюда «:has(> #экран-витрины)». Экраны
   с теми же именами есть у шашек (правила, рекорды) и шахмат (рекорды,
   оформление). Их столы ещё зелёные, и тёмный экран посреди них резал бы
   глаз точно так же, только наоборот. Когда дойдёт их очередь, хватит
   снять это уточнение.

   С 12 сентября сюда же добавлена СТРАНИЦА НАРД — её узнаём по доске
   («:has(.доска-нард)», такой доски больше нигде нет). Её стол уже
   тёмный, как витрина, и экран «Оформление» на ней должен выглядеть
   ровно как у дурака: заголовок слева, «‹» в углу, тёмные плитки.
   Правила и рекорды у нард зовутся иначе, поэтому список имён ниже
   на них не попадает — меняется только «Оформление». */

:where(#приложение:has(> #экран-витрины), #приложение:has(.доска-нард)) > :is(#экран-правил, #экран-рекордов, #экран-оформления) {
  /* Те же цвета, что внутри стола. Прежние правила экранов, которые
     берут «--текст», «--подложка», «--акцент», сами становятся тёмными
     с салатовым. Фон — общий графит сборника: и у дурака, и у нард
     экран выглядит одинаково. */
  --фон: var(--сб-фон);
  --панель: var(--сб-поверхность);
  --текст: var(--сб-текст);
  --текст-тихий: var(--сб-текст-тихий);
  --кнопка-фон: var(--сб-акцент);
  --кнопка-текст: var(--сб-акцент-текст);
  --акцент: var(--сб-акцент);
  --подложка: rgba(248, 245, 235, 0.06);
  --край: rgba(248, 245, 235, 0.14);
  --поле: clamp(12px, 3.6vw, 18px);
  /* Плитка — на тон светлее фона, как строки листа «Ещё». */
  --плитка: #1e2226;
  --плитка-край: rgba(255, 255, 255, 0.06);
  --плитка-нажата: #262a2f;

  align-items: center;
  gap: 10px;
  padding: calc(6px + var(--отступ-сверху)) calc(var(--поле) + var(--отступ-справа))
           calc(12px + var(--отступ-снизу)) calc(var(--поле) + var(--отступ-слева));
  overflow-x: hidden;
  color: var(--сб-текст);
  background:
    radial-gradient(75% 120px at 50% 0, rgba(210, 247, 107, 0.07), rgba(210, 247, 107, 0) 100%),
    var(--сб-фон);
}

/* Столбик — не шире, чем у витрины и стола (520 точек), и посередине.
   На телефоне ограничение не срабатывает. */
:where(#приложение:has(> #экран-витрины), #приложение:has(.доска-нард)) > :is(#экран-правил, #экран-рекордов, #экран-оформления) > * {
  box-sizing: border-box;
  width: 100%;
  max-width: 520px;
}

/* Заголовок — тот же плотный жирный набор, что у «Дурак» над столом
   и «Во что сыграем?» на витрине, и так же прижат влево. */
:where(#приложение:has(> #экран-витрины), #приложение:has(.доска-нард)) > :is(#экран-правил, #экран-рекордов, #экран-оформления) > .заголовок {
  flex: 0 0 auto;
  margin: 0;
  text-align: left;
  font-size: clamp(26px, 8.2vw, 37px);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--сб-текст);
}

/* В Telegram нашей строки «‹» нет — заголовок стоит сразу под его
   шапкой, как на витрине. */
html.в-телеграме :where(#приложение:has(> #экран-витрины), #приложение:has(.доска-нард)) > :is(#экран-правил, #экран-рекордов, #экран-оформления) > .заголовок {
  margin-top: 4px;
}

/* ---------- «‹» — прежняя кнопка «Назад», перенесённая в угол ----------
   Встаёт первой в столбике («order: -1»), 44×44 под палец, значок
   24 точки — один в один «‹» над столом. Поле слева отрицательное,
   чтобы стрелка встала у самого края, как у стола; на широком окне
   оно отсчитывается от края столбика, а не окна.

   У нард в стрелку превращается ТОЛЬКО кнопка «Оформление» — второй
   строкой ниже. Кнопка «Понятно» на её экране правил названа тем же
   именем, что «Назад» у дурака, и попади она сюда — исчезла бы
   единственная дверь с того экрана. */
:where(#приложение:has(> #экран-витрины)) :is(#кнопка-правила-назад, #кнопка-рекорды-назад, #кнопка-оформление-назад, #кнопка-рейтинг-игроков-назад, #кнопка-рейтинг-назад, #открытые-столы-назад),
#приложение:has(.доска-нард) #кнопка-оформление-назад,
/* Шапка рейтинга — одна и та же кнопка на всех четырёх страницах
   (index.html, шашки.html, шахматы.html, нарды.html), а «#экран-витрины»
   есть только на первой из них: без своего безусловного селектора
   стрелка «‹» на трёх остальных страницах не получала бы этот вид,
   а в Telegram ещё и не пряталась бы (см. правило display:none ниже) —
   игрок видел бы сразу и системную стрелку, и нашу (нашёл ревьюер).
   Та же причина у «Назад» экрана «Играть онлайн» (js/открытые-столы.js):
   он общий для дурака, шашек и нард, а витрина есть только у дурака.
   Приставка «#приложение» — ради веса: у шашек и нард правило
   «#приложение .кнопка:not(…)» (style-шашки.css, style-нарды.css)
   иначе перекрасило бы стрелку в салатовую плашку. */
#кнопка-рейтинг-игроков-назад,
#приложение #открытые-столы-назад {
  order: -1;
  position: relative;
  flex: 0 0 auto;
  align-self: flex-start;
  width: 44px;
  min-width: 44px;
  max-width: none;
  height: 44px;
  min-height: 44px;
  margin: -4px 0 -8px max(-10px, calc((100% - 520px) / 2 - 10px));
  padding: 0;
  font-size: 0;              /* слово «Назад» — только для чтеца экрана */
  line-height: 0;
  color: var(--сб-текст);
  background: none;
  border: none;
  border-radius: 12px;
  box-shadow: none;
}

:where(#приложение:has(> #экран-витрины)) :is(#кнопка-правила-назад, #кнопка-рекорды-назад, #кнопка-оформление-назад, #кнопка-рейтинг-игроков-назад, #кнопка-рейтинг-назад, #открытые-столы-назад)::before,
#приложение:has(.доска-нард) #кнопка-оформление-назад::before,
#кнопка-рейтинг-игроков-назад::before,
#открытые-столы-назад::before {
  content: "";
  position: absolute;
  inset: 0;
  width: 24px;
  height: 24px;
  margin: auto;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m15 4-8 8 8 8'/%3E%3C/svg%3E") center / 24px 24px no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m15 4-8 8 8 8'/%3E%3C/svg%3E") center / 24px 24px no-repeat;
}

:where(#приложение:has(> #экран-витрины)) :is(#кнопка-правила-назад, #кнопка-рекорды-назад, #кнопка-оформление-назад, #кнопка-рейтинг-игроков-назад, #кнопка-рейтинг-назад, #открытые-столы-назад):active,
#приложение:has(.доска-нард) #кнопка-оформление-назад:active,
#кнопка-рейтинг-игроков-назад:active,
#открытые-столы-назад:active {
  transform: scale(0.92);
  opacity: 0.7;
  box-shadow: none;
}

:where(#приложение:has(> #экран-витрины)) :is(#кнопка-правила-назад, #кнопка-рекорды-назад, #кнопка-оформление-назад, #кнопка-рейтинг-игроков-назад, #кнопка-рейтинг-назад, #открытые-столы-назад):focus-visible,
#приложение:has(.доска-нард) #кнопка-оформление-назад:focus-visible,
#кнопка-рейтинг-игроков-назад:focus-visible,
#открытые-столы-назад:focus-visible {
  outline: 2px solid var(--сб-акцент);
  outline-offset: -4px;
}

html.в-телеграме :where(#приложение:has(> #экран-витрины)) :is(#кнопка-правила-назад, #кнопка-рекорды-назад, #кнопка-оформление-назад, #кнопка-рейтинг-игроков-назад, #кнопка-рейтинг-назад, #открытые-столы-назад),
html.в-телеграме #приложение:has(.доска-нард) #кнопка-оформление-назад,
html.в-телеграме #кнопка-рейтинг-игроков-назад,
html.в-телеграме #открытые-столы-назад {
  display: none;
}

/* ---------- «Как играть» ----------
   Текст здесь читают подряд, поэтому он крупнее обычной подписи
   (16 точек на экране 390), с просторными строками (полторы высоты
   буквы) и полным белым цветом. Ширина строки на телефоне — около
   сорока знаков, на широком окне столбик не шире 520 точек, так что
   строка не растягивается в полосу, которую глаз теряет на переносе.

   Список занимает всё место до низа экрана и прокручивается сам.
   Низ списка тает в фон — так видно, что правила ещё не кончились;
   докрутили до конца — таять нечему, там пустое поле. */
:where(#приложение:has(> #экран-витрины)) #экран-правил {
  /* Образцы карт к правилу про подсветку — два рисунка новой колодой:
     та же кремовая бумага, та же красная черва, те же углы и раскладка
     значков, что у настоящей семёрки червей. Вторая — ровно такая же,
     только притушенная, как карта, которой сейчас ходить нельзя. */
  --образец-можно: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 250 350'%3E%3Crect x='2.5' y='2.5' width='245' height='345' rx='20' fill='%23f6ead5' stroke='%23463016' stroke-opacity='.3' stroke-width='5'/%3E%3Cg fill='%23c8102e' font-family='Times New Roman,Times,serif' font-size='60' font-weight='700' text-anchor='middle'%3E%3Ctext x='31' y='62'%3E7%3C/text%3E%3Cpath transform='translate(15 76) scale(1.3333)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3Cg transform='rotate(180 125 175)'%3E%3Ctext x='31' y='62'%3E7%3C/text%3E%3Cpath transform='translate(15 76) scale(1.3333)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3C/g%3E%3Cpath transform='translate(60 52) scale(2)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3Cpath transform='translate(142 52) scale(2)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3Cpath transform='translate(101 101) scale(2)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3Cpath transform='translate(60 151) scale(2)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3Cpath transform='translate(142 151) scale(2)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3Cpath transform='rotate(180 84 274) translate(60 250) scale(2)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3Cpath transform='rotate(180 166 274) translate(142 250) scale(2)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3C/g%3E%3C/svg%3E");
  /* Притушена так же, как в руке: бумага и масть темнее на четверть,
     но черва остаётся красной — красное отличается от чёрного
     и на такой карте. */
  --образец-нельзя: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 250 350'%3E%3Crect x='2.5' y='2.5' width='245' height='345' rx='20' fill='%23b6ad9e' stroke='%23463016' stroke-opacity='.3' stroke-width='5'/%3E%3Cg fill='%23940c22' font-family='Times New Roman,Times,serif' font-size='60' font-weight='700' text-anchor='middle'%3E%3Ctext x='31' y='62'%3E7%3C/text%3E%3Cpath transform='translate(15 76) scale(1.3333)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3Cg transform='rotate(180 125 175)'%3E%3Ctext x='31' y='62'%3E7%3C/text%3E%3Cpath transform='translate(15 76) scale(1.3333)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3C/g%3E%3Cpath transform='translate(60 52) scale(2)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3Cpath transform='translate(142 52) scale(2)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3Cpath transform='translate(101 101) scale(2)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3Cpath transform='translate(60 151) scale(2)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3Cpath transform='translate(142 151) scale(2)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3Cpath transform='rotate(180 84 274) translate(60 250) scale(2)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3Cpath transform='rotate(180 166 274) translate(142 250) scale(2)' d='M12 21 3 12C-3 4 7-2 12 5c5-7 15-1 9 7Z'/%3E%3C/g%3E%3C/svg%3E");
}

:where(#приложение:has(> #экран-витрины)) #экран-правил > .правила {
  flex: 1 1 auto;
  min-height: 0;
  gap: 8px;
  margin-top: 4px;
  padding-bottom: 24px;
  background: none;
  scrollbar-width: thin;
  scrollbar-color: rgba(248, 245, 235, 0.18) transparent;
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 24px), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 24px), transparent);
}

/* Одно правило — одна тёмная плитка. Номер — в кружке слева, текст
   ровным столбиком правее него: вторая строка не заезжает под номер. */
:where(#приложение:has(> #экран-витрины)) #экран-правил .правила .подпись {
  position: relative;
  display: block;
  margin: 0;
  padding: 12px 14px 13px 48px;
  text-indent: 0;
  font-size: clamp(15.5px, 4.1vw, 17px);
  line-height: 1.5;
  text-align: left;
  color: var(--сб-текст);
  background: var(--плитка);
  border: 1px solid var(--плитка-край);
  border-radius: 14px;
}

/* Номер правила — тихий, серым в тонком кружке: он помогает не сбиться,
   но не спорит с текстом. Кружок стоит вровень с первой строкой. */
:where(#приложение:has(> #экран-витрины)) #экран-правил .правила .подпись::before {
  content: counter(правило);
  position: absolute;
  left: 13px;
  top: 12px;
  box-sizing: border-box;
  width: 24px;
  height: 24px;
  border: 1px solid rgba(248, 245, 235, 0.16);
  border-radius: 50%;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 22px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  color: var(--сб-текст-тихий);
}

/* Правило про подсветку — абзац с классом «правила__подсветка»
   (его ставит разработчик в разметке; найдено по классу, а не по счёту,
   чтобы образцы не уехали, если правила переставят): «Светлую карту
   с салатовой чертой можно выбрать сейчас, серую — нельзя». Словами это понять труднее
   всего, поэтому под текстом лежат две карты — ровно те, что человек
   через минуту увидит у себя в руке: светлая приподнята, под ней
   салатовая черта с лёгким свечением; серая чуть осела.
   Обе карты, черта и свечение нарисованы одной вставкой «после»
   абзаца — четырьмя слоями фона. Тень у неё по контуру рисунка,
   поэтому каждая карта отбрасывает свою. */
:where(#приложение:has(> #экран-витрины)) #экран-правил .правила .подпись.правила__подсветка {
  padding-bottom: 106px;
}

:where(#приложение:has(> #экран-витрины)) #экран-правил .правила .подпись.правила__подсветка::after {
  content: "";
  position: absolute;
  left: 48px;
  bottom: 12px;
  width: 112px;
  height: 84px;
  background:
    var(--образец-можно) 0 0 / 50px 70px no-repeat,
    var(--образец-нельзя) 62px 5px / 50px 70px no-repeat,
    linear-gradient(var(--сб-акцент), var(--сб-акцент)) 5px 75px / 40px 3px no-repeat,
    radial-gradient(closest-side, rgba(210, 247, 107, 0.55), rgba(210, 247, 107, 0)) 0 70px / 50px 13px no-repeat;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.5));
  pointer-events: none;
}

/* ---------- «Рекорды» ----------
   Сверху заголовок и серая строка «Лучшая серия: …», под ними десять
   строк рекордов, внизу в один ряд две равные тихие кнопки — «Как я
   играю» и «Рейтинг игроков». В ряд, а не столбиком: так на экране 390
   все десять строк помещаются целиком, без прокрутки.
   Раскладка — сеткой: список забирает всё свободное место и, если
   строк больше, чем влезает, прокручивается сам; кнопки остаются внизу,
   под большим пальцем. */
:where(#приложение:has(> #экран-витрины)) > #экран-рекордов.экран--виден {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 260px));
  grid-template-rows: auto auto auto minmax(0, 1fr) auto;
  grid-template-areas:
    "назад     назад"
    "заголовок заголовок"
    "подпись   подпись"
    "таблица   таблица"
    "счёт      рейтинг";
  justify-content: center;
  /* Растянуть, а не ставить по центру: общее правило экранов выше
     центрирует детей столбика, а в сетке «по центру» значит «по центру
     своего ряда по высоте» — и в низком окне список, которому не хватило
     места, вылезал вверх поверх заголовка вместо того, чтобы прокручиваться. */
  align-items: stretch;
  justify-items: stretch;
  gap: 0 8px;
}

/* В Telegram строки «‹» нет — и в сетке для неё нет ряда. */
html.в-телеграме :where(#приложение:has(> #экран-витрины)) > #экран-рекордов.экран--виден {
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  grid-template-areas:
    "заголовок заголовок"
    "подпись   подпись"
    "таблица   таблица"
    "счёт      рейтинг";
}

:where(#приложение:has(> #экран-витрины)) #экран-рекордов > #кнопка-рекорды-назад { grid-area: назад; }
:where(#приложение:has(> #экран-витрины)) #экран-рекордов > .заголовок          { grid-area: заголовок; margin-top: 10px; }
:where(#приложение:has(> #экран-витрины)) #экран-рекордов > #лучший-рекорд       { grid-area: подпись; }
:where(#приложение:has(> #экран-витрины)) #экран-рекордов > #таблица-рекордов    { grid-area: таблица; }
:where(#приложение:has(> #экран-витрины)) #экран-рекордов > #кнопка-мой-счёт     { grid-area: счёт; }
:where(#приложение:has(> #экран-витрины)) #экран-рекордов > #кнопка-рейтинг-игроков { grid-area: рейтинг; }

/* Рейтинга игроков нет (нет связи с сервером) — «Как я играю» одна
   и занимает весь ряд. */
:where(#приложение:has(> #экран-витрины)) #экран-рекордов:not(:has(> #кнопка-рейтинг-игроков)) > #кнопка-мой-счёт {
  grid-column: 1 / -1;
}

/* «Лучшая серия: 12 побед» — серая строка под заголовком, как режим
   под «Дурак». */
:where(#приложение:has(> #экран-витрины)) #экран-рекордов > #лучший-рекорд {
  margin: 2px 0 0;
  text-align: left;
  font-size: clamp(14px, 3.8vw, 16px);
  font-weight: 500;
  line-height: 1.3;
  color: var(--сб-текст-тихий);
}

/* Низ списка тает в фон, как у правил: в низком окне видно, что строки
   ещё есть. Докрутили до конца — таять нечему, там пустое поле. */
:where(#приложение:has(> #экран-витрины)) #экран-рекордов > #таблица-рекордов {
  gap: 5px;
  margin-top: 12px;
  padding-bottom: 16px;
  scrollbar-width: thin;
  scrollbar-color: rgba(248, 245, 235, 0.18) transparent;
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 16px), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 16px), transparent);
}

/* Строка рекорда — тёмная плитка. Раскладка внутри прежняя: номер
   слева, сверху крупно «12 побед подряд», под ним мелко дата и стол. */
:where(#приложение:has(> #экран-витрины)) #таблица-рекордов .таблица__строка {
  grid-template-columns: 2em auto minmax(0, 1fr);
  gap: 2px 8px;
  padding: 8px 14px 9px 8px;
  background: var(--плитка);
  border: 1px solid var(--плитка-край);
  border-radius: 14px;
  box-shadow: none;
}

:where(#приложение:has(> #экран-витрины)) #таблица-рекордов .таблица__место {
  font-size: 15px;
  font-weight: 700;
  text-align: center;
  color: var(--сб-текст-тихий);
}

:where(#приложение:has(> #экран-витрины)) #таблица-рекордов .таблица__очки {
  font-size: clamp(16px, 4.3vw, 18px);
  font-weight: 700;
  line-height: 1.25;
  color: var(--сб-текст);
}

:where(#приложение:has(> #экран-витрины)) #таблица-рекордов :is(.таблица__дата, .таблица__сложность) {
  font-size: 13px;
  line-height: 1.3;
  color: var(--сб-текст-тихий);
}

/* Лучший рекорд — первая строка — единственное салатовое на экране:
   рамка, номер и лёгкий салатовый отлив плитки. */
:where(#приложение:has(> #экран-витрины)) #таблица-рекордов .таблица__строка:first-child {
  background:
    linear-gradient(rgba(210, 247, 107, 0.07), rgba(210, 247, 107, 0.07)),
    var(--плитка);
  border-color: var(--сб-акцент);
  box-shadow: inset 0 0 0 1px var(--сб-акцент);
}

:where(#приложение:has(> #экран-витрины)) #таблица-рекордов .таблица__строка:first-child .таблица__место {
  color: var(--сб-акцент);
}

/* «Здесь пока пусто», «Минутку…» — та же плитка, текст серым. */
:where(#приложение:has(> #экран-витрины)) #таблица-рекордов .таблица__пусто {
  padding: 16px 14px;
  font-size: 15px;
  line-height: 1.45;
  text-align: left;
  color: var(--сб-текст-тихий);
  background: var(--плитка);
  border: 1px solid var(--плитка-край);
  border-radius: 14px;
}

/* «Как я играю» и «Рейтинг игроков» — тихие: тёмная плитка с тонким
   контуром, как тихие кнопки на плашке итога. Равные по ширине. */
:where(#приложение:has(> #экран-витрины)) #экран-рекордов > :is(#кнопка-мой-счёт, #кнопка-рейтинг-игроков) {
  width: 100%;
  min-width: 0;
  min-height: 48px;
  margin: 4px 0 0;           /* над кнопками ещё пустое поле списка (16 точек) */
  padding: 0 10px;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--сб-текст);
  background: var(--плитка);
  border: 1px solid rgba(248, 245, 235, 0.14);
  border-radius: 14px;
  box-shadow: none;
}

:where(#приложение:has(> #экран-витрины)) #экран-рекордов > :is(#кнопка-мой-счёт, #кнопка-рейтинг-игроков):active {
  transform: translateY(1px);
  background: var(--плитка-нажата);
  box-shadow: none;
}

/* ---------- «Оформление» ----------
   Остался один раздел — прежний «Фон», теперь это цвет сукна на столе
   (выбор рубашки разработчик спрятал). Ярлык раздела — мелкими
   прописными серым, под ним сетка тёмных плиток: сверху кусочек сукна
   в раме, под ним имя. Выбранная — салатовая рамка и галочка (их рисуют
   общие правила выбора выше по файлу: они берут «--акцент», а он здесь
   салатовый). Сами образцы — в разделе «ЦВЕТ СУКНА» ниже. */
:where(#приложение:has(> #экран-витрины), #приложение:has(.доска-нард)) > #экран-оформления {
  overflow-y: auto;
  overscroll-behavior: contain;
}

:where(#приложение:has(> #экран-витрины), #приложение:has(.доска-нард)) #экран-оформления > .оформление__раздел {
  margin: 10px 0 0;
}

:where(#приложение:has(> #экран-витрины), #приложение:has(.доска-нард)) #экран-оформления .оформление__подпись {
  margin: 0 0 8px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--сб-текст-тихий);
}

:where(#приложение:has(> #экран-витрины), #приложение:has(.доска-нард)) #экран-оформления .оформление__кнопки {
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  gap: 8px;
}

:where(#приложение:has(> #экран-витрины), #приложение:has(.доска-нард)) #экран-оформления .оформление__выбор.оформление__выбор {
  gap: 8px;
  padding: 8px 8px 10px;
  color: var(--сб-текст);
  background: var(--плитка);
  border: 1px solid var(--плитка-край);
  border-radius: 14px;
}

:where(#приложение:has(> #экран-витрины), #приложение:has(.доска-нард)) #экран-оформления .оформление__выбор.оформление__выбор:active {
  background: var(--плитка-нажата);
}

/* Выбранная плитка. Список длинный по той же причине, что у общих
   правил выбора выше: фон выбранным помечает сама страница признаком
   «data-фон», а «Сукно» выбрано и тогда, когда признака нет вовсе. */
:where(#приложение:has(> #экран-витрины), #приложение:has(.доска-нард)) #экран-оформления :is(
  .кнопка.оформление__выбор.кнопка--активная,
  html[data-фон="сукно"]   .оформление__выбор[data-фон="сукно"],
  html:not([data-фон])     .оформление__выбор[data-фон="сукно"],
  html[data-фон="дыхание"] .оформление__выбор[data-фон="дыхание"],
  html[data-фон="лампа"]   .оформление__выбор[data-фон="лампа"],
  html[data-фон="туман"]   .оформление__выбор[data-фон="туман"],
  html[data-фон="отсвет"]  .оформление__выбор[data-фон="отсвет"]
) {
  padding: 7px 7px 9px;      /* на точку меньше — рамка стала толще */
  background:
    linear-gradient(rgba(210, 247, 107, 0.07), rgba(210, 247, 107, 0.07)),
    var(--плитка);
  border: 2px solid var(--сб-акцент);
}

:where(#приложение:has(> #экран-витрины), #приложение:has(.доска-нард)) #экран-оформления .оформление__имя {
  font-size: 13px;
  font-weight: 600;
}

:where(#приложение:has(> #экран-витрины), #приложение:has(.доска-нард)) #экран-оформления .оформление__скоро {
  font-size: 14px;
  color: var(--сб-текст-тихий);
}

/* ---------- Невысокое окно ----------
   Заголовок мельче, плитки теснее. Текст правил — не мельче 15 точек:
   читают здесь именно его. */
@media (max-height: 700px) {
  :where(#приложение:has(> #экран-витрины), #приложение:has(.доска-нард)) > :is(#экран-правил, #экран-рекордов, #экран-оформления) > .заголовок {
    font-size: clamp(22px, 6.6vw, 27px);
  }

  :where(#приложение:has(> #экран-витрины)) #экран-правил > .правила { gap: 6px; }

  :where(#приложение:has(> #экран-витрины)) #экран-правил .правила .подпись {
    padding: 10px 12px 11px 44px;
    font-size: 15px;
    line-height: 1.45;
  }

  :where(#приложение:has(> #экран-витрины)) #экран-правил .правила .подпись::before {
    left: 11px;
    top: 10px;
    width: 22px;
    height: 22px;
    font-size: 12px;
    line-height: 20px;
  }

  :where(#приложение:has(> #экран-витрины)) #экран-правил .правила .подпись.правила__подсветка {
    padding-bottom: 102px;
  }

  :where(#приложение:has(> #экран-витрины)) #экран-правил .правила .подпись.правила__подсветка::after {
    left: 44px;
    bottom: 10px;
  }

  :where(#приложение:has(> #экран-витрины)) #экран-рекордов > #таблица-рекордов {
    gap: 5px;
    margin-top: 10px;
  }

  :where(#приложение:has(> #экран-витрины)) #таблица-рекордов .таблица__строка {
    padding: 7px 12px 8px 6px;
  }
}

/* =====================================================================
   ЛОББИ ДУРАКА И ТРИ ШАГА ДО ПАРТИИ
   (эталон/дурак-01-лобби, -02-правила, -03-игроки, -04-настройки)

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

   Одно сознательное отступление от эталона. Там салатовая карточка —
   «Играть онлайн». У нас онлайна нет, карточка выключена и помечена
   «скоро» — красить её главным цветом значило бы звать туда, куда нельзя.
   Главная, салатовая — «Играть с ботами».

   Кнопка «Далее» на шагах прилипает к низу экрана: в низком окне Telegram
   третий шаг не помещается, и искать главную кнопку прокруткой нельзя.
   ===================================================================== */

/* Фактуры стола — зерно сукна и волокна дерева. Вынесены в переменные,
   чтобы рама картинки лобби, стол рассадки и пример перевода рисовались
   теми же слоями, что стол партии. */
:root {
  --текстура-зерно: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3'/%3E%3CfeColorMatrix values='1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
  --текстура-волокна: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='60'%3E%3Cfilter id='d'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.012 0.5' numOctaves='2'/%3E%3CfeColorMatrix values='1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1'/%3E%3C/filter%3E%3Crect width='240' height='60' filter='url(%23d)' opacity='0.7'/%3E%3C/svg%3E");
  --значок-вперёд: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 4 8 8-8 8'/%3E%3C/svg%3E");
  /* Та же стрелка, развёрнутая влево, — для видимой «Назад» на шагах. */
  --значок-назад: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m15 4-8 8 8 8'/%3E%3C/svg%3E");
}

/* ---------- Общее для лобби и шагов ---------- */
#экран-лобби,
.экран.путь {
  /* Фон — тёмный графит сборника, один на все игры: лобби дурака
     выглядит так же, как лобби шашек, шахмат и нард (решение владельца
     22.09). Сукно на фон экрана не выходит — оно только внутри рамы. */
  --фон: var(--сб-фон);
  --панель: var(--сб-поверхность);
  --текст: var(--сб-текст);
  --текст-тихий: var(--сб-текст-тихий);
  --кнопка-фон: var(--сб-акцент);
  --кнопка-текст: var(--сб-акцент-текст);
  --акцент: var(--сб-акцент);
  --подложка: rgba(248, 245, 235, 0.06);
  --край: rgba(248, 245, 235, 0.14);
  --поле: clamp(12px, 3.6vw, 18px);
  --плитка: #1e2226;
  --плитка-кромка: rgba(248, 245, 235, 0.12);
  --плитка-нажата: #262a2f;
  /* Для панели вкладок — те же имена, что у витрины. */
  --вт-поверхность: var(--сб-поверхность);
  --вт-текст: var(--сб-текст);
  --вт-текст-тихий: var(--сб-текст-тихий);
  --вт-акцент: var(--сб-акцент);
  --вт-панель-низ: clamp(52px, 14.36vw, 64px);
  /* Дерево — как у стола партии: рама картинки лобби рисуется теми же
     слоями. Сукно внутри рамы всегда бордовое (см. «ЦВЕТ СУКНА» ниже). */
  --дерево-свет: #9a6841;
  --дерево: #75492b;
  --дерево-тень: #4a2b17;

  align-items: center;
  gap: 10px;
  padding: calc(6px + var(--отступ-сверху)) calc(var(--поле) + var(--отступ-справа))
           calc(12px + var(--отступ-снизу)) calc(var(--поле) + var(--отступ-слева));
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  color: var(--сб-текст);
  text-align: left;
  background:
    radial-gradient(75% 120px at 50% 0, rgba(210, 247, 107, 0.07), rgba(210, 247, 107, 0) 100%) local,
    var(--сб-фон);
}

#экран-лобби::-webkit-scrollbar,
.экран.путь::-webkit-scrollbar { display: none; }

/* Резерв снизу под fixed-полосу вкладок — тот же приём, что у рейтинга
   и профиля (11543, 15905): «.нижние-вкладки» лежит поверх низа экрана
   и в поток не идёт, а обычный отступ базового правила выше (12px)
   её высоту не учитывает. Без резерва последняя карточка входа (у
   шашек это «Вдвоём на этом устройстве», четвёртая) уходит под полосу
   и не докручивается — экран и так «overflow-y: auto» (см. правило
   выше), прокрутка задумана, не хватало только места под самой полосой.
   «:has(> .нижние-вкладки)» — общее правило для лобби ЛЮБОЙ игры
   (дурак, шашки, шахматы, нарды у всех один и тот же «#экран-лобби»
   с полосой внутри), а не заплатка под конкретную. Шахматам и нардам,
   где карточек меньше и место было с запасом, лишний отступ ничего
   не портит: экран и без него короче окна, добавка просто увеличивает
   пустой хвост под последней карточкой, а не сдвигает видимое. */
#экран-лобби:has(> .нижние-вкладки) {
  padding-bottom: calc(var(--вт-панель-низ) + 12px + var(--отступ-снизу));
}

/* Столбик — не шире витрины (520) и посередине; ничего не сжимается —
   не влезло, экран прокручивается. */
#экран-лобби > :not(.нижние-вкладки),
.экран.путь > * {
  flex-shrink: 0;
  box-sizing: border-box;
  width: 100%;
  max-width: 520px;
}

/* У лобби и шагов поля не 8px, а var(--поле) (12–18px, см. «Общее для
   лобби и шагов» выше) — это отдельное решение оформителя, не тот баг,
   что чинили в .верх-игры. Поэтому здесь margin оставлен как раньше,
   своим числом, а не общей формулой базового класса. */
#экран-лобби > .верх-игры,
.экран.путь > .верх-игры {
  margin-left: -10px;
  margin-right: -10px;
  width: calc(100% + 20px);
  max-width: 540px;
}

/* Кнопки экрана: без серой вспышки, с салатовой обводкой с клавиатуры. */
:is(#экран-лобби, .экран.путь) button:focus-visible {
  outline: 2px solid var(--сб-акцент);
  outline-offset: 2px;
}

/* Плитка — общий вид карточек лобби и шагов: на тон светлее фона,
   тонкая светлая кромка, скругление 18. */
:is(.карточка-профиля, .карточка-входа, .вариант, .сводка, .карточка-тренировки) {
  box-sizing: border-box;
  background: var(--плитка);
  border: 1px solid var(--плитка-кромка);
  border-radius: 18px;
}

/* Значки в разметке — тонкие контуры набора; размер задаёт их коробка. */
:is(.карточка-профиля__стрелка, .карточка-входа__значок, .карточка-входа__стрелка,
    .сводка__значок, .карточка-тренировки__значок, .пример-перевода__стрелка) svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* ---------- Лобби ---------- */
#экран-лобби {
  gap: 12px;
  /* Снизу — место под панель вкладок, как у витрины. */
  padding-bottom: calc(var(--вт-панель-низ) + 14px + var(--отступ-снизу));
}

#экран-лобби > .лобби__заголовок {
  margin: 0;
  font-size: clamp(34px, 11vw, 48px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.025em;
  color: var(--сб-текст);
}

html.в-телеграме #экран-лобби > .лобби__заголовок { margin-top: 4px; }

/* Подпись сразу под заголовком лобби («Классическая игра для двоих»
   у шашек). Весь каркас лобби левосторонний, а общая «.подпись»
   центрирует текст — здесь она возвращается к левому краю и подтянута
   к заголовку. У дурака такой подписи нет, правило просто молчит. */
#экран-лобби > .лобби__заголовок + .подпись {
  margin: -6px 0 0;
  text-align: left;
  color: var(--сб-текст-тихий);
}

/* Недоигранная партия с другом — первой, заметно, но не главной кнопкой. */
#экран-лобби > .плашка-возврата {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  padding: 8px 14px;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.25;
  color: var(--сб-текст);
  background: rgba(210, 247, 107, 0.08);
  border: 1px solid rgba(210, 247, 107, 0.45);
  border-radius: 16px;
  cursor: pointer;
}

#экран-лобби > .плашка-возврата::before {
  content: "↻";
  font-size: 18px;
  line-height: 1;
  color: var(--сб-акцент);
}

/* Карточка профиля: аватар, имя, место в рейтинге, «›». */
.карточка-профиля {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 68px;
  padding: 10px 14px 10px 12px;
  font: inherit;
  text-align: left;
  color: var(--сб-текст);
  cursor: pointer;
}

.карточка-профиля > .аватар {
  --аватар: 48px;
  color: #aab0b6;
}

.карточка-профиля__текст {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.карточка-профиля__имя {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: clamp(16px, 4.6vw, 19px);
  font-weight: 700;
  line-height: 1.2;
}

.карточка-профиля__рейтинг {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 15px;
  line-height: 1.2;
  color: var(--сб-текст-тихий);
}

.карточка-профиля__рейтинг svg {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  color: var(--сб-акцент);
}

/* Места в рейтинге нет — строки нет вовсе: один кубок без числа
   читался бы как «ноль». */
.карточка-профиля__рейтинг--нет { display: none; }

.карточка-профиля__стрелка,
.карточка-входа__стрелка {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  color: var(--сб-текст-тихий);
}

/* Картинка лобби в деревянной раме — те же слои, что у рамы стола.
   Внутри — фото карт на сукне, по низу подпись с засечками, как на
   эталоне. Затемнение снизу — чтобы подпись читалась поверх карт. */
.лобби__картинка {
  --рама: clamp(7px, 2.3vw, 11px);
  position: relative;
  margin: 0;
  aspect-ratio: 16 / 10;
  border: var(--рама) solid transparent;
  border-radius: calc(var(--рама) + 14px);
  background:
    var(--текстура-волокна) border-box,
    linear-gradient(180deg, var(--дерево-свет) 0%, var(--дерево) 40%, var(--дерево-тень) 100%) border-box;
  background-size: 240px 60px, auto;
  background-repeat: repeat, no-repeat;
  background-blend-mode: soft-light, normal;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.60),
    0 14px 30px rgba(0, 0, 0, 0.55);
}

/* Фаска рамы — как у стола. */
.лобби__картинка::before {
  content: "";
  position: absolute;
  inset: calc(-1 * var(--рама));
  border-radius: inherit;
  pointer-events: none;
  box-shadow:
    inset 0 1.5px 0 rgba(255, 222, 184, 0.34),
    inset 0 -1.5px 0 rgba(0, 0, 0, 0.45),
    inset 1px 0 0 rgba(255, 222, 184, 0.10),
    inset -1px 0 0 rgba(0, 0, 0, 0.25);
}

/* Картинка лежит поверх рамки целиком, а не в потоке: иначе её родная
   высота (1200×800) растягивала рамку сильнее заданной пропорции. */
.лобби__рисунок {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 42%;
  border-radius: 14px;
}

/* Тень от рамы на сукно и затемнение под подписью. */
.лобби__картинка::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 14px;
  pointer-events: none;
  background: linear-gradient(to top, rgba(22, 4, 6, 0.78) 0%, rgba(22, 4, 6, 0) 50%);
  box-shadow:
    inset 0 0 0 1px rgba(0, 0, 0, 0.55),
    inset 0 10px 24px rgba(0, 0, 0, 0.50),
    inset 0 -8px 20px rgba(0, 0, 0, 0.35);
}

.лобби__подпись {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 9%;
  z-index: 1;
  max-width: 13em;
  margin: 0 auto;
  padding: 0 12px;
  font-family: Georgia, 'Times New Roman', Times, 'Noto Serif', 'Liberation Serif', serif;
  font-size: clamp(18px, 5.4vw, 23px);
  font-weight: 400;
  line-height: 1.2;
  text-align: center;
  text-wrap: balance;
  color: #f8f1e4;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.85);
}

/* Входы: онлайн (скоро), с ботами (главный), раздача дня, друзья, код. */
.лобби__входы {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.карточка-входа {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 68px;
  padding: 10px 16px 10px 14px;
  font: inherit;
  text-align: left;
  color: var(--сб-текст);
  cursor: pointer;
}

.карточка-входа__значок {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  margin: 0 4px;
}

.карточка-входа__текст {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.карточка-входа__название {
  font-size: clamp(17px, 5vw, 21px);
  font-weight: 700;
  line-height: 1.2;
}

.карточка-входа__подпись {
  font-size: clamp(13px, 3.7vw, 15px);
  line-height: 1.25;
  color: var(--сб-текст-тихий);
}

.карточка-входа:not(:disabled):active,
.карточка-профиля:active {
  transform: scale(0.985);
  background-color: var(--плитка-нажата);
}

/* Играть онлайн — главная: теперь это настоящий подбор соперника,
   а не ботов, поэтому салатовый акцент стоит на ней. */
.карточка-входа.карточка-входа--играть-онлайн {
  color: var(--сб-акцент-текст);
  background: var(--сб-акцент);
  border-color: var(--сб-акцент);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    0 8px 22px rgba(210, 247, 107, 0.16);
}

.карточка-входа--играть-онлайн .карточка-входа__подпись,
.карточка-входа--играть-онлайн .карточка-входа__стрелка {
  color: rgba(16, 19, 10, 0.68);
}

.карточка-входа.карточка-входа--играть-онлайн:active {
  background: var(--сб-акцент);
  filter: brightness(0.95);
}

/* Онлайн — есть, но выключен: приглушён, справа «скоро». */
.карточка-входа--онлайн:disabled { cursor: default; }
.карточка-входа--онлайн:disabled > :not(.пометка-скоро) { opacity: 0.5; }

/* Друзья — одна строка, карточка ниже. */
.карточка-входа--друзья { min-height: 58px; }

/* «Вдвоём на этом устройстве» — четвёртый вход, полноценная карточка
   ТОГО ЖЕ ВИДА, что «Играть онлайн» и «Играть с ботом» (решение владельца
   24.09: «в том же стиле, что играть онлайн или с ботом» — прежняя
   версия этого класса нарочно ужимала карточку, что и вызвало замечание).
   Своих отличий у неё нет — только высота чуть ниже, тот же приём,
   что у --друзья: подпись «Один телефон на двоих» умещается в одну
   строку. Класс общий: тот же вход есть у шашек, шахмат и нард. */
.карточка-входа--вдвоём { min-height: 58px; }

#экран-лобби .пометка-скоро {
  flex: 0 0 auto;
  padding: 3px 10px 4px;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--сб-текст);
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid rgba(248, 245, 235, 0.16);
  border-radius: 999px;
}

/* «Раздача дня» — тихая плитка; салатовая только искра впереди. */
#экран-лобби .кнопка.кнопка--раздача-дня {
  width: 100%;
  min-height: 50px;
  padding: 8px 16px;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--сб-текст);
  background: var(--плитка);
  border: 1px solid rgba(210, 247, 107, 0.30);
  border-radius: 18px;
  box-shadow: none;
}

#экран-лобби .кнопка.кнопка--раздача-дня::before {
  content: "✦ ";
  color: var(--сб-акцент);
}

#экран-лобби .кнопка.кнопка--раздача-дня.кнопка--раздача-сыграна,
#экран-лобби .кнопка.кнопка--раздача-дня.кнопка--раздача-сыграна:disabled {
  font-size: 15px;
  color: var(--сб-текст);
  background: var(--плитка);
  border: 1px solid var(--плитка-кромка);
}

/* «Есть код? Войти» — тихая ссылка под входами. */
#экран-лобби .лобби__код {
  align-self: center;
  min-height: 44px;
  padding: 0 12px;
  font: inherit;
  font-size: 15px;
  color: var(--сб-текст-тихий);
  background: none;
  border: none;
  text-decoration: underline dotted;
  text-underline-offset: 4px;
  cursor: pointer;
}

/* ---------- Шаги: шапка ---------- */
.путь__шапка {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: 12px;
  row-gap: 2px;
}

html.в-телеграме .экран.путь > .путь__шапка { margin-top: 4px; }

.путь__заголовок {
  flex: 0 1 auto;
  min-width: 0;
  margin: 0;
  font-size: clamp(28px, 8.8vw, 40px);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -0.025em;
  color: var(--сб-текст);
}

/* Пилюля режима — «С ботами», «С друзьями». Тихая: салатовый на шаге
   у полосы шагов и у «Далее». */
.путь__режим {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  padding: 3px 13px 4px;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--сб-текст);
  border: 1px solid var(--сб-граница);
  border-radius: 999px;
}

.путь__режим:empty,
.путь__шаг:empty { display: none; }

.путь__шаг {
  flex: 1 0 100%;
  margin: 0;
  font-size: 15px;
  line-height: 1.3;
  color: var(--сб-текст-тихий);
}

/* ---------- Полоса шагов ----------
   Кружок с цифрой и имя; между шагами черта. Пройденный — салатовый
   контур с галочкой, текущий — залитый салатовым кружок со свечением,
   впереди — серый контур. Черта салатовая, если ведёт к уже
   достигнутому шагу. Черты растягиваются, полоса занимает всю ширину. */
.экран.путь > .шаги {
  display: flex;
  align-items: center;
  margin: 4px 0 4px;
  padding: 0;
  list-style: none;
}

.шаги__шаг {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
  font-size: clamp(12.5px, 3.6vw, 14px);
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  color: var(--сб-текст-тихий);
}

.шаги__шаг + .шаги__шаг { flex: 1 1 auto; }

.шаги__шаг + .шаги__шаг::before {
  content: "";
  flex: 1 1 auto;
  min-width: 8px;
  height: 1.5px;
  margin: 0 8px;
  border-radius: 1px;
  background: rgba(248, 245, 235, 0.22);
}

.шаги__номер {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  box-sizing: border-box;
  width: clamp(28px, 8.2vw, 32px);
  height: clamp(28px, 8.2vw, 32px);
  border: 1.5px solid rgba(248, 245, 235, 0.32);
  border-radius: 50%;
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
}

.шаги__галочка {
  display: none;
  width: 60%;
  height: 60%;
}

.шаги__шаг--пройден,
.шаги__шаг--текущий { color: var(--сб-акцент); }

.шаги__шаг--пройден::before,
.шаги__шаг--текущий::before { background: var(--сб-акцент); }

.шаги__шаг--пройден .шаги__номер { border-color: var(--сб-акцент); }
.шаги__шаг--пройден .шаги__цифра { display: none; }
.шаги__шаг--пройден .шаги__галочка { display: block; }

.шаги__шаг--текущий { font-weight: 600; }

.шаги__шаг--текущий .шаги__номер {
  color: var(--сб-акцент-текст);
  background: var(--сб-акцент);
  border-color: var(--сб-акцент);
  box-shadow: 0 0 14px rgba(210, 247, 107, 0.45);
}

/* На 320 и уже (маленькие телефоны) три подписи «Правила / Игроки /
   Настройки» в кегле-минимуме не помещались — третий шаг уезжал за
   край окна. Кружок с цифрой и шрифт подписи и так уже на нижней
   границе своих clamp(), сжимать их некуда — поэтому ужимаем только
   зазоры вокруг: промежуток между кружком и подписью и черту-разделитель
   между шагами. Подписи остаются видны у всех трёх шагов. */
@media (max-width: 359px) {
  .шаги__шаг { gap: 4px; }

  .шаги__шаг + .шаги__шаг::before {
    min-width: 4px;
    margin: 0 4px;
  }
}

/* ---------- Шаги: вопросы и подписи ---------- */
.путь__вопрос {
  margin: 8px 0 0;
  font-size: clamp(22px, 6.4vw, 28px);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.015em;
}

.путь__раздел {
  margin: 6px 0 -2px;
  font-size: clamp(17px, 5vw, 21px);
  font-weight: 700;
  line-height: 1.2;
}

.путь__подпись,
.путь__подсказка {
  margin: 0;
  font-size: 14px;
  line-height: 1.35;
  text-align: center;
  text-wrap: balance;
  color: var(--сб-текст-тихий);
}

/* «Включая вас» — сразу под числами. */
.числа + .путь__подпись { margin-top: -4px; }

#путь-блок-сложности {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

#путь-блок-сложности.скрыт { display: none; }

.путь__ссылка {
  align-self: center;
  width: auto;
  min-height: 44px;
  padding: 0 12px;
  font: inherit;
  font-size: 15px;
  color: var(--сб-текст-тихий);
  background: none;
  border: none;
  text-decoration: underline;
  text-decoration-color: rgba(133, 139, 148, 0.5);
  text-underline-offset: 4px;
  cursor: pointer;
}

.экран.путь > .путь__ссылка { width: auto; }

/* ---------- Шаг 1: варианты правил ---------- */
.варианты {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.вариант {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  min-height: 96px;
  padding: 12px 16px 12px 14px;
  font: inherit;
  text-align: left;
  color: var(--сб-текст);
  border-width: 1.5px;
  cursor: pointer;
}

.вариант:active { background-color: var(--плитка-нажата); }

.вариант.вариант--выбран {
  background:
    linear-gradient(rgba(210, 247, 107, 0.06), rgba(210, 247, 107, 0.06)),
    var(--плитка);
  border-color: var(--сб-акцент);
  box-shadow: 0 0 18px rgba(210, 247, 107, 0.12);
}

/* Две карты новой колоды внахлёст, чуть веером. */
.вариант__карты {
  --в: clamp(58px, 17vw, 70px);
  --ш: calc(var(--в) / 1.4);
  display: flex;
  align-items: center;
  padding: 0 4px 0 2px;
}

.вариант__карты > .карта {
  flex: 0 0 auto;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.45);
}

.вариант__карты > .карта + .карта { margin-left: calc(var(--ш) * -0.42); }
.вариант__карты > .карта:first-child { rotate: -7deg; }
.вариант__карты > .карта:last-child { rotate: 6deg; translate: 0 2px; }

.вариант__текст {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.вариант__название {
  font-size: clamp(18px, 5.3vw, 22px);
  font-weight: 700;
  line-height: 1.15;
}

.вариант__описание {
  font-size: clamp(13px, 3.8vw, 15px);
  line-height: 1.3;
  color: var(--сб-текст-тихий);
}

/* Кружок выбора: пустой — серый контур, выбран — салатовый с галочкой. */
.вариант__отметка {
  display: grid;
  place-items: center;
  box-sizing: border-box;
  width: 30px;
  height: 30px;
  border: 1.5px solid rgba(248, 245, 235, 0.35);
  border-radius: 50%;
  color: transparent;
}

.вариант__отметка svg {
  display: block;
  width: 18px;
  height: 18px;
  stroke-width: 2.2;
}

.вариант--выбран .вариант__отметка {
  color: var(--сб-акцент-текст);
  background: var(--сб-акцент);
  border-color: var(--сб-акцент);
}

/* Пример перевода — на сукне в раме, как стол: две карты и стрелка. */
.пример-перевода,
.рассадка {
  --рама: clamp(7px, 2.3vw, 11px);
  --сукно-свет: #6e181c;
  --сукно: #4f0d10;
  --сукно-тень: #2a0507;
  position: relative;
  border: var(--рама) solid transparent;
  background:
    var(--текстура-зерно) padding-box,
    radial-gradient(120% 95% at 50% 38%, var(--сукно-свет) 0%, var(--сукно) 52%, var(--сукно-тень) 100%) padding-box,
    var(--текстура-волокна) border-box,
    linear-gradient(180deg, var(--дерево-свет) 0%, var(--дерево) 40%, var(--дерево-тень) 100%) border-box;
  background-size: 160px 160px, auto, 240px 60px, auto;
  background-repeat: repeat, no-repeat, repeat, no-repeat;
  background-blend-mode: soft-light, normal, soft-light, normal;
  box-shadow:
    inset 0 0 0 1px rgba(0, 0, 0, 0.55),
    inset 0 10px 26px rgba(0, 0, 0, 0.50),
    inset 0 -8px 20px rgba(0, 0, 0, 0.35),
    0 0 0 1px rgba(0, 0, 0, 0.60),
    0 14px 30px rgba(0, 0, 0, 0.55);
}

.пример-перевода::before,
.рассадка::before {
  content: "";
  position: absolute;
  inset: calc(-1 * var(--рама));
  border-radius: inherit;
  pointer-events: none;
  box-shadow:
    inset 0 1.5px 0 rgba(255, 222, 184, 0.34),
    inset 0 -1.5px 0 rgba(0, 0, 0, 0.45),
    inset 1px 0 0 rgba(255, 222, 184, 0.10),
    inset -1px 0 0 rgba(0, 0, 0, 0.25);
}

.пример-перевода {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 18px 16px 14px;
  border-radius: calc(var(--рама) + 16px);
}

.пример-перевода.скрыт { display: none; }

.пример-перевода__карты {
  --в: clamp(72px, 22vw, 92px);
  --ш: calc(var(--в) / 1.4);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(14px, 5vw, 26px);
}

.пример-перевода__карты > .карта {
  flex: 0 0 auto;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.5), 0 10px 20px rgba(0, 0, 0, 0.3);
}

.пример-перевода__карты > .карта:first-child { rotate: -5deg; }
.пример-перевода__карты > .карта:last-child { rotate: 4deg; }

.пример-перевода__стрелка {
  flex: 0 0 auto;
  width: clamp(38px, 11vw, 48px);
  height: clamp(38px, 11vw, 48px);
  color: #f8f1e4;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.6));
}

.пример-перевода__стрелка svg { stroke-width: 2; }

.пример-перевода__подпись {
  margin: 0;
  font-size: 14px;
  line-height: 1.3;
  text-align: center;
  color: rgba(248, 245, 235, 0.78);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7);
}

/* ---------- Шаг 2 и 3: переключатель и числа ---------- */
.переключатель {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 4px;
  box-sizing: border-box;
  padding: 4px;
  background: var(--плитка);
  border: 1px solid var(--плитка-кромка);
  border-radius: 18px;
}

.переключатель.скрыт { display: none; }

.переключатель__вариант {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  min-width: 0;
  min-height: 48px;
  padding: 4px 6px;
  font: inherit;
  /* Три ячейки в ряд на 360 — по 106 точек: «Без таймера» при таком
     кегле встаёт в одну строку. */
  font-size: clamp(14px, 4vw, 16.5px);
  font-weight: 600;
  line-height: 1.15;
  text-align: center;
  color: var(--сб-текст);
  background: none;
  border: none;
  border-radius: 14px;
  cursor: pointer;
}

.переключатель__вариант:not(:disabled):not(.переключатель__вариант--выбран):not(.кнопка--активная):active {
  background: var(--плитка-нажата);
}

/* Один и тот же приём выбора уровня бота (дурак, шахматы, шашки, нарды),
   но два разных имени модификатора «выбрано»: дурак и шахматы ставят
   «переключатель__вариант--выбран» сами (js/шахматы-лобби.js), а
   выбор бота в шашках и нардах красит js/шашки-экран.js и
   js/нарды-экран.js классом «кнопка--активная» — эти два файла вне
   этого задания, их не трогаем. Чтобы вид совпадал один-в-один на
   всех четырёх играх, читаем оба имени одним правилом. */
.переключатель__вариант.переключатель__вариант--выбран,
.переключатель__вариант.кнопка--активная {
  font-weight: 700;
  color: var(--сб-акцент-текст);
  background: var(--сб-акцент);
  box-shadow: 0 4px 14px rgba(210, 247, 107, 0.22);
}

/* Выключенный вариант должен читаться, иначе человек решит, что экран
   сломался. Держим одну меру на всех экранах — примерно 0,6 от белого,
   как у фильтров рейтинга и у подбора игроков в комнате. Прежние 0,38
   на шаге «Настройки» превращали «30 сек» в еле различимую тень. */
.переключатель__вариант:disabled {
  color: rgba(248, 245, 235, 0.6);
  cursor: default;
}

/* Выбранный вариант выключенной пары. Раньше на него падало правило
   выше и текст становился бледно-белым по салатовому — прочесть было
   нельзя. Салатовая пилюля всегда с тёмной надписью, как кнопки лобби;
   свечение убрано — оно звало нажать на то, что не нажимается. */
.переключатель__вариант.переключатель__вариант--выбран:disabled,
.переключатель__вариант.кнопка--активная:disabled {
  color: var(--сб-акцент-текст);
  box-shadow: none;
}

/* «скоро» внутри переключателя — та же тёмная пилюля, что у «Играть
   онлайн» в лобби, у подбора игроков в комнате и у фильтров рейтинга.
   Стоит второй строкой под названием: ячейка вдвое уже кнопки лобби,
   рядом слово не встанет.

   Раньше здесь был просто бледный текст в 0,45 от белого — на шаге
   «Настройки» («30 сек», «60 сек») его почти не было видно, и одна и
   та же пометка выглядела на трёх экранах по-разному. */
.переключатель__вариант > .пометка-скоро {
  margin-top: 2px;
  padding: 1px 8px 2px;
  font-size: 10px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: rgba(248, 245, 235, 0.62);
  background: rgba(0, 0, 0, 0.4);
  border: 1px solid rgba(248, 245, 235, 0.14);
  border-radius: 999px;
}

.числа {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 8px;
}

.числа__число {
  min-width: 0;
  min-height: 52px;
  padding: 0;
  font: inherit;
  font-size: clamp(18px, 5.4vw, 22px);
  font-weight: 600;
  color: var(--сб-текст);
  background: var(--плитка);
  border: 1px solid var(--плитка-кромка);
  border-radius: 14px;
  cursor: pointer;
}

.числа__число:not(:disabled):not(.числа__число--выбран):active { background: var(--плитка-нажата); }

.числа__число.числа__число--выбран {
  font-weight: 800;
  color: var(--сб-акцент-текст);
  background: var(--сб-акцент);
  border-color: var(--сб-акцент);
  box-shadow: 0 4px 14px rgba(210, 247, 107, 0.22);
}

.числа__число:disabled {
  opacity: 0.35;
  cursor: default;
}

/* ---------- Шаг 2: стол рассадки ----------
   Овальный стол — дерево и сукно, как стол партии. Места — по числу
   игроков, по кругу, начиная с «Вы» наверху и дальше по часовой.
   Угол места считается из его номера и числа мест (их пишет игра:
   «--номер-места» и «--мест»), точка — на овале рамы. Места крупнее
   пальца (48–58 точек) и выступают за край стола наполовину — поэтому
   у стола поля вокруг. */
.рассадка {
  --место: clamp(48px, 14.5vw, 58px);
  --рама: clamp(9px, 2.8vw, 13px);
  box-sizing: border-box;
  align-self: center;
  aspect-ratio: 2.15 / 1;
  margin: calc(var(--место) / 2) auto calc(var(--место) / 2 + 4px);
  border-radius: 999px;
}

/* Стол у́же столбика на одно место: крайние места выступают за край
   стола наполовину и не должны упираться в край экрана. */
.экран.путь > .рассадка {
  width: calc(100% - var(--место));
  max-width: 440px;
}

.рассадка__место {
  --угол: calc(-90deg + var(--номер-места, 0) * 360deg / var(--мест, 4));
  position: absolute;
  left: calc(50% + (50% + var(--рама) / 2) * cos(var(--угол)));
  top: calc(50% + (50% + var(--рама) / 2) * sin(var(--угол)));
  z-index: 1;
  display: grid;
  place-items: center;
  width: var(--место);
  height: var(--место);
  margin: calc(var(--место) / -2) 0 0 calc(var(--место) / -2);
  border-radius: 50%;
  color: #8a9199;
  background: #171a1d;
  box-shadow:
    0 0 0 2px rgba(0, 0, 0, 0.35),
    0 5px 12px rgba(0, 0, 0, 0.55);
}

/* Значок аватара (круг с человеком) — во всё место: его круг и есть
   кольцо места, цветом роли. */
.рассадка__место > .аватар {
  --аватар: var(--место);
  color: inherit;
}

.рассадка__место--я {
  color: var(--сб-акцент);
  box-shadow:
    0 0 0 2px rgba(0, 0, 0, 0.35),
    0 5px 12px rgba(0, 0, 0, 0.55),
    0 0 18px rgba(210, 247, 107, 0.45);
}

/* Напарник «2 на 2» — свой: салатовый, но тише «Вы». */
.рассадка__место--напарник { color: rgba(210, 247, 107, 0.6); }

.рассадка__имя {
  position: absolute;
  top: calc(100% + 3px);
  left: 50%;
  translate: -50% 0;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
  color: var(--сб-акцент);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7);
}

/* ---------- Шаг 3: сводка и карточка тренировки ---------- */
.сводка,
.карточка-тренировки {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 72px;
  padding: 12px 16px;
}

.карточка-тренировки.скрыт { display: none; }

.сводка__значок,
.карточка-тренировки__значок {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  margin: 0 4px;
  color: #c9ced3;
}

.сводка__текст,
.карточка-тренировки__текст {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.сводка__главное {
  font-size: clamp(17px, 5vw, 20px);
  font-weight: 700;
  line-height: 1.2;
}

.карточка-тренировки__название {
  font-size: clamp(16px, 4.6vw, 18px);
  font-weight: 600;
  line-height: 1.2;
}

.сводка__подпись,
.карточка-тренировки__подпись {
  font-size: 14px;
  line-height: 1.3;
  color: var(--сб-текст-тихий);
}

/* ---------- «Далее» / «Начать игру» ----------
   Салатовая во всю ширину, «›» справа, как на эталоне. Прилипает к низу
   экрана: пока шаг прокручивается, кнопка остаётся под пальцем. Под ней
   и над ней — фон экрана (тени цвета фона), чтобы прокручиваемое
   не просвечивало вокруг кнопки.

   С 11 сентября на шагах «Игроки» и «Настройки» рядом с ней стоит
   видимая «Назад» (владелец: «не хватает кнопки вернуться в предыдущие
   настройки»), и обе лежат в строке «путь__кнопки-шага». Тогда к низу
   прилипает вся строка, а не одна кнопка, и фон под ней — у строки.
   Главная кнопка выглядит одинаково и одна, и в строке. */
.экран.путь > .кнопка.путь__далее,
.экран.путь > .путь__кнопки-шага {
  position: sticky;
  bottom: calc(12px + var(--отступ-снизу));
  z-index: 2;
  margin: auto 0 0;
}

.экран.путь > .кнопка.путь__далее,
.экран.путь > .путь__кнопки-шага > .кнопка.путь__далее {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-width: 0;
  max-width: 520px;
  min-height: 58px;
  padding: 0 56px;
  font-size: clamp(18px, 5.4vw, 22px);
  font-weight: 800;
  letter-spacing: 0;
  color: var(--сб-акцент-текст);
  background: var(--сб-акцент);
  border: none;
  border-radius: 20px;
  /* Две последние тени — цвета фона экрана: они закрывают прокручиваемое
     содержимое над кнопкой и под ней, чтобы оно не выглядывало из-за неё. */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    0 8px 22px rgba(210, 247, 107, 0.16),
    0 -16px 16px -4px var(--сб-фон),
    0 18px 0 0 var(--сб-фон);
}

/* Строка «Назад · Далее»: «Назад» по своим словам, главная забирает
   остаток. Фон строки — цвет экрана: в просвет между кнопками
   прокручиваемое не просвечивает. Тени цвета фона — у строки, у главной
   внутри неё — только свои (блик и салатовое свечение). */
.экран.путь > .путь__кнопки-шага {
  display: flex;
  align-items: stretch;
  gap: 10px;
  background: var(--сб-фон);
  border-radius: 20px;
  box-shadow:
    0 -16px 16px -4px var(--сб-фон),
    0 18px 0 0 var(--сб-фон);
}

/* Поля у главной в строке уже, чем у одиночной (56): иначе на 360
   «Начать игру» переносилась в две строки. Слева 30, справа 38 —
   под стрелку «›», которая здесь стоит ближе к краю (14 вместо 20).
   Так «Начать игру» в одну строку влезает и на 320. */
.экран.путь > .путь__кнопки-шага > .кнопка.путь__далее {
  position: relative;
  flex: 1 1 auto;
  width: auto;
  max-width: none;
  margin: 0;
  padding: 0 38px 0 30px;
  white-space: nowrap;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    0 8px 22px rgba(210, 247, 107, 0.16);
}

/* «Назад» — тихая плитка той же высоты и того же скругления, что
   главная, со стрелкой «‹» перед словом. Цвет — как у плиток шага
   (варианты, сводка): видно, что это кнопка, но рука тянется к салатовой. */
.экран.путь > .путь__кнопки-шага > .кнопка.кнопка--мелкая {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-width: 0;
  min-height: 58px;
  margin: 0;
  padding: 0 18px 0 12px;
  font-size: clamp(15px, 4.3vw, 17px);
  font-weight: 600;
  letter-spacing: 0;
  color: var(--сб-текст);
  background: var(--плитка);
  border: 1px solid var(--плитка-кромка);
  border-radius: 20px;
  box-shadow: none;
}

.экран.путь > .путь__кнопки-шага > .кнопка.кнопка--мелкая::before {
  content: "";
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  background-color: currentColor;
  -webkit-mask: var(--значок-назад) center / contain no-repeat;
  mask: var(--значок-назад) center / contain no-repeat;
}

.экран.путь > .путь__кнопки-шага > .кнопка.кнопка--мелкая:active {
  transform: translateY(1px);
  background: var(--плитка-нажата);
}

.экран.путь > .кнопка.путь__далее::after,
.экран.путь > .путь__кнопки-шага > .кнопка.путь__далее::after {
  content: "";
  position: absolute;
  right: 20px;
  top: 50%;
  width: 24px;
  height: 24px;
  margin-top: -12px;
  background-color: currentColor;
  -webkit-mask: var(--значок-вперёд) center / contain no-repeat;
  mask: var(--значок-вперёд) center / contain no-repeat;
}

/* В строке «Назад · Далее» стрелка ближе к краю — см. поля главной там. */
.экран.путь > .путь__кнопки-шага > .кнопка.путь__далее::after {
  right: 14px;
}

.экран.путь > .кнопка.путь__далее:active,
.экран.путь > .путь__кнопки-шага > .кнопка.путь__далее:active {
  transform: translateY(1px);
  filter: brightness(0.95);
}

/* ---------- Невысокое окно ----------
   Всё то же, только плотнее: заголовки и плитки ниже, стол рассадки
   меньше. Кнопки — не ниже 44 точек. */
@media (max-height: 700px) {
  #экран-лобби,
  .экран.путь { gap: 8px; }

  #экран-лобби > .лобби__заголовок { font-size: clamp(28px, 9vw, 38px); }
  .лобби__картинка { aspect-ratio: 2 / 1; }
  .карточка-профиля { min-height: 60px; padding-top: 8px; padding-bottom: 8px; }
  .карточка-профиля > .аватар { --аватар: 42px; }
  .карточка-входа { min-height: 60px; padding-top: 8px; padding-bottom: 8px; }
  .карточка-входа--друзья,
  .карточка-входа--вдвоём { min-height: 52px; }

  .путь__заголовок { font-size: clamp(24px, 7.6vw, 32px); }
  .путь__вопрос { margin-top: 4px; font-size: clamp(20px, 5.8vw, 24px); }
  .путь__раздел { margin-top: 2px; }
  .вариант { min-height: 84px; padding-top: 10px; padding-bottom: 10px; }
  .вариант__карты { --в: clamp(52px, 15vw, 60px); }
  .пример-перевода { padding: 12px 14px 10px; gap: 8px; }
  .пример-перевода__карты { --в: clamp(60px, 18vw, 74px); }
  .переключатель__вариант { min-height: 44px; }
  .числа__число { min-height: 46px; }
  .рассадка { --место: clamp(44px, 12.5vw, 50px); aspect-ratio: 2.4 / 1; }
  .сводка, .карточка-тренировки { min-height: 62px; padding-top: 10px; padding-bottom: 10px; }
  .экран.путь > .кнопка.путь__далее,
  .экран.путь > .путь__кнопки-шага > .кнопка.путь__далее,
  .экран.путь > .путь__кнопки-шага > .кнопка.кнопка--мелкая { min-height: 52px; }
}

/* =====================================================================
   РЕЙТИНГ ИГРОКОВ И «КАК Я ИГРАЮ» — В СИСТЕМЕ ЛОББИ
   (эталон/дурак-06-рейтинг)

   Оба экрана открываются вкладками лобби «Рейтинг» и «Профиль», а были
   зелёными. Теперь — как лобби: тёмный фон, крупный заголовок слева,
   «‹» наверху (это прежняя кнопка «Назад», см. правило «‹» выше).

   Главное число экрана — «12 место» у рейтинга и «Побед 53%» у «Как
   я играю» — лежит на сукне в деревянной раме, с кубком, как карточка
   «Ваше место» на эталоне. Если числа нет, в той же раме стоит честная
   фраза («Вас в таблице пока нет») и кубок серый — выдуманного места
   не бывает. Отдельных узлов под имя и очки в карточке у разметки пока
   нет — они видны в своей строке списка.

   Строки списка — тёмные плитки: место, аватар, имя, очки (под ними
   тихо — победы). Своя строка в салатовой рамке, у первой тройки —
   кружки цвета медалей (их даёт общее правило рейтинга выше).
   ===================================================================== */

:root {
  /* Кубок из набора (img/дурак/значки/trophy.svg), чаша залита — так он
     читается «наградой», а не пустым контуром. */
  --значок-кубок: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 2h12v7c0 8-12 8-12 0Z' fill='%23000'/%3E%3Cpath d='M6 4H2v3c0 4 3 5 5 5M18 4h4v3c0 4-3 5-5 5M12 15v5M7 22h10M9 20h6'/%3E%3C/svg%3E");
  /* Корона над первым местом подиума (план «Рейтинг по макету», заход 2,
     пункт 3) — своя маска-SVG, тем же приёмом, что кубок выше: три зубца
     на подставке, залитые (не контур), красится через background тем же
     золотым градиентом, что и кубок. Картинок-файлов проект не хранит —
     только этот data-uri. */
  --значок-корона: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 20' fill='none'%3E%3Cpath fill='%23000' d='M2 7.5 6 10l6-8 6 8 4-2.5-2.3 10.5H4.3L2 7.5Z'/%3E%3Crect fill='%23000' x='4' y='16.5' width='16' height='2.3' rx='1'/%3E%3C/svg%3E");
}

/* Фон — тёмный графит сборника: оба экрана строит js/рейтинг-экран.js
   и вставляет в «#приложение» на ВСЕХ страницах (шашки, шахматы, нарды
   тоже), и выглядят они везде одинаково. */
#экран-рейтинга-игроков,
#экран-рейтинга {
  --фон: var(--сб-фон);
  --панель: var(--сб-поверхность);
  --текст: var(--сб-текст);
  --текст-тихий: var(--сб-текст-тихий);
  --кнопка-фон: var(--сб-акцент);
  --кнопка-текст: var(--сб-акцент-текст);
  --акцент: var(--сб-акцент);
  --подложка: rgba(248, 245, 235, 0.06);
  --край: rgba(248, 245, 235, 0.14);
  --поле: clamp(12px, 3.6vw, 18px);
  --плитка: #1e2226;
  --плитка-кромка: rgba(248, 245, 235, 0.12);
  --дерево-свет: #9a6841;
  --дерево: #75492b;
  --дерево-тень: #4a2b17;

  align-items: center;
  /* Зазор между блоками тесноват нарочно: на телефоне 390×844 каждые
     две точки здесь — это часть строки списка лидеров внизу. */
  gap: 8px;
  padding: calc(6px + var(--отступ-сверху)) calc(var(--поле) + var(--отступ-справа))
           calc(12px + var(--отступ-снизу)) calc(var(--поле) + var(--отступ-слева));
  overflow-x: hidden;
  text-align: left;
  color: var(--сб-текст);
  background:
    radial-gradient(75% 120px at 50% 0, rgba(210, 247, 107, 0.07), rgba(210, 247, 107, 0) 100%),
    var(--сб-фон);
}

/* План «Рейтинг по макету», партия 6, шаг 1: страница рейтинга
   прокручивается ЦЕЛИКОМ, как лобби и витрина (тот же набор свойств,
   что у «#экран-лобби», строка 10143) — список внутри больше не носит
   свой скролл (ниже по файлу у «#рейтинг-таблица» он снят). Только
   «#экран-рейтинга-игроков»: «#экран-рейтинга» («Как я играю») живёт
   по старой модели, перевод — отдельная задача (план, раздел 3). */
#экран-рейтинга-игроков {
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
}

#экран-рейтинга-игроков::-webkit-scrollbar { display: none; }

/* ---------- Золотая палитра владельца (leaderboard_cloudcode_pack_v1) ----------
   Решение владельца: «Золото как в макете — пусть рейтинг выглядит
   особенным». Здесь общее правило сборника «один салатовый акцент»
   уступает золоту, но только на ЭТОМ экране — селектор нарочно один-
   единственный «#экран-рейтинга-игроков», без «#экран-рейтинга» рядом:
   «Как я играю» этих чисел не видит и не меняется.
   Числа — из prototype/styles.css макета: --bg/--surface/--gold/--muted.
   Фон самой страницы («--фон», тёмный графит) этот набор не трогает. */
#экран-рейтинга-игроков {
  --рейтинг-золото-поверхность: #141416; /* фон карточек и строк таблицы */
  /* Прежний #e1c27c был слишком светлым и разбавленным — на снимке 390×844
     числа очков читались почти как белые. Замер по самому макету владельца
     (durak_390x844.png, гистограмма пикселей чисел на подиуме) показал
     заметно более насыщенный и чуть более тёмный оттенок — здесь он и
     взят как новое единое значение. */
  --рейтинг-золото: var(--рейтинг-золото-общее);             /* сами золотые числа и подсветка своей строки */
  --рейтинг-золото-край: var(--рейтинг-золото-край-общее); /* золотые обводки — тот же тон, что и «--рейтинг-золото» */
  /* Тон золота один на весь сборник: сами числа объявлены на «#приложение»
     («--рейтинг-золото-общее» / «--рейтинг-золото-край-общее»), а этот
     экран и «.рейтинг-панель-игр» (шторка выбора игры) ниже по файлу
     лишь читают их отсюда — второй копии нет и поднимать нечего. */
  --рейтинг-золото-текст-тихий: #aaa9a7; /* приглушённый текст макета */
  --рейтинг-золото-текст-тёмный: #2b1f06; /* тёмный текст поверх золотой заливки (активные фильтры) */
  /* Три медальных градиента жили раньше литералами в двух местах
     (кружок места у строк и, теперь, кружок номера на подиуме) — вынесены
     сюда одной переменной на каждую медаль, план «Рейтинг по макету»,
     шаг «подиум 2-1-3»: поменялся тон медали — правка одна, а не две. */
  --рейтинг-медаль-1: linear-gradient(160deg, #ffdc73, #e0a516);
  --рейтинг-медаль-2: linear-gradient(160deg, #eef2f6, #b7c1cb);
  --рейтинг-медаль-3: linear-gradient(160deg, #eab989, #c07f45);
  /* Сплошные тона тех же медалей — для тонкого кольца вокруг аватара
     на подиуме: градиент на кольце в пару пикселей толщиной смотрится
     полосато, сплошной цвет там уместнее. */
  --рейтинг-серебро: #b7c1cb;
  --рейтинг-бронза: #c07f45;
  /* Стрелка движения места («↑ 12» / «↓ 5») рядом с очками в строке —
     план «движение места»: свои два цвета, приглушённый «—» берёт уже
     заведённый «--рейтинг-золото-текст-тихий» выше, третий не заводим. */
  --рейтинг-движение-вверх: #57c17b; /* место выросло */
  --рейтинг-движение-вниз: #e2645f; /* место упало */
  /* Высота нижней полосы вкладок — то же число, что у витрины и лобби
     (см. «--вт-панель-низ» там же), второй раз не выдумываем: полоса
     «Лобби · Рейтинг · Профиль» встаёт на этот экран тем же самым
     узлом (js/нижние-вкладки.js), с той же высотой. Набор «--вт-*»
     («.нижние-вкладки» их читает, а сами объявлены только на витрине,
     листе «Ещё» и лобби — у этого экрана своей копии не было вовсе,
     без неё вся полоса встаёт без фона и без цвета текста, «color:
     var(--вт-акцент)» у невалидной переменной откатывается в никуда).
     «--вт-акцент» — золото макета вместо салатового: активная вкладка
     «Рейтинг» здесь тоже золотая, как и остальные акценты экрана. */
  --вт-панель-низ: clamp(52px, 14.36vw, 64px);
  --вт-поверхность: var(--сб-поверхность);
  --вт-граница: var(--сб-граница);
  --вт-текст: var(--сб-текст);
  --вт-текст-тихий: var(--сб-текст-тихий);
  --вт-акцент: var(--рейтинг-золото);
  --вт-акцент-текст: var(--рейтинг-золото-текст-тёмный);
  /* Общий зазор для карточки «Моё место»: одна переменная читается и
     в «bottom» самой sticky-карточки, и в padding-bottom этого экрана
     (оба правила — ниже по файлу), чтобы отступ карточки от полосы
     вкладок и запас экрана под прокрутку всегда были одним и тем же
     числом, а не двумя случайно совпавшими магическими. */
  --рейтинг-моё-место-запас: 12px;
}

/* План «Рейтинг по макету», заход 2, пункт 6: базовый «.экран» задаёт
   снизу только 8px + отступ безопасной зоны — этого мало, когда поверх
   списка встаёт ещё и fixed-полоса вкладок: нижняя строка списка (или
   «моё место» под ним) пряталась под ней. Резерв — тот же приём, что
   у «#экран-лобби» (см. правило там). «:has(> .нижние-вкладки)» —
   на случай, если полоса почему-то не построилась (нет window.
   НижниеВкладки, см. «заполнитьНижниеВкладки»): без полосы лишний
   отступ снизу не нужен. */
/* Правка 26.09 (беда: 1280×1000, карточка «Моё место» при открытии
   наполовину под полосой). Раньше экран тянулся до низа окна, а полоса
   (position: fixed) лежала поверх его низа — всё, что по потоку попадало
   в эти 64 точки, пряталось под ней, при любой длине списка и высоте
   окна найдётся случай, когда туда попадает карточка. Теперь сама
   область прокрутки кончается над полосой («bottom» — ровно высота
   полосы, как в «.нижние-вкладки»): карточка либо видна целиком, либо
   обрезана краем прокрутки, как любая строка списка. Снизу внутри
   остаётся только запас «--рейтинг-моё-место-запас» — в конце прокрутки
   от низа карточки до полосы те же 12 точек, что и прежде. */
#экран-рейтинга-игроков:has(> .нижние-вкладки) {
  bottom: calc(var(--вт-панель-низ) + var(--отступ-снизу));
  padding-bottom: var(--рейтинг-моё-место-запас);
}

/* Возврат «css-Б2», находка смотрителя (беда 1, снимок 1280×800):
   «.нижние-вкладки» — тоже прямой потомок «#экран-рейтинга-игроков»
   и раньше сюда попадала наравне с заголовками и карточками. Её
   собственная разметка (правило «НИЖНЯЯ ПАНЕЛЬ ВКЛАДОК» в начале
   файла) держит кнопки в колонке 520 через ПОЛЯ (padding), а сама
   полоса должна залегать «left:0; right:0» во всю ширину окна — но
   «max-width» ниже (читает «--колонка-широкая», у рейтинга это 440,
   см. «@media (min-width: 700px)») сжимал КОРПУС полосы до 440px
   и прижимал его к левому краю (у «right» нет партнёра «margin:auto»,
   расти в исходное положение нечем). На 1280×800 фон полосы прикрывал
   только половину ширины экрана — «своя» строка списка (колонка по
   центру экрана, 420–860px) высовывалась из-под правого края этого
   обрезанного фона. У «#экран-лобби» то же самое правило чуть ниже
   по файлу уже исключает полосу («:not(.нижние-вкладки)») — здесь
   исключения не было, теперь есть. */
:is(#экран-рейтинга-игроков, #экран-рейтинга) > :not(:is(#кнопка-рейтинг-игроков-назад, #кнопка-рейтинг-назад, .нижние-вкладки)) {
  box-sizing: border-box;
  width: 100%;
  /* Экран сам стал прокручивающимся flex-контейнером (шаг 1) — без
     этого дети сжимались бы, чтобы влезть в окно, как раньше. */
  flex-shrink: 0;
  /* Была литералом 520px — теперь читает общую переменную сборника
     («--колонка-широкая», объявлена в широком медиазапросе ниже по
     файлу), с тем же числом как запасной вариант на телефоне, где
     переменной ещё нет. План «Рейтинг по макету», заход 2, раздел 3:
     на ПК у «#экран-рейтинга-игроков» переменная переопределена на
     телефонную ширину макета — см. правило внутри
     «@media (min-width: 700px) and (min-height: 600px)». */
  max-width: min(100%, var(--колонка-широкая, 520px));
}

/* Только «Как я играю» («#экран-рейтинга») — у «#экран-рейтинга-игроков»
   заголовок теперь внутри «.рейтинг-шапка» (см. блок «ШАПКА-КАРТОЧКА»
   ниже) и больше не прямой потомок экрана, это правило его не находит,
   плана «Рейтинг по макету», заход 2, пункт 4: «никакого clamp до 42px». */
#экран-рейтинга > .заголовок {
  margin: 0;
  text-align: left;
  font-size: clamp(30px, 9.6vw, 42px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.025em;
  color: var(--сб-текст);
}

html.в-телеграме :is(#экран-рейтинга-игроков, #экран-рейтинга) > :is(.заголовок, .рейтинг-шапка) { margin-top: 4px; }

/* =====================================================================
   ШАПКА-КАРТОЧКА «‹ Общий рейтинг (i)» — план «Рейтинг по макету»,
   заход 2, пункт 4. Разметку строит js/рейтинг-экран.js
   («убедитьсяЧтоЕстьШапка»): оборачивает существующий «h2.заголовок»
   в «.рейтинг-шапка» и кладёт рядом круглую кнопку «#кнопка-рейтинг-
   инфо» — тот же обработчик, что у «Как считается» внизу списка.
   Стрелку «‹» внутри шапки рисует та же общая кнопка «Назад», что
   раньше стояла внизу экрана (id «#кнопка-рейтинг-игроков-назад» не
   поменялся, его тем же приёмом переносит «убедитьсяЧтоЕстьШапка») —
   кнопка одна и та же на всех четырёх страницах (index.html, шашки,
   шахматы, нарды), а «#экран-витрины» есть только на первой из них,
   поэтому в блоке «"‹" — прежняя кнопка «Назад», перенесённая в угол»
   (чуть выше по файлу) у неё свой безусловный селектор по id, отдельно
   от условия про витрину — им же в Telegram её и прячет display:none,
   там работает системная стрелка. */
/* Сетка вместо ленты («display:flex; justify-content:space-between»):
   в Telegram кнопка «‹» слева уходит в display:none (см. правило чуть
   выше по файлу), а у ленты из двух оставшихся элементов заголовок
   съезжал влево — «space-between» не резервирует место под пропавшего
   соседа. Три ЯВНЫХ колонки одинаковой ширины по бокам держат место
   под кнопки, даже когда левой из них в разметке нет вовсе: заголовок
   всегда стоит во второй колонке и по-настоящему центрирован. Ширина
   боковых колонок — 44px, тот же размер, что у самих кнопок «‹» и «i»
   (зона нажатия сборника), так что они заполняют колонку без люфта. */
#экран-рейтинга-игроков > .рейтинг-шапка {
  display: grid;
  grid-template-columns: 44px 1fr 44px;
  align-items: center;
  gap: 10px;
  min-height: 64px;
}

.рейтинг-шапка__название {
  margin: 0;
  grid-column: 2;
  min-width: 0;
  /* В макете заголовок стоит слева у стрелки «‹», «i» — справа отдельно
     (владелец, снимок ПК ≈1900×1070). Центр был к месту, пока «i» была
     рядом с заголовком — теперь между ними весь просвет колонки. */
  text-align: left;
  font-size: 22px;
  font-weight: 700;
  /* План «рейтинг по макету», п. 1: у макета строка заголовка ниже
     (высота 25 при 22px), было 1.2 — держало лишний воздух сверху и снизу. */
  line-height: 1.12;
  letter-spacing: -0.01em;
  color: var(--сб-текст);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* «‹» внутри шапки — тот же общий узел, что и у других экранов (правила,
   рекорды, оформление): позиция, зона нажатия и SVG-стрелка приходят
   оттуда по id. Здесь только то, что общее правило не могло знать
   заранее: оно тянуло отрицательные верхние и нижние поля и «align-self:
   flex-start» под СТОЛБЕЦ (кнопка была прямым потомком экрана), а шапка —
   своя горизонтальная СТРОКА («display: flex», без direction — значит
   row). Без сброса кнопка прижималась бы к верху шапки мимо центра,
   где стоят название и «i». Селектор с id — нарочно, чтобы точно
   перебить того, у общего правила тоже есть id в списке «:is(...)». */
#экран-рейтинга-игроков > .рейтинг-шапка > #кнопка-рейтинг-игроков-назад.рейтинг-шапка__назад {
  grid-column: 1;
  align-self: center;
  margin-top: 0;
  margin-bottom: 0;
}

/* Кнопка «i» — раньше делила общий класс «.кнопка» (кнопки сборника),
   у которого «min-width: 116px; min-height: 46px» побеждают явную ширину
   и высоту здесь: круг растягивался в золотую овальную капсулу вместо
   тонкого контурного кружка. Свой класс вместо «.кнопка» — джаваскрипт
   больше не вешает общий класс на эту кнопку (js/рейтинг-экран.js,
   «убедитьсяЧтоЕстьШапка»), и переопределять чужой min-width не нужно.

   Зона нажатия — честные 44 точки (правило сборника), но САМ кружок
   заметно меньше (32–34px по макету владельца) и без жёлтой заливки:
   тонкая золотая обводка, буква «i» внутри, почти прозрачный фон. Видимый
   круг рисует «::before» — тем же приёмом (position:absolute; inset:0;
   margin:auto), каким выше нарисована стрелка «‹» внутри своей 44-точечной
   зоны нажатия; буква «i» — настоящий текст кнопки, стоит поверх круга
   в потоке (он в pointer-events не нуждается, а раз он не позиционирован —
   на месте псевдоэлемента, добавленного ПЕРЕД ним, буква рисуется позже
   и остаётся видна). */
.рейтинг-шапка__инфо {
  grid-column: 3;
  position: relative;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  font-size: 14px;
  font-weight: 800;
  font-style: italic;
  font-family: Georgia, "Times New Roman", serif;
  color: var(--рейтинг-золото);
  background: none;
  border: none;
  border-radius: 50%;
  box-shadow: none;
}

.рейтинг-шапка__инфо::before {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 33px;
  height: 33px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--рейтинг-золото) 14%, transparent);
  border: 1px solid var(--рейтинг-золото-край);
}

.рейтинг-шапка__инфо:active::before { background: color-mix(in srgb, var(--рейтинг-золото) 26%, transparent); }

/* «‹» у «Как я играю» не должен съезжать, когда внизу видна кнопка
   «Стереть счёт»: прежнее правило экрана обнуляло ей верхнее поле. */
#приложение #экран-рейтинга:has(#кнопка-стереть-счёт) > #кнопка-рейтинг-назад.кнопка {
  margin-top: -4px;
}

/* ---------- Главное число — на сукне в раме, с кубком ----------
   Только «#рейтинг-главное» («Как я играю»): у «#рейтинг-моё-место»
   план «Рейтинг по макету», партия 6, шаг 5 снимает сукно, раму и
   кубок целиком — по золотому макету карточка плоская (см. блок
   «Карточка «Моё место»» ниже). */
#рейтинг-главное {
  --сукно-свет: #6e181c;
  --сукно: #4f0d10;
  --сукно-тень: #2a0507;
  --рама: clamp(7px, 2.3vw, 11px);
  position: relative;
  display: flex;
  align-items: center;
  gap: 16px;
  min-height: 96px;
  margin: 4px 0 0;
  padding: 14px 20px 14px 16px;
  font-size: clamp(26px, 8vw, 34px);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.01em;
  text-align: left;
  text-wrap: balance;
  font-variant-numeric: tabular-nums;
  color: #f8f1e4;
  text-shadow: 0 2px 6px rgba(0, 0, 0, 0.55);
  border: var(--рама) solid transparent;
  border-radius: calc(var(--рама) + 16px);
  background:
    var(--текстура-зерно) padding-box,
    radial-gradient(120% 95% at 50% 38%, var(--сукно-свет) 0%, var(--сукно) 52%, var(--сукно-тень) 100%) padding-box,
    var(--текстура-волокна) border-box,
    linear-gradient(180deg, var(--дерево-свет) 0%, var(--дерево) 40%, var(--дерево-тень) 100%) border-box;
  background-size: 160px 160px, auto, 240px 60px, auto;
  background-repeat: repeat, no-repeat, repeat, no-repeat;
  background-blend-mode: soft-light, normal, soft-light, normal;
  box-shadow:
    inset 0 0 0 1px rgba(0, 0, 0, 0.55),
    inset 0 10px 26px rgba(0, 0, 0, 0.50),
    inset 0 -8px 20px rgba(0, 0, 0, 0.35),
    0 0 0 1px rgba(0, 0, 0, 0.60),
    0 14px 30px rgba(0, 0, 0, 0.55);
}

/* Кубок — золотой, как медаль первого места в списке. Только у
   «#рейтинг-главное» — «#рейтинг-моё-место» кубок больше не рисует. */
#рейтинг-главное::before {
  content: "";
  flex: 0 0 auto;
  width: clamp(44px, 13vw, 56px);
  height: clamp(44px, 13vw, 56px);
  background: linear-gradient(160deg, #ffe08a 0%, #f0bd3a 45%, #c98d12 100%);
  -webkit-mask: var(--значок-кубок) center / contain no-repeat;
  mask: var(--значок-кубок) center / contain no-repeat;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.55));
}

/* Фаска рамы — как у стола. Только у «#рейтинг-главное». */
#рейтинг-главное::after {
  content: "";
  position: absolute;
  inset: calc(-1 * var(--рама));
  border-radius: inherit;
  pointer-events: none;
  box-shadow:
    inset 0 1.5px 0 rgba(255, 222, 184, 0.34),
    inset 0 -1.5px 0 rgba(0, 0, 0, 0.45),
    inset 1px 0 0 rgba(255, 222, 184, 0.10),
    inset -1px 0 0 rgba(0, 0, 0, 0.25);
}

/* ---------- Карточка «Моё место» — плоский золотой макет ----------
   План «Рейтинг по макету», партия 6, шаг 5. Карточка теперь стоит
   всегда (кнопка-переключатель «соседи ↔ в начало списка» внутри,
   js/рейтинг-экран.js), приклеена к низу экрана над полосой вкладок
   (сам экран прокручивается целиком — шаг 1), поэтому «position:
   sticky», а не обычный поток. Числа — «.my-card» (prototype/
   styles.css:78): рамка 1px, радиус 15, поля 8/12/10. «order: 1»
   ставит карточку последней среди прямых детей экрана (у остальных
   order по умолчанию 0) — так она остаётся внизу, даже если сама
   короче списка над ней. */
#экран-рейтинга-игроков > #рейтинг-моё-место {
  order: 1;
  position: sticky;
  /* Проверено замером (getBoundingClientRect, оба размера экрана, оба
     конца прокрутки) 23.09: «bottom: 0» — единственное значение, при
     котором низ карточки не заходит под полосу вкладок И низ последней
     строки таблицы не заходит под карточку одновременно. Попытка снова
     прибавить сюда «--вт-панель-низ» (чтобы карточка «отлипала» раньше
     и меньше перекрывала строки над собой при scrollTop=0 — так экран
     смотрится на первый взгляд, до прокрутки) проверкой отклонена:
     bottom и padding-bottom экрана (правило «#экран-рейтинга-игроков:
     has(> .нижние-вкладки)» выше по файлу) считаются от одного и того
     же padding-box, поэтому лишняя «--вт-панель-низ» в bottom подрезает
     низ последней строки при прокрутке до конца — 78/0 превращается
     в 78/2 (числа и вывод — в отчёте штабу). Наезд карточки на строки
     ВЫШЕ неё при scrollTop=0 — не это правило: карточка «position:
     sticky» ничего не убирает из потока, строки над ней как шли, так
     и идут, а не «уступают» приклеенной карточке место; лечится не
     числом здесь, а другим приёмом (обсудить со штабом отдельно). */
  bottom: 0;
  z-index: 4;
  display: block;
  text-align: left;
  /* Поля обнуляем целиком, а не только сверху: карточка — это <p>
     (index.html), и без класса «.подпись» ей достаётся браузерное
     «margin: 1em 0» — под приклеенной к низу карточкой оставалось
     16 лишних точек пустоты.
     Верхнее поле — «auto», не число. Жалоба владельца 25.09: при
     коротком списке (мало игроков) скроллить нечего, sticky ничего
     не двигает, и карточка вставала сразу за «Все игроки показаны»,
     оставляя пустоту до полосы вкладок. Экран — flex-колонка на всю
     высоту окна («.экран» в начале файла), и «margin-top: auto» у
     последней по потоку карточки забирает весь свободный остаток
     колонки, подтягивая её к низу без магических чисел. При длинном
     списке свободного места нет — авто-поле само схлопывается в 0,
     и дальше карточку держит прежний sticky «bottom: 0» (числа тех
     замеров завязаны на «margin-bottom», у него он 0 и здесь, и там —
     не меняется). У «.подпись» ниже своё «margin-top», прежний поток
     фразы этим не трогаем. */
  margin: auto 0 0;
  padding: 8px 12px 10px;
  /* План «рейтинг по макету», п. 22: фон и рамка — числа именно карточки
     «Моё место» (prototype/styles.css: «.my-card»), не общая переменная
     «--рейтинг-золото-поверхность»/«--рейтинг-золото-край» — той же
     переменной красится плашка серии (её 45%-рамку трогать нельзя,
     решение штаба, п. 0.2) и другие узлы рейтинга. */
  background: linear-gradient(120deg, #171711, #0c0c0d);
  border: 1px solid #d8ba74;
  border-radius: 15px;
  box-shadow: none;
}

/* Прежняя кнопка «Назад» внизу экрана (её «убедитьсяЧтоЕстьШапка»
   обычно переносит в шапку как «‹») — на случай, если она всё же
   останется прямым потомком экрана, идёт следом за карточкой. */
#экран-рейтинга-игроков > #кнопка-рейтинг-игроков-назад {
  order: 2;
}

/* Между низом карточки (sticky, «bottom: 0» — см. длинную заметку выше)
   и полосой вкладок остаётся зазор ровно «--рейтинг-моё-место-запас»
   (12px, тот же резерв, что и в padding-bottom экрана, «#экран-рейтинга-
   игроков:has(> .нижние-вкладки)» выше по файлу). В макете этот зазор
   есть и должен быть плоским фоном страницы — у нас в нём при прокрутке
   видны обрывки строк таблицы (карточка sticky ничего не закрывает
   ниже своего собственного низа, строки под ней как шли, так и идут).
   Уточнение смотрителя 23.09 (сверка с 03_durak.png): зазор не убирать,
   а закрыть подложкой того же фона, что у самого экрана — «::after»
   сразу под карточкой («top: 100%» её собственного бокса), во всю её
   ширину, той же высоты, что и запас. «--сб-фон» без радиального
   свечения сверху экрана — оно гаснет уже на первых 120px и досюда,
   в самый низ списка, не достаёт. */
#экран-рейтинга-игроков > #рейтинг-моё-место::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  height: var(--рейтинг-моё-место-запас, 12px);
  background: var(--сб-фон);
  z-index: 4;
  pointer-events: none;
}

/* Недочёт «Е» (смотритель, снимок 23.09): карточка «Моё место» —
   sticky с «bottom: 0» (заметка выше) — приклеивается уже при
   scrollTop=0, если список длиннее экрана, и её верхний край может
   разрезать строку таблицы пополам: видна половина текста, обрыв
   выглядит как поломка вёрстки. Число здесь не лечит (см. заметку
   у «bottom: 0» — подвинуть карточку выше ценой другой, уже
   проверенной строки нельзя).

   Партия css-В, пункт 8: три захода подряд («height: 32px», «64px»,
   «16px») пытались решить это ОДНИМ сплошным градиентом на всю высоту
   зоны — и каждый раз мимо. Короткий градиент (16px) короче настоящего
   зазора между текстом и карточкой (13,5px на 1280, но 18,8px на 390) —
   на 390 верхние 2–3px букв остаются СНАРУЖИ зоны, совсем без затухания,
   и торчат резким обрывком прямо над рамкой карточки (ровно то, что
   увидел смотритель — обрывок «760»). Длинный градиент (64px), наоборот,
   красит и пустой зазор НАД текстом: буквы рождаются в кадре уже на
   70–79% пути к прозрачности — тусклым пятном, а не чёткой строкой,
   и это тоже читается как обрыв, просто более плавный.

   Смена приёма (вместо третьей попытки угадать число): тот же принцип,
   что у «.my-dock» в прототипе (prototype/styles.css:77) — сплошная
   подложка на высоту примерно одной строки таблицы («--рейтинг-строка»
   ≈ 53px, с запасом), и короткий градиент только у ДАЛЬНЕГО от карточки
   края этой подложки, а не по всей её высоте. Сплошной участок (нижние
   ~36px, ближе к карточке) гарантированно перекрывает весь известный
   зазор текст-карточка на обоих размерах (макс. 18,8px) — буква там
   не видна ни на 1%, ни на 100%, никакого частично-прозрачного обрывка
   в принципе не бывает. Короткий градиент (верхние ~20px, дальше от
   карточки) гасит только пустоту НАД текстом строки — там, по замеру,
   текста уже нет, поэтому «тусклое пятно вместо чёткой строки» тоже
   не возникает: снаружи от подложки строка стоит как обычно, чёткой,
   вплоть до момента, когда сама уходит под сплошной участок. */
#экран-рейтинга-игроков > #рейтинг-моё-место::before {
  content: "";
  position: absolute;
  bottom: 100%;
  left: 0;
  right: 0;
  height: 56px;
  background: linear-gradient(to bottom, transparent, var(--сб-фон) 20px, var(--сб-фон) 100%);
  z-index: 4;
  pointer-events: none;
}

/* Числа нет — в карточке честная фраза обычным кеглем (кубка тоже
   больше нет, см. блок выше). */
#экран-рейтинга-игроков > #рейтинг-моё-место.подпись {
  font-size: clamp(15px, 4.3vw, 17px);
  font-weight: 600;
  line-height: 1.35;
}

/* Добавки штаба «Б» и «В» — общая причина (нашла сверка с макетом,
   tests/сверка-рейтинга-с-макетом.js): у состояния «просто фраза, своего
   места нет» (класс «.подпись» — рейтинг ещё пуст, беда связи, сила ещё
   не измерена, «Вас в таблице пока нет» и т.п.) узел всё равно остаётся
   базовым «#рейтинг-моё-место» — «position: sticky; bottom: 0», золотая
   рамка-подложка карточки и градиент-затухание «::before» (правила выше,
   рассчитаны на карточку С ОЧКАМИ: гасить строку таблицы, уезжающую под
   приклеенную снизу карточку). У голой фразы нет ни своего места, ни
   строки таблицы под ней, которую нужно было бы гасить, — а sticky всё
   равно прижимает её к низу экрана. На коротком окне (860×610, пустой
   рейтинг шахмат) это кладёт фразу прямо на нижние вкладки, а на подиуме
   из двух игроков без личного места (1680×920) тот же градиент «::before»
   красит уже не строку, а низ карточек подиума — снаружи выглядит так,
   будто очки обрезаны, хотя на деле их просто закрашивает затухание
   сверху вниз (числа сверки — style.css ниже не режет, красит).
   По макету пустое состояние — просто «Пока нет результатов» по центру,
   без карточки «Моё место» вовсе: убираем и sticky, и золотую подложку,
   и оба псевдоэлемента — фраза идёт обычным потоком, без затухания. */
#экран-рейтинга-игроков > #рейтинг-моё-место.подпись {
  position: static;
  order: 0;
  /* Без карточки фраза остаётся обычным потоком, а не «margin-top:
     auto» базового правила выше (оно утащило бы её к низу экрана,
     съев весь свободный остаток колонки) — возвращаем прежнее
     верхнее поле карточки числом. */
  margin-top: 2px;
  background: none;
  border: none;
  box-shadow: none;
  border-radius: 0;
}

#экран-рейтинга-игроков > #рейтинг-моё-место.подпись::before,
#экран-рейтинга-игроков > #рейтинг-моё-место.подпись::after {
  content: none;
}

/* Ярлык «Моё место» / «Моё место среди друзей» — по золотому макету
   («.my-eyebrow», prototype/styles.css:79): растянут на всю ширину
   карточки над содержимым (grid-column: 1 / -1 у сетки кнопки ниже),
   мелкий, прописными буквами через CSS. */
#рейтинг-моё-место .рейтинг__карточка-подпись {
  display: block;
  grid-column: 1 / -1;
  max-width: 100%;
  margin: 0 0 5px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--рейтинг-золото);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Кнопка-карточка целиком (клик = «соседи по месту» / подиум,
   js/рейтинг-экран.js). Внутренности — сетка «.my-content»
   (prototype/styles.css:80): место, аватар+имя, очки и движение места
   в одну строку; подпись выше занимает её целиком. Сброс вида кнопки —
   она не должна читаться как кнопка браузера, кликабельна вся карточка.

   У новичка кнопки нет (жать некуда, своей строки в списке ещё нет),
   и то же самое содержимое лежит в «span.рейтинг__карточка-содержимое» —
   сетка у обоих узлов одна и та же, поэтому и правило одно.

   Колонки. В макете четыре ячейки: место, «игрок» (аватар и имя одним
   узлом), очки, стрелка. У нас узлов тоже четыре, но делятся они иначе:
   место, кружок аватара, имя, очки (стрелка лежит внутри очков). Тянется
   та колонка, где имя, — остальные по содержимому: иначе многоточие
   в длинном имени не сработало бы, а растягивался бы кружок аватара. */
#кнопка-рейтинг-моё-место,
#рейтинг-моё-место > .рейтинг__карточка-содержимое {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  width: 100%;
  margin: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  background: none;
  border: none;
  box-shadow: none;
}

/* У новичка кружка аватара нет вовсе (имени нет — нет и инициалов,
   «узелИнициалов» в js возвращает ничего), поэтому колонок три, а не
   четыре: иначе между местом и приглашением сыграть висела бы пустая
   колонка с двумя зазорами. */
#рейтинг-моё-место.рейтинг__карточка--новичок > .рейтинг__карточка-содержимое {
  grid-template-columns: auto minmax(0, 1fr) auto;
}

/* ---------- Ячейки внутри карточки «Моё место» ----------
   Ячейки списка («.рейтинг-место», «.рейтинг-имя» и прочие) оформлены
   только под предком «#рейтинг-таблица» — внутри карточки они остались
   бы голыми. Здесь свои правила по числам макета («.my-content …»,
   prototype/styles.css:80–83). */

/* Номер места — «.my-content .rank-number» (prototype:81): 21px,
   золотой. Тон золота у нас один на весь сборник (переменная), число
   макета #edcf87 второй копией не заводим. Цифры моноширинные, чтобы
   карточка не дёргалась при смене 9 → 10. */
#рейтинг-моё-место .рейтинг__карточка-место {
  font-size: 21px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  color: var(--рейтинг-золото);
}

/* Кружок с инициалами — «.my-content .row-player .avatar» (prototype:82):
   34 точки (в списке 35), тонкое кольцо и градиент — общие числа аватара
   макета (prototype:47, 70). Золотого кольца, как у своей строки списка,
   здесь нет: в карточке и так всё про меня, второй пометки не нужно. */
#рейтинг-моё-место .рейтинг-аватар__инициалы {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 1px solid #8f8266;
  border-radius: 50%;
  background: linear-gradient(135deg, #574e39, #272522);
  color: #e6cc8c;
  font-size: 12px;
  font-weight: 650;
  overflow: hidden;
}

/* Настоящее фото поверх инициалов. Класс «рейтинг-строка--фото» и адрес
   в «--фото-аватара» кладёт «поставитьФото» из js/рейтинг-экран.js — но
   не на карточку, а на её внутренний узел (кнопку или «содержимое»),
   поэтому предок в селекторе именно он. Буквы прячем прозрачным цветом,
   а не «display: none» у узла: узел и есть кружок, на котором лежит фото. */
#рейтинг-моё-место .рейтинг-строка--фото .рейтинг-аватар__инициалы {
  color: transparent;
  background-color: transparent;
  background-image: var(--фото-аватара);
  background-position: center;
  background-size: cover;
}

/* Имя — «.my-content .player-name» (prototype:83, 71): 14px, длинное
   обрезается многоточием, а не растягивает карточку. Насыщенность 600 —
   как у имён в списке; в макете веса у этой строки нет вовсе. */
#рейтинг-моё-место .рейтинг__карточка-имя {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
  font-size: 14px;
  font-weight: 600;
}

/* У новичка в этой же ячейке лежит не имя, а приглашение сыграть —
   его обрезать многоточием нельзя, оно должно переноситься. Флекс-строку
   базового правила тоже возвращаем в блок: подсказка — обычный текст,
   ему нужен перенос по словам, а не строка в ряд с пустым «__текст». */
#рейтинг-моё-место.рейтинг__карточка--новичок .рейтинг__карточка-имя {
  display: block;
  white-space: normal;
  overflow: visible;
}

#рейтинг-моё-место .рейтинг-новичок-подсказка {
  display: block;
  font-size: 12px;
  line-height: 1.35;
  color: var(--сб-текст-тихий);
}

/* Пилюля «Вы» рядом с именем — «.you-pill» макета (prototype:84):
   10px, поля 3/6, скругление 20, золотой текст на полупрозрачном
   золоте. В списке пилюля своя (заливка сплошным золотом) — там она
   отличает одну строку из многих, здесь отличать не от кого. */
#рейтинг-моё-место .рейтинг-имя__вы {
  display: inline-block;
  padding: 3px 6px;
  border-radius: 20px;
  font-size: 10px;
  font-weight: 700;
  white-space: nowrap;
  color: var(--рейтинг-золото);
  background: color-mix(in srgb, var(--рейтинг-золото) 19%, transparent);
  /* Раньше пилюля лежала ВНУТРИ того же обрезаемого узла, что и текст
     имени, и на длинном имени уезжала вместе с ним за край — чинили
     через «position: sticky». Теперь текст и пилюля — родные соседи
     (span'ы «__текст» и «__вы» внутри флекс-строки «.рейтинг__карточка-
     -имя», см. правило выше): ужимается и обрезается только «__текст»,
     пилюля с «flex-shrink: 0» стоит рядом всегда целиком, sticky не
     нужен вовсе. */
  flex-shrink: 0;
}

/* Очки — правый край карточки. В макете это две соседние ячейки сетки
   («.score» и «.delta», prototype:72–73), у нас стрелка движения лежит
   ВНУТРИ ячейки очков (так же, как в строке списка) — поэтому здесь
   не колонка сетки, а строчка из числа и стрелки, прижатая вправо. */
#рейтинг-моё-место .рейтинг__карточка-очки {
  justify-self: end;
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  white-space: nowrap;
}

#рейтинг-моё-место .рейтинг__карточка-очки-число {
  font-size: 16px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  /* Решение штаба 23.09: светлые, как в макете (prototype/styles.css,
     «.my-content .score» — своего цвета там нет, золотыми сделаны
     только «.my-eyebrow» и «.rank-number») и как числа очков в списке
     после правки п.13 (var(--сб-текст)) — оба места читаются одинаково. */
  color: var(--сб-текст);
}

/* Стрелка движения места — те же числа и цвета, что в списке
   («.delta», prototype:73): мелкая подпись, не переносится. */
#рейтинг-моё-место .рейтинг-движение {
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

#рейтинг-моё-место .рейтинг-движение--вверх { color: var(--рейтинг-движение-вверх); }
#рейтинг-моё-место .рейтинг-движение--вниз { color: var(--рейтинг-движение-вниз); }
#рейтинг-моё-место .рейтинг-движение--нет { color: var(--рейтинг-золото-текст-тихий); }

/* «Пока ни одной партии», «Минутку…» у «Как я играю» — тоже без золота. */
#экран-рейтинга:not(:has(.таблица__строка)) > #рейтинг-главное {
  font-size: clamp(20px, 6vw, 26px);
}

#экран-рейтинга:not(:has(.таблица__строка)) > #рейтинг-главное::before {
  background: rgba(248, 241, 228, 0.35);
}

/* Строка словами под главным числом — серым, слева. */
#экран-рейтинга > #рейтинг-подпись {
  max-width: 520px;
  margin: 0;
  font-size: 14px;
  line-height: 1.4;
  text-align: left;
  color: var(--сб-текст-тихий);
}

#экран-рейтинга > #рейтинг-динамика {
  justify-content: flex-start;
  max-width: 520px;
  margin: 0;
}

#экран-рейтинга .рейтинг__окно {
  padding: 5px 12px 6px;
  background: var(--плитка);
  box-shadow: inset 0 0 0 1px var(--плитка-кромка);
}

#экран-рейтинга .рейтинг__окно.рейтинг__окно--лучше {
  box-shadow: inset 0 0 0 1.5px var(--сб-акцент);
}

/* Серия дней — пилюля по центру колонки (макет владельца на ПК, окно
   ≈1900×1070): раньше стояла слева и на широком окне прилипала к краю.
   Селектор нарочно берёт ДВА id (у узла есть и «#серия-дней», не только
   класс) — тот же приём, что уже решает такой же спор у стрелки «‹»
   в шапке (см. правило «...> #кнопка-рейтинг-игроков-назад.рейтинг-шапка__назад»
   чуть выше по файлу): общее правило колонки экрана (≈11542) весит два
   id («:is(#экран-рейтинга-игроков, ...)» + «:not(:is(#id, #id, .класс))»)
   и без своего второго id просто перебивало бы «width: auto», сажая
   пилюлю на всю ширину колонки. */
#экран-рейтинга-игроков > #серия-дней.серия-дней {
  align-self: center;
  width: auto;
}

/* Добавка штаба «А»: на экране рейтинга плашка серии красится в
   золото рейтинга, как карточка «Моё место» (тёмная подложка + золотая
   рамка), а не в общий салатовый акцент сборника. Общий «.серия-дней»
   красит рамку и звезду через «--акцент», а на этом экране «--акцент»
   переопределён в «#экран-рейтинга-игроков» (см. блок выше по файлу)
   на «var(--сб-акцент)» — тот самый салатовый. Сам текст плашки уже
   светлый (общий класс читает «--текст», здесь это «--сб-текст»),
   трогаем только рамку, подложку и звезду — id экрана держит правило
   в границах этого экрана, лобби и другие страницы с общим «.серия-дней»
   не видит. */
#экран-рейтинга-игроков > #серия-дней.серия-дней {
  background: var(--рейтинг-золото-поверхность);
  border-color: var(--рейтинг-золото-край);
}

#экран-рейтинга-игроков > #серия-дней.серия-дней::before {
  color: var(--рейтинг-золото);
}

/* Тёплый вариант «вчера играли, сегодня ещё нет» (класс добавляет
   js/game.js, «освежитьСериюДней») — тем же приёмом: подложка теплее
   золотом, а не общим акцентом сборника. */
#экран-рейтинга-игроков > #серия-дней.серия-дней.серия-дней--вчера {
  background: color-mix(in srgb, var(--рейтинг-золото) 22%, var(--рейтинг-золото-поверхность));
}

/* ---------- Выбор игры и меры — сегментами, как фильтры эталона ----------
   Этих двух панелей на макете владельца нет, но выбрать игру и меру
   где-то надо. Поэтому они нарочно сделаны низкими и негромкими: раньше
   вдвоём съедали около 120 точек, и пятёрка лидеров не помещалась на
   экран телефона. Теперь каждая — тонкая полоска примерно в 40 точек,
   а палец всё равно попадает: невидимая подушка вокруг кнопки
   (правило «::after» ниже) доводит зону нажатия до 44 точек.

   Без «>» нарочно (партия 6, пункт 8.1): переключатель меры
   («#рейтинг-выбор-меры.рейтинг-меры») js переносит внутрь обёртки
   «.рейтинг-настройки-среза» под кнопку «Фильтры» — прямым потомком
   экрана он быть перестаёт, и правило с «>» перестало бы его находить
   (полоска осталась бы без подложки и рамки). */
#экран-рейтинга-игроков :is(.рейтинг-выбор, .рейтинг-меры) {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 3px;
  padding: 3px;
  background: var(--плитка);
  border: 1px solid var(--плитка-кромка);
  border-radius: 14px;
}

/* Выбор игры плиткой больше не обведён (партия 5, пункт 1): внутри него
   теперь одна кнопка-селектор макета со своей рамкой и своим фоном,
   а серая подложка вокруг неё давала вторую рамку вокруг первой. У меры
   («Сила игры | Очки за победы») подложка остаётся — там пара кнопок,
   и полоса показывает, что это один переключатель. */
#экран-рейтинга-игроков > .рейтинг-выбор {
  gap: 0;
  padding: 0;
  background: none;
  border: none;
  border-radius: 0;
}

/* Вторая панель прижата к первой: это один смысловой блок «что смотрим». */
#экран-рейтинга-игроков > .рейтинг-меры { margin-top: -4px; }

#экран-рейтинга-игроков :is(.рейтинг-выбор, .рейтинг-меры) .кнопка.кнопка--выбор {
  position: relative;
  min-width: 0;
  min-height: 34px;
  padding: 4px 6px;
  font-size: clamp(13px, 3.7vw, 14.5px);
  font-weight: 600;
  letter-spacing: 0;
  color: var(--сб-текст);
  background: none;
  border: none;
  border-radius: 11px;
  box-shadow: none;
}

/* Подушка для пальца: кнопка нарисована низкой, а нажимается на 44 точки
   по высоте — за счёт прозрачного слоя, выступающего сверху и снизу.
   Полоски стоят в 6 точках друг от друга, поэтому подушки соседей
   не пересекаются и промахнуться мимо своей кнопки нельзя. */
#экран-рейтинга-игроков :is(.рейтинг-выбор, .рейтинг-меры) .кнопка.кнопка--выбор::after {
  content: "";
  position: absolute;
  inset: -5px 0;
}

/* Решение штаба: на ЭТОМ экране активная кнопка меры («Сила игры» /
   «Очки за победы») — золотая с тёмным текстом, как в макете владельца,
   а не салатовая, как в остальном сборнике. Селектор со своим «#»
   (id экрана) сильнее общего «.рейтинг-меры .кнопка--активная» без «#»
   (см. выше по файлу) — тот и дальше красит «Как я играю» в акцент темы. */
#экран-рейтинга-игроков :is(.рейтинг-выбор, .рейтинг-меры) .кнопка.кнопка--выбор.кнопка--активная {
  font-weight: 700;
  color: var(--рейтинг-золото-текст-тёмный);
  background: var(--рейтинг-золото);
  box-shadow: 0 4px 14px color-mix(in srgb, var(--рейтинг-золото) 22%, transparent);
}

/* ---------- Выбор игры стал одной кнопкой с шевроном, не лентой ----------
   Раньше внутри «.рейтинг-выбор» стояла лента кнопок по одной на игру
   (та же вёрстка, что у «.рейтинг-меры» рядом). С пятой игрой лента
   перестала бы влезать в ширину телефона, поэтому теперь внутри одна
   кнопка с названием текущей игры — нажатие открывает список отдельной
   панелью (устройство панели — ниже, после списка лидеров).
   Контейнер и его плитка-подложка не поменялись; здесь только сама
   кнопка: текст слева вместо центра и шеврон справа — знак «нажми,
   раскроется список», иначе её легко спутать с тихим переключателем
   «Сила игры / Очки за победы» строкой ниже, у того шеврона нет.

   Специфичность отбора та же, что у общего «.кнопка.кнопка--выбор»
   выше (id + три класса) — иначе оно бы её пересилило; побеждает
   именно это правило, потому что стоит в файле ниже. */
#экран-рейтинга-игроков .кнопка.кнопка--выбор.рейтинг-выбор__кнопка {
  /* Числа макета («.selector» в prototype/styles.css), партия 5, пункт 1:
     кнопка ростом 56 точек, своя рамка и тёмный градиент вместо серой
     плитки вокруг. Правый отступ 32 = 14 точек поля плюс 18 точек места
     под шеврон: сам шеврон нарисован «::before» и лежит поверх поля,
     как знак, а не как ещё одна колонка. */
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 56px;
  padding: 7px 32px 7px 14px;
  font-size: 18px;
  font-weight: 650;
  text-align: left;
  background: linear-gradient(135deg, #191919, #0c0c0e);
  border: 1px solid #8c7950;
  border-radius: 16px;
  box-shadow: none;
  /* Партия 6, пункт 8.7: название игры — обычный светлый текст экрана,
     не золото. Золотым остаётся только шеврон (сам красит себя ниже,
     через border, не наследует color) и картинка-значок слева (img
     цвет текста не наследует вовсе) — только буквы стали белее.

     Раньше здесь был литерал #f8f5eb — переменная «--сб-текст» дублировалась
     в style-коллекция.css и на странице реально давала другое число.
     Дубль убран (style.css ~838), «--сб-текст» теперь одна на весь
     сборник, поэтому кнопка снова берёт её через var(). */
  color: var(--сб-текст);
}

/* Уголок из двух границ вместо картинки или второго шрифта. Квадрат
   9×9 повёрнут на 45°, поэтому по диагонали занимает около 13 точек —
   столько же места, сколько шеврон-картинка в отведённых макетом
   18 точках справа (партия 5, пункт 1). */
#экран-рейтинга-игроков .кнопка.кнопка--выбор.рейтинг-выбор__кнопка::before {
  content: "";
  position: absolute;
  top: 50%;
  right: 14px;
  width: 9px;
  height: 9px;
  margin-top: -6px;
  border-right: 2px solid var(--рейтинг-золото);
  border-bottom: 2px solid var(--рейтинг-золото);
  transform: rotate(45deg);
}

/* Значок игры слева в кнопке (узел кладёт js/рейтинг-экран.js, договор
   имён партии 5) — 36×36, как в макете («.selector .game-symbol»).
   «object-fit: contain» нужен потому, что картинки игр разной формы:
   без него квадратная рамка растянула бы узкую фигуру. */
#экран-рейтинга-игроков .рейтинг-выбор-игры__значок {
  flex: none;
  width: 36px;
  height: 36px;
  object-fit: contain;
}

/* Запасной значок игры на кнопке выбора (js/рейтинг-экран.js,
   «значокВыбраннойИгры»): картинки файла нет или она не загрузилась —
   вместо битого <img> кружок с первой буквой игры, тем же приёмом,
   что у «.профиль-очки__значок--запаска» в профиле. */
#экран-рейтинга-игроков .рейтинг-выбор-игры__значок--запаска {
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  color: var(--сб-текст);
  background: var(--сб-поверхность);
  border: 1px solid var(--сб-граница);
  border-radius: 50%;
}

/* Значок пункта «Все игры» — свой SVG (сетка из четырёх квадратов),
   в макете он мельче значков игр: «.selector .icon» — 25×25, а не 36×36.
   Место под значок в строке кнопки (gap: 12px между значком и текстом)
   было рассчитано на 36×36 — если просто уменьшить width/height, текст
   «Все игры» сдвинется влево. Поэтому вместе с уменьшением добавлен
   margin: 5,5px по кругу — сама картинка занимает 25×25, а с отступами
   снова даёт 36×36 в потоке, и она стоит по центру прежнего места. */
#экран-рейтинга-игроков .рейтинг-выбор-игры__значок.рейтинг-выбор-игры__значок--все {
  width: 25px;
  height: 25px;
  margin: 5.5px;
}

/* Подпись под кнопкой выбора игры (узел кладёт js/рейтинг-экран.js,
   партия 6, пункт 8.6) — по макету идёт по левому краю, а не по центру,
   как обычная «.подпись» экрана («.экран > .подпись», выше по файлу).
   Пара id нужна, чтобы перебить это общее правило — класс id всегда
   сильнее, сколько бы классов у общего правила ни было. */
#экран-рейтинга-игроков #рейтинг-выбор-игры-подпись {
  margin: 0;
  font-size: 12px;
  text-align: left;
  /* План «рейтинг по макету», п. 4: у макета подпись чуть светлее общего
     тихого текста — цвет только здесь, общую переменную не трогаем. */
  color: #aaa9a7;
}

/* ---------- Строка «подпись слева — „Фильтры“ справа» (партия 6, 8.1) ----------
   Рядов настроек было три подряд (мера и две пары переключателей), и до
   первой строки списка на 390×844 оставалось меньше половины экрана.
   Теперь они свёрнуты под одну кнопку: js («убедитьсяЧтоЕстьСтрокаПодписи»)
   ставит на место подписи строку-обёртку, кладёт подпись в неё первой,
   кнопку «Фильтры» — второй, а сами ряды переносит в «.рейтинг-настройки-
   среза» под этой строкой. Здесь только вид: подпись слева, кнопка
   справа, между ними всё свободное место. */
.рейтинг-подпись-строка {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

/* Кнопка «Фильтры» — мелкий «чип» над списком: рамка и фон дорожки
   макета («.tabs», prototype/styles.css:37 — #111113 и #404040),
   подпись 12px. Тихая нарочно: это не действие экрана, а дверца
   к настройкам среза. Ширина по надписи — общие правила кнопки
   растянули бы её на всю строку. */
#экран-рейтинга-игроков .рейтинг-настройки__кнопка.кнопка {
  flex: 0 0 auto;
  width: auto;
  min-width: 0;
  min-height: 32px;
  padding: 5px 12px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--сб-текст-тихий);
  background: #111113;
  border: 1px solid #404040;
  border-radius: 12px;
  box-shadow: none;
}

/* Что-то в срезе выбрано не по умолчанию (js дописывает к надписи счёт:
   «Фильтры · 2») — кнопка становится золотой, как и все выбранные
   значения на этом экране. Так видно, что список показан не целиком,
   даже когда сами ряды свёрнуты. */
#экран-рейтинга-игроков .рейтинг-настройки__кнопка.рейтинг-настройки__кнопка--задано.кнопка {
  color: var(--рейтинг-золото);
  border-color: var(--рейтинг-золото-край);
  background: color-mix(in srgb, var(--рейтинг-золото) 12%, #111113);
}

/* Обёртка со свёрнутыми рядами: столбик с тем же зазором, что между
   парами переключателей (5px). Свёрнутое состояние — общий класс
   «скрыт» (js его снимает и ставит), своего «display: none» здесь нет:
   общее правило «.скрыт» помечено «!important» и перебивает этот
   «display: grid» само. */
.рейтинг-настройки-среза {
  display: grid;
  gap: 5px;
}

/* ---------- Сегмент «Все игроки | Друзья» ----------
   План «Рейтинг по макету», заход 2, пункт 1. Раньше это была первая
   из трёх пар «.рейтинг__фильтры» — теперь js («вынестиКругИгроков»)
   переносит тот же узел (классы «переключатель рейтинг__фильтр» не
   меняются) внутрь обёртки «#рейтинг-круг» сразу под выбором игры.

   Партия 6, пункт 8.5: рамка и padding: 3px раньше стояли на ОБОИХ
   узлах сразу (обёртке и переключателе внутри неё) — второй слой рамки
   отъедал место у кнопок, и «Все игроки» переносилось на две строки.
   Теперь рамка/фон/отступ — только на внешней обёртке, переключатель
   внутри просто тянется на всю её ширину без своей рамки.
   Числа — из prototype/styles.css макета, «.tabs». */
#экран-рейтинга-игроков #рейтинг-круг {
  display: flex;
  padding: 3px;
  border: 1px solid #404040;
  border-radius: 14px;
  background: #111113;
}

#экран-рейтинга-игроков #рейтинг-круг .переключатель.рейтинг__фильтр {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  gap: 3px;
  padding: 0;
  border: none;
  border-radius: 0;
  background: none;
}

/* Кнопки сегмента — те же 44 точки по высоте, что у остальных
   переключателей экрана, просто без своей рамки (её несёт полоса выше).
   «white-space: nowrap» (пункт 8.5) — «Все игроки» больше не переносится
   на две строки, даже когда кнопке достаётся мало места. */
#экран-рейтинга-игроков #рейтинг-круг .переключатель__вариант {
  flex: 1 1 0;
  min-width: 0;
  min-height: 44px;
  /* План «рейтинг по макету», п. 6: у макета кнопка ниже, воздух сверху и
     снизу меньше. Ширина на 1280 — забота ПК-исполнителя (раздел 3 плана). */
  padding: 1px 6px;
  font-size: 14px;
  font-weight: 550;
  color: #c4c3c0;
  white-space: nowrap;
  border: 1px solid transparent;
  border-radius: 10px;
}

/* Активная половина — золотой градиент макета, не плоское золото, как
   у остальных переключателей экрана (у тех — решение штаба «золото как
   в макете», здесь макет прямо даёт градиент, а не ровный тон). */
#экран-рейтинга-игроков #рейтинг-круг .переключатель__вариант.переключатель__вариант--выбран {
  color: #17140e;
  background: linear-gradient(125deg, #f1db9c, #c5a35d);
  border-color: #e5c67d;
  box-shadow: 0 4px 15px rgba(184, 141, 48, 0.13);
}

/* Кнопка «Добавить друга» в пустом круге «Друзья» (js/рейтинг-экран.js,
   «кнопкаДобавитьДруга» — у неё общий класс «.кнопка», салатовая, как
   везде в сборнике). Здесь она рядом с золотым переключателем «Все
   игроки / Друзья» — тот же градиент и тёмный текст, а не акцент темы.
   «:not(.рейтинг-круг__друзья)» — жалоба владельца 23.09: без этого
   исключения селектор (он ловит ЛЮБУЮ прямую кнопку таблицы) забивал
   по специфичности (2 id) более узкое правило тихой ссылки «Мои
   друзья» ниже (1 id + класс) — она тоже красилась золотым градиентом
   и сливалась с этой кнопкой в одну «обрезанную плашку». */
#экран-рейтинга-игроков #рейтинг-таблица > button.кнопка:not(.рейтинг-круг__друзья) {
  color: #17140e;
  background: linear-gradient(125deg, #f1db9c, #c5a35d);
  box-shadow: 0 4px 15px rgba(184, 141, 48, 0.13);
}

/* «Мои друзья» — тихая мелкая ссылка, не широкая серая кнопка, какой
   была раньше. По макету владельца в сегменте «Все игроки/Друзья»
   её нет вовсе — теперь она стоит внутри самого круга «Друзья»: под
   списком друзей или, в пустом состоянии, рядом с «Добавить друга»
   (js/рейтинг-экран.js, «нарисоватьОчки» кладёт её последним узлом
   таблицы). Узел там же, внутри «#рейтинг-таблица», а не рядом с
   сегментом — но выше не текла своя рамка, которую нужно было бы
   гасить, поэтому вес кнопки остаётся прежним, тихим. */
#экран-рейтинга-игроков .рейтинг-круг__друзья {
  align-self: center;
  width: auto;
  min-height: 32px;
  padding: 4px 10px;
  font-size: 13px;
  font-weight: 500;
  color: var(--сб-текст-тихий);
  background: none;
  border: none;
  box-shadow: none;
  text-decoration: underline;
  text-decoration-color: rgba(133, 139, 148, 0.5);
  text-underline-offset: 3px;
  /* Жалоба владельца 23.09: список стоит на «gap: 0» (#рейтинг-таблица,
     строки вплотную) — без своего отступа ссылка прилипала к узлу
     перед ней (в пустом круге это кнопка «Добавить друга»). Отступ
     нужен всегда перед этой ссылкой, откуда бы она ни шла — держим
     его тут, а не смежным селектором под один-единственный случай. */
  margin-top: 12px;
}

/* ---------- Две пары фильтров: «Правила дурака» и «Состав игроков» ----------
   Третья пара, «Круг игроков», переехала в свой узел выше («#рейтинг-
   круг») — здесь остались только эти две. На макете все три ряда были
   одной высоты, вплотную друг к другу; теперь их два, устройство то же.
   Работает пока только левый вариант каждой пары, правый честно помечен
   «скоро» — поэтому вся пара выключена. Выключенное должно читаться,
   иначе человек решит, что игра сломалась: держим ту же меру, что
   у «Открыть подбор игроков» в комнате — примерно 0,6 от белого. */
/* Без «>» перед «.рейтинг__фильтры» нарочно, по той же причине, что
   у полоски меры выше (партия 6, пункт 8.1): js переносит ряды внутрь
   обёртки «.рейтинг-настройки-среза», прямым потомком экрана они быть
   перестают. С «>» ряды после переноса потеряли бы и столбик, и зазор,
   и свои поля — пары переключателей слиплись бы в кучу. */
#экран-рейтинга-игроков .рейтинг__фильтры {
  display: grid;
  gap: 5px;
}

#экран-рейтинга-игроков .рейтинг__фильтры > .рейтинг__фильтр {
  margin: 0;
  gap: 3px;
  padding: 3px;
  border-radius: 14px;
}

/* Ряды фильтров ниже обычного переключателя: нажимать их всё равно
   нельзя (обе половины выключены), а на макете владельца они как раз
   такие — тонкие. Освободившиеся точки уходят списку лидеров. */
#экран-рейтинга-игроков .рейтинг__фильтр > .переключатель__вариант {
  min-height: 38px;
  padding: 3px 6px;
  font-size: clamp(13px, 3.8vw, 15px);
  border-radius: 11px;
}

/* Пометка «скоро» — общая тёмная пилюля (см. правило переключателя
   выше). Здесь только зазор поменьше: ряд низкий, и лишние точки
   сверху растягивали бы его обратно. */
#экран-рейтинга-игроков .рейтинг__фильтр > .переключатель__вариант > .пометка-скоро {
  margin-top: 1px;
}

/* Активный вариант трёх пар («Все игроки», «Подкидной», «Личный») —
   золото макета вместо салатового акцента сборника (решение штаба:
   «золото как в макете», салатового на этом экране нет вовсе). Селектор
   с «#экран-рейтинга-игроков» весомее общего «.переключатель__вариант--
   выбран» без «#» (см. в начале файла) — тот и дальше красит переключатели
   ВСЕХ остальных экранов сборника в салатовый, здесь его просто перебивают. */
#экран-рейтинга-игроков .рейтинг__фильтр > .переключатель__вариант.переключатель__вариант--выбран {
  color: var(--рейтинг-золото-текст-тёмный);
  background: var(--рейтинг-золото);
  box-shadow: 0 4px 14px color-mix(in srgb, var(--рейтинг-золото) 22%, transparent);
}

/* Тот же выбранный вариант, но у выключенной пары — золотая пилюля без
   свечения (свечение звало бы нажать на то, что пока не нажимается). */
#экран-рейтинга-игроков .рейтинг__фильтр > .переключатель__вариант.переключатель__вариант--выбран:disabled {
  color: var(--рейтинг-золото-текст-тёмный);
  box-shadow: none;
}

/* ---------- Список ----------
   План «Рейтинг по макету», партия 6, шаг 1: список больше не держит
   свой «пол» высоты и не прокручивается сам по себе — прокручивается
   весь экран (см. правило «#экран-рейтинга-игроков» выше), список
   просто занимает сколько нужно контенту («flex: 0 0 auto»). Прежние
   вычисления пола 224–306px и наезда «Моё место» на подиум устарели:
   своя строка внизу списка больше не приклеена (не «position: sticky»,
   правило ниже по файлу), карточка «Моё место» — отдельный узел под
   списком, наезжать ей больше не на что. */
#экран-рейтинга-игроков > #рейтинг-таблица {
  /* Шаг 1: список больше не тянет остаток высоты и не прокручивается
     сам — прокручивается весь экран (см. правило «#экран-рейтинга-
     игроков» выше). «overflow: visible» перебивает «.таблица»
     («overflow-y: auto», строка 3581) — без него список продолжал бы
     скроллиться внутри себя вторым слоем поверх прокрутки страницы. */
  flex: 0 0 auto;
  min-height: 0;
  overflow: visible;
  /* Строки макета стоят вплотную, разделяет их волосок-граница,
     а не просвет, — поэтому общего зазора у списка больше нет. */
  gap: 0;
}

/* Зазор убран у всего списка разом, а нужен он был не только строкам:
   без него слиплись бы фразы сервера под таблицей и строки соперников
   у меры «сила игры» (они идут подписями подряд). Поэтому просвет
   возвращаем точечно — только там, где после строки или подписи снова
   идёт подпись. Строк таблицы это правило не касается: они и должны
   стоять вплотную. */
#экран-рейтинга-игроков > #рейтинг-таблица > .рейтинг-строка + .подпись,
#экран-рейтинга-игроков > #рейтинг-таблица > .подпись + .подпись {
  margin-top: 5px;
}

/* Строка списка — ровная таблица, а не лента плиток (партия 5, пункт 2;
   макет: «.rank-row» в prototype/styles.css). Плитки у каждой строки
   больше нет: ни заливки, ни рамки, ни скругления — только волосок-
   разделитель снизу. Так список читается сверху вниз одним столбиком
   цифр, а подсветка остаётся приметой ОДНОЙ строки — своей.
   Высота 53 и отступы 5/8 — числа макета (пункт 19). */
#рейтинг-таблица .рейтинг-строка {
  /* План «рейтинг по макету», п. 15: столбец места по числу макета —
     30px («.rank-row» в prototype/styles.css), было 2.2em (шире). */
  grid-template-columns: 30px 35px minmax(0, 1fr) auto;
  grid-template-areas:
    "место аватар имя очки"
    "место аватар имя победы";
  align-items: center;
  column-gap: 10px;
  row-gap: 0;
  min-height: 53px;
  padding: 5px 8px;
  background: none;
  border: none;
  border-bottom: 1px solid #272626;
  border-radius: 0;
  box-shadow: none;
}

/* Аватар — значком набора, как у соперников за столом. Размер 35 точек —
   число макета («.row-player .avatar», партия 5, пункт 6). */
#рейтинг-таблица .рейтинг-строка::before {
  content: "";
  grid-area: аватар;
  width: 35px;
  height: 35px;
  color: #aab0b6;
  background-color: currentColor;
  -webkit-mask: var(--значок-аватар) center / contain no-repeat;
  mask: var(--значок-аватар) center / contain no-repeat;
}

/* Настоящее фото вместо нарисованного человечка — только у своей строки
   (js/рейтинг-экран.js кладёт готовый адрес в «--фото-аватара» и класс
   ровно как лобби кружок над таблицей, .аватар--фото выше). Компонуем
   оба класса в селекторе, чтобы это правило било и базовый значок выше,
   и салатовую заливку «--я::before» ниже — той нужен фон currentColor,
   этому нужен прозрачный фон под фотографией. Без border-radius фото
   стало бы квадратным: круглость кружку давала маска-значок, а без
   неё её больше неоткуда взять. */
#рейтинг-таблица .рейтинг-строка.рейтинг-строка--фото::before {
  -webkit-mask: none;
  mask: none;
  background-color: transparent;
  background-image: var(--фото-аватара);
  background-position: center;
  background-size: cover;
  border-radius: 50%;
}

/* Тонкое кольцо вокруг аватара строки (макет, «.row-player .avatar»,
   рамка 1px #8f8266) — рисуется ВТОРЫМ псевдоэлементом, а не рамкой
   у первого. Причина та же, что уже описана у своей строки ниже: у
   значка-силуэта маска обрезает весь рендер псевдоэлемента целиком,
   вместе с рамкой и тенью, — кольцо на «::before» просто не появилось бы.
   «::after» маски не несёт, лежит в той же ячейке сетки поверх аватара
   и одинаково обводит и силуэт, и настоящее фото, и плашку инициалов.
   Шапка столбцов, своя карточка (у неё кольцо золотое, своё) и строка-
   разрыв аватара не показывают — им кольцо не рисуем. */
#рейтинг-таблица .рейтинг-строка:not(.рейтинг-строка--шапка, .рейтинг-строка--я, .рейтинг-строка--разрыв)::after {
  content: "";
  grid-area: аватар;
  width: 35px;
  height: 35px;
  border: 1px solid #8f8266;
  border-radius: 50%;
  pointer-events: none;
}

/* Инициалы вместо силуэта (узел кладёт js/рейтинг-экран.js, договор имён
   партии 5): непрозрачная плашка с градиентом макета, буквы по центру.
   Плашка лежит в той же ячейке сетки, что и «::before», и закрывает его
   собой; на всякий случай силуэт ещё и прячется правилом ниже — иначе
   на старом браузере без «:has()» человечек просвечивал бы сквозь края
   букв. */
#рейтинг-таблица .рейтинг-аватар__инициалы {
  grid-area: аватар;
  display: grid;
  place-items: center;
  width: 35px;
  height: 35px;
  border-radius: 50%;
  background: linear-gradient(135deg, #574e39, #272522);
  color: #e6cc8c;
  font-size: 12px;
  font-weight: 650;
  overflow: hidden;
}

#рейтинг-таблица .рейтинг-строка:not(.рейтинг-строка--фото):has(.рейтинг-аватар__инициалы)::before {
  display: none;
}

/* Фото сильнее инициалов: пока стоит класс «--фото» (кладёт «поставитьФото»
   из js/рейтинг-экран.js), плашка букв не нужна — под ней иначе
   просвечивало бы настоящее фото. Один отбор закрывает и строку списка,
   и карточку подиума: класс «--фото» один и тот же, меняется только
   предок, на котором он стоит. */
#рейтинг-таблица .рейтинг-строка--фото .рейтинг-аватар__инициалы {
  display: none;
}

/* У своей карточки кольцо золотое: её «::before» инициалы прячут вместе
   с встроенным в маску золотым кольцом, поэтому возвращаем его тенью —
   у настоящего узла тень не обрезается ничем. */
#рейтинг-таблица .рейтинг-строка--я .рейтинг-аватар__инициалы {
  box-shadow: 0 0 0 2px var(--рейтинг-золото);
}

#рейтинг-таблица .рейтинг-место {
  grid-area: место;
  justify-self: center;
  width: auto;
  height: auto;
  background: none;
  /* План «рейтинг по макету», п. 15: у макета номер места мельче и не
     такой жирный, как основной текст строки. */
  font-size: 14px;
  font-weight: 650;
  color: var(--сб-текст);
}

#рейтинг-таблица .рейтинг-имя {
  grid-area: имя;
  /* План «рейтинг по макету», п. 16: у макета имя обычным текстом строки,
     не крупнее и не жирнее его — отступы на широком экране (1280+) —
     забота ПК-исполнителя (раздел 3 плана), здесь их не трогаем. */
  font-size: 14px;
  font-weight: 400;
}

/* Метка «Вы» у своей строки — золотая пилюля с тёмным текстом, как в
   макете владельца (карточка «моё место»). Отступ от имени теперь даёт
   «gap» флекс-родителя («.рейтинг-имя» / «.рейтинг-подиум-имя»), не
   «margin-left» здесь. */
#рейтинг-таблица .рейтинг-имя__вы {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
  color: var(--рейтинг-золото-текст-тёмный);
  background: var(--рейтинг-золото);
  /* Раньше «Вы» лежала внутри обрезаемого узла имени как последний
     ребёнок и на длинном имени уезжала за экран вместе с текстом —
     чинили через «position: sticky». Теперь текст и пилюля — родные
     соседи во флекс-строке («__текст» и «__вы», см. «.рейтинг-имя» /
     «.рейтинг-подиум-имя» выше и ниже), обрезается только «__текст»,
     sticky не нужен. Селектор общий по «#рейтинг-таблица» — без
     класса-предка между ними, поэтому чинит бейдж и в обычной строке
     списка, и на карточке подиума разом. */
  flex-shrink: 0;
}

/* Стрелка движения места — мелкая подпись сразу после числа очков
   (js/рейтинг-экран.js, «узелДвижения»/«строкаТаблицы»): своя ячейка,
   не отдельный столбец, поэтому «white-space: nowrap», чтобы «↑ 12»
   не переносилось на вторую строку внутри узкой колонки очков. */
#рейтинг-таблица .рейтинг-движение {
  display: inline-block;
  margin-left: 4px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

/* План «рейтинг по макету», п. 14: цвет стрелки в списке своим литералом,
   не через общую переменную — она же красит карточку «Моё место» (не моя
   зона), а по макету («.delta», --green) их зелёный чуть светлее нашего. */
#рейтинг-таблица .рейтинг-движение--вверх { color: #7fcea0; }
#рейтинг-таблица .рейтинг-движение--вниз { color: var(--рейтинг-движение-вниз); }
#рейтинг-таблица .рейтинг-движение--нет { color: var(--рейтинг-золото-текст-тихий); }

#рейтинг-таблица .рейтинг-очки {
  grid-area: очки;
  align-self: end;
  font-size: 14px;
  font-weight: 650;
}

/* Владелец вернул золото числам очков во ВСЕЙ таблице (не только своей
   строке) — план «п. 13» выше когда-то отменил его, сверяясь со старым
   первоисточником макета, но решение снова поменялось. Селектор нарочно
   «:not(шапка)»: строка «#рейтинг-таблица .рейтинг-очки» (id + 1 класс)
   по специфичности сильнее, чем «.рейтинг-строка--шапка .рейтинг-очки»
   (0 id + 2 класса — число id решает независимо от количества классов),
   и без «:not» перекрасила бы заодно и подпись колонки в шапке — там
   должен остаться тихий цвет шапки (inherit), не золото. */
#рейтинг-таблица .рейтинг-строка:not(.рейтинг-строка--шапка) .рейтинг-очки {
  color: var(--рейтинг-золото);
}

#рейтинг-таблица .рейтинг-победы {
  grid-area: победы;
  align-self: start;
  justify-self: end;
  font-size: 12px;
  color: var(--сб-текст-тихий);
}

/* План «рейтинг по макету», п. 15: кружки-медали для первой тройки были
   и в списке, и на подиуме — по первоисточнику макета («.rank-number»)
   в списке у номера места никакого кружка нет, только на подиуме
   (там свои медали, см. «.рейтинг-подиум-медаль» ниже). Убрано. */

/* ---------- Подиум первой тройки (план «Рейтинг по макету», шаг
   «подиум 2-1-3») ----------
   Рисуется первым узлом внутри «#рейтинг-таблица», перед обычными
   строками (js/рейтинг-экран.js, «нарисоватьОчки» и «подиумУзел»).
   Карточки в разметке уже идут в готовом порядке 2-1-3 — здесь только
   раскладка и размеры, ничего не переставляем. Число карточек — счётный
   класс от js («рейтинг-подиум--1/2/3»): частичная тройка не рисует
   пустых мест, и сетка под каждое число своя, а не всегда «три колонки
   с дырой». Первое место крупнее и на плашке повыше — по атрибуту
   «data-место», как и цвет медали у обычных строк.

   Размеры аватаров — числами через переменные (сверка со снимком
   макета у смотрителя, добавка «первый заметно приподнят»): боковые
   места остаются прежними 73px («--рейтинг-подиум-аватар»), у первого
   места отдельная переменная («--рейтинг-подиум-аватар-центр») — 86px,
   как в макете, — сетка снизу выровнена по нижнему краю
   («align-items: end» у «.рейтинг-подиум-сетка»), поэтому просто более
   высокий центр и даёт «приподнятость», без отдельного отступа. */
#рейтинг-таблица .рейтинг-подиум {
  --рейтинг-подиум-аватар: 73px;
  /* Партия 5, пункт 4: у макета первое место 86 точек, а не 110 —
     подиум стал ниже на 24 точки, и список под ним дышит. Маски колец
     считаются от этой переменной через calc() (правила ниже), поэтому
     кольцо и медаль поехали за ней сами, руками ничего не пересчитываем. */
  --рейтинг-подиум-аватар-центр: 86px;
  /* Размер золотого кубка слева от «Лидеры» (план «рейтинг по макету»,
     п. 11 — prototype/styles.css: «.heading-trophy», кубок не квадратный,
     33 на 40 точек). Две переменные, а не число в правиле картинки,
     чтобы менять в одном месте. */
  --рейтинг-кубок-ш: 33px;
  --рейтинг-кубок-в: 40px;
  margin-bottom: 6px;
}

/* «Лидеры» — заголовок раздела по макету («.section-heading»): крупный,
   по левому краю и с широким просветом до самого подиума (партия 5,
   пункт 21). Раньше подпись стояла по центру в 8 точках от карточек
   и читалась как подпись К подиуму, а не как название раздела. */
#рейтинг-таблица .рейтинг-подиум > .подпись {
  margin: 0 0 24px;
  text-align: left;
  font-size: 22px;
  /* Базовый «.подпись» (общий класс сборника) красит текст тихим серым
     и не жирнит его — здесь заголовок раздела, а не пояснение под
     заголовком: жирный и светлый, как «h2.section-heading» в макете
     владельца (prototype/styles.css:41 — там кегль и вес берёт браузер
     от тега h2 по умолчанию, тут явно, узел — «p», не «h2»). */
  font-weight: 700;
  color: var(--сб-текст);
}

/* Заголовок подиума теперь строка «кубок + текст» (js/рейтинг-экран.js,
   заголовокПодиума) — .подпись выше уже даёт отступ и центр, здесь только
   раскладка кубка и текста в одну строку по центру. */
#рейтинг-таблица .рейтинг-подиум-заголовок {
  display: flex;
  align-items: center;
  /* Кубок и слово «Лидеры» прижаты к левому краю колонки — заголовок
     раздела в макете стоит слева, а не по центру (пункт 21). */
  justify-content: flex-start;
  gap: 8px;
}

#рейтинг-таблица .рейтинг-подиум-кубок {
  width: var(--рейтинг-кубок-ш, 33px);
  height: var(--рейтинг-кубок-в, 40px);
  flex: none;
}

#рейтинг-таблица .рейтинг-подиум-сетка {
  display: grid;
  align-items: end;
  /* 5 точек — зазор макета («.podium»), партия 5, пункт 4. */
  column-gap: 5px;
}

/* Три карточки — 2 слева, 1 в центре (шире, ему и место крупнее),
   3 справа: порядок в разметке уже такой, здесь только ширины колонок. */
#рейтинг-таблица .рейтинг-подиум--3 .рейтинг-подиум-сетка {
  /* Центр шире не на глазок: аватар первого места (86 точек) крупнее
     боковых (73), колонке нужен запас, чтобы он не подпирал соседей.
     Доля 1.1 — число макета («.podium»): прежние 1.4 были посчитаны
     под аватар в 110 точек, которого больше нет (партия 5, пункт 4). */
  grid-template-columns: 1fr 1.1fr 1fr;
}

/* Две карточки — третьего места не хватает, но растягивать сетку
   в три колонки не нужно: пустая треть читалась бы как «потеряли». */
#рейтинг-таблица .рейтинг-подиум--2 .рейтинг-подиум-сетка {
  grid-template-columns: 1fr 1fr;
  max-width: 76%;
  margin: 0 auto;
}

/* Одна карточка — единственный лидер стоит по центру, один в один. */
#рейтинг-таблица .рейтинг-подиум--1 .рейтинг-подиум-сетка {
  grid-template-columns: 1fr;
  max-width: 40%;
  margin: 0 auto;
}

#рейтинг-таблица .рейтинг-подиум-карточка {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0;
  /* Карточка — элемент сетки «.рейтинг-подиум-сетка» (колонки «1fr»/
     «1.1fr»/«1fr»), а у неё самой нет «overflow», поэтому по умолчанию
     минимальная ширина элемента сетки считается по содержимому: на
     длинном имени и больших очках («999 999 999») карточка раздувалась
     до ~436px и уезжала за правый край экрана. «min-width: 0» разрешает
     карточке сжаться до своей доли сетки — дальше длинное имя внутри
     (см. «.рейтинг-подиум-имя» ниже) уходит в многоточие, а крупные
     очки («-очки» ниже) не режутся вовсе — сжимается их кегль. */
  min-width: 0;
  /* «container-type: inline-size» — карточка становится «линейкой», от
     которой считаются «cqi» (1cqi = 1% её ширины) у длинных очков ниже
     («.рейтинг-подиум-очки--длинные»/«--очень-длинные»). Ширина у карточки
     и без этого уже не зависит от контента (строка выше про «min-width:0» +
     «stretch» по умолчанию у элемента сетки задают её жёстко из ширины
     колонки), поэтому контейнер не схлопывается. */
  container-type: inline-size;
}

/* Аватар крупнее макета (было 40/52px) — план «Рейтинг по макету»,
   заход 2, пункт 3: размер числом через переменную (см. «.рейтинг-подиум»
   выше), у боковых мест — 73px. */
#рейтинг-таблица .рейтинг-подиум-аватар {
  position: relative;
  width: var(--рейтинг-подиум-аватар, 73px);
  height: var(--рейтинг-подиум-аватар, 73px);
  background-color: currentColor;
  color: #aab0b6;
}

/* Первое место — крупнее остальных двух (своя переменная
   «--рейтинг-подиум-аватар-центр»: 86 точек против 73 боковых),
   по макету владельца. */
#рейтинг-таблица .рейтинг-подиум-карточка[data-место="1"] .рейтинг-подиум-аватар {
  width: var(--рейтинг-подиум-аватар-центр, 110px);
  height: var(--рейтинг-подиум-аватар-центр, 110px);
}

#рейтинг-таблица .рейтинг-подиум-карточка[data-место="1"] .рейтинг-подиум-аватар { color: var(--рейтинг-золото); }
#рейтинг-таблица .рейтинг-подиум-карточка[data-место="2"] .рейтинг-подиум-аватар { color: var(--рейтинг-серебро); }
#рейтинг-таблица .рейтинг-подиум-карточка[data-место="3"] .рейтинг-подиум-аватар { color: var(--рейтинг-бронза); }

/* Мягкое золотое свечение вокруг портрета первого места — по макету
   владельца (references/screens/03_durak.png) и прототипу пакета
   (prototype/styles.css: «.first .podium-portrait { box-shadow: 0 0
   20px #d3a44520 }»). Тон — не новый литерал, а «--рейтинг-золото»
   через color-mix, как и у других полупрозрачных золотых слоёв этого
   экрана выше по файлу.
   Раньше свечение было «filter: drop-shadow» на самом аватаре — но
   у аватара своя маска-силуэт (круг, правило «...аватар:not(
   .рейтинг-строка--фото)» ниже), а маска накладывается ПОСЛЕ filter
   и обрезает тень по кругу: на снимке получалось тонкое кольцо вместо
   мягкого ореола (нашёл штаб по снимку 23.09). Поэтому свечение теперь
   не на аватаре, а на подложке позади него — «::before» у самой
   карточки (она — единственный предок с «position:relative», строка
   выше по файлу; маска аватара его не касается вовсе). Корона у карточки
   стоит «position:absolute» и в обычный поток не входит (см. правило
   «.рейтинг-подиум-корона» ниже) — аватар первый ребёнок карточки
   в потоке, поэтому круг подложки можно положить точно по центру
   аватара через «--рейтинг-подиум-аватар-центр» без догадок.
   ПРАВКА (смотритель, снимок 23.09, «Г2»): прежний приём — круг НА 14px
   ШИРЕ аватара с radial-gradient (золото 40% в центре → прозрачно на
   краю) — оказался невидим: центр круга закрыт самим аватаром, а
   видимое кольцо (7px за край) приходится на почти прозрачный хвост
   градиента. Теперь круг РОВНО в размер аватара (без +14px), а свечение
   даёт «box-shadow» СНАРУЖИ этого круга — тень не обрезается маской
   (маска стоит на аватаре, не на «::before») и целиком видна за краем.
   «z-index: 0» по-прежнему держит свечение позади аватара (тот
   красится следом за «::before» в порядке разметки и стоит выше
   в том же слое стека).
   ПРАВКА 2 (возврат «css-Б2», смотритель, снимок 23.09, беда 3):
   «spread» 5px + «blur» 8px + 65% непрозрачности сделали кольцо
   видимым, но смотритель на живом снимке увидел его «тонким и сухим»
   рядом с ярким размытым ореолом эталона. Числа подняты: «blur» 24px
   (втрое) даёт мягкий, а не резкий край, «spread» 10px (вдвое) —
   ощутимо шире аватара, непрозрачность 80% (было 65%) — ближе к
   цвету самого золота, не полупрозрачная примесь. Приём тот же самый
   (box-shadow на «::before» позади аватара) — ни маски, ни
   drop-shadow на самом аватаре не добавлено. */
#рейтинг-таблица .рейтинг-подиум-карточка[data-место="1"]::before {
  content: "";
  position: absolute;
  top: calc(var(--рейтинг-подиум-аватар-центр, 110px) / 2);
  left: 50%;
  width: var(--рейтинг-подиум-аватар-центр, 110px);
  height: var(--рейтинг-подиум-аватар-центр, 110px);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  box-shadow: 0 0 24px 10px color-mix(in srgb, var(--рейтинг-золото) 80%, transparent);
  z-index: 0;
  pointer-events: none;
}

/* Значок-силуэт — тот же приём двойной маски, что и у своей строки
   в списке («.рейтинг-строка--я::before» ниже): кольцо встроено ВНУТРЬ
   маски вторым слоем, потому что маска обрезает рендер элемента целиком,
   включая box-shadow, — тенью кольцо здесь не нарисовать. Кольцо
   и силуэт красит один «currentColor» (цвет медали, правила выше),
   поэтому оба слоя сливаются в фигуру одного цвета. Радиусы — той же
   пропорцией, что и раньше (значок 0,85 от диаметра, кольцо толщиной
   3px с отступом от края), но через calc() от «--рейтинг-подиум-аватар»,
   а не литералом: раньше размер аватара («.рейтинг-подиум» выше) и его
   маска были двумя разными числами и могли разъехаться, поменяй кто-то
   одно без другого (нашёл ревьюер) — теперь маска сама пересчитывается
   вслед за переменной. Дробь «×30/73» и подобные — те же самые доли,
   что были прежде записаны готовым числом (30px при 73px диаметра). */
#рейтинг-таблица .рейтинг-подиум-карточка:not(.рейтинг-строка--фото) .рейтинг-подиум-аватар {
  -webkit-mask-image: var(--значок-аватар), radial-gradient(circle, transparent calc(var(--рейтинг-подиум-аватар, 73px) * 30 / 73), #000 calc(var(--рейтинг-подиум-аватар, 73px) * 30 / 73) calc(var(--рейтинг-подиум-аватар, 73px) * 33 / 73), transparent calc(var(--рейтинг-подиум-аватар, 73px) * 33 / 73));
  mask-image: var(--значок-аватар), radial-gradient(circle, transparent calc(var(--рейтинг-подиум-аватар, 73px) * 30 / 73), #000 calc(var(--рейтинг-подиум-аватар, 73px) * 30 / 73) calc(var(--рейтинг-подиум-аватар, 73px) * 33 / 73), transparent calc(var(--рейтинг-подиум-аватар, 73px) * 33 / 73));
  -webkit-mask-size: calc(var(--рейтинг-подиум-аватар, 73px) * 62 / 73) calc(var(--рейтинг-подиум-аватар, 73px) * 62 / 73), var(--рейтинг-подиум-аватар, 73px) var(--рейтинг-подиум-аватар, 73px);
  mask-size: calc(var(--рейтинг-подиум-аватар, 73px) * 62 / 73) calc(var(--рейтинг-подиум-аватар, 73px) * 62 / 73), var(--рейтинг-подиум-аватар, 73px) var(--рейтинг-подиум-аватар, 73px);
  -webkit-mask-position: center, center;
  mask-position: center, center;
  -webkit-mask-repeat: no-repeat, no-repeat;
  mask-repeat: no-repeat, no-repeat;
}

/* У первого места сама аватарка крупнее («--рейтинг-подиум-аватар-центр»,
   86px вместо 73) — та же идея calc() от СВОЕЙ переменной, теми же
   долями, какими раньше были записаны её собственные литералы
   (47px/50px/93px при диаметре 110px), чтобы кольцо не съезжало и не
   мельчало, если размер первого места когда-нибудь поменяют отдельно
   от боковых. */
#рейтинг-таблица .рейтинг-подиум-карточка[data-место="1"]:not(.рейтинг-строка--фото) .рейтинг-подиум-аватар {
  -webkit-mask-image: var(--значок-аватар), radial-gradient(circle, transparent calc(var(--рейтинг-подиум-аватар-центр, 110px) * 47 / 110), #000 calc(var(--рейтинг-подиум-аватар-центр, 110px) * 47 / 110) calc(var(--рейтинг-подиум-аватар-центр, 110px) * 50 / 110), transparent calc(var(--рейтинг-подиум-аватар-центр, 110px) * 50 / 110));
  mask-image: var(--значок-аватар), radial-gradient(circle, transparent calc(var(--рейтинг-подиум-аватар-центр, 110px) * 47 / 110), #000 calc(var(--рейтинг-подиум-аватар-центр, 110px) * 47 / 110) calc(var(--рейтинг-подиум-аватар-центр, 110px) * 50 / 110), transparent calc(var(--рейтинг-подиум-аватар-центр, 110px) * 50 / 110));
  -webkit-mask-size: calc(var(--рейтинг-подиум-аватар-центр, 110px) * 93 / 110) calc(var(--рейтинг-подиум-аватар-центр, 110px) * 93 / 110), var(--рейтинг-подиум-аватар-центр, 110px) var(--рейтинг-подиум-аватар-центр, 110px);
  mask-size: calc(var(--рейтинг-подиум-аватар-центр, 110px) * 93 / 110) calc(var(--рейтинг-подиум-аватар-центр, 110px) * 93 / 110), var(--рейтинг-подиум-аватар-центр, 110px) var(--рейтинг-подиум-аватар-центр, 110px);
}

/* Инициалы на подиуме (js кладёт «span.рейтинг-аватар__инициалы» внутрь
   аватара карточки — решение штаба, партия 5). Маску-силуэт снимаем
   целиком: она обрезает не только сам элемент, но и всё, что внутри, —
   буквы попали бы под тот же нож, что и кольцо с тенью (см. длинный
   комментарий выше). Раз маски нет, кольцо возвращаем тенью той же
   толщины, что рисовала маска, — 3 точки, и того же цвета: «currentColor»
   у аватара уже покрашен по месту (золото/серебро/бронза, правила выше).
   Имя класса в отборе повторено дважды нарочно: правила масок выше несут
   ещё и «[data-место="1"]», и без этого повтора первое место осталось бы
   с маской, а его буквы — обрезанными. */
#рейтинг-таблица .рейтинг-подиум-карточка:not(.рейтинг-строка--фото) .рейтинг-подиум-аватар.рейтинг-подиум-аватар:has(.рейтинг-аватар__инициалы) {
  -webkit-mask: none;
  mask: none;
  background-color: transparent;
  border-radius: 50%;
  box-shadow: 0 0 0 3px currentColor;
}

/* Плашка инициалов занимает весь аватар подиума (73 точки у боковых,
   86 у первого — числа живут в переменных «--рейтинг-подиум-аватар»
   и «--рейтинг-подиум-аватар-центр», здесь только «во весь размер»).
   Буквы крупнее, чем в списке: аватар тут вдвое больше строчного. */
#рейтинг-таблица .рейтинг-подиум-аватар .рейтинг-аватар__инициалы {
  width: 100%;
  height: 100%;
  font-size: 20px;
}

#рейтинг-таблица .рейтинг-подиум-карточка[data-место="1"] .рейтинг-подиум-аватар .рейтинг-аватар__инициалы {
  font-size: 24px;
}

/* Настоящее фото (класс «рейтинг-строка--фото» кладёт «поставитьФото»
   из js) — маска снята целиком, кольцо тут можно обычной тенью: фото
   не обрезает её так, как обрезает маска силуэта (см. комментарий выше). */
#рейтинг-таблица .рейтинг-подиум-карточка.рейтинг-строка--фото .рейтинг-подиум-аватар {
  -webkit-mask: none;
  mask: none;
  background-color: transparent;
  background-image: var(--фото-аватара);
  background-position: center;
  background-size: cover;
  border-radius: 50%;
}

#рейтинг-таблица .рейтинг-подиум-карточка[data-место="1"].рейтинг-строка--фото .рейтинг-подиум-аватар {
  box-shadow: 0 0 0 3px var(--рейтинг-золото);
}
#рейтинг-таблица .рейтинг-подиум-карточка[data-место="2"].рейтинг-строка--фото .рейтинг-подиум-аватар {
  box-shadow: 0 0 0 3px var(--рейтинг-серебро);
}
#рейтинг-таблица .рейтинг-подиум-карточка[data-место="3"].рейтинг-строка--фото .рейтинг-подиум-аватар {
  box-shadow: 0 0 0 3px var(--рейтинг-бронза);
}

/* Кружок с цифрой места — «кружок-номер» из плана, 35px (был 20px),
   на нижнем крае аватара: центр кружка ложится на его нижний край
   (margin-top — минус половина диаметра кружка, то же число, что
   в макете, «bottom:-18px» у «.medal»). */
#рейтинг-таблица .рейтинг-подиум-медаль {
  position: relative;
  z-index: 1;
  margin-top: -18px;
  width: 35px;
  height: 35px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-size: 16px;
  font-weight: 700;
  /* Тонкая обводка фона таблицы — отделяет кружок от аватара под ним,
     иначе на светлой медали граница с фото или силуэтом теряется. */
  border: 2px solid var(--рейтинг-золото-поверхность);
}
/* Картинка медали — вторым слоем фона ПОВЕРХ прежнего золотого/
   серебряного/бронзового градиента (план «Рейтинг по макету», шаг 7):
   цифра места — это textContent того же узла, она рисуется в обычном
   потоке текста и всегда оказывается НАД фоном, картинку медали
   отдельно накрывать не нужно. Если файл из «--значок-медаль» не
   загрузится (404 или его вовсе нет — переменная не задана), верхний
   слой background-image молча пропадает, а градиент под ним как раз
   и остаётся тем самым «честным отсутствием»: место читается всегда. */
#рейтинг-таблица .рейтинг-подиум-карточка[data-место="1"] .рейтинг-подиум-медаль {
  color: #3a2a05;
  background-image: var(--значок-медаль, none), var(--рейтинг-медаль-1);
  background-repeat: no-repeat, no-repeat;
  background-position: center, center;
  background-size: cover, cover;
}
#рейтинг-таблица .рейтинг-подиум-карточка[data-место="2"] .рейтинг-подиум-медаль {
  color: #2b2f33;
  background-image: var(--значок-медаль, none), var(--рейтинг-медаль-2);
  background-repeat: no-repeat, no-repeat;
  background-position: center, center;
  background-size: cover, cover;
}
#рейтинг-таблица .рейтинг-подиум-карточка[data-место="3"] .рейтинг-подиум-медаль {
  color: #3a2410;
  background-image: var(--значок-медаль, none), var(--рейтинг-медаль-3);
  background-repeat: no-repeat, no-repeat;
  background-position: center, center;
  background-size: cover, cover;
}

/* Корона над первым местом — план, пункт 3: 38×33, над аватаром.
   «position:relative» для неё несёт сама карточка (правило выше).
   Сама картинка короны из макета (PNG, шаг 7 плана «Рейтинг по
   макету») лежит в «::after» — БЕЗ маски: mask обрезала бы готовую
   PNG по контуру svg-силуэта из «--значок-корона», рассчитанного на
   плоскую заливку, а не на объёмную картинку владельца. Золотой
   silhouette через mask остаётся в «::before» как запасной вид —
   он ниже в дереве («::after» рисуется позже «::before» у одного
   и того же элемента, то есть поверх), и виден, только если файл
   картинки не загрузится: короны без вида не бывает. */
#рейтинг-таблица .рейтинг-подиум-корона {
  position: absolute;
  top: -22px;
  left: 50%;
  z-index: 1;
  width: 38px;
  height: 33px;
  transform: translateX(-50%);
  pointer-events: none;
}
#рейтинг-таблица .рейтинг-подиум-корона::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(160deg, #ffe08a 0%, #f0bd3a 45%, #c98d12 100%);
  -webkit-mask: var(--значок-корона) center / contain no-repeat;
  mask: var(--значок-корона) center / contain no-repeat;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.5));
}
#рейтинг-таблица .рейтинг-подиум-корона::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--значок-корона-картинка, none);
  background-position: center;
  background-size: contain;
  background-repeat: no-repeat;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.5));
}

/* Имя и очки теперь лежат ВНУТРИ тумбы-основания (см. правило
   «.рейтинг-подиум-основание» ниже), не под аватаром — план, пункт 3.
   «display:flex» и своя ширина нужны, чтобы «ellipsis» у длинного
   имени вообще сработал: без ограничения ширины блоку нечего обрезать.
   Сам текст имени и пилюля «Вы» — родные span'ы внутри («__текст» и
   «__вы», та же пара, что у строки списка и карточки «Моё место»,
   см. «.рейтинг-имя» выше): обрезается многоточием только «__текст»
   (правило «.рейтинг-имя__текст» тоже выше, оно общее на все три места),
   «Вы» с «flex-shrink: 0» у «#рейтинг-таблица .рейтинг-имя__вы» стоит
   рядом целиком. Карточка по умолчанию по центру («.рейтинг-подиум-
   -карточка»: text-align:center) — здесь тот же центр даёт «justify-
   -content», раз строка теперь флекс, а не одиночный текстовый узел. */
#рейтинг-таблица .рейтинг-подиум-имя {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 6px;
  width: 100%;
  min-width: 0;
  font-size: 14px;
  /* План «рейтинг по макету», п. 9: у макета имя на тумбе обычным весом,
     не полужирным — очки рядом и так золотые и крупные, различие видно. */
  font-weight: 400;
  color: var(--сб-текст);
}

/* Очки на подиуме — число, резать его многоточием нельзя (жалоба
   владельца: «999 999 999» обрезалось до «999 9…»). Поэтому здесь
   «white-space: nowrap» без «overflow: hidden»/«text-overflow: ellipsis» —
   строка выводится целиком всегда, а под узкую карточку сам кегль
   уменьшается «clamp»-ом от ширины окна. Прямой («A*vw») клэмп на
   границе 390 точек чуть занижал бы кегль у коротких очков вроде
   «1 240» — вместо него «calc(A*vw - Bpx)»: прямая подобрана так, что
   при 390 точках (обычная ширина телефона) она даёт ровно верхнюю
   границу — 19px, прежний размер, а при 320 (самый узкий телефон) —
   14px, с запасом умещает даже «999 999 999» на самой тесной боковой
   карточке (~87 точек внутри тумбы). Нижняя граница clamp — 13px —
   просто страховка на случай ещё более узкого окна. */
#рейтинг-таблица .рейтинг-подиум-очки {
  display: block;
  width: 100%;
  /* Обычный кегль (до 5 цифр вроде «1 240») лежит в переменной, а не
     литералом в «font-size» — его же переиспользуют модификаторы
     «--длинные»/«--очень-длинные» ниже через «var()», чтобы не заводить
     вторую копию этого «clamp» под каждую длину числа. */
  --рейтинг-подиум-очки-кегль: clamp(13px, calc(7.1vw - 8.7px), 19px);
  font-size: var(--рейтинг-подиум-очки-кегль);
  font-weight: 750;
  /* План «рейтинг по макету», п. 9: коэффициент макета 1.45 (19px → 27.5,
     22px у первого места → 31.9) — было 1.3, строка выглядела тесной. */
  line-height: 1.45;
  font-variant-numeric: tabular-nums;
  color: var(--рейтинг-золото);
  white-space: nowrap;
}

/* Первое место — та же прямая, сдвинутая под свои границы: 22px на
   390 точках (прежний размер), 16px на 320 (запас на центральной
   карточке, она шире боковых). */
#рейтинг-таблица .рейтинг-подиум-карточка[data-место="1"] .рейтинг-подиум-очки {
  --рейтинг-подиум-очки-кегль: clamp(15px, calc(8.6vw - 11.5px), 22px);
  font-size: var(--рейтинг-подиум-очки-кегль);
}

/* Длинные очки (6+ цифр) на узкой карточке не влезают даже с «clamp»
   выше — «999 999 999» при обычном кегле шире самой тумбы (замер:
   93×82 на 320, 126×104 на 390 — текст ощутимо больше места). Классы
   вешает разработчик на span очков: «--длинные» — 6–7 цифр (от 100 000),
   «--очень-длинные» — 8+ цифр (от 10 000 000). Обычные очки (до 5 цифр)
   эти классы не получают — их вид по макету не трогаем, работает
   переменная «--рейтинг-подиум-очки-кегль» из правил выше.

   Кегль через «cqi» (контейнер — сама карточка, см. «container-type»
   у «.рейтинг-подиум-карточка» выше) устроен так, что доля занятой
   ширины НЕ зависит от того, боковая карточка это или центральная
   первого места (шире на 10% — «1.1fr» у сетки) и от ширины экрана:
   при кегле «N·cqi» текст шириной «X·em» всегда занимает «X·N / 100»
   от ширины карточки, какой бы та ни была. При «tabular-nums» цифра
   и пробел-разделитель занимают одинаковую ширину ≈0.6em — значит:
     «999 999 999» (9 цифр, 2 пробела, 11 знаков) ≈ 6.6em,
     «9 999 999» (7 цифр, 2 пробела, 9 знаков) — худший случай
     «--длинные» — ≈5.4em.
   Запас ≥5% по этому расчёту давал 14cqi/17cqi — но замер Playwright на
   320 (span «999 999 999» при 14cqi: scrollWidth 94 / clientWidth 91;
   span «555 555 555» при 17cqi: scrollWidth 85 / clientWidth 82) показал
   перебор ~3.5%: у самого числа места МЕНЬШЕ, чем у карточки (мешают
   внутренние отступы карточки), а цифры на деле чуть шире 0.6em из
   расчёта. Пересчёт от замера с запасом ≥8% (новый N = старый N ×
   clientWidth×0.92 / scrollWidth): очень-длинные 14×91×0.92/94 ≈ 12.5 →
   берём 12; длинные 17×82×0.92/85 ≈ 15.1 → берём 15.
   Запас держится на ЛЮБОЙ ширине (320/390/768/1280) и у боковых, и у
   центральной карточки — это и есть смысл «cqi» здесь, отдельный расчёт
   на каждую ширину/карточку не нужен. «min()» со старым «clamp» —
   подстраховка сверху: на широком экране, где «N·cqi» вырастет больше
   старого потолка (19px/22px), в дело возвращается прежний кегль.
   Отдельная строка под «[data-место="1"]» нужна из-за специфичности:
   обычная строка ниже её не перебивает. */
#рейтинг-таблица .рейтинг-подиум-очки.рейтинг-подиум-очки--длинные {
  font-size: min(var(--рейтинг-подиум-очки-кегль), 15cqi);
}

#рейтинг-таблица .рейтинг-подиум-очки.рейтинг-подиум-очки--очень-длинные {
  font-size: min(var(--рейтинг-подиум-очки-кегль), 12cqi);
}

#рейтинг-таблица .рейтинг-подиум-карточка[data-место="1"] .рейтинг-подиум-очки.рейтинг-подиум-очки--длинные {
  font-size: min(var(--рейтинг-подиум-очки-кегль), 15cqi);
}

#рейтинг-таблица .рейтинг-подиум-карточка[data-место="1"] .рейтинг-подиум-очки.рейтинг-подиум-очки--очень-длинные {
  font-size: min(var(--рейтинг-подиум-очки-кегль), 12cqi);
}

/* Тёмная тумба-основание под каждым игроком — теперь контейнер имени
   и очков (план, пункт 3), не пустая плашка фиксированной высоты:
   высота у всех троих складывается из одного и того же «padding»,
   а «повыше у первого» получается из более крупных аватара и шрифта
   очков над ней, как в макете. Градиент и скругление — числа макета.
   План «рейтинг по макету», п. 7: у прототипа (prototype/styles.css,
   «.podium-base») тонкая рамка ВСЁ ЖЕ есть — снизу без неё (тумба
   сливается со списком под ней), у первого места цвет теплее. Старое
   решение «Партия 6, пункт 8.8» об отсутствии рамки было ошибкой на
   глаз, сверка с исходником макета её не подтвердила. */
#рейтинг-таблица .рейтинг-подиум-основание {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
  padding: 19px 4px 10px;
  border: 1px solid #2f2d26;
  border-bottom: none;
  border-radius: 30px 30px 0 0;
  background: linear-gradient(180deg, #171716, #080809);
}

#рейтинг-таблица .рейтинг-подиум-карточка[data-место="1"] .рейтинг-подиум-основание {
  border-color: #5e4f30;
}

/* Своя карточка на подиуме — та же метка по смыслу, что своя строка
   в списке («рейтинг-строка--я»), но своим классом: сетка карточки
   подиума устроена иначе (колонка, не грид-таблица строки), общий
   класс строки бы просто не подошёл по вёрстке. Золотым остаётся
   только имя — обводку тумбы см. комментарий выше (пункт 8.8). */
#рейтинг-таблица .рейтинг-подиум-карточка--я .рейтинг-подиум-имя {
  color: var(--рейтинг-золото);
}

/* Шапка списка «МЕСТО / ИГРОК / ОЧКИ» — план «Рейтинг по макету», заход 2,
   пункт 5. Числа макета: фон #151517 (темнее золотой поверхности строк —
   в макете шапка заметно темнее), скругление 8px сверху (первая плитка
   таблицы), 10px, letter-spacing 0.5px, прописные буквы через CSS,
   а не текстом в разметке (регистр — дело оформления). */
#рейтинг-таблица .рейтинг-строка.рейтинг-строка--шапка {
  /* Базовая сетка строки («#рейтинг-таблица .рейтинг-строка» выше) —
     ДВЕ строки грида: «место/аватар/имя» растянуты на обе (там снизу
     под «очки» ещё умещается мелкая «победы»), а «очки» лежит только
     в верхней. В обычной строке это осмысленно, в шапке — нет: «победы»
     там нет вовсе (у меры «очки» рисуются только МЕСТО/ИГРОК/ОЧКИ), но
     вторая, пустая строка сетки всё равно съедала пару пикселей высоты
     авто-подгонкой — из-за этого «очки» с «align-self: center» ниже
     всё равно центрировались НЕ по той же высоте, что «место»/«имя»
     (жалоба владельца 23.09). Одна строка сетки убирает саму разницу:
     нечему больше растягивать «место» ниже, чем «очки». */
  grid-template-areas: "место аватар имя очки победы";
  /* У меры «очки» ячейки «победы» в шапке нет вовсе — пятая колонка
     просто пустует (auto = 0). А у меры «сила игры» шапка кладёт ЧЕТВЁРТУЮ
     подпись «Партий» (класс «.рейтинг-победы», см. «шапкаТаблицы» в
     js/рейтинг-экран.js) — без своей area она попадала в базовую сетку
     строки («0 12709») со ВТОРОЙ implicit-строкой грида и опускалась ниже
     остальных подписей (задание штаба 23.09, второй заход). Отдельная
     колонка вместо второй строки держит «Партий» на той же линии. */
  grid-template-columns: 30px 35px minmax(0, 1fr) auto auto;
  /* План «рейтинг по макету», п. 12: у макета шапка не совсем тонкая
     полоска, а плитка высотой 34 (min-height, не жёсткая height — длинный
     заголовок игры не обрежется, если вдруг не влезет). */
  min-height: 34px;
  padding: 0 8px;
  background: #151517;
  border: none;
  border-radius: 8px 8px 0 0;
  font-size: 10px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--рейтинг-золото-текст-тихий);
}

#рейтинг-таблица .рейтинг-строка--шапка::before { visibility: hidden; height: 0; }

/* «.рейтинг-очки»/«.рейтинг-победы» у обычной строки стоят на дне своей
   грид-ячейки (align-self: end, см. правило выше) — там под ними снизу
   есть вторая строка сетки для «победы». У шапки этой второй строки
   нет («шапкаТаблицы» кладёт «победы» только у меры «сила»), а ячейка
   «место» растянута на обе строки и центрируется по ВСЕЙ высоте —
   из-за этого «очки», прижатые к низу ТОЛЬКО своей (верхней) строки,
   оказывались заметно выше центра «место»: жалоба владельца 23.09
   («РЕЙТИНГ» стоит выше «МЕСТО» и «ИГРОК»). В шапке все подписи —
   просто текст в одну линию, поэтому здесь центрируем принудительно. */
#рейтинг-таблица .рейтинг-строка--шапка :is(.рейтинг-место, .рейтинг-имя, .рейтинг-очки, .рейтинг-победы) {
  align-self: center;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: inherit;
}

/* Своя строка — по плану «Рейтинг по макету», партия 6, шаг 5: карточка
   «Моё место» переехала в отдельный узел под списком (ниже по файлу),
   своя строка ВНУТРИ таблицы больше не карточка и не липнет к низу —
   просто лёгкая подсветка (числа макета «.rank-row.own-row»), одна и
   та же всегда, а не только пока после неё есть другие строки.
   «position: relative» нужен как опора для золотого кольца вокруг
   аватара («::before» ниже). */
#рейтинг-таблица .рейтинг-строка.рейтинг-строка--я {
  position: relative;
  background: #e1c27c10;
  border: none;
  border-bottom: 1px solid #272626;
  border-radius: 8px;
  outline: 1px solid #d0b27680;
  box-shadow: none;
}

/* Золотое кольцо вокруг аватара своей строки — по макету. ПОДТВЕРЖДЕНО:
   у значка-силуэта маска («-webkit-mask: var(--значок-аватар) center /
   contain no-repeat» в базовом правиле «::before» выше) обрезает ВЕСЬ
   рендер псевдоэлемента целиком — в том числе «box-shadow»: в вычисленном
   стиле тень была, на экране (снимок смотрителя) её не было. Наложить
   кольцо СВЕРХУ маски нельзя — обрежется вместе со значком. Поэтому для
   силуэта кольцо не накладываем, а включаем ВНУТРЬ самой маски вторым
   слоем — узкий «бублик» в той же 35×35 области, что и значок. У маски
   несколько слоёв по умолчанию объединяются («mask-composite: add» —
   это начальное значение, отдельно указывать не нужно), а красит оба
   слоя один и тот же «currentColor» (золото — ниже), поэтому кольцо и
   силуэт сливаются в одну золотую фигуру. Сам значок при этом чуть
   уменьшен (31 точка вместо во весь бокс), иначе кольцу внутри тех же
   35 точек не остаётся места — маска обрежет и его тоже. Числа выросли
   вслед за аватаром строки (32 → 35, партия 5, пункт 6) теми же долями,
   чтобы кольцо не стало уже самого значка.
   У настоящей фотографии (класс «--фото», кладёт js/рейтинг-экран.js)
   маска снята целиком («mask: none» в правиле «--фото::before» выше) —
   там обрезать «box-shadow» нечему, поэтому кольцо там по-прежнему
   рисуем им, отдельным правилом ниже. */
#рейтинг-таблица .рейтинг-строка--я::before {
  color: var(--рейтинг-золото);
  border-radius: 50%;
}

#рейтинг-таблица .рейтинг-строка--я:not(.рейтинг-строка--фото)::before {
  -webkit-mask-image: var(--значок-аватар), radial-gradient(circle, transparent 14px, #000 14px 16px, transparent 16px);
  mask-image: var(--значок-аватар), radial-gradient(circle, transparent 14px, #000 14px 16px, transparent 16px);
  -webkit-mask-size: 31px 31px, 35px 35px;
  mask-size: 31px 31px, 35px 35px;
  -webkit-mask-position: center, center;
  mask-position: center, center;
  -webkit-mask-repeat: no-repeat, no-repeat;
  mask-repeat: no-repeat, no-repeat;
}

#рейтинг-таблица .рейтинг-строка--я.рейтинг-строка--фото::before {
  box-shadow: 0 0 0 2px var(--рейтинг-золото);
}

#рейтинг-таблица .рейтинг-строка--я :is(.рейтинг-место, .рейтинг-очки) {
  color: var(--рейтинг-золото);
}

#рейтинг-таблица .рейтинг-строка--я:not(:is([data-место="1"], [data-место="2"], [data-место="3"])) .рейтинг-место {
  background: none;
}

#рейтинг-таблица .рейтинг-строка--я .рейтинг-победы { color: var(--сб-текст-тихий); }

/* ---------- Конец списка, беда и новичок (партия 5, новые узлы js) ----------
   Все четыре узла ниже кладёт js/рейтинг-экран.js по договору имён;
   тексты для человека живут там же, здесь только вид.

   Конец списка — «Показать ещё», а когда показывать нечего, на том же
   месте тихая строка «Все игроки показаны». Обёртка одна и та же,
   поэтому конец списка не прыгает, когда кнопка сменяется фразой. */
#экран-рейтинга-игроков .рейтинг-список-конец {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 16px;
  font-size: 13px;
  color: var(--сб-текст-тихий);
}

/* Две кнопки конца списка — одна и та же тихая кнопка макета
   («.secondary-button», prototype/styles.css:76): «Показать ещё» в
   обычном списке и «В начало списка» в срезе соседей (js/рейтинг-
   экран.js, «концоСписка»). Вид им даёт общий класс «кнопка--тихая»,
   здесь только поведение в узкой строке: ширина по надписи и никакого
   сжатия — иначе на 320 точках «В начало списка» ломалось бы на две
   строки, а кнопка становилась выше «Показать ещё». */
#экран-рейтинга-игроков .рейтинг-список-конец > #кнопка-рейтинг-показать-ещё.кнопка,
#экран-рейтинга-игроков .рейтинг-список-конец > #кнопка-рейтинг-в-начало.кнопка {
  flex: 0 0 auto;
  width: auto;
  white-space: nowrap;
}

/* Кнопка «Повторить» под сообщением о беде — по центру и по ширине
   слова: во всю колонку она читалась бы как главное действие экрана. */
#экран-рейтинга-игроков #кнопка-рейтинг-повторить {
  align-self: center;
  width: auto;
  margin-top: 8px;
}

/* Новичок: его карточка «моё место» есть всегда, но места и очков
   в ней ещё нет (js ставит «—» и 0). Поэтому у карточки добавлена
   четвёртая строка сетки — под подсказку «сыграйте первую партию»;
   строка «победы» в шаблоне оставлена, чтобы ячейка побед у меры
   «сила игры» не создавала лишний ряд. */
#рейтинг-таблица .рейтинг-строка.рейтинг-строка--я.рейтинг-строка--новичок {
  grid-template-areas:
    "метка метка метка метка"
    "место аватар имя очки"
    "место аватар имя победы"
    "подсказка подсказка подсказка подсказка";
}

#рейтинг-таблица .рейтинг-новичок-подсказка {
  grid-area: подсказка;
  font-size: 12px;
  line-height: 1.35;
  color: var(--сб-текст-тихий);
}

/* Строка-разрыв «⋯» — между несмежными местами (например, между
   пятёркой лидеров и вашими соседями). Это не игрок: ни аватара,
   ни колонок, только знак по центру, чтобы список не читался как
   сплошной ряд подряд идущих мест. */
#рейтинг-таблица .рейтинг-строка.рейтинг-строка--разрыв {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 36px;
  font-size: 14px;
  color: var(--сб-текст-тихий);
}

#рейтинг-таблица .рейтинг-строка--разрыв::before { display: none; }

/* Фразы сервера в списке — серым; ярлыки разделов — мелкими прописными. */
#рейтинг-таблица > .подпись { color: var(--сб-текст-тихий); }

#рейтинг-таблица > .подпись.рейтинг-пояснение {
  color: var(--сб-текст);
  background: var(--плитка);
  border-left-color: var(--сб-акцент);
}

#рейтинг-таблица > .подпись.рейтинг-соперник { background: var(--плитка); }

/* «Как считается» — тихая ссылка под списком. */
#экран-рейтинга-игроков > #кнопка-рейтинг-как-считается.кнопка {
  align-self: center;
  width: auto;
  min-height: 44px;
  padding: 0 12px;
  font-size: 15px;
  font-weight: 500;
  color: var(--сб-текст-тихий);
  background: none;
  border: none;
  box-shadow: none;
  text-decoration: underline;
  text-decoration-color: rgba(133, 139, 148, 0.5);
  text-underline-offset: 4px;
}

#экран-рейтинга-игроков > #рейтинг-объяснение .подпись { color: var(--сб-текст-тихий); }

/* ---------- «Как я играю»: строки счёта ---------- */
#экран-рейтинга > #таблица-рейтинга {
  flex: 1 1 auto;
  min-height: 0;
  gap: 6px;
  scrollbar-width: thin;
  scrollbar-color: rgba(248, 245, 235, 0.18) transparent;
}

#таблица-рейтинга .таблица__раздел {
  margin: 10px 0 0;
  padding: 0 2px 2px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--сб-текст-тихий);
  border-bottom: none;
}

#таблица-рейтинга .таблица__строка {
  min-height: 48px;
  padding: 8px 14px;
  background: var(--плитка);
  border: 1px solid var(--плитка-кромка);
  border-radius: 14px;
}

#таблица-рейтинга .рейтинг__название {
  font-size: 15.5px;
  font-weight: 600;
  color: var(--сб-текст);
}

#таблица-рейтинга .рейтинг__доля {
  color: var(--сб-текст);
  background: rgba(248, 245, 235, 0.08);
}

#таблица-рейтинга .таблица__пусто {
  padding: 14px;
  font-size: 15px;
  line-height: 1.45;
  text-align: left;
  color: var(--сб-текст-тихий);
  background: var(--плитка);
  border: 1px solid var(--плитка-кромка);
  border-radius: 14px;
}

/* Приписка «Счёт ведётся с …» — без плитки (см. общее правило выше). */
#таблица-рейтинга .таблица__строка ~ .таблица__пусто,
#экран-рейтинга:not(:has(#рейтинг-подпись.скрыт)) #таблица-рейтинга .таблица__пусто + .таблица__пусто {
  padding: 8px 2px 0;
  font-size: 12.5px;
  background: none;
  border: none;
}

/* «Стереть счёт партий» — осторожная тихая плитка у низа. */
#экран-рейтинга > #кнопка-стереть-счёт.кнопка {
  align-self: center;
  width: min(100%, 300px);
  min-height: 44px;
  border-radius: 14px;
}

/* ---------- Невысокое окно ---------- */
@media (max-height: 700px) {
  :is(#экран-рейтинга-игроков, #экран-рейтинга) { gap: 8px; }
  /* Только «Как я играю» — у «#экран-рейтинга-игроков» заголовок теперь
     внутри «.рейтинг-шапка» и не прямой потомок экрана (см. правило
     «#экран-рейтинга > .заголовок» выше по файлу, тот же повод). */
  #экран-рейтинга > .заголовок { font-size: clamp(26px, 8vw, 34px); }
  /* Невысокое окно — шапке-карточке тоже нужно чуть сжаться, тем же
     приёмом, что у заголовка «Как я играю» строкой выше. */
  #экран-рейтинга-игроков > .рейтинг-шапка { min-height: 52px; }
  #экран-рейтинга-игроков .рейтинг-шапка__название { font-size: 19px; }
  /* Только «#рейтинг-главное» — у «#рейтинг-моё-место» с шага 5 плана
     «Рейтинг по макету», партия 6, нет ни крупного шрифта, ни высокого
     пола: плоская карточка и так компактна на любой высоте окна. */
  #рейтинг-главное {
    min-height: 76px;
    padding-top: 10px;
    padding-bottom: 10px;
    font-size: clamp(22px, 6.8vw, 28px);
  }
  #экран-рейтинга-игроков > #рейтинг-моё-место.подпись { font-size: 15px; }
  #рейтинг-таблица .рейтинг-строка { min-height: 48px; padding-top: 5px; padding-bottom: 5px; }
}

/* ---------- Широкий монитор: строки просторнее ----------
   Макет (docs/02_RESPONSIVE_RU.md, раздел «Компьютер»): от 1200 точек
   строка около 64 точек, аватар около 40. Колонку в две мы всё равно
   не разводим (закон «все игры выглядят одинаково»), но список на
   большом экране перестаёт выглядеть телефонной лентой: просвет между
   строками больше, аватары крупнее. Столбец аватара в сетке строки
   растёт тем же числом — шапка столбцов стоит на той же сетке, поэтому
   её заголовки уезжают вместе со строками, отдельного правила не надо.
   Условие по высоте — чтобы широкое, но низкое окно (лежачий телефон,
   узкая полоса браузера) не получило высокие строки: там и так тесно. */
@media (min-width: 1200px) and (min-height: 700px) {
  #рейтинг-таблица .рейтинг-строка {
    grid-template-columns: 2.2em 40px minmax(0, 1fr) auto;
    min-height: 64px;
  }

  #рейтинг-таблица .рейтинг-строка::before {
    width: 40px;
    height: 40px;
  }

  #рейтинг-таблица .рейтинг-строка:not(.рейтинг-строка--шапка, .рейтинг-строка--я, .рейтинг-строка--разрыв)::after {
    width: 40px;
    height: 40px;
  }

  #рейтинг-таблица .рейтинг-аватар__инициалы {
    width: 40px;
    height: 40px;
    font-size: 13px;
  }

  /* Золотое кольцо своей строки живёт внутри маски (см. «ПОДТВЕРЖДЕНО»
     выше), поэтому растёт не само — числа те же доли от 40 точек,
     какими были от 35. */
  #рейтинг-таблица .рейтинг-строка--я:not(.рейтинг-строка--фото)::before {
    -webkit-mask-image: var(--значок-аватар), radial-gradient(circle, transparent 16px, #000 16px 18px, transparent 18px);
    mask-image: var(--значок-аватар), radial-gradient(circle, transparent 16px, #000 16px 18px, transparent 18px);
    -webkit-mask-size: 35px 35px, 40px 40px;
    mask-size: 35px 35px, 40px 40px;
  }

  /* Строка-разрыв ростом не меняется: это знак, а не игрок. */
  #рейтинг-таблица .рейтинг-строка.рейтинг-строка--разрыв { min-height: 36px; }
}

/* =====================================================================
   ПАНЕЛЬ ВЫБОРА ИГРЫ — ШТОРКА СНИЗУ

   Список игр (кнопка-триггер оформлена выше) сделан шторкой снизу,
   а не окошком по центру: тот же приём, что у листа «Ещё» (см.
   «.лист-ещё» в начале файла) — большой палец на телефоне и так тянется
   к низу экрана, а не к середине, и вид получается тем же самым, что
   игрок уже видел на «⋯», меньше сюрпризов. Анимации появления взяты
   ровно те же (keyframes «лист-ещё-вверх» и «лист-ещё-фон», объявлены
   там же) — устройство разметки своё: панель лежит не внутри «.лист-
   ещё», а отдельным узлом прямо в «#приложение», как и просил
   разработчик, чтобы «position: fixed» не зависело от предков.

   Панель — вне «#экран-рейтинга-игроков», поэтому переменные экрана
   («--плитка», «--подложка», «--край» и другие, которыми красится
   базовая кнопка «Закрыть» и поле поиска) ей не видны — объявлены
   заново прямо на корне панели, теми же числами, что у самого экрана
   рейтинга выше и у других тёмных экранов сборника.

   Ответ владельца пришёл: «Золото как в макете». Поменялись только
   значения «--акцент» и «--край» в этом наборе — ровно как и было
   предсказано здесь строкой раньше, устройство панели то же самое. */
.рейтинг-панель-игр {
  --текст: var(--сб-текст);
  --текст-тихий: var(--сб-текст-тихий);
  --кнопка-фон: var(--сб-акцент);
  --кнопка-текст: var(--сб-акцент-текст);
  /* Был var(--сб-акцент) (салатовый) — по макету панель выбора игры
     золотая. Число одно на весь сборник и живёт в «--рейтинг-золото-
     общее»/«--рейтинг-золото-край-общее» на «#приложение» (общий предок
     этой панели и «#экран-рейтинга-игроков») — здесь только чтение,
     второй копии числа больше нет. */
  --акцент: var(--рейтинг-золото-общее);
  --подложка: rgba(248, 245, 235, 0.06);
  --край: var(--рейтинг-золото-край-общее);
  --плитка: #1e2226;
  --плитка-кромка: rgba(248, 245, 235, 0.12);
  --плитка-нажата: #262a2f;
  --поле: clamp(12px, 3.6vw, 18px);

  position: fixed;
  inset: 0;
  z-index: 30;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
}

.рейтинг-панель-игр.скрыт { display: none; }

/* Затемнение — клик по нему закрывает панель (js/рейтинг-экран.js). */
.рейтинг-панель-игр__фон {
  position: absolute;
  inset: 0;
  background: rgba(5, 7, 8, 0.6);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  animation: лист-ещё-фон 0.2s ease-out;
}

.рейтинг-панель-игр__окно {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  max-width: 520px;
  /* Не выше экрана минус верхний вырез — список внутри прокрутится сам. */
  max-height: calc(100% - 24px - var(--отступ-сверху));
  padding: 22px calc(var(--поле) + var(--отступ-справа)) calc(12px + var(--отступ-снизу))
           calc(var(--поле) + var(--отступ-слева));
  color: var(--сб-текст);
  /* План «рейтинг по макету», п. 28: числа именно окна выбора игры
     (prototype/styles.css: «#picker»), не общая переменная
     «--сб-поверхность» — той же переменной красится окно шторки
     «Как считается», её вид этот пункт не трогает. */
  background: linear-gradient(140deg, #1a1a1c, #0d0d0f);
  border: 1px solid #796543;
  border-bottom: none;
  border-radius: 24px 24px 0 0;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 -12px 32px rgba(0, 0, 0, 0.45);
  animation: лист-ещё-вверх 0.22s cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* Ручка сверху. План «рейтинг по макету», п. 33: своя ширина и цвет,
   не общий знак шторки листа «Ещё» (prototype/styles.css: «.sheet-
   handle» — 48×4, тёплый серый, не белый полупрозрачный). */
.рейтинг-панель-игр__окно::before {
  content: "";
  position: absolute;
  top: 8px;
  left: 50%;
  width: 48px;
  height: 4px;
  margin-left: -24px;
  border-radius: 4px;
  background: #939087;
}

/* Партия css-В, пункт 1: раньше шапка была одной строкой-лентой
   («display: flex»), и поле поиска втискивалось в неё третьим
   элементом рядом с заголовком и «×» — а в макете заголовок и «×»
   стоят одной строкой сверху, поле поиска отдельной строкой во всю
   ширину под ними. Сетка с именованными областями решает это без
   оглядки на порядок узлов в разметке (js кладёт их как заголовок,
   ×, поле — но каждый узел сам называет свою область классом, а не
   местом в потоке, так что порядок можно не подгонять под css). */
.рейтинг-панель-игр__шапка {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas:
    "заголовок закрыть"
    "поиск поиск";
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

/* Заголовок «Выбрать игру» — как dialog-header h2 макета
   (prototype/styles.css:95): размер 22px, буквы чуть плотнее,
   без своего отступа снизу (зазор уже даёт flex-gap шапки). */
.рейтинг-панель-игр__заголовок {
  grid-area: заголовок;
  margin: 0;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.4px;
  color: var(--текст);
}

/* ---------- Поле поиска с лупой (партия 6, пункт 8.11) ----------
   Обёртка встала в шапке на место самого поля, поэтому тянется теперь
   она, а поле внутри занимает всю её ширину. Лупа лежит ПОВЕРХ поля
   слева, а не рядом с ним: так у поля остаётся его собственная рамка,
   а не вторая рамка вокруг первой. */
.рейтинг-панель-игр__поле-поиска {
  grid-area: поиск;
  position: relative;
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  min-width: 0;
}

/* Сама лупа — «.search-symbol» макета (prototype/styles.css:98–99):
   кружок 16×16 обводкой 1,6 точки и косая ручка уголком. Рисуем
   правилами, без картинки: заводить файл ради двух фигур не из чего. */
.рейтинг-панель-игр__лупа {
  position: absolute;
  top: 50%;
  left: 14px;
  width: 16px;
  height: 16px;
  margin-top: -8px;
  border: 1.6px solid var(--текст-тихий);
  border-radius: 50%;
  pointer-events: none;
}

.рейтинг-панель-игр__лупа::after {
  content: "";
  position: absolute;
  right: -3px;
  bottom: -5px;
  width: 1.6px;
  height: 7px;
  background: var(--текст-тихий);
  transform: rotate(-40deg);
}

/* Место слева под лупу: 14 до кружка + 16 сам кружок + 10 просвета. */
.рейтинг-панель-игр__поле-поиска > .рейтинг-панель-игр__поиск {
  width: 100%;
  padding-left: 40px;
}

.рейтинг-панель-игр__поиск {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 48px;
  padding: 0 14px;
  font: inherit;
  font-size: 16px;
  color: var(--сб-текст);
  /* План «рейтинг по макету», п. 32: числа именно поля поиска шторки
     (prototype/styles.css: «.search-field» — фон #242426, рамка 1px
     #575656, радиус 13), не общие «--плитка»/«--сб-граница» — те красят
     и другие тихие плашки сборника, здесь только своё поле. */
  background: #242426;
  border: 1px solid #575656;
  border-radius: 13px;
  -webkit-appearance: none;
  appearance: none;
}

.рейтинг-панель-игр__поиск::placeholder { color: var(--сб-текст-тихий); }

.рейтинг-панель-игр__поиск:focus {
  outline: none;
  border-color: var(--акцент);
}

/* «×» вместо слова «Закрыть» (партия 6, пункт 8.11): вид крестика —
   в общем правиле «.рейтинг-панель-игр__закрыть.кнопка,
   .рейтинг-инфо__закрыть» ниже по файлу, одном на обе шторки. */
.рейтинг-панель-игр__закрыть { grid-area: закрыть; flex-shrink: 0; }

/* Список — прокручивается сам, если игр станет больше, чем влезает
   в невысокое окно. Пункты не сжимаются: сжатие испортило бы только
   высоту под палец. Отступ снизу у поля окна уже учёл полосу жеста
   телефона («--отступ-снизу»), здесь только зазор до самого края. */
.рейтинг-панель-игр__список {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-height: 0;
  gap: 6px;
  overflow-y: auto;
  padding-bottom: 4px;
  -webkit-overflow-scrolling: touch;
}

/* Заголовок группы «ИГРЫ» / «СКОРО» внутри списка — как option-heading
   макета (prototype/styles.css:112): 11 точек, разрядка 1, поля 17/4/8.

   Партия 6, пункт 8.11: на снимке смотритель заголовка не увидел.
   Две поправки, обе про это. «flex-shrink: 0» — список это столбик-флекс
   с прокруткой, и всё, у чего нет этого свойства, он сжимает первым
   (у пунктов оно уже стоит, у заголовка не стояло). «text-transform»
   страхует регистр: заглавные буквы сейчас приходят из js текстом,
   но регистр — дело оформления, и если текст в js когда-нибудь напишут
   строчными, заголовок всё равно останется заголовком. */
.рейтинг-панель-игр__раздел {
  flex-shrink: 0;
  margin: 17px 4px 8px;
  font-size: 11px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: #b0aeaa;
}

/* Партия css-В, пункт 7: раньше кнопка пункта была одной строкой-лентой
   («display: flex») — «подпись-мелкая» лежала третьим элементом ленты
   рядом с подписью, и «display: block» её не спасал (блочность решает,
   что происходит ВНУТРИ узла, а не его место среди соседей по флексу).
   Сетка с двумя строками кладёт мелкую подпись честно ПОД названием:
   области «значок подпись галочка» / «значок мелкая галочка» — значок
   и галочка/шеврон растянуты на обе строки (spans по имени области),
   вторая строка занята только там, где есть мелкая подпись. Ширины
   строк — «min-content» (не «auto»): «auto» забрал бы себе весь запас
   от «min-height: 70px» и увёл единственную строку названия наверх,
   а «min-content» отдаёт высоту только тому, что правда есть, а лишний
   запас центрует «align-content» — так у пунктов БЕЗ мелкой подписи
   вторая строка не появляется как пустой довесок. */
/* План «рейтинг по макету», п. 29: пункт — строка без своего фона
   и рамки, с разделителем снизу (prototype/styles.css: «.game-option» —
   border-bottom 1px solid #303031, radius 0, padding 10px 6px), а не
   отдельная карточка. Подсветку нажатия («:active» ниже) оставляем —
   это отклик пальца, а не расхождение с макетом. */
.рейтинг-панель-игр__пункт {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-rows: min-content min-content;
  grid-template-areas:
    "значок подпись галочка"
    "значок мелкая галочка";
  align-items: center;
  align-content: center;
  column-gap: 0;
  row-gap: 0;
  flex-shrink: 0;
  width: 100%;
  min-height: 70px;
  padding: 10px 6px;
  font: inherit;
  font-size: 16px;
  font-weight: 600;
  text-align: left;
  color: var(--сб-текст);
  background: none;
  border: none;
  border-bottom: 1px solid #303031;
  border-radius: 0;
  cursor: pointer;
  transition: transform 0.12s ease, background-color 0.12s ease;
}

.рейтинг-панель-игр__пункт:active {
  transform: scale(0.98);
  background: var(--плитка-нажата);
}

/* Игры из группы «СКОРО» — как .game-option:disabled макета
   (prototype/styles.css:111): приглушены и не реагируют на палец. */
.рейтинг-панель-игр__пункт:disabled {
  opacity: 0.42;
  cursor: default;
}

.рейтинг-панель-игр__пункт:disabled:active {
  transform: none;
  background: none;
}

/* Значок игры слева от подписи (план «Рейтинг по макету», шаг 7).
   Своя плитка-подложка («--плитка-нажата», уже есть в наборе панели
   выше) — запасной цвет, если картинка не найдётся: квадрат остаётся
   видимым и не превращается в дыру, просто без рисунка внутри.
   У пункта «Все игры» этого узла в разметке нет вовсе (js его не
   создаёт) — не «не загрузилось», а сознательно пусто. */
/* План «рейтинг по макету», п. 31: своя рамка и радиус плитки, фон —
   градиент под картинкой значка (prototype/styles.css: «.game-tile» —
   border 1px #37362e, radius 12, background linear-gradient(135deg,
   #242420,#101012)). Картинка значка и градиент — два слоя одного
   «background-image» через запятую: картинка сверху, градиент под ней,
   у каждого слоя свой размер/повтор той же запятой. */
.рейтинг-панель-игр__значок {
  grid-area: значок;
  flex-shrink: 0;
  width: 50px;
  height: 50px;
  /* Зазор до подписи — своим полем, а не общим «column-gap» сетки:
     у задела «скоро» (ниже по файлу) этого узла в разметке нет вовсе,
     и без своего поля подпись у него верно начинается без отступа
     слева (общий «column-gap» добавил бы пустой зазор всегда, даже
     когда значка нет — колонка сетки под него всё равно существует). */
  margin-right: 12px;
  background-image: var(--значок-игры, none), linear-gradient(135deg, #242420, #101012);
  background-position: center, center;
  /* Плитка 50×50 (макет prototype/styles.css:105), сама картинка внутри
     47×47 (prototype/styles.css:106) — небольшое поле вокруг рисунка,
     не «contain» во всю плитку. Градиент-подложка — во всю плитку. */
  background-size: 47px 47px, cover;
  background-repeat: no-repeat, no-repeat;
  border: 1px solid #37362e;
  border-radius: 12px;
}

.рейтинг-панель-игр__подпись {
  grid-area: подпись;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Вторая строка подписи «Общий рейтинг» у пункта «Все игры» (и «скоро»
   у задела) — как .option-name small макета (prototype/styles.css:109).
   Раньше «display: block» не давал второй строки: подпись-мелкая была
   отдельным ребёнком строки-флекса и просто уезжала вправо в ту же
   строку (см. заметку у «.рейтинг-панель-игр__пункт» выше) — теперь
   у неё собственная область сетки строкой ниже названия, «display:
   block» не нужен для переноса (это уже делает сетка), но не мешает. */
.рейтинг-панель-игр__подпись-мелкая {
  grid-area: мелкая;
  display: block;
  margin-top: 2px;
  font-size: 12px;
  font-weight: 400;
  color: var(--текст-тихий);
}

/* Текущая игра — золотая рамка и приглушённая золотая заливка, как в
   макете (план «рейтинг по макету», п. 30 — prototype/styles.css:
   «.game-option[aria-pressed=true]»: рамка 1px #ccaf6c со всех сторон,
   радиус 14, градиент 130deg, своя ширина поля вместо базовых 10px 6px). */
.рейтинг-панель-игр__пункт--активна {
  font-weight: 700;
  color: var(--текст);
  background: linear-gradient(130deg, rgba(183, 151, 71, 0.125), #101013);
  border: 1px solid #ccaf6c;
  border-radius: 14px;
  padding: 10px 12px;
}

/* Галочка активного пункта — .game-option>.icon макета
   (prototype/styles.css:110). Раньше прижималась к правому краю через
   «margin-left: auto» в строке-флексе — теперь она в своей области
   сетки «галочка» (растянута на обе строки, как и значок слева),
   правым краем и так стоит колонка «auto» по содержимому; свой зазор
   слева от подписи — тем же приёмом, что у значка (не «column-gap»
   сетки, он бы добавлял зазор даже пустой второй строке). */
.рейтинг-панель-игр__галочка {
  grid-area: галочка;
  flex-shrink: 0;
  margin-left: 12px;
  color: var(--акцент);
}

/* Шеврон «›» у невыбранных пунктов (партия 6, пункт 8.11) — стоит там
   же, где у выбранного пункта галочка, и той же ширины, чтобы подписи
   игр не съезжали друг относительно друга. План «рейтинг по макету»,
   п. 33: цвет золотой, как в макете (prototype/styles.css: «.game-
   option .icon» — обе стрелки золотые). Выбранный пункт по-прежнему
   виден без этого шеврона: своя золотая рамка и заливка (правило
   «.рейтинг-панель-игр__пункт--активна» ниже). */
.рейтинг-панель-игр__шеврон {
  grid-area: галочка;
  flex-shrink: 0;
  margin-left: 12px;
  font-size: 20px;
  line-height: 1;
  color: var(--акцент);
}

.рейтинг-панель-игр__пусто {
  padding: 20px 4px;
  text-align: center;
}

/* =====================================================================
   ШТОРКА «КАК СЧИТАЕТСЯ» (партия 6, пункт 8.2)

   Раньше объяснение очков и строка «Всего в таблице…» лежали прямо на
   экране, под списком, и их было видно всегда — на макете владельца
   там нет ни того, ни другого. Теперь обоими узлами владеет шторка:
   js («убедитьсяЧтоЕстьШторкаИнфо») физически переносит их внутрь окна,
   а открывает шторку «i» в шапке.

   Устройство — один в один шторка выбора игры выше: затемнённый фон,
   окно снизу со скруглёнными верхними углами, шапка с заголовком и «×»,
   показ и скрытие общим классом «скрыт». Числа тоже её — второго вида
   шторки в сборнике заводить незачем; своё здесь только то, что внутри
   не список игр, а текст.
   ===================================================================== */

/* Переменные — как у шторки выбора игры: панель живёт вне
   «#экран-рейтинга-игроков» (js кладёт её в «#приложение»), и набор
   экрана ей не виден. Читаем общие числа сборника и общее золото. */
.рейтинг-инфо {
  --текст: var(--сб-текст);
  --текст-тихий: var(--сб-текст-тихий);
  --акцент: var(--рейтинг-золото-общее);
  --поле: clamp(12px, 3.6vw, 18px);

  position: fixed;
  inset: 0;
  z-index: 30;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
}

.рейтинг-инфо.скрыт { display: none; }

/* Затемнение — клик по нему закрывает шторку (js/рейтинг-экран.js). */
.рейтинг-инфо__фон {
  position: absolute;
  inset: 0;
  background: rgba(5, 7, 8, 0.6);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  animation: лист-ещё-фон 0.2s ease-out;
}

/* Окно. Прокручивается оно само целиком (а не текст внутри него):
   объяснение бывает длинным, а на низком окне два вложенных скролла
   человек путает. Потолок высоты — 80% экрана, чтобы за шторкой всегда
   был виден кусок списка и было понятно, куда возвращаться. */
.рейтинг-инфо__окно {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  max-width: 520px;
  max-height: min(80vh, calc(100% - 24px - var(--отступ-сверху)));
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 22px calc(var(--поле) + var(--отступ-справа)) calc(16px + var(--отступ-снизу))
           calc(var(--поле) + var(--отступ-слева));
  color: var(--сб-текст);
  background: var(--сб-поверхность);
  border-radius: 20px 20px 0 0;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 -12px 32px rgba(0, 0, 0, 0.45);
  animation: лист-ещё-вверх 0.22s cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* Ручка сверху — тот же знак шторки, что у листа «Ещё» и у выбора игры. */
.рейтинг-инфо__окно::before {
  content: "";
  position: absolute;
  top: 8px;
  left: 50%;
  width: 36px;
  height: 4px;
  margin-left: -18px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.18);
}

.рейтинг-инфо__шапка {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

/* Заголовок «Как считается» — «.dialog-header h2» макета
   (prototype/styles.css:95), те же 22px. */
.рейтинг-инфо__заголовок {
  margin: 0;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.4px;
  color: var(--сб-текст);
}

/* «×» — круглая кнопка-значок макета («.icon-button», prototype:21, 96):
   44 точки под палец, крупный тонкий крестик золотом. Правило одно на
   обе шторки: и «Как считается», и выбор игры закрываются одинаковым
   крестиком, второй копии этих чисел заводить незачем.
   План «рейтинг по макету», п. 27: у обеих кнопок (js/рейтинг-экран.js,
   «кнопкаЭл») className — ровно «рейтинг-панель-игр__закрыть» или
   «рейтинг-инфо__закрыть», класса «кнопка» на них нет и не было — с ним
   в селекторе правило не совпадало никогда, кнопка оставалась голой
   браузерной (сверка нашла 13px/чёрный/рамка вместо золотого крестика). */
.рейтинг-панель-игр__закрыть,
.рейтинг-инфо__закрыть {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  min-width: 0;
  height: 44px;
  min-height: 44px;
  padding: 0;
  font: inherit;
  font-size: 32px;
  font-weight: 300;
  line-height: 1;
  color: var(--акцент);
  background: none;
  border: none;
  border-radius: 12px;
  box-shadow: none;
  cursor: pointer;
}

.рейтинг-панель-игр__закрыть:active,
.рейтинг-инфо__закрыть:active {
  transform: none;
  background: rgba(248, 245, 235, 0.06);
}

/* Правила начисления и сводка «Всего в таблице…» переехали сюда со
   экрана как есть, вместе со своими классами. Своей прокрутки у них
   быть не должно (её держит окно): «#рейтинг-объяснение» несёт класс
   «таблица» с «overflow-y: auto» и потолком ширины 420 — и то и другое
   здесь перебиваем. */
#рейтинг-инфо #рейтинг-объяснение {
  flex: 0 0 auto;
  width: 100%;
  max-width: none;
  overflow: visible;
}

/* Текст правил — 14 точек, спокойный тёплый серый макета
   («#info-content p», prototype/styles.css:130). */
#рейтинг-инфо #рейтинг-объяснение .подпись {
  font-size: 14px;
  line-height: 1.45;
  color: #ceccc7;
}

/* Сводка «Всего в таблице…» — последней строкой и тише правил: это
   справка о таблице, а не само объяснение. */
#рейтинг-инфо #рейтинг-итог {
  flex: 0 0 auto;
  margin: 0;
  font-size: 13px;
  line-height: 1.4;
  text-align: left;
  color: var(--сб-текст-тихий);
}

/* =====================================================================
   ЦВЕТ СУКНА — ВСЕГДА БОРДОВЫЙ

   Решение владельца от 22.09: сукно у дурака одно — бордовое, как
   на макете. Выбора цвета сукна нет, и на фон страницы сукно не
   выходит вовсе: служебные экраны дурака (лобби, шаги, комната,
   рейтинг, «Как играть») тёмные, как у шашек, шахмат и нард.

   Сукно живёт только там, где нарисован стол в деревянной раме:
   «#зона-стола» (стол партии), «.рассадка» (места за столом в комнате),
   «.пример-перевода» (картинка в правилах) и плашка главного числа
   на «Как я играю». Каждый из этих узлов объявляет три тона сукна
   у себя (светлее посередине, основной и тёмный к бортам), зерно ткани
   и тень от рамы рисует то же правило стола — раздел «Стол: деревянная
   рама и бордовое сукно». Образец в «Оформлении» у дурака теперь
   показывает фон СТРАНИЦЫ (общее правило «.образец-фона», как у шашек),
   сукна там больше нет.

   Признак «data-фон» на странице остался за выбором ФОНА у шашек,
   шахмат и нард (слой «.фон-игры» в начале файла) — сукна он больше
   не касается.
   ===================================================================== */

/* =====================================================================
   ШИРОКОЕ ОКНО: планшет и монитор — игра на весь экран

   КАК БЫЛО. 10 сентября владелец прислал снимок с компьютера: «у меня
   посередине полоса идёт, а слева справа огромное пространство». Тогда
   колонку шириной с телефон оформили отдельным «экраном» (480 точек,
   скругление, тень), а 11 сентября, после слов «на планшете и на большом
   экране масштаб неверный», стали увеличивать этот «экран» целиком
   (transform: scale) по высоте окна. Владелец после выкладки: «по
   планшету так же и осталось, очень маленькое поле и игра не на весь
   экран». Он прав: увеличенный телефон — всё тот же телефон. Лёжа
   (1180×820) увеличения не было вовсе, и сукно было узкой полосой
   посередине с пустыми краями.

   КАК СТАЛО. Ни увеличения, ни рамки: приложение занимает всё окно,
   как на телефоне, а экраны раскладываются на настоящую ширину.
     • Стол — те же ряды в том же порядке (шапка, соперник или места
       компании, сукно с колодой, «Вы», подсказка, рука, кнопки), но во
       всю ширину окна с обычными полями. Сукно забирает всю свободную
       высоту. Карта в руке, карты на сукне и колода считаются от места,
       которое им досталось, — на планшете они заметно крупнее
       телефонных, а лёжа их держит высота окна.
     • Витрина, лобби и шаги — ШИРОКОЙ колонкой (760 точек), а не во всю
       ширину. Причина — чтение: в карточках входа и вариантах правил
       строка слева, а стрелка или галочка справа; растянутые на 1180–1920
       точек, они разъезжаются так, что глаз теряет, что к чему. У витрины
       картинки плиток держат свои пропорции, и в две колонки шириной
       по 370 они уже крупные. На планшете стоя 760 — это почти вся
       ширина, лёжа и на мониторе — ясная колонка, а не телефонная полоса.
   Кнопки, текст, панели — прежнего размера: на планшете точка экрана
   физически крупнее, чем на телефоне, и те же размеры читаются свободно.
   Крупнеет то, во что играют, — карты.

   ПОЛЁТ КАРТ И БРОСОК. js/game.js («увеличениеЭкрана») и
   js/движение-карт.js («увеличениеВокруг») меряют увеличение сами:
   ширина узла на экране делённая на его ширину в разметке. Увеличения
   больше нет — они получают ровно 1, как на телефоне. Переменная
   «--масштаб» ушла вместе со ступенями: из скриптов её никто не читал.

   ЭТАП Э8 (10.09, снимок владельца): «посередине полоса, слева-справа
   пусто» — а это была правда только про шашки, шахматы и нарды, потому
   что почти все правила ниже держались за «:has(#экран-витрины)», то
   есть срабатывали ТОЛЬКО на index.html. У шашек, шахмат и нард широкое
   окно оставалось без единого из этих правил.

   ЧТО ОБОБЩЕНО (работает теперь на всех четырёх страницах): ширина
   колонки лобби и шагов, поля по бокам, нижняя полоса вкладок, потолок
   ширины доски у шашек и шахмат (новый), фон вокруг колонки (новый,
   см. блок «Э8: ШИРОКИЙ ЭКРАН» ниже раздела).

   ЧТО СОЗНАТЕЛЬНО ОСТАВЛЕНО ТОЛЬКО ДУРАКУ (и почему): раскладка
   карточного стола (ряды карт растут вместе с шириной — у настольных
   игр вместо ряда карт квадратная доска, для неё это чужой приём),
   лёжа-раскладка лобби в две колонки (решение владельца по этому
   заходу — колонка остаётся ОДНА, не разводим на разные экраны разное
   число колонок), и «шапка стола в одну строку лёжа» (использует те же
   классы, что и шапка нард, — трогать её было бы риском для чужой,
   уже работающей игры, а декрет этого не просит).

   ПОРОГ 700×600 — прежний. Уже 700 это телефон или узкое окно — там
   телефонная раскладка и так занимает всё. Ниже 600 по высоте — это
   лежащий на боку телефон, у него своя телефонная раскладка. */
@media (min-width: 700px) and (min-height: 600px) {
  :root {
    /* Поле по краям экрана: 21 точка на 700, 35 на 1180, не больше 48. */
    --поле-широкое: clamp(20px, 3vw, 48px);
    /* Колонка лобби и шагов — ОДНО число на все четыре игры (решение
       владельца «все игры выглядят одинаково»). Раньше здесь стояло 760 —
       число, придуманное для сетки из семи плиток витрины (см. «ГЛАВНОЕ
       ОТЛИЧИЕ…» выше), а лобби и шаги дурака брали его молча просто
       потому, что жили с витриной на одной странице. У шашек, шахмат
       и нард лобби всегда стояло на 520 (общий, не запертый замком
       расчёт, см. «Общее для лобби и шагов» ниже по файлу) — теперь
       и у дурака то же самое число, чтобы лобби всех игр выглядели
       одной программой, а не четырьмя разными. */
    --колонка-широкая: 520px;
    /* Карта в руке. На телефоне — 30,5 сотых ширины окна, не больше
       17 сотых его высоты и не больше 136 точек. На планшете стоя
       держит ширина: 24 сотых (а не 30,5 — иначе на 768–820 шесть карт
       веера легли бы с сильным нахлёстом): 820×1180 — 197 точек против
       119 на телефоне, 768×1024 — 184. Лёжа держит высота: 20 сотых
       (на телефоне 17 — там над рукой высокий столбик рядов, а лёжа
       шапка в одну строку, см. ниже): 1180×820 — 164, монитор
       1920×1080 — 216. Потолок 220 — на высоком мониторе карта
       не плакат. */
    --в-рука: clamp(56px, min(24vw, calc(var(--доступно) * 0.2)), 220px);
  }

  /* План «Рейтинг по макету», заход 2, пункт 7: макет владельца для
     рейтинга — двухколоночная страница сайта (карточки лидеров рядом
     с таблицей), но закон сборника «все игры выглядят одинаково» тут
     весомее — колонку в две не разводим ни для одного экрана. Вместо
     этого экран рейтинга на ПК просто держит ту же телефонную ширину,
     что и на 390 (число из макета, «.tabs»/«.table» в prototype/
     styles.css: контейнер там 440px) — не общую колонку 520, которая
     у него и так уже читается через «var(--колонка-широкая, 520px)»
     чуть выше по файлу (см. блок «ШАПКА-КАРТОЧКА»). */
  #экран-рейтинга-игроков {
    --колонка-широкая: 440px;
  }

  /* Витрина — сетка из семи плиток, а не форма из карточек: только ей
     оставлена прежняя широкая колонка (обоснование числа 760 — см.
     «ГЛАВНОЕ ОТЛИЧИЕ ОТ ПРЕЖНЕГО ПОДХОДА» в начале раздела витрины).
     Своя переменная, а не «--колонка-широкая», — чтобы она никогда
     больше не утекала молча в лобби и шаги, как было раньше. */
  :root:has(#экран-витрины) {
    --колонка-витрина-широкая: 760px;
  }

  /* ---------- Стол: те же ряды, на всю ширину ----------
     Ряды (шапка, соперник, «Вы», подсказка, рука, кнопки) — во всю
     ширину экрана, поля по краям шире телефонных. Сукно выступает за
     ряды на 8 точек с каждой стороны, как на телефоне, и забирает всю
     свободную высоту — прежний потолок (480 точек) снят. */
  :root:has(#экран-витрины) #экран-игры:has(> #зона-стола) {
    --поле: var(--поле-широкое);
    --зазор-рядов: 12px;
  }

  :root:has(#экран-витрины) #экран-игры > :is(.верх-игры, .шапка-игры, #соперники, #рука-бота, #строка-меня, #подсказка, #рука-человека) {
    max-width: none;
  }

  /* Три кнопки действий — группой под рукой, не шире 720 точек. Во всю
     ширину 1180–1920 «Взять» и «Бито» вытягивались в полосы по 500–600
     точек, и ряд переставал читаться как три кнопки. */
  :root:has(#экран-витрины) #экран-игры > #панель-кнопок {
    max-width: 720px;
  }

  :root:has(#экран-витрины) #экран-игры > #зона-стола {
    width: calc(100% + 16px);
    max-height: none;
    /* Колода растёт вместе с картой в руке: три четверти её роста
       (на телефоне потолок 100 точек — это 84 сотых руки). */
    --колода-потолок: calc(var(--в-рука) * 0.75);
  }

  /* ---------- Витрина широкой колонкой, лобби и шаги — своей ----------
     Витрина — сетка из семи плиток: ей 760, на планшете стоя это почти
     вся ширина, лёжа и на мониторе — ясная колонка посередине. Почему
     не во всю ширину — см. начало раздела. Лобби и шаги — формы,
     а не сетка: им хватает 520 на любой игре (объяснение — у переменной
     «--колонка-широкая» в начале этого блока). Панель вкладок внизу
     по-прежнему во всю ширину, а вкладки на ней — по ширине колонки. */
  #экран-витрины.витрина > :not(.нижние-вкладки):not(.лист-ещё) {
    max-width: var(--колонка-витрина-широкая);
  }

  /* Резерв под полосу вкладок — ещё раз, прямо у сетки плиток.
     У самого экрана «#экран-витрины.витрина» запас снизу уже есть
     (правило 883–886, тот же приём, что у лобби/рейтинга/профиля), но
     на широком окне (снимок Playwright, 1280) нижний ряд «Домино /
     Морской бой» всё равно вылезал под полосу даже после прокрутки
     до конца. Сетка плиток — последний ряд в потоке перед полосой
     (сама полоса «position: fixed» и в поток не входит вовсе), поэтому
     запас продублирован здесь: край сетки отодвинут от полосы своим
     же отступом, а не только отступом всего экрана. Хуже узкому окну
     от этого не становится — тот же запас там уже стоял молча (760
     здесь работает от 700 точек, то есть и на 768 тоже, а там наезда
     не было и раньше). */
  #экран-витрины.витрина > .витрина__плитки {
    margin-bottom: calc(var(--вт-панель-низ) + 12px + var(--отступ-снизу));
  }

  /* Ряд «Домино / Морской бой» подходил к полосе вкладок вплотную
     (было 3 точки вместо нужных 8). Причина — не сама ширина 768:
     от ~800 точек и шире колонка плиток упирается в свой потолок
     «--колонка-витрина-широкая» (760) и дальше не растёт, а значит
     и все ряды плиток от 800 до самого широкого монитора — одной
     и той же, максимальной высоты. Первый ряд «Нарды / Шахматы» плюс
     второй «Дурак / Шашки» съедают на этой высоте столько места, что
     третьему ряду («Домино») тесно перед полосой на ЛЮБОЙ ширине
     от 800 — не только на 768 (проверено перебором ширин от 700
     до 1920 через подмену style.css в Playwright — зазор везде
     одинаковый, отрицательный).
     Одним «--вт-зазор-рядов» это не почить: у соседних плиток в общем
     списке есть свой минимум зазора — 4 точки (иначе палец может
     соскользнуть в щель между ними, отдельная проверка), а чтобы
     дотянуть зазор до полосы с 3 точек хотя бы до 8, зазор между
     рядами пришлось бы зажать ниже 4 — нельзя. Поэтому экономия
     из трёх маленьких источников разом, только на широком окне:
     — зазор между рядами уже 5 точек, а не 8 (с запасом выше
       минимума в 4);
     — верхний отступ шапки убран (4 точки: над заголовком «Во что
       сыграем?» здесь и так есть вырез/статус-бар);
     — отступ фильтров от подзаголовка сведён к 2 точкам (было до 6):
       у фильтров нет соседа-кнопки над ними, зажимать некого.
     Итого на 768 зазор до полосы — 40 точек (за старым запасом),
     на 1280 — 10. На 320 и 390 (узкое окно, блок сюда не заходит)
     ничего не поменялось — своя, прежняя формула. */
  #экран-витрины.витрина {
    --вт-зазор-рядов: 5px;
  }

  #экран-витрины.витрина .витрина__шапка {
    padding-top: 0;
  }

  #экран-витрины.витрина .витрина__фильтры {
    margin-top: 2px;
  }

  :is(#экран-лобби > :not(.нижние-вкладки), .экран.путь > *),
  .экран.путь > .кнопка.путь__далее {
    max-width: var(--колонка-широкая);
  }

  /* Схема рассадки на шаге «Игроки» держит пропорцию овала (2,15 к 1):
     во всю колонку 760 она вырастала до 353 точек, и лёжа кнопка
     «Далее» уезжала под нижний край. Схеме хватает 560 — места на ней
     крупнее телефонных, а шаг помещается на экран целиком. Число не
     зависит от «--колонка-широкая» (520 меньше 560 и так не мешает),
     оставлено своим, как было. */
  #приложение .экран.путь > .рассадка {
    max-width: 560px;
  }

  /* Нижняя полоса вкладок. Базовое правило («НИЖНЯЯ ПАНЕЛЬ ВКЛАДОК»,
     выше по файлу) уже держит её в 520 точках на любой ширине окна —
     ровно то, что нужно лобби и шагам после этого захода. Только
     у витрины полоса стоит под сеткой плиток шириной 760, и, если её
     не подровнять, вкладки станут заметно у́же самой сетки. Здесь —
     то же самое число, что у сетки, «--колонка-витрина-широкая». */
  :root:has(#экран-витрины) .нижние-вкладки {
    padding-left: max(8px, (100% - var(--колонка-витрина-широкая)) / 2);
    padding-right: max(8px, (100% - var(--колонка-витрина-широкая)) / 2);
  }
}

/* ---------- Лёжа: лобби в две колонки ----------
   Лёжа в одну колонку картинка лобби (16 на 10) занимала весь экран,
   а входы — «Играть онлайн», «С ботами», «Пригласить друзей» — уезжали
   под нижний край: чтобы начать игру, надо было прокручивать. Здесь
   порядок тот же, но слева — профиль и картинка, справа — входы, сразу
   видно всё. Название «Дурак» — над обеими колонками.
   Ширина пары колонок — до 1200 точек, посередине; поля — как у стола. */
@media (min-width: 700px) and (min-height: 600px) and (min-aspect-ratio: 5 / 4) {
  :root:has(#экран-витрины) #экран-лобби.экран--виден {
    display: grid;
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
    grid-template-areas:
      "верх      верх"
      "возврат   возврат"
      "заголовок заголовок"
      "профиль   входы"
      "картинка  входы";
    grid-template-rows: auto auto auto auto 1fr;
    align-content: start;
    column-gap: 28px;
    row-gap: 12px;
    padding-left: calc(max(var(--поле-широкое), (100% - 1200px) / 2) + var(--отступ-слева));
    padding-right: calc(max(var(--поле-широкое), (100% - 1200px) / 2) + var(--отступ-справа));
  }

  :root:has(#экран-витрины) #экран-лобби > :not(.нижние-вкладки) {
    max-width: none;
  }

  :root:has(#экран-витрины) #экран-лобби > .верх-игры {
    grid-area: верх;
    width: auto;
    max-width: none;
  }

  :root:has(#экран-витрины) #экран-лобби > .плашка-возврата { grid-area: возврат; }
  :root:has(#экран-витрины) #экран-лобби > .лобби__заголовок { grid-area: заголовок; }
  :root:has(#экран-витрины) #экран-лобби > .карточка-профиля { grid-area: профиль; }
  :root:has(#экран-витрины) #экран-лобби > .лобби__картинка { grid-area: картинка; align-self: start; }
  :root:has(#экран-витрины) #экран-лобби > .лобби__входы { grid-area: входы; align-self: start; }

  /* Две плашки возврата разом (недоигранная партия и с другом, и с ботом):
     по умолчанию обе получают один grid-area «возврат» из правила выше
     и лягут друг на друга. Пока видна только одна — этот :has() не
     подходит, и раскладка остаётся ровно прежней, в одну строку.
     Как только видны обе — добавляем вторую строку сетки с тем же
     row-gap 12px, что и между остальными карточками лобби. */
  :root:has(#экран-витрины) #экран-лобби.экран--виден:has(> #кнопка-вернуться-в-игру:not(.скрыт)):has(> #кнопка-доиграть-с-ботом:not(.скрыт)) {
    grid-template-areas:
      "верх        верх"
      "возврат     возврат"
      "возврат-бот возврат-бот"
      "заголовок   заголовок"
      "профиль     входы"
      "картинка    входы";
    grid-template-rows: auto auto auto auto auto 1fr;
  }

  :root:has(#экран-витрины) #экран-лобби.экран--виден:has(> #кнопка-вернуться-в-игру:not(.скрыт)):has(> #кнопка-доиграть-с-ботом:not(.скрыт)) > #кнопка-доиграть-с-ботом {
    grid-area: возврат-бот;
  }
}

/* ---------- Лёжа: шапка стола в одну строку ----------
   Лёжа каждая точка высоты на счету: сукно и рука живут под столбиком
   рядов. Шапка «Дурак / Подкидной · 36 карт» в две строки забирала
   у сукна 60 точек. Здесь она та же, что в низком окне телефона
   (см. «Шапка в низком окне — одна строка»): «Дурак · Подкидной ·
   36 карт» по центру строки «‹ ⋯», чуть крупнее — 17 и 15 точек.
   Порог — окно шире своей высоты и не выше 900: на мониторе 1920×1080
   места хватает и двум строкам. */
@media (min-width: 700px) and (min-height: 600px) and (max-height: 900px) and (min-aspect-ratio: 5 / 4) {
  :root:has(#экран-витрины) #экран-игры > .шапка-игры {
    flex-direction: row;
    align-items: baseline;
    justify-content: center;
    gap: 0.35em;
    box-sizing: border-box;
    height: 28px;
    padding: 0 56px;
    overflow: hidden;
    white-space: nowrap;
    pointer-events: none;
  }

  :root:has(#экран-витрины) #экран-игры .шапка-игры__заголовок {
    flex: 0 0 auto;
    font-size: 17px;
    font-weight: 700;
    line-height: 28px;
    letter-spacing: 0;
  }

  :root:has(#экран-витрины) #экран-игры .шапка-игры__подзаголовок {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 15px;
    line-height: 28px;
  }

  :root:has(#экран-витрины) #экран-игры .шапка-игры__подзаголовок:not(:empty)::before {
    content: "· ";
  }

  /* Строка «‹ ⋯» видна (браузер, старый Telegram): шапка встаёт в неё.
     «‹ ⋯» занимает в столбике 32 точки, шапка — 28, и поднимается она
     на свою высоту и просвет — середины строк совпадают. */
  html:not(.в-телеграме):has(#экран-витрины) #экран-игры > .верх-игры + .шапка-игры,
  html.в-телеграме.без-настроек:has(#экран-витрины) #экран-игры > .верх-игры + .шапка-игры {
    margin-top: calc(-28px - var(--зазор-рядов));
  }
}

/* =====================================================================
   Э8: ШИРОКИЙ ЭКРАН — ДОСКА И ФОН НА ВСЕХ ЧЕТЫРЁХ СТРАНИЦАХ

   Снятого выше замка «:has(#экран-витрины)» мало: колонка форм (лобби,
   шаги) и без него уже стояла в 520 точек — см. «Общее для лобби
   и шагов» дальше по файлу, там нет привязки к ширине окна вовсе.
   Не хватало другого: (1) вокруг узкой колонки не было НИЧЕГО, кроме
   ровного тёмного цвета — отсюда и жалоба «пусто по бокам»; (2) у шашек
   и шахмат сама доска, панели игроков и ряд кнопок под ней ничем не
   ограничены по ширине (см. style-шашки.css/style-шахматы.css: «Обёртка
   шире экрана ровно на его поля» — расчёт на телефон, где расти
   некуда) — на мониторе клетка стала бы огромной. У нард то же самое
   уже решено в её собственном файле (переменная «--д-ширина», потолок
   520) — этот блок её не трогает.

   ПОЧЕМУ ЧЕРЕЗ «:has()», А НЕ ПРАВКОЙ ФАЙЛА ИГРЫ. Файлы style-шашки.css
   и style-шахматы.css — чужие (правит их разработчик), а подключены
   они ПОСЛЕ этого файла: при равном весе правила их margin победил бы
   просто порядком строки в html. «:has(...)» в начале селектора здесь
   не проверка «а есть ли на странице...» (она почти всегда правда) —
   это подъём веса ровно настолько, чтобы моё правило победило их,
   не трогая чужой файл. Тот же приём этот файл уже использует для
   другой цели — отличать страницу дурака («:has(#экран-витрины)»). */
@media (min-width: 700px) and (min-height: 600px) {
  :root {
    /* Потолок доски настольных игр (шашки, шахматы): растёт вместе
       с окном, но не бесконечно. 600 — решение штаба (план Э8): чуть
       шире колонки форм (520), доска — квадрат, ему нужно немного
       больше воздуха, чем ряду кнопок под ней. */
    --колонка-доски: 600px;
    /* Пятно по центру для широкого окна — того же цвета и той же силы
       (5 сотых), что уже существующий тихий огонёк сверху, просто
       крупнее и с центром чуть ниже середины — там, где останавливается
       взгляд на колонке карточек. Одна переменная на весь сборник: ей
       крашены и «#приложение» (шашки, шахматы и нарды — их стол и
       второстепенные экраны своего фона не рисуют, берут общий,
       см. ниже), и места, что красят фон сами (витрина, лобби, шаги,
       стол дурака) — так сборник не распадается на четыре чуть разных
       тёмных фона. */
    --огонёк-центр: radial-gradient(55% 48% at 50% 32%, rgba(248, 245, 235, 0.05), rgba(248, 245, 235, 0) 100%);
  }

  /* «:has(#приложение)» истинно всегда (узел один на страницу и стоит
     всегда) — здесь он ровно за тем весом, что описан в шапке блока. */
  :root:has(#приложение) #приложение {
    background:
      var(--огонёк-центр),
      radial-gradient(75% 220px at 50% 0, rgba(210, 247, 107, 0.06), rgba(210, 247, 107, 0) 100%),
      var(--сб-фон);
  }

  #экран-витрины.витрина {
    background:
      radial-gradient(75% 120px at 50% 0, rgba(210, 247, 107, 0.07), rgba(210, 247, 107, 0) 100%) local,
      var(--огонёк-центр) local,
      var(--вт-фон);
  }

  #экран-лобби,
  .экран.путь {
    background:
      radial-gradient(75% 120px at 50% 0, rgba(210, 247, 107, 0.07), rgba(210, 247, 107, 0) 100%) local,
      var(--огонёк-центр) local,
      var(--сб-фон);
  }

  #экран-игры:has(> #зона-стола) {
    background:
      var(--огонёк-центр),
      radial-gradient(75% 120px at 50% 0, rgba(210, 247, 107, 0.07), rgba(210, 247, 107, 0) 100%),
      var(--сб-фон);
  }

  /* ---------- Доска шашек и шахмат: потолок и центр ----------
     «.обёртка-доски», «.панель-доски», «.панель-игрока-шахмат»,
     «.панель-игрока-шашек», «#запись-ходов» — во всех этих правилах
     в файле игры задана ширина в обрез экрана и отрицательный отступ
     (телефонный приём: доска встаёт от края до края). Здесь только
     ограничена ширина и добавлено центрирование — что ширину задаёт
     файл игры, а не max-width, не мешает: браузер берёт меньшее из двух.
     «.обёртка-доски» — общее имя класса и у нард тоже, поэтому это
     правило её тоже задевает; раньше (потолок нард был 520) это было
     не важно — 520 меньше 600, правило ничего не меняло. Оформитель
     поднял потолок нард до 880 (16.09, жалоба на маленький планшетный
     стол) — теперь 600 реально обрезает нардовскую доску, и правило
     ниже («ШИРОКАЯ ДОСКА НАРД») эту обрезку для неё отменяет. */
  :root:has(.обёртка-доски) :is(.обёртка-доски, .панель-доски, .панель-игрока-шахмат, .панель-игрока-шашек, #запись-ходов) {
    max-width: var(--колонка-доски);
    margin-inline: auto;
  }
}

/* ---------- ШИРОКАЯ ДОСКА НАРД ----------
   Потолок 600 выше рассчитан на КВАДРАТНУЮ доску шашек/шахмат — нардам
   он тесен: их доска шире, чем выше, и на планшете имеет смысл занимать
   до 880 (см. style-нарды.css, «ШИРОКОЕ ОКНО»). Своей ширины не задаёт —
   просто снимает чужой потолок, а сколько занять, по-прежнему решает
   «--д-ширина».

   Вес подобран НАРОЧНО таким же, как у правила выше, а не больше: там
   в списке «:is(...)» затесался «#запись-ходов» — id, поэтому у ВСЕГО
   правила вес не 0,3,0 (как кажется на глаз по трём простым классам),
   а 1,2,0. Простой «.обёртка-доски» без id это правило не перебивает,
   сколько ниже по файлу его ни пиши. «#экран-игры» здесь — не ради
   узости выбора (id один на страницу), а ровно чтобы дотянуть вес
   до тех же 1,2,0 и выиграть порядком строки. */
:root:has(.доска-нард) #экран-игры .обёртка-доски {
  max-width: none;
}

/* =====================================================================
   КОМНАТА ДУРАКА — ЭКРАН 05 (эталон/дурак-05-комната.png)

   Здесь компания собирается перед партией: хозяин видит стол, сажает
   ботов на свободные места, зовёт друзей и нажимает «Начать».

   Вид — тот же, что у лобби и трёх шагов до партии: тёмная страница,
   плитки на тон светлее, крупный заголовок слева, один салатовый акцент.
   Стол — тот же овал из дерева и сукна, что на шаге «Игроки» (класс
   «рассадка»): рама, фаска, тень и цвет сукна из «Оформления» берутся
   оттуда. Здесь только размер стола и то, где стоят места.

   Все правила держатся за «.комната» (и её имя «#комната» там, где
   нужно перебить старые правила экрана кода). Прежняя прихожая списком
   («#комната-старая») — запасной вид; её правила выше по файлу, а здесь
   ей только возвращена раскладка столбиком (см. последний подраздел).
   Экран красится тёмным, только пока «.комната» видна: «:has» — тот же
   приём, каким выше включаются правила прихожей.
   ===================================================================== */

:root {
  /* ---------- Значки комнаты ----------
     Копии «img/дурак/значки/*.svg» из набора владельца — «Пригласить»
     (ссылка), свободное место (плюс), подбор (галочка), режим «С друзьями»
     (группа), бот за столом (робот). Вписаны сюда по той же причине, что
     и значки стола (см. «Значки из набора владельца»): маску браузер
     берёт только у настоящей картинки, а вписанный значок от сервера
     не зависит. Стрелка «›» — уже вписанная «--значок-вперёд». */
  --значок-ссылка: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m10 7 3-3c6-6 13 1 7 7l-3 3M14 17l-3 3C5 26-2 19 4 13l3-3M8 16l8-8'/%3E%3C/svg%3E");
  --значок-плюс: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 4v16M4 12h16'/%3E%3C/svg%3E");
  --значок-галочка: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12 5 5L20 6'/%3E%3C/svg%3E");
  --значок-группа: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='6' r='3'/%3E%3Ccircle cx='4' cy='8' r='2'/%3E%3Ccircle cx='20' cy='8' r='2'/%3E%3Cpath d='M6 21v-5c0-6 12-6 12 0v5ZM1 20v-5c0-2 1-3 3-3M23 20v-5c0-2-1-3-3-3'/%3E%3C/svg%3E");
  /* Робот и корона — не маской, а картинкой своего цвета: они лежат
     на маленьком тёмном кружке-значке у места, а у одного узла маска
     красила бы и кружок, и рисунок в одну краску. Корона хозяина
     в наборе не нашлась и нарисована здесь тем же пером (сетка 24,
     линия 1,7, круглые концы). */
  --значок-робот-светлый: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23e4e6eb' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='6' width='18' height='15' rx='4'/%3E%3Cpath d='M12 6V3M1 11v6M23 11v6M9 16h6'/%3E%3Ccircle cx='8' cy='11' r='1' fill='%23e4e6eb'/%3E%3Ccircle cx='16' cy='11' r='1' fill='%23e4e6eb'/%3E%3Ccircle cx='12' cy='2' r='1'/%3E%3C/svg%3E");
  --значок-корона-салатовая: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23d2f76b' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.5 16 3 7l5.5 4L12 4l3.5 7L21 7l-1.5 9Z' fill='%23d2f76b'/%3E%3Cpath d='M4.5 19.5h15'/%3E%3C/svg%3E");
}

/* ---------- Экран, пока видна комната ----------
   Поля и фон — как у лобби и шагов: тёмный фон сборника и едва заметное
   салатовое свечение сверху. Экран прокручивается сам (это поведение
   включает js/game.js), полоса прокрутки не видна, вбок — никогда. */
#экран-комнаты:has(> #комната:not(.скрыт)) {
  align-items: center;
  gap: 0;
  padding: calc(6px + var(--отступ-сверху)) calc(clamp(12px, 3.6vw, 18px) + var(--отступ-справа))
           calc(12px + var(--отступ-снизу)) calc(clamp(12px, 3.6vw, 18px) + var(--отступ-слева));
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  color: var(--сб-текст);
  text-align: left;
  /* Тот же тёмный графит со слабым салатовым свечением сверху, что
     у лобби и тройки «Друг / Комната / Вход». */
  background:
    radial-gradient(75% 120px at 50% 0, rgba(210, 247, 107, 0.07), rgba(210, 247, 107, 0) 100%) local,
    var(--сб-фон);
}

#экран-комнаты:has(> #комната:not(.скрыт))::-webkit-scrollbar { display: none; }

/* Столбик — не шире витрины (520) и посередине, как у лобби и шагов.
   Растёт на всю высоту экрана: тогда «Начать» стоит внизу, под пальцем,
   даже когда за столом двое и всё остальное короткое.
   Цвета внутри — те же имена, что у шагов: прежние правила экрана кода,
   которые берут «--текст», «--подложка», «--акцент», сами переходят
   на тёмный вид с салатовым акцентом. */
#экран-комнаты > #комната.комната {
  --поле: clamp(12px, 3.6vw, 18px);
  /* Фон — тёмный графит сборника, как у всех служебных экранов.
     Сукном красится только рассадка внутри комнаты, не сам экран. */
  --фон: var(--сб-фон);
  --панель: var(--сб-поверхность);
  --текст: var(--сб-текст);
  --текст-тихий: var(--сб-текст-тихий);
  --кнопка-фон: var(--сб-акцент);
  --кнопка-текст: var(--сб-акцент-текст);
  --акцент: var(--сб-акцент);
  --подложка: rgba(248, 245, 235, 0.06);
  --край: rgba(248, 245, 235, 0.14);
  --плитка: #1e2226;
  --плитка-кромка: rgba(248, 245, 235, 0.12);
  --плитка-нажата: #262a2f;
  /* Дерево — как у стола партии и схемы рассадки. */
  --дерево-свет: #9a6841;
  --дерево: #75492b;
  --дерево-тень: #4a2b17;
  /* Цвет чужого места — холодный светло-серый с лёгкой сиренью, как
     кольцо «Максима» на макете. Салатовый — только свои: «Вы» и напарник. */
  --комната-чужой: #c3c5d1;

  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-sizing: border-box;
  width: 100%;
  max-width: 520px;
  margin: 0 auto;
  color: var(--сб-текст);
  text-align: left;
}

#комната > * {
  flex-shrink: 0;
  box-sizing: border-box;
  min-width: 0;
  margin: 0;
}

#комната button:focus-visible {
  outline: 2px solid var(--сб-акцент);
  outline-offset: 2px;
}

/* ---------- Шапка: «Комната игры», режим, правила, «Игроки 3/4» ----------
   Как на макете: заголовок слева, крупный и жирный (он чуть крупнее
   заголовков шагов — так на эталоне), всё остальное — по центру. */
#комната > .комната__шапка {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  /* В браузере над шагами стоит строка «‹ ⋯», а над комнатой её нет —
     без этого поля заголовок прилипал к верхнему краю окна. */
  margin-top: 12px;
  text-align: center;
}

/* В Telegram сверху его собственная шапка — там хватает четырёх точек,
   как у шагов. */
html.в-телеграме #комната > .комната__шапка { margin-top: 4px; }

.комната__заголовок {
  align-self: stretch;
  margin: 0 0 4px;
  font-size: clamp(30px, 10vw, 44px);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -0.025em;
  text-align: left;
  color: var(--сб-текст);
}

/* Пилюля режима — та же «путь__режим», что на шагах, но здесь она
   главная строка шапки, как на макете: салатовый контур и надпись,
   впереди значок группы («С друзьями»). */
.комната__шапка > .путь__режим {
  gap: 8px;
  min-height: 32px;
  padding: 4px 15px 5px 12px;
  font-size: 15px;
  font-weight: 700;
  color: var(--сб-акцент);
  background: rgba(210, 247, 107, 0.07);
  border: 1.5px solid var(--сб-акцент);
  box-shadow: 0 0 14px rgba(210, 247, 107, 0.14);
}

.комната__шапка > .путь__режим--друзья::before {
  content: "";
  flex: 0 0 auto;
  width: 19px;
  height: 19px;
  background-color: currentColor;
  -webkit-mask: var(--значок-группа) center / contain no-repeat;
  mask: var(--значок-группа) center / contain no-repeat;
}

.комната__правила {
  margin: 0;
  font-size: 15px;
  line-height: 1.3;
  color: var(--сб-текст-тихий);
}

.комната__правила:empty { display: none; }

.комната__игроки {
  margin: 4px 0 0;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.25;
  color: var(--сб-текст);
}

/* ---------- Стол ----------
   Тот же овал, что на шаге «Игроки», только во всю ширину столбика
   и чуть выше (1,8 к 1 против 2,15): за ним сидят живые люди, у каждого
   имя под местом, и имена должны помещаться на сукне.

   Рама толще, чем у схемы на шаге, — как на макете: там борт стола
   примерно вдвое толще кромки плиток и читается как настоящее дерево.

   Поля сверху и снизу — под места: верхнее выступает над бортом
   на полместа, у нижнего под ним ещё и имя. */
#комната > .рассадка.рассадка--комната {
  --место: clamp(48px, 14.5vw, 58px);
  --рама: clamp(12px, 3.8vw, 17px);
  /* Где стоят места. Сверху и снизу — на борту (середина рамы), по бокам —
     на сукне, отступив от борта: иначе имя «Свободно» под боковым местом
     вылезало бы за край экрана. Так и на макете — «Максим» и «Свободно»
     сидят на сукне, «Вы» и «Анна» — на борту. */
  --радиус-x: calc(50% - var(--место) * 0.42);
  --радиус-y: calc(50% + var(--рама) / 2);
  width: 100%;
  max-width: none;
  aspect-ratio: 1.8 / 1;
  margin: calc(var(--место) / 2 + 2px) 0 calc(var(--место) / 2 + 26px);
}

/* Места — по кругу от «Вы» наверху, дальше по часовой. Позицию берём
   из порядка мест на столе, а не из «--номер-места»: код кладёт первым
   «Вы», за ним соседей по часовой (js/дурак-комната.js, «порядокМест»),
   а «--номер-места» у него — номер кресла на сервере, от 1. Хозяин
   обычно сидит в кресле 1, и по этому числу «Вы» уезжало бы вправо.
   Порядок узлов верен всегда, как бы ни пересаживались. */
#комната > .рассадка--комната > .рассадка__место:nth-child(1) { --позиция: 0; }
#комната > .рассадка--комната > .рассадка__место:nth-child(2) { --позиция: 1; }
#комната > .рассадка--комната > .рассадка__место:nth-child(3) { --позиция: 2; }
#комната > .рассадка--комната > .рассадка__место:nth-child(4) { --позиция: 3; }
#комната > .рассадка--комната > .рассадка__место:nth-child(5) { --позиция: 4; }
#комната > .рассадка--комната > .рассадка__место:nth-child(6) { --позиция: 5; }

/* Место — кнопка размером 48–58 точек (палец попадает с запасом, имя
   под местом тоже нажимается — оно внутри кнопки). Тёмный диск со светом
   сверху, кольцо и человечек — значок аватара цветом роли. Значок чуть
   больше диска, чтобы его кольцо легло ровно по краю, как на макете. */
#комната > .рассадка--комната > .рассадка__место {
  --угол: calc(-90deg + var(--позиция, 0) * 360deg / var(--мест, 4));
  left: calc(50% + var(--радиус-x) * cos(var(--угол)));
  top: calc(50% + var(--радиус-y) * sin(var(--угол)));
  -webkit-appearance: none;
  appearance: none;
  padding: 0;
  border: 0;
  font: inherit;
  color: var(--комната-чужой);
  background: radial-gradient(circle at 50% 30%, #2a3036 0%, #181b1f 62%, #111417 100%);
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.45),
    0 6px 14px rgba(0, 0, 0, 0.55);
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.15s ease;
}

#комната > .рассадка--комната > .рассадка__место:disabled { cursor: default; }

#комната > .рассадка--комната > .рассадка__место > .аватар {
  --аватар: 120%;
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  color: inherit;
  transition: opacity 0.2s ease;
}

/* «Вы» и напарник — свои: салатовое кольцо со свечением. Напарник чуть
   тише — на макете «Вы» и «Анна» почти одинаковы, но «Вы» ищут первым. */
#комната > .рассадка--комната > .рассадка__место--я,
#комната > .рассадка--комната > .рассадка__место--напарник {
  color: var(--сб-акцент);
}

#комната > .рассадка--комната > .рассадка__место--я {
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.45),
    0 6px 14px rgba(0, 0, 0, 0.55),
    0 0 20px rgba(210, 247, 107, 0.50);
}

#комната > .рассадка--комната > .рассадка__место--напарник {
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.45),
    0 6px 14px rgba(0, 0, 0, 0.55),
    0 0 16px rgba(210, 247, 107, 0.34);
}

/* Свободное место — дырка за столом, а не игрок: полупрозрачный диск,
   пунктирное кольцо и плюс посередине. */
#комната > .рассадка--комната > .рассадка__место--свободно {
  color: rgba(248, 245, 235, 0.88);
  background: rgba(12, 14, 16, 0.5);
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
}

#комната > .рассадка--комната > .рассадка__место--свободно::before {
  content: "";
  position: absolute;
  inset: 0;
  border: 2px dashed rgba(248, 245, 235, 0.72);
  border-radius: 50%;
  pointer-events: none;
}

#комната > .рассадка--комната > .рассадка__место--свободно > .аватар {
  --аватар: 44%;
  -webkit-mask-image: var(--значок-плюс);
  mask-image: var(--значок-плюс);
}

/* Имя под местом. Свои — салатовым, чужие — белым, пустое — тише.
   Длинное имя обрезается многоточием по ширине, в которой боковое место
   ещё не упирается в край экрана. */
#комната > .рассадка--комната .рассадка__имя {
  top: calc(100% + 6px);
  max-width: calc(var(--место) * 1.7);
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--сб-текст);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85);
}

#комната > .рассадка--комната > .рассадка__место--я .рассадка__имя,
#комната > .рассадка--комната > .рассадка__место--напарник .рассадка__имя {
  color: var(--сб-акцент);
}

#комната > .рассадка--комната > .рассадка__место--свободно .рассадка__имя {
  font-weight: 600;
  color: rgba(248, 245, 235, 0.78);
}

/* Бот — тёмный кружок с роботом у правого нижнего края места: с одного
   взгляда видно, кто за столом живой, а кто нет. */
#комната > .рассадка--комната > .рассадка__место--бот::after {
  content: "";
  position: absolute;
  right: -4px;
  bottom: -4px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--значок-робот-светлый) center / 14px 14px no-repeat, #2a2f35;
  box-shadow: 0 0 0 2px #111417, 0 2px 4px rgba(0, 0, 0, 0.5);
  pointer-events: none;
}

/* Хозяин стола — салатовая корона у правого верхнего края. У себя
   не рисуем: хозяин и так знает, что стол его, а гостю важно видеть,
   кто нажмёт «Начать». */
#комната > .рассадка--комната > .рассадка__место--хозяин:not(.рассадка__место--я)::after {
  content: "";
  position: absolute;
  right: -4px;
  top: -4px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--значок-корона-салатовая) center / 14px 14px no-repeat, #2a2f35;
  box-shadow: 0 0 0 2px #111417, 0 2px 4px rgba(0, 0, 0, 0.5);
  pointer-events: none;
}

/* Нет связи — человек за столом, но не отвечает: место и имя гаснут.
   Место при этом не пунктирное — оно не свободно. */
#комната > .рассадка--комната > .рассадка__место--нет-связи > .аватар { opacity: 0.38; }

#комната > .рассадка--комната > .рассадка__место--нет-связи .рассадка__имя {
  color: var(--сб-текст-тихий);
}

/* Палец на месте — оно сразу вжимается (класс «--нажимается» код ставит
   на касание, не дожидаясь сервера), свободное ещё и загорается салатовым:
   видно, что нажатие дошло. */
#комната > .рассадка--комната > .рассадка__место--нажимается,
#комната > .рассадка--комната > .рассадка__место:not(:disabled):active {
  transform: scale(0.92);
}

#комната > .рассадка--комната > .рассадка__место--свободно.рассадка__место--нажимается::before,
#комната > .рассадка--комната > .рассадка__место--свободно:not(:disabled):active::before {
  border-color: var(--сб-акцент);
}

@media (hover: hover) {
  #комната > .рассадка--комната > .рассадка__место:not(:disabled):hover > .аватар {
    filter: brightness(1.18);
  }
}

/* Ответ сервера в пути — вокруг нажатого места бежит салатовая дуга,
   у свободного места крутится само пунктирное кольцо. Остальные места
   в это время не нажимаются (их выключает код) и просто стоят. */
#комната > .рассадка--комната > .рассадка__место--ждёт-ответа { cursor: progress; }

#комната > .рассадка--комната > .рассадка__место--ждёт-ответа:not(.рассадка__место--свободно)::before {
  content: "";
  position: absolute;
  inset: -6px;
  border: 2.5px solid transparent;
  border-top-color: var(--сб-акцент);
  border-right-color: var(--сб-акцент);
  border-radius: 50%;
  pointer-events: none;
  animation: комната-ждём-ответа 0.9s linear infinite;
}

#комната > .рассадка--комната > .рассадка__место--свободно.рассадка__место--ждёт-ответа::before {
  border-color: var(--сб-акцент);
  animation: комната-ждём-ответа 2.4s linear infinite;
}

@keyframes комната-ждём-ответа {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  #комната > .рассадка--комната > .рассадка__место--ждёт-ответа::before { animation: none; }
}

/* ---------- Команды при 2 на 2 ----------
   Две плитки рядом: точка команды, название, кто в ней. Своя точка
   салатовая со свечением — того же цвета, что кольца своих мест за
   столом; чужая — серая, как кольца соперников. */
#комната > .комната__команды {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.комната__команда {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas:
    "точка подпись"
    ".     состав";
  align-items: center;
  column-gap: 10px;
  row-gap: 3px;
  min-height: 58px;
  padding: 10px 12px 11px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0) 70%),
    var(--сб-поверхность);
  border: 1px solid var(--плитка-кромка);
  border-radius: 14px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    0 6px 16px rgba(0, 0, 0, 0.22);
}

.комната__команда::before {
  content: "";
  grid-area: точка;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--комната-чужой);
}

.комната__команда--наша::before {
  background: var(--сб-акцент);
  box-shadow: 0 0 8px rgba(210, 247, 107, 0.55);
}

.комната__команда-подпись {
  grid-area: подпись;
  min-width: 0;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--сб-текст);
}

.комната__команда-состав {
  grid-area: состав;
  min-width: 0;
  font-size: 13px;
  line-height: 1.3;
  color: var(--сб-текст-тихий);
  overflow-wrap: anywhere;
}

/* ---------- Весть и сообщения ----------
   «Анна вошла», «ждём четвёртого», отказы сервера, ответ на «Позвать»
   и «Скопировать» — плитка во всю ширину с салатовой чертой слева:
   видно, что это слово игры, а не подпись. */
#комната > .сеть-сообщение {
  width: 100%;
  padding: 10px 14px;
  font-size: 14px;
  line-height: 1.35;
  text-align: left;
  color: var(--сб-текст);
  background: var(--плитка);
  border: 1px solid var(--плитка-кромка);
  border-left: 3px solid var(--сб-акцент);
  border-radius: 6px 14px 14px 6px;
}

/* ---------- «Пригласить друга» ----------
   Обведённая плитка во всю ширину, как на макете: значок ссылки слева,
   надпись посередине, «›» справа. Не залита — залита на экране одна
   кнопка, «Начать». */
#комната > .комната__пригласить {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-width: 0;
  min-height: 54px;
  padding: 0 54px;
  font-size: clamp(17px, 4.9vw, 20px);
  font-weight: 700;
  letter-spacing: 0;
  color: var(--сб-текст);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.045), rgba(255, 255, 255, 0) 65%),
    var(--сб-поверхность);
  border: 1.5px solid rgba(248, 245, 235, 0.55);
  border-radius: 18px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.28);
}

#комната > .комната__пригласить::before,
#комната > .комната__пригласить::after {
  content: "";
  position: absolute;
  top: 50%;
  background-color: currentColor;
}

#комната > .комната__пригласить::before {
  left: 18px;
  width: 24px;
  height: 24px;
  margin-top: -12px;
  -webkit-mask: var(--значок-ссылка) center / contain no-repeat;
  mask: var(--значок-ссылка) center / contain no-repeat;
}

#комната > .комната__пригласить::after {
  right: 16px;
  width: 22px;
  height: 22px;
  margin-top: -11px;
  opacity: 0.8;
  -webkit-mask: var(--значок-вперёд) center / contain no-repeat;
  mask: var(--значок-вперёд) center / contain no-repeat;
}

#комната > .комната__пригласить:not(:disabled):active {
  transform: translateY(1px);
  background: var(--плитка-нажата);
  box-shadow: none;
}

/* Мест не осталось — звать некого: кнопка гаснет целиком. */
#комната > .комната__пригласить:disabled {
  opacity: 0.4;
  cursor: default;
}

/* ---------- Код комнаты — мелкой строкой ----------
   Вход по коду жив, поэтому код виден, но уже не главный предмет
   экрана: «Код», тёмная плашка с салатовой рамкой и четырьмя знаками
   моноширинным шрифтом (та же тёмная плитка и та же рамка, что
   у большой плашки на «#комната-старая» и у поля ввода кода —
   кремовой бумаги на этом экране больше нет, второй яркий цвет
   рядом с салатовым убрали по замечанию смотрителя) и тихая
   «Скопировать код». */
#комната > .комната__код {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 44px;
}

/* Слово «Код» — только у видимой комнаты: снимок доступности Playwright
   показывает нарисованный CSS текст и у спрятанных узлов, а лишнее
   «Код» на витрине сбивало бы проверки (тот же приём, что у «›» листа). */
#комната:not(.скрыт) > .комната__код::before {
  content: "Код";
  font-size: 14px;
  font-weight: 600;
  color: var(--сб-текст-тихий);
}

#комната > .комната__код > .код-игры {
  max-width: none;
  padding: 1px 7px 2px;
  font-size: 20px;
  line-height: 1.25;
  letter-spacing: 0.16em;
  text-indent: 0.16em;
  color: var(--сб-текст);
  background: var(--плитка);
  border: 2px solid var(--сб-акцент);
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45);
}

#комната > .комната__код > .код-игры--ждём {
  color: rgba(248, 245, 235, 0.45);
  background: rgba(248, 245, 235, 0.08);
  box-shadow: none;
}

#комната > .комната__код > #кнопка-копировать-код {
  width: auto;
  min-width: 0;
  min-height: 44px;
  padding: 0 14px;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--сб-текст);
  background: none;
  border: 1px solid var(--сб-граница);
  border-radius: 12px;
  box-shadow: none;
}

#комната > .комната__код > #кнопка-копировать-код:active {
  transform: translateY(1px);
  background: var(--плитка-нажата);
}

/* ---------- «Открыть подбор игроков» — пока «скоро» ----------
   Кружок-отметка, надпись и справа «скоро» — та же пометка, что
   у «Играть онлайн» в лобби. Подбора ещё нет, поэтому кружок пустой
   и приглушён; когда подбор включат, включённое состояние уже готово —
   салатовое кольцо с галочкой и свечением, как на макете. */
#комната > .комната__подбор {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 44px;
  padding: 0 2px;
  font: inherit;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.25;
  text-align: left;
  color: var(--сб-текст);
  background: none;
  border: none;
  cursor: pointer;
}

#комната > .комната__подбор::before {
  content: "";
  flex: 0 0 auto;
  box-sizing: border-box;
  width: 28px;
  height: 28px;
  border: 2px solid rgba(248, 245, 235, 0.42);
  border-radius: 50%;
}

#комната > .комната__подбор > :first-child {
  flex: 1 1 auto;
  min-width: 0;
}

#комната > .комната__подбор[aria-checked="true"]::before {
  border-color: var(--сб-акцент);
  box-shadow: 0 0 12px rgba(210, 247, 107, 0.5);
}

#комната > .комната__подбор[aria-checked="true"]::after {
  content: "";
  position: absolute;
  left: 7px;
  top: 50%;
  width: 18px;
  height: 18px;
  margin-top: -9px;
  background-color: var(--сб-акцент);
  -webkit-mask: var(--значок-галочка) center / contain no-repeat;
  mask: var(--значок-галочка) center / contain no-repeat;
}

#комната > .комната__подбор:disabled { cursor: default; }

/* Приглушаем ровно настолько, чтобы читалось: 0,6 от белого на тёмном
   даёт контраст около 5 при норме 4,5 для подписи в 16 точек. Сама
   пометка «скоро» не гаснет — это она и объясняет, почему выключено. */
#комната > .комната__подбор:disabled::before,
#комната > .комната__подбор:disabled > :not(.комната__скоро) { opacity: 0.6; }

/* Строка подбора — сетка: слева кружок, справа подпись, а пометка («в списке
   виден, подбор — только на двоих») стоит ПОД подписью и переносится по
   словам. В одну строку длинная пометка наезжала на подпись (снимок 390). */
#комната > .комната__подбор {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  grid-template-rows: minmax(44px, auto) auto;
  column-gap: 12px;
  align-items: center;
}

#комната > .комната__подбор::before { grid-column: 1; grid-row: 1; }
#комната > .комната__подбор > :first-child { grid-column: 2; grid-row: 1; }

#комната > .комната__подбор[aria-checked="true"]::after { top: 22px; }

#комната > .комната__подбор > .комната__скоро {
  grid-column: 2;
  grid-row: 2;
  justify-self: start;
  margin: -4px 0 8px;
  border-radius: 14px;
  text-align: left;
  overflow-wrap: anywhere;
}

#комната .комната__скоро {
  flex: 0 0 auto;
  margin-left: auto;
  padding: 3px 10px 4px;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--сб-текст);
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid rgba(248, 245, 235, 0.16);
  border-radius: 999px;
}

/* ---------- «Начать» ----------
   Та же главная кнопка, что «Далее» на шагах: салатовая во всю ширину,
   58 точек, скругление 20. Прилипает к низу экрана: на тесном телефоне
   стол с командами длиннее окна, и искать главную кнопку прокруткой
   нельзя. Тени цвета фона над ней и под ней — чтобы прокручиваемое
   не просвечивало вокруг прилипшей кнопки.

   «Отступ снизу» здесь больше обычного: под «Начать» ещё одна прилипшая
   кнопка — «Выйти из комнаты» (см. правило ниже, «#комната > #кнопка-
   комната-отмена»). Раньше она стояла последней в потоке и на длинном
   столе (пять-шесть игроков) уезжала далеко вниз — без прокрутки до
   самого конца экрана её было не найти (жалоба владельца, 26.09).
   Теперь обе кнопки — двухэтажный «подвал» у нижнего края: «Начать»
   сверху, «Выйти» под ней, обе видны сразу.

   Погашенная («Ожидаем игрока…», «Ждём, когда хозяин начнёт») — серая
   плитка с серой надписью, как на макете: видно, что кнопка есть,
   но сейчас она молчит. Цвета непрозрачные — под прилипшей кнопкой
   проезжает стол. */
#комната > .комната__начать {
  position: sticky;
  bottom: calc(12px + var(--отступ-снизу) + 52px);
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-width: 0;
  min-height: 58px;
  margin-top: auto;
  padding: 0 20px;
  font-size: clamp(18px, 5.4vw, 22px);
  font-weight: 800;
  letter-spacing: 0;
  color: var(--сб-акцент-текст);
  background: var(--сб-акцент);
  border: none;
  border-radius: 20px;
  /* Две последние тени — цвета фона экрана: прячут за кнопкой то, что
     проезжает над ней и под ней при прокрутке (как у «Далее» на шагах).
     Пятая тень (70px) продлевает это укрытие вниз, до самого низа
     экрана — то есть и под «Выйти из комнаты» тоже: без неё сквозь
     прозрачные поля вокруг этой кнопки было бы видно, как под ней
     проезжает стол. */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    0 8px 22px rgba(210, 247, 107, 0.16),
    0 -16px 16px -4px var(--сб-фон),
    0 calc(26px + var(--отступ-снизу)) 0 0 var(--сб-фон),
    0 calc(70px + var(--отступ-снизу)) 0 0 var(--сб-фон);
}

#комната > .комната__начать:not(:disabled):active {
  transform: translateY(1px);
  filter: brightness(0.95);
}

#комната > .комната__начать:disabled {
  color: #8d939a;
  background: linear-gradient(180deg, #3b4046 0%, #32363b 100%);
  border: none;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.07),
    0 -16px 16px -4px var(--сб-фон),
    0 calc(26px + var(--отступ-снизу)) 0 0 var(--сб-фон),
    0 calc(70px + var(--отступ-снизу)) 0 0 var(--сб-фон);
  cursor: default;
}

/* Ожидаем игрока / хозяина — слева от надписи крутится то же кольцо,
   что и в «.ожидание-крутится» (тот же keyframes «колечко-ожидания»,
   второй не заводим). Класс ставит js/дурак-комната.js по самой надписи
   на кнопке; цвет кольца берём из currentColor — кнопка уже серая
   от «:disabled» выше, и кольцо становится того же приглушённого цвета. */
#комната > .комната__начать.комната__ожидает::before {
  content: "";
  display: inline-block;
  flex: 0 0 auto;
  width: 1em;
  height: 1em;
  margin-right: 10px;
  border: 0.15em solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: колечко-ожидания 1.1s linear infinite;
}

/* Отступ подсказки от того, что выше — для редкого случая, когда стол
   короткий (мало игроков) и всё помещается без прокрутки: тогда кнопка
   «Выйти из комнаты» стоит на своём месте в потоке, а не прилипшая
   снизу, и этот отступ — просто воздух перед ней. У самой кнопки
   свой отступ не нужен: она прилипшая, margin в её родном месте
   в потоке на видимую позицию не влияет. */
#комната > .комната__подсказка {
  margin-top: calc(18px + var(--отступ-снизу));
}

#комната > .комната__подсказка {
  font-size: 14px;
  line-height: 1.35;
  text-align: center;
  text-wrap: balance;
  color: var(--сб-текст-тихий);
}

/* «Выйти из комнаты» — та же мелкая второстепенная кнопка, что и везде
   в проекте (класс «кнопка кнопка--мелкая» уже висит на ней в разметке):
   тихая подложка и тонкая рамка вместо заливки — вид говорит «можно
   нажать», но взгляд не отвлекает от «Начать». Раньше это правило само
   снимало и подложку, и рамку, оставляя голый подчёркнутый текст —
   смотритель заметил (26.09), что так зона нажатия маленькая и на
   тёмной странице кнопка теряется. Стиль общей мелкой кнопки (подложка,
   рамка) не трогаем, только растягиваем на всю ширину колонки (палец
   попадает куда угодно, не только в узкое слово по центру), центрируем
   текст и возвращаем ему обычный, не приглушённый цвет — с тихим цветом
   кнопка на вид была неотличима от соседней погашенной «Ожидаем
   игрока…» (замечание смотрителя, тот же день).

   Прилипает к низу экрана вторым «этажом», под кнопкой «Начать» — иначе
   на длинном столе (пять-шесть игроков) она уезжала в конец разметки
   и без прокрутки до самого низа была не видна (жалоба владельца,
   26.09). z-index выше, чем у «Начать» (3 против 2), — иначе кнопка
   оказалась бы под её тенью-укрытием и не нажималась пальцем. */
#комната > #кнопка-комната-отмена {
  position: sticky;
  bottom: calc(12px + var(--отступ-снизу));
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-width: 0;
  color: var(--сб-текст);
}

/* ---------- Невысокое окно ----------
   Всё то же, только плотнее: заголовок ниже, стол площе и места меньше
   (но не меньше 44 точек), кнопки — не ниже 48. Остальное прокручивается,
   «Начать» при этом стоит у нижнего края. */
@media (max-height: 700px) {
  #экран-комнаты > #комната.комната { gap: 8px; }
  .комната__заголовок { margin-bottom: 2px; font-size: clamp(26px, 8.4vw, 34px); }
  #комната > .комната__шапка { gap: 4px; }
  .комната__игроки { margin-top: 2px; }
  /* Стол чуть площе телефонного, но не слишком: за столом на шесть мест
     боковые места стоят друг над другом, и на плоском овале подпись
     верхнего наезжала на кружок нижнего (замер на 320×568: не хватало
     двух точек). Имена здесь же мельче на точку. */
  #комната > .рассадка.рассадка--комната {
    --место: clamp(44px, 12.5vw, 50px);
    aspect-ratio: 1.95 / 1;
  }

  #комната > .рассадка--комната .рассадка__имя { font-size: 14px; }
  .комната__команда { min-height: 50px; padding-top: 8px; padding-bottom: 9px; }
  #комната > .комната__пригласить { min-height: 48px; }
  #комната > .комната__начать { min-height: 52px; }
}

/* ---------- Широкое окно: планшет и монитор ----------
   Столбик — той же колонкой, что у лобби и шагов (520, см. «Э8» выше
   по файлу — раньше здесь стояли отдельные 760, теперь дурак и в этом
   месте вровень с остальными играми). Стол — не шире 560, как схема
   рассадки на шаге «Игроки»: во всю колонку овал вырастал бы выше
   половины экрана. Места на нём крупнее телефонных.
   «#комната.комната» — узел только новой комнаты дурака; у шашек
   «#экран-комнаты» устроен проще (код и кнопки без рассадки), это
   правило её не задевает, замок снят без риска. */
@media (min-width: 700px) and (min-height: 600px) {
  #экран-комнаты > #комната.комната {
    max-width: var(--колонка-широкая);
  }

  #комната > .рассадка.рассадка--комната {
    --место: 64px;
    --рама: 18px;
    align-self: center;
    max-width: 560px;
  }
}

/* ---------- Прежняя прихожая — запасной вид ----------
   Её узлы теперь лежат в обёртке «#комната-старая», а не прямо в экране,
   и правила экрана кода «столбик по центру» до них не доставали: блоки
   прижимались к левому краю. Обёртка сама становится тем же столбиком
   с теми же просветами, что у экрана, и стоит посередине по высоте. */
#комната-старая {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: inherit;
  width: 100%;
  margin-top: auto;
  margin-bottom: auto;
}

#комната-старая > .подпись {
  max-width: 330px;
  line-height: 1.35;
}

/* =====================================================================
   Экран «Найти игру» — список открытых столов

   Разметку строит js/открытые-столы.js сам (готовыми классами .экран,
   .таблица, .таблица__строка, .кнопка) — здесь только вид. Экран был
   зелёным сукном с синей кнопкой Telegram, как игровой стол; правило
   владельца требует другого — тёмной страницы с одним салатовым
   акцентом, как у остальных экранов сборника. Переменные и раскладка
   взяты с тех же образцов, что дал штаб: рейтинг игроков (список,
   плитки, «‹»-стрелка назад) и лобби (фон, отступы, колонка 520).
   ===================================================================== */

/* Фон — тёмный графит сборника: один и тот же у дурака и у шашек,
   которым js/открытые-столы.js тоже подключён. */
#экран-открытые-столы {
  --фон: var(--сб-фон);
  --панель: var(--сб-поверхность);
  --текст: var(--сб-текст);
  --текст-тихий: var(--сб-текст-тихий);
  --кнопка-фон: var(--сб-акцент);
  --кнопка-текст: var(--сб-акцент-текст);
  --акцент: var(--сб-акцент);
  --подложка: rgba(248, 245, 235, 0.06);
  --край: rgba(248, 245, 235, 0.14);
  --поле: clamp(12px, 3.6vw, 18px);
  --плитка: #1e2226;
  --плитка-кромка: rgba(248, 245, 235, 0.12);

  align-items: center;
  gap: 10px;
  padding: calc(6px + var(--отступ-сверху)) calc(var(--поле) + var(--отступ-справа))
           calc(12px + var(--отступ-снизу)) calc(var(--поле) + var(--отступ-слева));
  text-align: left;
  color: var(--сб-текст);
  background:
    radial-gradient(75% 120px at 50% 0, rgba(210, 247, 107, 0.07), rgba(210, 247, 107, 0) 100%),
    var(--сб-фон);
}

/* Колонка — как у лобби и рейтинга: до 520 точек, по центру. Обе кнопки
   в исключении — у них своя ширина: «Назад» становится стрелкой
   в верхнем углу (общий приём сборника, см. список «‹» выше в файле),
   «Создать открытый стол» — обычная кнопка меню на 360. */
#экран-открытые-столы > :not(:is(#открытые-столы-создать, #открытые-столы-назад)) {
  box-sizing: border-box;
  width: 100%;
  max-width: 520px;
}

#экран-открытые-столы > .заголовок {
  margin: 0;
  text-align: left;
  font-size: clamp(28px, 9vw, 38px);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -0.02em;
  color: var(--сб-текст);
}

html.в-телеграме #экран-открытые-столы > .заголовок { margin-top: 4px; }

/* Сообщение над списком («сервер не отвечает», «пока никто не открыл
   стол») — тёмная плитка с текстом слева, как пустая таблица рейтинга,
   а не строка по центру пустоты. */
#открытые-столы-сообщение {
  margin: 0;
  padding: 14px;
  font-size: 15px;
  line-height: 1.45;
  text-align: left;
  color: var(--сб-текст-тихий);
  background: var(--плитка);
  border: 1px solid var(--плитка-кромка);
  border-radius: 14px;
}

/* ---------- Строка стола ----------
   Тёмная плитка в две строки: сверху — кто уже сидит, снизу — счёт
   мест и сколько стол ждёт, мелко и тихо. Кнопка «Сесть» занимает
   правый край во всю высоту плитки — палец всегда находит одно и то
   же место, сколько бы текста ни было слева. Она же — единственное
   салатовое пятно в строке: это главное действие списка, поэтому
   красится акцентом, а не тихой подложкой обычной мелкой кнопки. */
#открытые-столы-список .таблица__строка {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-rows: auto auto auto;
  grid-template-areas:
    "игроки    игроки    кнопка"
    "счёт      время     кнопка"
    "сложность сложность кнопка";
  align-items: center;
  column-gap: 8px;
  row-gap: 2px;
  padding: 8px 8px 8px 12px;
  background: var(--плитка);
  border: 1px solid var(--плитка-кромка);
  border-radius: 14px;
  box-shadow: none;
}

#открытые-столы-список .таблица__очки {
  grid-area: игроки;
  min-width: 0;
  font-size: 15px;
  font-weight: 700;
  color: var(--сб-текст);
}

#открытые-столы-список .таблица__место {
  grid-area: счёт;
  min-width: 0;
  font-size: 12px;
  font-weight: 700;
  color: var(--сб-текст-тихий);
  white-space: nowrap;
}

/* Точка-разделитель перед «ждёт…» — оформлением, чтобы js не пришлось
   собирать строку самому. */
#открытые-столы-список .таблица__место::after {
  content: " ·";
  opacity: 0.7;
}

#открытые-столы-список .таблица__дата {
  grid-area: время;
  min-width: 0;
  font-size: 12px;
  color: var(--сб-текст-тихий);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Правила стола («Подкидной», «Переводной, парами») — третья строчка
   плитки, мелко и тихо, как и остальные подписи-уточнения. Своя строка,
   а не довесок к имени игрока: текст бывает длиннее, чем счёт мест или
   время ожидания, и не должен отжимать их. Пустой ячейки не бывает —
   на случай, если стол когда-нибудь придёт без описания правил, строка
   схлопывается сама, не оставляя дырки в плитке. */
#открытые-столы-список .таблица__сложность {
  grid-area: сложность;
  min-width: 0;
  font-size: 12px;
  color: var(--сб-текст-тихий);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

#открытые-столы-список .таблица__сложность:empty {
  display: none;
}

#открытые-столы-список .таблица__строка > .кнопка.кнопка--мелкая {
  grid-area: кнопка;
  min-height: 44px;
  min-width: 64px;
  padding: 0 16px;
  font-size: 14px;
  font-weight: 800;
  color: var(--сб-акцент-текст);
  background: var(--сб-акцент);
  border: none;
  box-shadow: none;
  white-space: nowrap;
}

#открытые-столы-список .таблица__строка > .кнопка.кнопка--мелкая:disabled {
  opacity: 0.55;
  background: var(--сб-акцент);
  color: var(--сб-акцент-текст);
  cursor: default;
}

/* Узкий телефон (320): плитке и кнопке нужно чуть меньше воздуха,
   а «Сесть» — остаться целой, а не обрезанной. */
@media (max-width: 340px) {
  #открытые-столы-список .таблица__строка {
    padding: 7px 6px 7px 10px;
    column-gap: 6px;
  }
  #открытые-столы-список .таблица__строка > .кнопка.кнопка--мелкая {
    min-width: 56px;
    padding: 0 10px;
    font-size: 13px;
  }
}

/* «Есть код? Войти» — третье, самое тихое действие на экране: ниже
   «Найти игру» (520 точек, самая широкая и яркая) и «Создать игру»
   (360, обычная кнопка меню). Без этого правила она получила бы
   те же 520 точек, что и главная кнопка сверху (общая для колонки
   520, см. правило выше), — тихая мелкая кнопка не должна быть
   заметнее по размеру, чем действие над ней. Ширина — по тексту,
   по центру, как «Есть код?» выглядит в лобби (класс «.лобби__код»);
   высота и подложка остаются от общего «.кнопка--мелкая». */
#экран-открытые-столы > #открытые-столы-код {
  align-self: center;
  width: auto;
  max-width: none;
}

/* =====================================================================
   Экран «Играть онлайн» / «Ищем соперника»

   Разметку строит js/подбор-экран.js сам (готовыми классами .экран,
   .заголовок, .сеть-ожидание, .сеть-сообщение, .кнопка) — здесь только
   вид. Причина зелёного сукна: класс «.экран» своего фона не красит
   (см. правило «.экран» выше в файле) — фон под ним даёт body, а его
   «--фон» по умолчанию — сукно стола (см. «:root», строка с пометкой
   «сукно стола»). Экран подбора этот «--фон» не переопределял, поэтому
   сквозь него было видно зелёное сукно, а кнопки красились цветом кнопки
   Telegram (--кнопка-фон по умолчанию), а не салатовым акцентом сборника.
   Чинится тем же приёмом, что у лобби и экрана «Найти игру»: свои
   переменные из общей палитры сборника «--сб-*» (см. «Общие цвета
   сборника» в начале файла). Фон — тёмный графит сборника, такой же,
   как на остальных служебных экранах любой игры. */
#экран-подбор-соперника {
  --фон: var(--сб-фон);
  --текст: var(--сб-текст);
  --текст-тихий: var(--сб-текст-тихий);
  --кнопка-фон: var(--сб-акцент);
  --кнопка-текст: var(--сб-акцент-текст);
  --акцент: var(--сб-акцент);
  --подложка: rgba(248, 245, 235, 0.06);
  --край: rgba(248, 245, 235, 0.14);

  align-items: center;
  justify-content: center;
  gap: 14px;
  text-align: center;
  color: var(--сб-текст);
  background: var(--сб-фон);
}

/* =====================================================================
   Экран «Профиль» (план профиль-по-макету, Э4)

   Разметку строит js/профиль-экран.js — своя, без html. Узлы и вложенность
   взяты оттуда (функции «построитьРазметкуПрофиля», «построитьКарточку»,
   «блокОчков»). Здесь только вид: размеры, цвета, отступы.

   Числа — из макета владельца (leaderboard_cloudcode_pack_v1,
   prototype/styles.css), строки указаны у каждого правила. Золото —
   ТОЛЬКО ссылкой на общую переменную «--рейтинг-золото-общее»
   (объявлена на «#приложение», style.css:333) — второго золотого
   литерала в сборнике не заводим, как и у рейтинга рядом.

   Приглушённый серый макета (--muted #aaa9a7, styles.css:4) и цвета
   стрелки движения (--green/--red, styles.css:5) у рейтинга объявлены
   ЛОКАЛЬНО внутри «#экран-рейтинга-игроков» (11458–11507) — снаружи
   того блока их не видно. Общей переменной на «#приложение» для них
   нет, поэтому здесь те же числа объявлены заново, с пометкой откуда.
   ===================================================================== */

/* ---------- Каркас: прокрутка, поля, цвет текста ----------
   Тот же набор свойств, что у «#экран-рейтинга-игроков» (11442–11448,
   11426–11427) — экран рядом в той же системе лобби, должен листаться
   и иметь те же боковые поля.
   Фон — СВОЙ, тёмный графит сборника, тем же набором, что у рейтинга
   (11652–11682). Без него сквозь экран просвечивало сукно «body» (строки
   260–322): оно красится цветом темы Telegram, и в светлой теме экран
   выходил бледно-салатовым с зерном, а белый текст на нём пропадал
   (снимок владельца 23.09). Свои «--фон/--текст/--кнопка-*» — по той же
   причине: общие классы внутри экрана («.кнопка», «.таблица__пусто»)
   читают их и иначе взяли бы светлые цвета темы. */
#экран-профиля-игрока {
  --фон: var(--сб-фон);
  --панель: var(--сб-поверхность);
  --текст: var(--сб-текст);
  --кнопка-фон: var(--сб-акцент);
  --кнопка-текст: var(--сб-акцент-текст);
  --акцент: var(--сб-акцент);
  --край: rgba(248, 245, 235, 0.14);
  /* Тот же тихий серый и подложка, что почти везде в файле (например
     «#экран-подбор-соперника» выше) — нужны классу «.таблица__пусто»
     («Загружаем…», «Повторить»): он их только читает, здесь объявляем. */
  --текст-тихий: var(--сб-текст-тихий);
  --подложка: rgba(248, 245, 235, 0.06);
  /* Боковое поле — то же число, что у рейтинга («--поле», 11415),
     второй раз не выдумываем, а объявляем заново: имя переменной
     совпадает, но область видимости — только свой экран, конфликта
     с чужим блоком нет. */
  --поле: clamp(12px, 3.6vw, 18px);
  /* Зелёный/красный стрелки движения места — те же числа, что
     у рейтинга («--рейтинг-движение-вверх/-вниз», 11488–11489):
     общей переменной на «#приложение» для них нет, повторяем здесь. */
  --профиль-движение-вверх: #57c17b;
  --профиль-движение-вниз: #e2645f;
  /* Запас между последней строкой экрана и полосой вкладок — тем же
     приёмом, что «--рейтинг-моё-место-запас» у рейтинга (11768–11773):
     одна переменная, а не число прямо в правиле ниже. */
  --профиль-запас-снизу: 12px;

  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  align-items: center;
  gap: 8px;
  padding: calc(6px + var(--отступ-сверху)) calc(var(--поле) + var(--отступ-справа))
           calc(12px + var(--отступ-снизу)) calc(var(--поле) + var(--отступ-слева));
  text-align: left;
  color: var(--сб-текст);
  background:
    radial-gradient(75% 120px at 50% 0, rgba(210, 247, 107, 0.07), rgba(210, 247, 107, 0) 100%),
    var(--сб-фон);
}

#экран-профиля-игрока::-webkit-scrollbar { display: none; }

/* Находка обхода лобби (беда: строка очков и кнопка «Как я играю»
   впритык к полосе вкладок на нескольких ширинах, зазор 5–8px при
   пороге 8). Прежний приём добавлял запас только через padding-bottom,
   а сам экран («.экран», inset:0) всё равно тянулся до самого низа
   окна — полоса (position: fixed) лежала поверх этого нижнего края,
   и на некоторых ширинах округление clamp()/vh «съедало» пару пикселей
   запаса. Тот же структурный приём, что у рейтинга (11784–11797):
   область прокрутки САМА кончается над полосой («bottom» — ровно
   высота полосы), а не прячется под ней с расчётом на точный padding.
   Снизу внутри остаётся только запас «--профиль-запас-снизу». */
#экран-профиля-игрока:has(> .нижние-вкладки) {
  bottom: calc(var(--вт-панель-низ) + var(--отступ-снизу));
  padding-bottom: var(--профиль-запас-снизу);
}

/* На ПК держит ту же телефонную ширину колонки, что рейтинг (11527–11541,
   переменная «--колонка-широкая» из @media (min-width:700px) and
   (min-height:600px), объявлена на «:root», 13949) — тем же приёмом:
   всем прямым детям экрана одна и та же потолочная ширина, чтобы карточка,
   «Ваши очки по играм» и дверь «Как я играю» не растягивались на 1280px.
   Кнопка «‹» здесь не отдельный узел экрана (в отличие от рейтинга) —
   она уже внутри «.профиль-шапка», исключать нечего. Полосу
   «Лобби · Рейтинг · Профиль» (.нижние-вкладки) исключаем — она должна
   покрывать всю ширину окна, а не сжиматься до потолочной ширины колонки
   (тот же баг, что чинили у рейтинга, найден ревьюером 23.09). */
#экран-профиля-игрока > :not(.нижние-вкладки) {
  box-sizing: border-box;
  width: 100%;
  flex-shrink: 0;
  max-width: min(100%, var(--колонка-широкая, 520px));
}

/* ---------- Шапка «‹ Профиль» ----------
   Та же сетка в три колонки, что у шапки рейтинга (11577–11598):
   боковые колонки по 44px держат место под кнопку «‹», даже когда
   в Telegram её нет (там же работает системная стрелка). */
#экран-профиля-игрока > .профиль-шапка {
  display: grid;
  grid-template-columns: 44px 1fr 44px;
  align-items: center;
  gap: 10px;
  min-height: 64px;
}

#экран-профиля-игрока .профиль-шапка__название {
  margin: 0;
  grid-column: 2;
  min-width: 0;
  text-align: center;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--сб-текст);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* «‹» профиля — свой id («#кнопка-профиля-назад»), общий приём кнопки
   «Назад» (та же 44×44 зона, та же SVG-стрелка, то же исчезновение
   в Telegram), что и у «#кнопка-рейтинг-игроков-назад» (9673–9727):
   общий список id там трогать нельзя (правило задания — старые правила
   не менять), поэтому набор повторён здесь для нового id. */
#экран-профиля-игрока #кнопка-профиля-назад.профиль-шапка__назад {
  grid-column: 1;
  position: relative;
  align-self: center;
  flex: 0 0 auto;
  width: 44px;
  min-width: 44px;
  height: 44px;
  min-height: 44px;
  margin: 0;
  padding: 0;
  font-size: 0;
  line-height: 0;
  color: var(--сб-текст);
  background: none;
  border: none;
  border-radius: 12px;
  box-shadow: none;
}

#экран-профиля-игрока #кнопка-профиля-назад.профиль-шапка__назад::before {
  content: "";
  position: absolute;
  inset: 0;
  width: 24px;
  height: 24px;
  margin: auto;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m15 4-8 8 8 8'/%3E%3C/svg%3E") center / 24px 24px no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m15 4-8 8 8 8'/%3E%3C/svg%3E") center / 24px 24px no-repeat;
}

#экран-профиля-игрока #кнопка-профиля-назад.профиль-шапка__назад:active {
  transform: scale(0.92);
  opacity: 0.7;
  box-shadow: none;
}

#экран-профиля-игрока #кнопка-профиля-назад.профиль-шапка__назад:focus-visible {
  outline: 2px solid var(--сб-акцент);
  outline-offset: -4px;
}

html.в-телеграме #экран-профиля-игрока #кнопка-профиля-назад.профиль-шапка__назад {
  display: none;
}

/* ---------- Карточка игрока ----------
   «.profile-hero» макета (styles.css:126–127: «margin:20px auto;
   text-align:center», аватар 100×100) — только тут аватар такой
   крупный, нигде больше в сборнике. */
#экран-профиля-игрока > .профиль-карточка {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: 100%;
  margin: 8px 0 4px;
  text-align: center;
}

/* Круг без фото — тот же градиент и цвет букв, что «.avatar» макета
   (styles.css:49): «linear-gradient(135deg,#574e39,#272522)», буквы
   «#e6cc8c» — свой тёплый тон карточки, это НЕ золото рейтинга
   («--рейтинг-золото-общее» рядом заметно ярче и насыщенней), поэтому
   ссылкой на общую переменную его не заменяем.
   Ширина — «не меньше 84px на 320, не больше 100px» (условие задания):
   84px даёт 27vw уже на 311px, а к 375px клампится в потолок 100px. */
#экран-профиля-игрока .профиль-карточка__аватар {
  position: relative;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(84px, 27vw, 100px);
  height: clamp(84px, 27vw, 100px);
  overflow: hidden;
  font-weight: 650;
  font-size: clamp(26px, 8vw, 32px);
  color: #e6cc8c;
  background: linear-gradient(135deg, #574e39, #272522);
  border-radius: 50%;
}

#экран-профиля-игрока .профиль-карточка__инициалы {
  line-height: 1;
  user-select: none;
}

/* Настоящее фото — тем же приёмом, что общий «.аватар--фото» (7640–7648):
   js кладёт готовый «url("…")» в «--фото-аватара» и добавляет класс.
   Буквы прячем — иначе фото и текст читались бы поверх друг друга. */
#экран-профиля-игрока .профиль-карточка__аватар--фото {
  background-image: var(--фото-аватара);
  background-position: center;
  background-size: cover;
}

#экран-профиля-игрока .профиль-карточка__аватар--фото > .профиль-карточка__инициалы {
  display: none;
}

#экран-профиля-игрока .профиль-карточка__имя {
  font-size: clamp(17px, 4.6vw, 18px);
  font-weight: 600;
  line-height: 1.25;
  color: var(--сб-текст);
}

#экран-профиля-игрока .профиль-карточка__место {
  font-size: 13px;
  line-height: 1.3;
  color: var(--сб-текст-тихий);
}

/* Очки золотом — тот же набор, что «.podium-score» макета (styles.css:59):
   19px, вес 750, табличные цифры (колонка чисел не «пляшет» по ширине),
   без переноса. */
#экран-профиля-игрока .профиль-карточка__очки {
  margin-top: 2px;
  font-size: 19px;
  font-weight: 750;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--рейтинг-золото-общее);
}

/* Стрелка движения места — общие классы «.рейтинг-движение(--вверх|
   --вниз|--нет)» (их же ставит js/профиль-экран.js, «узелДвижения»,
   один в один с рейтингом), но САМИ цвета у общих классов объявлены
   только внутри «#экран-рейтинга-игроков»/«#рейтинг-моё-место»
   (11958–11966, 12561–12571) — здесь классы те же, а цвет свой,
   через переменные этого экрана.

   Хвост проверки смотрителя (профиль, 768): на превью значок читался
   как «красная точка» — стрелка и число были мелкими (12px, отступ от
   очков всего 1px) и сливались в одно пятно. Здесь только своя карточка:
   в таблице и в «Моё место» тот же класс остаётся 11px как был, эти
   правила его не трогают. */
#экран-профиля-игрока .профиль-карточка__движение {
  margin-top: 4px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.2px;
  white-space: nowrap;
}

#экран-профиля-игрока .профиль-карточка__движение.рейтинг-движение--вверх { color: var(--профиль-движение-вверх); }
#экран-профиля-игрока .профиль-карточка__движение.рейтинг-движение--вниз { color: var(--профиль-движение-вниз); }
#экран-профиля-игрока .профиль-карточка__движение.рейтинг-движение--нет { color: var(--сб-текст-тихий); }

/* ---------- «Ваши очки по играм» ----------
   Обёртка меняет содержимое по состоянию (загрузка/беда/блок/честная
   строка, js «показатьОчки»). Отступ сверху 4 точки — старая правка
   магическим числом (было 14), она подвинула список, но НЕ убрала
   саму причину находки обхода лобби: тесно бывает не из-за отступа
   сверху, а из-за того, что список игр растёт (в каталоге прибавилась
   9-я игра — Монополия) и его суммарная высота от раза к разу разная.

   НАСТОЯЩАЯ причина находки (проверено замером в браузере на 320 и на
   768/1280 при длинном имени): список очков и весь экран прокручивались
   ОДНИМ куском («overflow-y: auto» стоит на «#экран-профиля-игрока»
   целиком). Пока список не докрутили руками, последняя строка (или
   кнопка «Как я играю» — она идёт в потоке СРАЗУ после этой обёртки)
   встаёт ровно там, где закончилось содержимое СВЕРХУ — от высоты
   шапки, карточки и самого списка эта позиция не зависит и никаким
   запасом СНИЗУ экрана (bottom/padding-bottom правила выше по файлу)
   не подвинуть: подвинуть её может только то, что стоит ДО неё
   в потоке, а список игр — как раз оно, и он растёт вместе с каталогом.

   Структурный приём: список получает СВОЮ, отдельную прокрутку внутри
   гибкого («flex») экрана — «flex: 1 1 auto» с «min-height: 0» отдаёт
   обёртке ровно ту высоту, что осталась после шапки, карточки, строки
   серии и кнопки «Как я играю» (у них выше по файлу «flex-shrink: 0» —
   не сжимаются), а «overflow-y: auto» уже на САМОЙ обёртке прячет её
   же лишние строки за краем ЭТОЙ маленькой области. Строка списка,
   которой не хватило места, обрежется здесь и не будет считаться
   «на экране» (тот же приём, что «элементРеальноСверху» в обходе
   лобби — обрезанное прокруткой не участвует в замере зазоров).
   Кнопка «Как я играю» и полоса вкладок при этом больше НЕ зависят от
   длины списка вовсе: они всегда стоят там же, где встали бы при
   пустом списке — расстояние между ними и полосой вкладок теперь
   постоянное, а не «как повезло с суммарной высотой каталога». */
#экран-профиля-игрока .профиль-очки-место {
  width: 100%;
  margin-top: 4px;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  /* Запас ниже последней строки СПИСКА — та же переменная, что у запаса
     перед полосой вкладок (16317): один и тот же зазор, а не два
     случайно совпавших числа. */
  padding-bottom: var(--профиль-запас-снизу);
}

#экран-профиля-игрока .профиль-очки-место::-webkit-scrollbar { display: none; }

/* «.game-breakdown{margin-top:22px}» макета — но margin уже у обёртки
   выше, здесь достаточно ширины. */
#экран-профиля-игрока .профиль-очки {
  display: flex;
  flex-direction: column;
  width: 100%;
}

/* «.option-heading» макета (styles.css:112): 11px, «#b0aeaa», разрядка
   1px, отступы «17px 4px 8px». В самом прототипе текст набран уже
   заглавными («ВАШИ ОЧКИ ПО ИГРАМ», prototype/app.js:65) — у нас его
   даёт js обычным регистром, регистр меняем здесь. Боковой отступ 4px
   макета не берём — строки и итог ниже (15791, 15842) набраны без
   бокового отступа, заголовок выравниваем по ним (нашёл ревьюер 23.09). */
#экран-профиля-игрока .профиль-очки__заголовок {
  /* Боковые 8px — по строкам ниже (у них теперь те же 8px, как у строк
     рейтинга), чтобы заголовок стоял с ними в одну линию. */
  margin: 17px 8px 8px;
  font-size: 11px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: #b0aeaa;
}

/* Строка игры — тем же видом, что строка списка рейтинга
   («#рейтинг-таблица .рейтинг-строка», 12884–12901): без плитки и без
   скругления, только волосок-разделитель того же цвета, те же боковые
   8px и высота 53px. Раньше здесь стояло скругление 8px при нижней
   черте — на снимке владельца это читалось как «подчёркнутые полосы».
   В разметке строка — кнопка (клик уводит в рейтинг своей игры,
   js «открытьРейтингИгры»), вид кнопки браузера сбрасываем. */
#экран-профиля-игрока .профиль-очки__строка {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 53px;
  padding: 5px 8px;
  font: inherit;
  text-align: left;
  color: inherit;
  background: none;
  border: none;
  border-bottom: 1px solid #272626;
  border-radius: 0;
}

/* Нажатие — лёгкая подсветка плитки, чтобы было видно «нажалось»
   (то же требование, что у карт и других кнопок сборника). */
#экран-профиля-игрока .профиль-очки__строка:active {
  background: rgba(248, 245, 235, 0.05);
}

#экран-профиля-игрока .профиль-очки__значок {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  object-fit: contain;
}

/* Запасной значок: картинки игры нет (не нарисована или не доехала
   до сервера) — js/профиль-экран.js ставит вместо <img> кружок с первой
   буквой игры. Битой картинки на экране не бывает. */
#экран-профиля-игрока .профиль-очки__значок--запаска {
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  color: var(--сб-текст);
  background: var(--сб-поверхность);
  border: 1px solid var(--сб-граница);
  border-radius: 50%;
}

#экран-профиля-игрока .профиль-очки__игра {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 15px;
  color: var(--сб-текст);
}

/* Число очков — тот же вес и размер, что «.рейтинг-очки» списка
   рейтинга (12573–12580): 17px, вес 700, золото общей переменной. */
#экран-профиля-игрока .профиль-очки__число {
  flex: 0 0 auto;
  font-size: 17px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--рейтинг-золото-общее);
}

/* «.breakdown-total» макета (styles.css:118): «margin:16px 0;color:gold;
   font-weight:700» — целиком золотой, обе половины. */
#экран-профиля-игрока .профиль-очки__итог {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin: 16px 0 4px;
  /* Те же боковые 8px, что у строк выше, — иначе «Всего» и число
     съехали бы из столбца. */
  padding: 0 8px;
  font-weight: 700;
  color: var(--рейтинг-золото-общее);
}

#экран-профиля-игрока .профиль-очки__итог-подпись {
  font-size: 15px;
}

#экран-профиля-игрока .профиль-очки__итог-число {
  font-size: 18px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---------- Строка серии дней ----------
   Тихая подпись под блоком очков — «--muted» макета, тот же тон,
   что и у приглушённых элементов рейтинга. Пустая строка скрыта общим
   «.скрыт» (js её и переключает). */
#экран-профиля-игрока .профиль-серия {
  margin: 10px 0 0;
  font-size: 13px;
  line-height: 1.4;
  text-align: center;
  color: var(--сб-текст-тихий);
}

/* «Вчера играли — сыграйте сегодня»: тёплое приглашение, не тревога —
   мягкий золотой вместо обычного серого (значение — не новый золотой
   литерал: цвет читает ту же общую переменную рейтинга, смешанную
   с прозрачностью через «color-mix», второго числа тут нет). */
#экран-профиля-игрока .профиль-серия--вчера {
  color: color-mix(in srgb, var(--рейтинг-золото-общее) 70%, var(--сб-текст-тихий));
}

/* ---------- Нижняя полоса вкладок ----------
   Без своего набора «--вт-*» полоса встаёт без фона и цвета текста
   (то же объяснение, что у рейтинга, 11493–11497) — переменных на этом
   экране раньше не было вовсе. Акцент золотой, как и весь экран рядом. */
#экран-профиля-игрока {
  --вт-панель-низ: clamp(52px, 14.36vw, 64px);
  --вт-поверхность: var(--сб-поверхность);
  --вт-граница: var(--сб-граница);
  --вт-текст: var(--сб-текст);
  --вт-текст-тихий: var(--сб-текст-тихий);
  --вт-акцент: var(--рейтинг-золото-общее);
  /* Тёмный текст поверх золотой заливки активной вкладки — то же число,
     что у рейтинга («--рейтинг-золото-текст-тёмный», 11472): общей
     переменной на «#приложение» для него тоже нет. */
  --вт-акцент-текст: #2b1f06;
}

/* Небольшой отступ от блока очков — кнопка «Как я играю» получает
   ширину и центрирование от общего правила «.экран > .кнопка» (669–678),
   здесь только зазор сверху. */
#экран-профиля-игрока > #кнопка-профиля-как-я-играю {
  margin-top: 6px;
}

/* Решение владельца (коммит 07ed072, 25.09): карточка «Моё место» идёт
   ПОСЛЕ всего списка обычным потоком и не закрывает его последнюю
   строку. Снимаем «position: sticky» у базового правила выше по файлу —
   карточка больше не прилипает к низу экрана поверх таблицы, а стоит
   последней среди прямых детей экрана (её «order: 1» это уже держит).
   Из-за этого при коротком списке карточка вправду может оказаться
   ниже края окна, пока список не прокручен, — это ожидаемо. Вместе со
   sticky убираем и псевдоэлементы-затухания «::before»/«::after»: они
   были рассчитаны на приклеенную карточку и без sticky только мешают. */
#экран-рейтинга-игроков > #рейтинг-моё-место:not(.подпись) {
  position: relative;
  bottom: auto;
  margin: auto 0 0;
}
#экран-рейтинга-игроков > #рейтинг-таблица { margin-bottom: 24px; }
#экран-рейтинга-игроков > #рейтинг-моё-место::before,
#экран-рейтинга-игроков > #рейтинг-моё-место::after { content: none; }

/* Правка исполнителя 26.09: у общего «.экран» уже есть зазор между всеми
   прямыми детьми — «gap: 8px» (строка 11686). «margin-bottom: 24px» у
   таблицы (блок владельца сразу выше) добавляется ПОВЕРХ этого зазора —
   перед карточкой набегает двойной разрыв в 32px. При длинном списке
   (от 8 игроков, без прокрутки не помещается) на ширине 768 этого хватало,
   чтобы карточка при обычном открытии экрана (без прокрутки) частично
   пряталась под полосой вкладок: замер до правки — низ карточки 931.9,
   верх полосы 936, т. е. запаса не оставалось (нашлось прогоном
   tests/обход-рейтинга.js, сценарий «дурак-все-игроки» 768). Убираем
   задвоение: перед карточкой остаётся один зазор — общий «gap», как между
   всеми остальными блоками экрана. На прокрутку списка до конца это не
   влияет: там положение карточки держит запас --рейтинг-моё-место-запас
   (строка 11773), а не эта пара отступов. На коротком списке тоже без
   изменений: margin-top:auto карточки просто забирает освободившееся
   место себе, прижимая её к низу ровно как раньше.
   Правка нарочно только до 1023px: на планшетной ширине (768) этого
   хватает под самый длинный список ровно с запасом. От 1024 и шире
   таблица сама становится выше (строки крупнее по clamp(...vw...)),
   этих 24px недостаточно даже без задвоения — там нужна отдельная
   задача с более широким разбором, не эта точечная правка. */
@media (max-width: 1023px) {
  #экран-рейтинга-игроков > #рейтинг-таблица { margin-bottom: 0; }
}

/* ======================================================================
   СТЕКЛО — общие классы сборника (этап П1 «Захвата», 02.10)
   ======================================================================
   Пять классов, которыми игра рисует «парящие» стеклянные панели поверх
   своей картинки (карты, доски) — без файлов-картинок, только CSS:
     .стекло-панель       — большие панели: пульт, лист удара, итог раунда,
                            карточки лобби;
     .стекло-капсула      — вытянутые «таблетки»: раунд, игроки, подписи;
     .стекло-кнопка-круг  — круглые кнопки 44×44: «‹», «⋯», «−», «+»;
     .стекло-акцент       — салатовая главная кнопка («Готово», «Ударить»);
     .стекло-полоса       — парящая нижняя полоса «Игры · Рейтинг · Профиль».

   Из чего стекло: полупрозрачный тёмный слой (#15181B), тонкая светлая
   кромка сверху и слева, мягкая тёмно-синяя тень снизу, размытие того,
   что лежит под панелью (backdrop-filter), и сверху два градиента —
   блик (светлое пятно у верхнего левого угла) и перелив (холодный
   голубоватый отсвет у нижнего правого).

   ВАЖНО для разработчиков:
   1. Классы вешаются на САМИ панели. Никогда — на #приложение, .экран
      или общий родитель листов: у элемента с размытием всё
      «position: fixed» внутри начинает отсчитываться от него, а не от
      окна, и общий лист «⋯» с накладками уезжают (см. комментарий
      у накладки «.экран» выше).
   2. Размытие — не больше 20 точек: на слабых телефонах оно дорогое.
      Числа размытия записаны прямо в классах (а не переменными), чтобы
      проверка tests/стекло-классы.js могла их прочесть и сравнить с 20.
   3. Запасной вид — то же стекло без размытия, но плотнее (тёмный слой
      почти непрозрачный, чтобы текст читался над любой картинкой).
      Включается сам, если браузер размытие не умеет (@supports ниже),
      и настройкой «Эффекты стекла: Лёгкие» — класс
      «стекло-без-размытия» на body (или на html).
   4. Форму (скругление, размер круга) другая игра может поменять своей
      переменной, не переписывая класс: например у пульта задать
      --стекло-радиус-панель равным 24px.
   Классы пока включает только «Захват»; остальные игры их не трогают. */
:root {
  /* Цвет стекла — #15181B, записан тремя числами, чтобы подставлять
     разную прозрачность: rgba(var(--стекло-ргб), 0.6). */
  --стекло-ргб: 24, 42, 68;
  /* Цвет запасного вида без размытия — прежний тёмный (#15181B). */
  --стекло-ргб-запасная: 21, 24, 27;

  /* Насколько стекло тёмное (0 — прозрачное, 1 — сплошное). Холодный
     сине-стальной слой, светлее и прозрачнее прежнего; вуаль оставлена
     достаточной, чтобы белый текст читался над светлым песком карты. */
  --стекло-плотность-панель: 0.5;
  --стекло-плотность-капсула: 0.46;
  --стекло-плотность-круг: 0.46;
  --стекло-плотность-полоса: 0.56;
  /* Запасной вид без размытия: почти сплошной, иначе картинка под
     панелью «шумит» и текст хуже читается. */
  --стекло-плотность-запасная: 0.93;

  /* Кромка: светлая сверху и слева (там «свет»), едва видная справа
     и снизу. */
  --стекло-кромка: rgba(255, 255, 255, 0.42);
  --стекло-кромка-тихая: rgba(255, 255, 255, 0.18);
  --стекло-кромка-внутри: rgba(255, 255, 255, 0.24);
  /* Светлая полоска внутри у верхнего края. */
  --стекло-кромка-сверху: rgba(255, 255, 255, 0.22);

  /* Блик (белый) и перелив (холодный голубой) — цвета градиентов. */
  --стекло-блик: rgba(255, 255, 255, 0.17);
  --стекло-перелив: rgba(122, 170, 255, 0.14);

  /* Тень — тёмно-синяя, мягкая, уходит вниз. */
  --стекло-тень-цвет: rgba(4, 12, 38, 0.55);
  --стекло-тень: 0 12px 30px var(--стекло-тень-цвет);
  --стекло-тень-малая: 0 5px 14px var(--стекло-тень-цвет);

  /* Насыщенность картинки под стеклом: чуть ярче — стекло «живее». */
  --стекло-насыщенность: 140%;

  /* Текст на стекле и на салатовой кнопке. Свои значения — запасные,
     если общие цвета сборника почему-то не заданы. */
  --стекло-текст: var(--сб-текст, #f4f4ed);
  --стекло-акцент-цвет: var(--сб-акцент, #d2f76b);
  --стекло-акцент-текст: var(--сб-акцент-текст, #10130a);
  /* Блик на салатовом — заметнее, чем на тёмном. */
  --стекло-акцент-блик: rgba(255, 255, 255, 0.55);
  /* Мягкое салатовое свечение вокруг и тень снизу. */
  --стекло-акцент-тень: 0 0 20px rgba(210, 247, 107, 0.45), 0 6px 16px rgba(4, 12, 38, 0.5);

  /* Форма. */
  --стекло-радиус-панель: 20px;
  --стекло-радиус-полоса: 26px;
  --стекло-радиус-капсула: 999px;
  --стекло-радиус-акцент: 14px;
  /* Круглая кнопка — 44 точки: меньше пальцем уже промахиваются. */
  --стекло-круг: 44px;
  /* Обводка выбранного с клавиатуры (Tab) элемента. */
  --стекло-фокус: var(--сб-акцент, #d2f76b);
}

/* --- Панель: пульт, листы, итог раунда, карточки лобби ---------------- */
.стекло-панель {
  color: var(--стекло-текст);
  background:
    linear-gradient(160deg, var(--стекло-блик) 0%, transparent 42%),
    linear-gradient(330deg, var(--стекло-перелив) 0%, transparent 55%),
    rgba(var(--стекло-ргб), var(--стекло-плотность-панель));
  border: 1px solid var(--стекло-кромка-тихая);
  border-top-color: var(--стекло-кромка);
  border-left-color: var(--стекло-кромка);
  border-radius: var(--стекло-радиус-панель);
  box-shadow:
    inset 1px 1px 0 var(--стекло-кромка-внутри),
    inset 0 12px 14px -12px var(--стекло-кромка-сверху),
    var(--стекло-тень);
  -webkit-backdrop-filter: blur(16px) saturate(var(--стекло-насыщенность));
  backdrop-filter: blur(16px) saturate(var(--стекло-насыщенность));
}

/* --- Капсула: раунд, игроки, подписи областей, пилюли ----------------- */
.стекло-капсула {
  color: var(--стекло-текст);
  background:
    linear-gradient(170deg, var(--стекло-блик) 0%, transparent 55%),
    linear-gradient(350deg, var(--стекло-перелив) 0%, transparent 60%),
    rgba(var(--стекло-ргб), var(--стекло-плотность-капсула));
  border: 1px solid var(--стекло-кромка-тихая);
  border-top-color: var(--стекло-кромка);
  border-left-color: var(--стекло-кромка);
  border-radius: var(--стекло-радиус-капсула);
  box-shadow:
    inset 1px 1px 0 var(--стекло-кромка-внутри),
    inset 0 10px 12px -10px var(--стекло-кромка-сверху),
    var(--стекло-тень-малая);
  -webkit-backdrop-filter: blur(12px) saturate(var(--стекло-насыщенность));
  backdrop-filter: blur(12px) saturate(var(--стекло-насыщенность));
}

/* --- Круглая кнопка: «‹», «⋯», «−», «+» -------------------------------- */
.стекло-кнопка-круг {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  box-sizing: border-box;
  width: var(--стекло-круг);
  height: var(--стекло-круг);
  min-width: var(--стекло-круг);
  min-height: var(--стекло-круг);
  padding: 0;
  color: var(--стекло-текст);
  background:
    linear-gradient(150deg, var(--стекло-блик) 0%, transparent 50%),
    linear-gradient(330deg, var(--стекло-перелив) 0%, transparent 60%),
    rgba(var(--стекло-ргб), var(--стекло-плотность-круг));
  border: 1px solid var(--стекло-кромка-тихая);
  border-top-color: var(--стекло-кромка);
  border-left-color: var(--стекло-кромка);
  border-radius: 50%;
  box-shadow:
    inset 1px 1px 0 var(--стекло-кромка-внутри),
    inset 0 8px 10px -8px var(--стекло-кромка-сверху),
    var(--стекло-тень-малая);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.12s ease, background-color 0.12s ease;
  -webkit-backdrop-filter: blur(12px) saturate(var(--стекло-насыщенность));
  backdrop-filter: blur(12px) saturate(var(--стекло-насыщенность));
}

/* Нажатие видно: кнопка чуть «вдавливается». */
.стекло-кнопка-круг:active {
  transform: scale(0.94);
}

/* --- Акцент: салатовая главная кнопка ---------------------------------- */
.стекло-акцент {
  color: var(--стекло-акцент-текст);
  /* Сперва сплошной салатовый — для старых браузеров, не знающих
     color-mix; следующая строка их не касается. */
  background:
    linear-gradient(170deg, var(--стекло-акцент-блик) 0%, transparent 48%),
    var(--стекло-акцент-цвет);
  /* Салатовый на 92% — сквозь него чуть-чуть проступает картинка,
     и кнопка остаётся «стеклом», а тёмный текст читается так же. */
  background:
    linear-gradient(170deg, var(--стекло-акцент-блик) 0%, transparent 48%),
    color-mix(in srgb, var(--стекло-акцент-цвет) 92%, transparent);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-top-color: rgba(255, 255, 255, 0.45);
  border-left-color: rgba(255, 255, 255, 0.45);
  border-radius: var(--стекло-радиус-акцент);
  box-shadow:
    inset 1px 1px 0 rgba(255, 255, 255, 0.4),
    inset 0 -6px 10px -6px rgba(90, 130, 0, 0.35),
    var(--стекло-акцент-тень);
  font-weight: 700;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.12s ease, filter 0.12s ease;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

.стекло-акцент:active {
  transform: translateY(1px) scale(0.98);
  filter: brightness(0.92);
}

/* Выключенная главная кнопка — бледная, нажимать не тянет. */
.стекло-акцент:disabled,
.стекло-акцент[aria-disabled="true"] {
  opacity: 0.45;
  cursor: default;
  transform: none;
  filter: grayscale(0.4);
}

/* --- Полоса: парящая нижняя «Игры · Рейтинг · Профиль» ----------------- */
.стекло-полоса {
  color: var(--стекло-текст);
  background:
    linear-gradient(175deg, var(--стекло-блик) 0%, transparent 60%),
    linear-gradient(340deg, var(--стекло-перелив) 0%, transparent 55%),
    rgba(var(--стекло-ргб), var(--стекло-плотность-полоса));
  border: 1px solid var(--стекло-кромка-тихая);
  border-top-color: var(--стекло-кромка);
  border-left-color: var(--стекло-кромка);
  border-radius: var(--стекло-радиус-полоса);
  box-shadow:
    inset 1px 1px 0 var(--стекло-кромка-внутри),
    inset 0 12px 14px -12px var(--стекло-кромка-сверху),
    var(--стекло-тень);
  -webkit-backdrop-filter: blur(20px) saturate(var(--стекло-насыщенность));
  backdrop-filter: blur(20px) saturate(var(--стекло-насыщенность));
}

/* Обводка для тех, кто ходит клавишей Tab. */
.стекло-кнопка-круг:focus-visible,
.стекло-акцент:focus-visible {
  outline: 2px solid var(--стекло-фокус);
  outline-offset: 2px;
}

/* --- Запасной вид 1: браузер не умеет размытие --------------------------
   Без размытия полупрозрачное стекло пропускает всю пестроту картинки,
   и текст читается хуже — поэтому слой делаем почти сплошным. Блик,
   перелив, кромка и тень остаются: панель по-прежнему «стеклянная»,
   просто плотная. Размытия здесь не пишем вовсе — браузер его не знает.
   Примечание: старые iPhone (до iOS 18) знают только -webkit-размытие,
   поэтому попадут и сюда, и в размытие с приставкой — получат плотное
   стекло с размытием; читается это хорошо, поломки нет. */
@supports not (backdrop-filter: blur(1px)) {
  .стекло-панель {
    background:
      linear-gradient(160deg, var(--стекло-блик) 0%, transparent 42%),
      linear-gradient(330deg, var(--стекло-перелив) 0%, transparent 55%),
      rgba(var(--стекло-ргб-запасная), var(--стекло-плотность-запасная));
  }
  .стекло-капсула {
    background:
      linear-gradient(170deg, var(--стекло-блик) 0%, transparent 55%),
      linear-gradient(350deg, var(--стекло-перелив) 0%, transparent 60%),
      rgba(var(--стекло-ргб-запасная), var(--стекло-плотность-запасная));
  }
  .стекло-кнопка-круг {
    background:
      linear-gradient(150deg, var(--стекло-блик) 0%, transparent 50%),
      linear-gradient(330deg, var(--стекло-перелив) 0%, transparent 60%),
      rgba(var(--стекло-ргб-запасная), var(--стекло-плотность-запасная));
  }
  .стекло-акцент {
    background:
      linear-gradient(170deg, var(--стекло-акцент-блик) 0%, transparent 48%),
      var(--стекло-акцент-цвет);
  }
  .стекло-полоса {
    background:
      linear-gradient(175deg, var(--стекло-блик) 0%, transparent 60%),
      linear-gradient(340deg, var(--стекло-перелив) 0%, transparent 55%),
      rgba(var(--стекло-ргб-запасная), var(--стекло-плотность-запасная));
  }
}

/* --- Запасной вид 2: настройка «Эффекты стекла: Лёгкие» -----------------
   Класс «стекло-без-размытия» ставит игра на body (или html). Здесь
   размытие ОТКЛЮЧАЕТСЯ явно — «backdrop-filter: none», — иначе оно
   осталось бы от основного правила. Слой — такой же плотный, как
   в запасном виде 1. */
.стекло-без-размытия .стекло-панель {
  background:
    linear-gradient(160deg, var(--стекло-блик) 0%, transparent 42%),
    linear-gradient(330deg, var(--стекло-перелив) 0%, transparent 55%),
    rgba(var(--стекло-ргб-запасная), var(--стекло-плотность-запасная));
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.стекло-без-размытия .стекло-капсула {
  background:
    linear-gradient(170deg, var(--стекло-блик) 0%, transparent 55%),
    linear-gradient(350deg, var(--стекло-перелив) 0%, transparent 60%),
    rgba(var(--стекло-ргб-запасная), var(--стекло-плотность-запасная));
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.стекло-без-размытия .стекло-кнопка-круг {
  background:
    linear-gradient(150deg, var(--стекло-блик) 0%, transparent 50%),
    linear-gradient(330deg, var(--стекло-перелив) 0%, transparent 60%),
    rgba(var(--стекло-ргб-запасная), var(--стекло-плотность-запасная));
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.стекло-без-размытия .стекло-акцент {
  background:
    linear-gradient(170deg, var(--стекло-акцент-блик) 0%, transparent 48%),
    var(--стекло-акцент-цвет);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.стекло-без-размытия .стекло-полоса {
  background:
    linear-gradient(175deg, var(--стекло-блик) 0%, transparent 60%),
    linear-gradient(340deg, var(--стекло-перелив) 0%, transparent 55%),
    rgba(var(--стекло-ргб-запасная), var(--стекло-плотность-запасная));
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

