/* ==========================================================================
   МОРСКОЙ БОЙ: НАСТРОЙКИ И РАССТАНОВКА
   ==========================================================================
   Экран один, а шага два: пока партии нет, здесь спрашивают режим заданий, а
   как только партия заведена, тот же экран становится расстановкой.

   ЧТО ЗДЕСЬ НЕ ПИШЕТСЯ. Кнопки, чипы, карточки, шторки, шапка игры и свод
   правил уже есть в `frame.css`: `.btn`, `.chip`, `.set-card`, `.choice`,
   `.mast`, `.howto`, `.set-go`, `.eyebrow`. Своих копий не заводим, иначе
   однажды они разойдутся. Здесь только то, чего в каркасе нет: своя вода,
   полка расстановки, поля заданий и заглушка связки.

   КРАСКА И ШРИФТ ТОЛЬКО ИЗ `css/tokens.css`. Из приложения перенесены
   ГЕОМЕТРИЯ И ПРИЁМЫ, числами: доска десять на десять, корпус ровно в клетку
   высотой, стоячий корабль это тот же рисунок, довёрнутый на девяносто
   градусов вокруг центра. Ни одного цвета оттуда не взято. На календаре на
   этом уже обожглись.

   МОБИЛЬНЫЙ И ДЕСКТОП РАЗНЫЕ, а не один растянутый. На телефоне полка
   расстановки это две строки во всю ширину, а метка задания стоит НАД полем.
   На широком экране полка становится одной строкой, метка уходит в левую
   колонку рядом с полем, и доска перестаёт растягиваться: вода шириной в
   пятьсот шестьдесят пикселей это уже не доска, а обои.
   ========================================================================== */

/* ==========================================================================
   ЗАГЛУШКА СВЯЗКИ

   Видна ТОЛЬКО тому, у кого пары нет, и тогда занимает место игры целиком:
   играть всё равно нечем, эта игра без второго не начинается никак. У
   связанной пары её нет вовсе, даже строчкой (владелец).

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

.bs-nuzhnyi-dvoe {
  margin-top: var(--s-5);
  padding: var(--s-8) var(--s-5);
  min-height: 46svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--s-3);
  background: var(--c-card-bg);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
}

.bs-nuzhnyi-dvoe__chto {
  max-width: 34ch;
  font: 400 var(--t-body-l) var(--f-sans);
  color: var(--c-text);
}

.bs-nuzhnyi-dvoe__zachem {
  max-width: 38ch;
  font: 400 var(--t-body-s) var(--f-sans);
  color: var(--c-muted);
}

.bs-nuzhnyi-dvoe .btn { margin-top: var(--s-2); min-width: 220px; }

/* ==========================================================================
   ЖДЁМ ВТОРОГО: СВОЕГО ВИДА БОЛЬШЕ НЕТ

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

   Теперь это общая завеса каркаса (`.veil` в `frame.css`, разметка `завеса` в
   `ui.js`), одна на все игры. Держать здесь свою копию значило бы завести
   второй ответ на вопрос, у которого ответ уже есть, и разойтись с шашками на
   первой же правке.
   ========================================================================== */

/* ==========================================================================
   СВОЯ ВОДА

   Квадрат из ста клеток, картинка воды на всю доску (в приложении она так и
   разбирается, одним полотном на семьсот двадцать, а не плиткой на клетку).

   КОРПУС ЛЕЖИТ ПОВЕРХ, коробкой ровно в свои клетки: ширина это длина корабля
   в десятых долях доски, высота всегда одна клетка. Стоячий корабль занимает
   ТУ ЖЕ горизонтальную коробку и доворачивается на девяносто градусов вокруг
   центра: поворот вокруг центра сохраняет центр, поэтому коробка ложится
   ровно в свои клетки, а рисунок остаётся тем самым, что нарисовали для
   приложения. Растянутый прямоугольник вместо него был бы уже другой лодкой.

   ЧУЖОЙ ВОДЫ ЗДЕСЬ НЕТ И БЫТЬ НЕ МОЖЕТ: сервер её не присылает до первого
   выстрела, и это защита партии.
   ========================================================================== */

.bs-doska {
  position: relative;
  margin-top: var(--s-5);
  width: 100%;
  aspect-ratio: 1;
  /* Ширина кратна десяти, см. правило ниже. */
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--c-surface) url('/next/images/battleship/water.webp') center / cover no-repeat;
  border: 1px solid var(--c-border-strong);
}

/*
 * Сетка нарисована светом, а не линиями поверх воды: рисунок воды сам по себе
 * неровный, и жёсткая решётка по нему читается как сетка на фотографии.
 *
 * ПЛОТНОСТЬ 55, А НЕ 34, и это починка, а не вкус. Владелец: «клетки на
 * десктопе странные, некоторые прямоугольные и шире остальных». Я дважды искал
 * причину в геометрии, дважды ошибся и дважды сказал, что починил.
 *
 * Геометрия оказалась ни при чём. Обмер настоящих пикселей снимка дал разброс
 * промежутков РОВНО В ОДИН пиксель на клетке в пятьдесят шесть, и столько же
 * дала решётка из ста ячеек, то есть способ рисовать не виноват.
 *
 * Линии не смещались, они МЕСТАМИ ПРОПАДАЛИ. Сетка лежит поверх фотографии
 * воды, у которой яркость гуляет от почти чёрного до бликов заката, а линия
 * взята прозрачностью 34% от одного светлого цвета. Над блеском такая линия
 * теряется совсем, и строка между двумя видимыми читается как клетка вдвое
 * выше. На тёмной половине доски всё было ровно, поэтому беда и выглядела
 * случайной.
 *
 * Проверено тремя досками рядом на настоящей воде: 34% тонет в бликах, 55%
 * видно везде, двухцветная (тёмная плюс светлая, как на доске шашек) тоже
 * видна, но её линия вдвое толще и на клетке в 55 пикселей выглядит тяжело.
 */
.bs-doska__setka {
  position: absolute;
  inset: 0;
  /*
   * ДВЕ ЛИНИИ РЯДОМ, ТЁМНАЯ И СВЕТЛАЯ, а не одна светлая погуще.
   *
   * Одна светлая не спасала ни на 34%, ни на 55%: над бликом заката она
   * пропадает при любой плотности, потому что блик светлее её. Обмер пикселей
   * это и показал: в тёмной половине доски промежутки ровные, а в светлой
   * линию не находит даже машина, не то что глаз. Хуже всего при масштабе
   * экрана 125 и 150 процентов, то есть на обычном рабочем ноутбуке.
   *
   * Пара «тёмная плюс светлая» не зависит от фона вовсе: над блеском видна
   * тёмная, над тенью светлая, и хотя бы одна из двух контрастна ВСЕГДА. Тот
   * же приём и по той же причине лежит в основе доски шашек, где он записан
   * так: «тёмная линия сверху и слева, светлая снизу и справа».
   *
   * Проверено снимками при масштабах 100, 125 и 150 на настоящей воде.
   */
  background:
    repeating-linear-gradient(to right,
      rgba(0, 0, 0, .5) 0 1px,
      color-mix(in srgb, var(--c-edge) 50%, transparent) 1px 2px,
      transparent 2px 10%),
    repeating-linear-gradient(to bottom,
      rgba(0, 0, 0, .5) 0 1px,
      color-mix(in srgb, var(--c-edge) 50%, transparent) 1px 2px,
      transparent 2px 10%);
}

/*
 * ШИРИНА ДОСКИ КРАТНА ДЕСЯТИ, и ставит её JS, а не эта таблица.
 *
 * Владелец: «клетки на десктопе странные, некоторые прямоугольные и шире
 * остальных». Сетка нарисована повторяющимся градиентом с шагом 10%, значит
 * линия номер k стоит на k×W/10. Пока доска была наглухо 420, шаг равнялся
 * ровно 42 и все клетки совпадали. Когда доска стала тянуться, ширина
 * сделалась какой угодно: на 555 пикселях шаг равен 55,5, линия попадает на
 * половину пикселя, сглаживание размазывает её на два и при прозрачности 34%
 * она пропадает совсем. Поэтому на снимке видны клетки ВДВОЕ шире соседних:
 * это не широкая клетка, это две с пропавшей линией между ними.
 *
 * ПЕРВАЯ ПОПЫТКА БЫЛА ЗДЕСЬ, `width: round(down, 100%, 10px)` под `@supports`,
 * и она не сработала: на снимке владельца доска осталась 555. Проверить в
 * браузере я не смог, и поставил правило, о котором нельзя было сказать,
 * применяется оно или нет. Так делать нельзя, и оно убрано.
 *
 * Теперь ширину ставит `подогнатьДоску()` в screens/battleship.js: измерить и
 * округлить вниз до десятка. Это работает в любом браузере, потому что не
 * зависит ни от какой новой возможности CSS.
 */
.bs-doska__korpus,
.bs-doska__mina {
  position: absolute;
  height: 10%;
  object-fit: contain;
  pointer-events: none;
}

.bs-doska__korpus--stoymya { transform: rotate(90deg); }

.bs-doska__mina { width: 10%; }

/* ==========================================================================
   ПОЛКА РАССТАНОВКИ

   Одна кнопка и одна строка о том, зачем она. Ручной расстановки нет и не
   будет: владелец снял её в приложении 29.07.2026, и причина записана там же,
   двадцать клеток корабля и пять мин канцелярии перед игрой на десять минут.
   ========================================================================== */

.bs-polka {
  margin-top: var(--s-4);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

.bs-polka__kn { width: 100%; }
.bs-polka__kn[disabled] { opacity: .45; }

/* ==========================================================================
   СТРОКА ПРО ПРЕМИУМ

   Одна строка под настройками, и только у бесплатной пары. Стоит ЗДЕСЬ, а не
   выскакивает после отказа: узнать про уровни в ту секунду, когда в них
   упёрся, значит узнать поздно.
   ========================================================================== */

.bs-podstrochnik {
  margin-top: var(--s-3);
  font: 400 var(--t-body-s) var(--f-sans);
  color: var(--c-muted);
}

/* ==========================================================================
   РЕДАКТОР СВОИХ ЗАДАНИЙ

   Пятнадцать полей: десять кораблей и пять мин. Простым списком их не заполнит
   никто, и потому здесь три вещи, которых нет у обычной формы.

   ГРУППЫ ПО РАЗМЕРУ. Размер корабля это вес задания: четырёхпалубный тонет
   дольше всех и стоит дороже всех. Группы подписаны своим весом («4 клетки»),
   от большого к малому.

   ГРУППЫ СКЛАДЫВАЮТСЯ, И ЭТО ГЛАВНАЯ РАЗНИЦА МЕЖДУ ТЕЛЕФОНОМ И МОНИТОРОМ. На
   360 пятнадцать полей во всю длину это простыня выше тысячи пикселей, по
   которой ищут, где остановились; сложенная группа занимает одну строку и
   своим счётчиком говорит, сколько в ней осталось. На 1024 складывать нечего:
   там всё раскрыто и поля стоят в два столбца.

   СЧЁТ ЗАПОЛНЕННОГО ВИДЕН ВСЕГДА, «10 из 15», и он же полоской. Без него
   непонятно, сколько ещё, а пятнадцать это как раз то число, которое считать
   в уме уже не хочется.

   КНОПКИ «СОХРАНИТЬ» НЕТ. Запись сама, через полторы секунды после последней
   буквы, ровно как в редакторе дня календаря.
   ========================================================================== */

.bs-red__verkh {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
}

/* Счёт заполненного. Моно, потому что число меняется по букве: у обычного
   шрифта цифры разной ширины, и строка дёргалась бы на переходе с 9 на 10. */
.bs-red__schyot {
  flex: 0 0 auto;
  font: 600 var(--t-label-m) var(--f-mono);
  letter-spacing: var(--tr-label-m);
  color: var(--c-gold);
}

/* Полоска под счётом. Она не украшение: число говорит, сколько сделано, а
   полоска, сколько осталось, и второе видно боковым зрением. */
.bs-red__shkala {
  margin-top: var(--s-2);
  height: 3px;
  border-radius: var(--r-pill);
  background: var(--c-surface-alt);
  overflow: hidden;
}

.bs-red__shkala i {
  display: block;
  height: 100%;
  border-radius: var(--r-pill);
  background: var(--g-flame);
  transition: width var(--m-standard) var(--m-ease);
}

.bs-red__kak {
  margin-top: var(--s-2);
  font: 400 var(--t-body-s) var(--f-sans);
  color: var(--c-faint);
}

/* Кнопка возврата к обходу. Тихая: обход и так открывается сам при входе, а
   эта кнопка нужна только тому, кто закрыл шторку и хочет вернуться. */
.bs-red__kn { width: 100%; margin-top: var(--s-4); }

/* ---------- шторка: одно задание ---------- */

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

   ОБЁРТКА ФЛЕКСОМ ОБЯЗАТЕЛЬНА. `.sheet__title` общей шторки это обычный блок,
   и два `span` внутри него встают в подбор: владелец увидел слипшееся
   «Корабль, 4 клетки1 / 15». Разводим их здесь, своей обёрткой, а не флексом
   на общем классе: он один на все игры. */
.bs-sh__shapka {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
}

.bs-sh__imya { flex: 1; min-width: 0; }

.bs-sh__shag {
  flex: 0 0 auto;
  font: 600 var(--t-label-m) var(--f-mono);
  letter-spacing: var(--tr-label-m);
  color: var(--c-faint);
}

/* Кто ВЫПОЛНИТ написанное. Единственное пояснение, оставшееся во всём
   редакторе, и оно не украшение: правило у кораблей и у мин разное, и без этой
   строки режим приходится угадывать. */
.bs-sh__kto {
  margin: 0 0 var(--s-3);
  font: 600 var(--t-body-s) var(--f-sans);
  color: var(--c-gold);
}

.bs-sh__pole { min-height: 110px; }

/* Три кубика ступеней жара, под полем и по центру. Ступень выбрана на партию,
   но заданий пятнадцать, и одна острота на всех превращает список в пятнадцать
   одинаковых строк; кубик даёт выбрать остроту каждой строке отдельно.

   ЦВЕТ ИЗ ОБЩЕЙ ШКАЛЫ ЖАРА (`--c-heat-*`), той же, что у лестницы на плитках
   игр в каркасе. Правило оттуда дословно: «цвет уровня обязан совпадать с тем,
   который он носит внутри игры». Три ступени растянуты по пятиступенчатой шкале
   через одну, иначе первая и вторая различались бы только на просвет. */
.bs-sh__kubiki {
  display: flex;
  justify-content: center;
  gap: var(--s-4);
  margin: var(--s-3) 0 var(--s-4);
}

.bs-kub {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--tap); height: var(--tap);
  border: 0;
  background: none;
  color: var(--c-dim);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color var(--m-micro) var(--m-ease), transform var(--m-micro) var(--m-ease);
}

/* ЦВЕТ ВИДЕН СРАЗУ, а не по наведению. Сначала кубики были серыми и красились
   при касании, но касание на телефоне не наводится: там цвет не показался бы
   никогда, и три кубика читались бы как три одинаковых. */
.bs-kub--zh1 { color: var(--c-heat-1); }
.bs-kub--zh2 { color: var(--c-heat-3); }
.bs-kub--zh3 { color: var(--c-heat-5); }

.bs-kub:hover,
.bs-kub:focus-visible { outline: none; transform: translateY(-2px) scale(1.08); }

/* Пока строка едет с сервера. Без этого второе касание по тому же кубику
   выглядело бы как «не сработало», а на деле шло бы вторым запросом. */
.bs-kub[disabled] { opacity: .4; cursor: default; transform: none; }

/* Ход по флоту. Столбиком на телефоне и в ряд от узкого предела: сквозное
   правило шторок, главное действие всегда снизу и во всю ширину.

   ПРИЛИПАЕТ К НИЗУ ШТОРКИ. Во весь экран содержимое иногда длиннее видимого,
   и кнопки хода уезжали бы вниз, за край: их пришлось бы искать прокруткой при
   поднятой клавиатуре, то есть ровно тогда, когда они нужнее всего. Подложка
   непрозрачная, иначе текст задания просвечивал бы сквозь них. */
.bs-sh__khod {
  position: sticky;
  bottom: calc(var(--s-2) * -1);
  z-index: 1;
  display: grid;
  gap: var(--s-2);
  padding: var(--s-3) 0 var(--s-2);
  margin-top: var(--s-2);
  background: var(--c-surface-high);
}

.bs-sh__khod .btn { width: 100%; }

@media (min-width: 480px) {
  .bs-sh__khod { grid-template-columns: 1fr 1fr; }
  /* «Далее» справа, «Назад» слева: порядок чтения, а не порядок разметки.
     В разметке главная кнопка идёт второй, и на телефоне она внизу. */
}

.bs-pole__vvod {
  display: block;
  width: 100%;
  min-height: 60px;
  padding: var(--s-3);
  border-radius: var(--r-ctl);
  border: 1px solid var(--c-border-strong);
  background: var(--c-surface-alt);
  color: var(--c-text);
  font: 400 var(--t-body-m) var(--f-sans);
  /* Ниже шестнадцати пикселей телефон приближает страницу на фокусе поля, и
     доска уезжает за край. Число из токенов, оно там ровно для этого. */
  font-size: max(var(--t-input-min), 15px);
  resize: vertical;
}

.bs-pole__vvod::placeholder { color: var(--c-dim); }
.bs-pole__vvod:focus { outline: none; border-color: var(--c-gold); }
/* ==========================================================================
   СОСТОЯНИЕ ЗАПИСИ И ИТОГ
   ========================================================================== */

.bs-sostoyanie {
  margin-top: var(--s-2);
  min-height: 16px;
  text-align: right;
  font: 600 var(--t-label-s) var(--f-mono);
  letter-spacing: var(--tr-label-s);
  text-transform: uppercase;
  color: var(--c-faint);
}

.bs-sostoyanie--zhdyom { color: var(--c-gold); }
.bs-sostoyanie--ok { color: var(--c-done); }
.bs-sostoyanie--beda { color: var(--c-danger); }

.bs-beda { margin-top: var(--s-3); }

/* Расстояния между блоками каркас держит парами соседей (`.set-card + .set-card`
   и так далее), и наши блоки в эти пары не попадают: полка не карточка, а свод
   правил стоит после строки беды. Дописываем недостающие пары здесь, а не
   вешаем отступ на сам блок: иначе он появится и там, где соседа нет. */
.bs-polka + .set-card { margin-top: var(--s-5); }
.bs-beda + .howto { margin-top: var(--s-4); }

/* Нажал «готово», и кнопки больше нет: ждать нечего, кроме второй доски. */
.bs-gotov {
  margin-top: var(--s-4);
  padding: var(--s-4);
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--c-done) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--c-done) 30%, transparent);
  color: var(--c-text);
  font: 400 var(--t-body-m) var(--f-sans);
  text-align: center;
}

/* Отмена партии. Тихая нарочно: она нужна тем, кто передумал играть в этом
   режиме, а не тем, кто ищет, что бы нажать. */
.bs-tikho {
  display: block;
  width: 100%;
  margin-top: var(--s-4);
  padding: var(--s-3);
  border: 0;
  background: none;
  color: var(--c-faint);
  font: 400 var(--t-body-s) var(--f-sans);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.bs-tikho:hover { color: var(--c-muted); }

/* ==========================================================================
   ШИРОКИЙ ЭКРАН

   Форма и здесь остаётся колонкой (это правило каркаса, `.screen--форма`), но
   внутри неё раскладка другая, а не та же в растянутом виде:

     доска перестаёт расти вместе с колонкой и встаёт по центру;
     полка расстановки складывается в одну строку;
     группы редактора перестают складываться и стоят раскрытыми;
     поля встают в два столбца.

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

@media (min-width: 1024px) {
  /*
   * ДОСКА ТЯНЕТСЯ ПО ЭКРАНУ (владелец: «на десктопе ещё доску увеличить, чтобы
   * она растягивалась в зависимости от экрана»). Было наглухо 420.
   *
   * Мерим ВЫСОТОЙ окна, а не шириной, и это не прихоть: доска квадратная, и на
   * широком низком мониторе именно высота решает, влезет она или нет. Семьдесят
   * процентов высоты оставляют место шапке сверху и полке с кнопкой снизу.
   */
  .bs-doska {
    max-width: min(70vh, 620px);
    margin-inline: auto;
  }

  /*
   * ШИРЕ СТАНОВИТСЯ САМА ФОРМА, а не стол внутри неё.
   *
   * Первая попытка растягивала стол отрицательными полями и мерила его в `vw`.
   * Арифметика показала, почему так нельзя: слева стоит колонка навигации в 264
   * пикселя, и на окне 1024 содержимому остаётся 760. Стол в 880 вылез бы под
   * колонку и дал горизонтальную прокрутку, то есть худшее, что бывает с
   * вёрсткой, причём ровно на самом узком из широких экранов.
   *
   * Расширение самой формы такого не умеет: `max-width` не связывает, когда
   * места меньше, а `margin-inline: auto` каркаса держит её по центру КОЛОНКИ,
   * а не окна. Класс вешает экран, и только на шаге расстановки: на шаге
   * выбора это форма, и широкой ей быть незачем.
   */
  .screen--forma.bs-shiroko { max-width: 880px; margin-inline: auto; }

  .bs-polka {
    flex-direction: row;
    align-items: center;
    gap: var(--s-4);
  }

  /*
   * «ПЕРЕМЕШАТЬ» ВО ВСЮ ШИРИНУ, как «Начать игру» (владелец: «почему кнопка
   * перемешать другого размера, а не как кнопка готово»).
   *
   * Здесь стояло `width: auto`, и кнопка сжималась по своей надписи. Задумка
   * была в том, что полка сложится в строку и рядом встанет что-то ещё, но
   * рядом с ней ничего нет: приписку про флот владелец снял, и кнопка осталась
   * одна, короткая, под доской во всю ширину. Две кнопки на экране обязаны
   * выглядеть парой, раз делают они одно и то же дело, начало партии.
   */
  .bs-polka__kn { width: 100%; flex: 1 1 auto; }

  /* Правил редактора здесь больше нет: ни складных групп, ни списка строк.
     Заполнение идёт обходом в шторке, а на широком экране шторка сама встаёт
     карточкой посередине (`frame.css`), то есть тем самым окном, о котором
     просил владелец. Своей ширины ей отсюда задавать не надо. */

  .bs-nuzhnyi-dvoe { min-height: 40svh; }
}


/* ==========================================================================
   БОЙ
   ==========================================================================
   Отсюда и до конца файла живёт ЭКРАН БОЯ. Всё, что выше, принадлежит
   настройкам и расстановке; правила у обеих частей общие (краска только из
   токенов, телефон и десктоп разные), а классы разные, и пересечений между
   ними нет.

   Вид из приложения, ветка `_play()` и `_WaterPainter` в
   lib/games/battleship/battleship_game.dart: две воды одна под другой, чужая
   крупнее (3 к 2), своя приглушена. Нижней полосы с лицом и точками кораблей
   здесь нет: владелец её снял, и всё, что она несла, разошлось по подписям
   над водами и по строке связи наверху.
   ========================================================================== */

/* ДОСКА САМА СЕБЕ ЭКРАН, как у шашек: партия занимает весь просвет, верхней
   и нижней полос каркаса у неё нет (nav.js), значит перекрывать нечего. */
.bs {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: flex;
  flex-direction: column;
  padding-top: env(safe-area-inset-top, 0px);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  overflow: hidden;

  /* ---------- краска для канвы ----------
     Канва не умеет читать классы, поэтому пять цветов объявлены здесь, а
     рисующий берёт их с самого холста. Три из них это токены как есть.

     Вода это НЕ ЦВЕТ, А ГЛУБИНА: мель светлее дна, и от этого доска
     перестаёт быть прямоугольником. Оба оттенка выведены из токенов: синий
     игрока (--c-player-1, 92 181 255) на фоне приложения (--c-bg, 10 6 6),
     разведённый до 18 процентов на мели и до 7 на глубине. Записаны числами,
     а не через color-mix, потому что эти строки уходят в canvas, а
     color-mix в нём разбирают не все браузеры. */
  --bs-melj: rgb(25, 37, 51);
  --bs-glubina: rgb(16, 18, 23);
  /* Промах холодный НАРОЧНО: горячее на этой доске значит попадание, и два
     тёплых знака означали бы противоположное одним цветом. */
  --bs-kholod: var(--c-neon);
  --bs-zoloto: var(--c-gold);
  --bs-zoloto-svetloe: var(--c-gold-light);
}

/* Комната: высоко над открытым морем, освещённое облако между тобой и водой.
   Одной картинкой, прижатой верхом. */
.bs__komnata,
.bs__mgla {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}
.bs__komnata {
  background: url('/next/images/battleship/table.webp') center top / cover no-repeat;
}
/* Затемнение только там, где слова. Числа из приложения, пять остановок:
   60 процентов сверху, 30 на восьмой части высоты, чисто на трети и на двух
   третях, 20 у самого низа. Середину не трогаем: там стоят воды, и они
   непрозрачны сами по себе. */
.bs__mgla {
  background: linear-gradient(to bottom,
    rgba(0, 0, 0, .60) 0%,
    rgba(0, 0, 0, .30) 12%,
    rgba(0, 0, 0, 0) 35%,
    rgba(0, 0, 0, 0) 62%,
    rgba(0, 0, 0, .20) 100%);
}
/* Всё, кроме двух задников, поднимается над ними. `:not` нужен, а не для
   красоты: без него правило перебивало задникам position (та же вескость, но
   ниже по файлу), они становились обычными потоковыми блоками, и комната
   получала нулевую высоту. Та же ловушка, что у шашек. */
.bs > :not(.bs__komnata):not(.bs__mgla) { position: relative; z-index: 1; }

/* ---------- верх ---------- */

/* Стрелка и строка связи В ОДНУ СТРОКУ: сквозное правило каркаса. Строка под
   одну стрелку не говорит ничего и стоит столько же, сколько строка с делом.
   Справа стоит то, что в приложении лежало в нижней полосе: отказ сервера и
   пропавшая связь. Молчащий отказ неотличим от «нажатие не дошло». */
.bs__verkh {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-4);
}
.bs__svyazj {
  flex: 1;
  min-width: 0;
  text-align: right;
  font: 600 var(--t-label-s) var(--f-mono);
  letter-spacing: var(--tr-label-s);
  color: var(--c-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bs__svyazj--net { color: var(--c-danger); }

/* ---------- две воды ---------- */

.bs__vodyi {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: 0 var(--s-3) var(--s-3);
}
.bs-chastj {
  display: flex;
  flex-direction: column;
  min-height: 0;
  gap: var(--s-2);
}
/* Чужая вода крупнее своей: по ней стреляют, свою просто смотрят. Числа из
   приложения, flex 3 и flex 2. */
.bs-chastj--chuzhaya { flex: 3; }
/* Своя тише, чтобы никогда не спорить с той, по которой идёт охота. */
.bs-chastj--svoya { flex: 2; opacity: .82; }

/* Подпись это ПИЛЮЛЯ СО СВОИМ ФОНОМ, а не строка поверх картинки: за ней в
   одном месте открытое небо, в другом глубокая вода, и мелкая моношрифтовая
   строка не выживает на освещённом облаке. Из приложения вместе с причиной. */
.bs-podpisj {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: 6px var(--s-3);
  border-radius: var(--r-tag);
  border: 1px solid var(--c-border-strong);
  background: var(--c-card-bg);
}
.bs-podpisj__chto {
  flex: 1;
  min-width: 0;
  font: 600 var(--t-label-s) var(--f-mono);
  letter-spacing: var(--tr-label-m);
  color: var(--c-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bs-podpisj--gorit .bs-podpisj__chto { color: var(--c-gold-light); }
/* «Стреляй» справа: единственное золотое слово на экране, и оно означает, что
   ход твой. Ни счётчика, ни таймера рядом нет, гадать не о чем. */
.bs-podpisj__zov {
  flex: none;
  font: 600 var(--t-label-s) var(--f-mono);
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  color: var(--c-gold);
}

/* Короб держит квадрат по центру. Размер канве считает рисующий: он берёт
   меньшую сторону короба, потому что вода всегда квадрат. */
.bs-korob {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Скругление 3.6 процента это клетка на 0.36 из приложения: сторона делится
   на десять, значит доля стороны в десять раз меньше.
   Тень под всей доской нужна затем, чтобы море позади читалось как позади;
   без неё это прямоугольник, наклеенный на фотографию. Тонкий латунный кант
   внутри взят оттуда же, светлым золотом при 20 процентах (--c-gold-light,
   253 230 138): числами, потому что тень цвет из переменной разбирает не
   всякая старая сборка Safari. */
.bs-korob canvas {
  display: block;
  border-radius: 3.6%;
  box-shadow: 0 5px 14px rgba(0, 0, 0, .5),
              inset 0 0 0 1px rgba(253, 230, 138, .20);
  touch-action: manipulation;
}
.bs-chastj--chuzhaya .bs-korob canvas { cursor: crosshair; }

/* ==========================================================================
   БОЙ НА ШИРОКОМ ЭКРАНЕ

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

@media (min-width: 1024px) {
  /* Слой берёт всё, что осталось от боковой колонки каркаса. */
  .bs { inset: 0 0 0 var(--kolonka, 264px); }
  .bs__vodyi {
    flex-direction: row;
    gap: var(--s-6);
    padding: 0 var(--s-6) var(--s-6);
  }
  /* Рядом обе воды равны: тут не за что бороться высотой, места хватает
     обеим. Своя всё равно чуть тише, чтобы взгляд возвращался к чужой. */
  .bs-chastj--chuzhaya,
  .bs-chastj--svoya { flex: 1; }
  .bs-chastj--svoya { opacity: .9; }
}

/* ---------- стол под доской расстановки ---------- */

/*
 * ОТКУДА. Владелец: «я жду партнёра, и там на заднике темнота, доска есть, но
 * за ней темнота». Стол был постелен только на экране боя, а расстановка это
 * уже игра, а не анкета: пара смотрит на свой флот и ждёт второго. Без стола
 * переход из расстановки в бой выглядел как переход в другую игру.
 *
 * Комната и мгла берутся ТЕ ЖЕ, что в бою (`.bs__комната`, `.bs__мгла`), и это
 * важнее вида: две картины одного стола разошлись бы на первой же правке.
 * Здесь только коробка, к которой они прижимаются.
 */
/*
 * СТОЛ ЭТО ТЕЛО ЭКРАНА, а не коробка внутри него.
 *
 * Отступа сверху здесь больше НЕТ, и это не мелочь: пока стол был коробкой,
 * отступ отодвигал доску от шапки. Теперь класс висит на всём теле, и тот же
 * отступ отодвигал бы шапку от края экрана. Он переехал на саму доску, ниже.
 */
.bs-stol { position: relative; }

/*
 * СТОЛ НА ВЕСЬ ЭКРАН, А НЕ КАРТОЧКОЙ. Владелец: «задняя картинка на всю высоту
 * и ширину». Первая редакция была коробкой с отступами и скруглением, то есть
 * карточкой со столом внутри; за её краями оставалась та самая темнота, из-за
 * которой всё и началось.
 *
 * `fixed`, а не `absolute`, и это единственный способ выйти на весь экран
 * отсюда: экран настроек это форма шириной пятьсот шестьдесят, и стол,
 * прижатый к ней, шире неё не станет никогда.
 *
 * В бою те же классы остаются `absolute` внутри `.bs`, который сам занимает
 * весь экран, поэтому там ничего не меняется.
 */
.bs-stol .bs__komnata,
.bs-stol .bs__mgla { position: fixed; }

/*
 * ВСЁ СОДЕРЖИМОЕ ПОВЕРХ ЗАДНИКОВ, а не одна доска.
 *
 * Правило то же, что у `.bs` в бою, и теперь оно наконец достаёт до всех:
 * задники стали прямыми детьми тела экрана, а не соседями по коробке.
 *
 * ПОЧЕМУ ЭТО НЕ КОСМЕТИКА. Комната это НЕПРОЗРАЧНАЯ картинка, и с тех пор как
 * она стала `fixed`, она накрывала весь экран, а `position: fixed` рисуется
 * поверх обычного потока. Прежняя редакция поднимала детей коробки, а ребёнок
 * у неё был один, доска. Шапка со стрелкой назад, полка с «перемешать» и
 * «готово» лежали снаружи и ушли под картинку целиком: владелец увидел это как
 * «кнопки исчезли, готово в чёрной плашке».
 *
 * `:not` нужен по делу, а не для красоты: правило ЗАДАЁТ `position`, и всё, у
 * кого он уже свой, надо исключить поимённо. Иначе оно молча ломает соседа.
 *
 * ЧЕТЫРЕ ИСКЛЮЧЕНИЯ, и каждое стоило бы отдельной поломки:
 *   `.bs__комната`, `.bs__мгла` — задники. Без них правило перебивало им
 *      `position` (та же вескость, но ниже по файлу), они становились обычными
 *      блоками потока, и комната получала нулевую высоту;
 *   `.veil`   — завеса ожидания второго, она `fixed` на весь экран с
 *      `z-index: 50`. Опущенная в поток, она перестала бы накрывать что-либо и
 *      встала бы серым прямоугольником посреди страницы;
 *   `.set-go` — липкая кнопка внизу, она `sticky`. Опущенная в поток, она
 *      перестала бы липнуть и уехала бы за нижний край.
 *
 * Обе последние уже позиционированы, а значит и так рисуются выше задников:
 * поднимать их нечем и незачем.
 */
.bs-stol > :not(.bs__komnata):not(.bs__mgla):not(.veil):not(.set-go) {
  position: relative;
  z-index: 1;
}

/*
 * У ЛИПКОЙ КНОПКИ СНИМАЕМ ЗАЛИВКУ. Владелец: «кнопка готово с чёрной рамкой
 * какой-то», и на десктопе, и на телефоне.
 *
 * Рамка это не рамка, а фон самой полосы `.set-go`: каркас заливает её
 * градиентом в `--c-bg`, чтобы содержимое, уезжающее под липкую кнопку,
 * растворялось, а не обрезалось по живому. Приём верный, пока фон страницы это
 * и есть `--c-bg`. Здесь фон страницы теперь МОРЕ, и та же заливка читается
 * чёрной плашкой поперёк воды.
 *
 * Снимаем только на этом экране: у остальных настроек фон прежний, и там
 * растворение работает как задумано.
 */
.bs-stol > .set-go { background: none; }

/* Отступ сверху вернулся доске: стол его больше не держит (см. выше). */
.bs-stol .bs-doska { margin-top: var(--s-5); }
