/*
 * Галерея-стрим на карточке товара.
 *
 * Разметку отдаёт inc/product-gallery-stream.php вместо карусели ядра.
 * Здесь — только раскладка потока и просмотрщик.
 *
 * ГЛАВНАЯ МЫСЛЬ. Фотографии не живут в своей колонке: они становятся
 * ячейками СТРАНИЧНОЙ сетки. Иначе поток был бы заперт в левой половине, а в
 * референсе снимки уходят и под инфо-панель, и во всю ширину контента.
 * Делается это `display: contents` у промежуточных обёрток — колонки блока и
 * контейнеров галереи: они перестают быть боксами, и `<figure>` оказываются
 * прямыми детьми сетки `.uc-item-page`. Шаблон в базе при этом не тронут.
 */

/* ---------- Общее ---------- */

/* СКРЫТЫЙ НАБОР ОБЯЗАН ОСТАВАТЬСЯ СКРЫТЫМ. Атрибут `hidden` прячет элемент
   правилом из стилей браузера, а наши `display: contents` и `display: flex`
   ниже — авторские, и они сильнее. Без этой строки все наборы цветов
   вываливались бы на страницу разом. */
.mit-gallery__set[hidden] {
  display: none !important;
}

/* И СКРЫТЫЙ ЭКЗЕМПЛЯР PRODUCT DETAILS — ТОЖЕ. Их у товара с цветами разной
   чётности два: один в сетке, другой в инфо-колонке; показан всегда ровно
   один, переключает их `product-gallery.js` по чётности показанного набора.
   Причина `!important` та же, что строкой выше: `display` мы задаём авторским
   правилом, и оно перебило бы `hidden` из стилей браузера. */
.mit-details[hidden] {
  display: none !important;
}

/* ШИРИНА СТРАНИЧНОЙ СЕТКИ — ЯВНО ВО ВСЮ ПОЛОСУ. Она лежит в колоночном
   флексе `main` с выравниванием по центру, а такой родитель ужимает ребёнка
   по его содержимому. У товара с четырьмя снимками содержимого хватало, и
   это не бросалось в глаза; у товара с ОДНИМ снимком сужалась вся страница
   вместе с инфо-панелью — и на десктопе, и на телефоне.

   Хуже того, ширина начинала зависеть от полей самих снимков: герой с
   отрицательным полем делал сетку уже, сетка съезжала, и герой уезжал вместе
   с ней. Явные сто процентов разрывают этот круг. Правило общее на обе
   ширины: причина у них одна. */
.wp-block-columns.uc-item-page {
  width: 100%;
}

.mit-gallery__item {
  margin: 0;
}
.mit-gallery__zoom {
  display: block;
  /* По содержимому, а не во всю ячейку: ширину задаёт снимок, ужатый по
     высоте, и обёртка должна повторять её, иначе прицел клика окажется
     шире картинки. */
  width: fit-content;
  max-width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  /* Кнопка — обёртка снимка, и своей типографики у неё нет. */
  font: inherit;
  line-height: 0;
}
/* НЕ ВЫШЕ ЭКРАНА, НО И НЕ ОБРЕЗАН. Кадр 2:3 в семь колонок — это больше
   тысячи пикселей высоты: чтобы увидеть снимок целиком, приходится листать.
   Ограничиваем высоту экраном и даём ширине посчитаться от неё: пропорции
   съёмки важнее того, чтобы кадр заполнил ячейку до края. `dvh`, а не `vh`,
   — в Safari адресная строка меняет высоту экрана.

   `width`/`height` в `auto` при заданных `max-*` — это и есть «впиши, сохранив
   пропорции»: браузер берёт собственный размер снимка из атрибутов и
   уменьшает его по меньшему из двух ограничений. Атрибуты у нас есть всегда,
   поэтому место под кадр известно до загрузки и страница не прыгает. */
.mit-gallery__img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100dvh;
  background: var(--wp--preset--color--base-2, rgba(0, 0, 0, .04));
}

/* ГЕРОЙ — ИСКЛЮЧЕНИЕ ИЗ ПРАВИЛА ВЫШЕ: он занимает отведённую ему ширину
   целиком, а высота считается от неё.
 *
 * ЭТО РАЗМЕН, И СДЕЛАН ОН ОСОЗНАННО. Ограничение по высоте и заполнение по
 * ширине несовместимы: кадр 2:3 в семь колонок — это около 1200 пикселей,
 * больше экрана. Из двух ограничений оставлено ширина: первый снимок
 * открывает страницу, и поле сбоку от него читается недоделанной вёрсткой,
 * а его высота всё равно доглядывается тем же движением, которым покупатель
 * идёт дальше по галерее. Все ОСТАЛЬНЫЕ снимки по-прежнему вписаны в
 * видимую область — им доглядывать нечем, они уже в потоке.
 *
 * Пропорции при этом целы: `height` остаётся `auto`, растяжения нет. */
.mit-gallery__item:first-child .mit-gallery__zoom {
  width: 100%;
}
.mit-gallery__item:first-child .mit-gallery__img {
  width: 100%;
  max-height: none;
}

/* ---------- Десктоп: страничная сетка в 12 колонок ---------- */

/* 780.01, А НЕ 781. Пара «781 / 780» оставляла между собой щель: при дробной
   ширине области просмотра (масштаб 110 %, дробный DPR, узкое окно) значение
   попадало в интервал (780; 781), и не срабатывал НИ ОДИН из двух блоков —
   карточка рассыпалась в один столбец. Ревью, находка M-5. Дробное значение
   здесь не придирка: оно смыкает диапазоны. */
@media (min-width: 780.01px) {
  /* Селектор из двух классов — не прихоть: раскладку колонок ядро печатает
     правилом `.wp-block-columns-is-layout-flex { display: flex }` ниже наших
     стилей по документу. При равной силе побеждает последний, поэтому здесь
     нужен вес побольше. */
  .wp-block-columns.uc-item-page {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    /* 56px — замер референса: столько между колонками пар и почти столько
       же между героем и панелью. При двенадцати колонках это даёт снимку в
       шесть колонок ровно 47% ширины контента, как у Zara. */
    column-gap: 3.5rem;
    /* По вертикали воздуха больше, чем по горизонтали: соседи по строке
       читаются парой, а строки друг от друга должны отделяться. */
    row-gap: 7rem;
    align-items: start;
  }
  /* Колонка галереи и обёртки наборов растворяются: их дети встают в сетку
     страницы напрямую. */
  .wp-block-columns.uc-item-page > .wp-block-column:not(.uc-item-info),
  .mit-gallery,
  .mit-gallery__set {
    display: contents;
  }
  /* Инфо-панель — правые пять колонок первой строки. Строку задаём явно:
     в разметке она идёт ПОСЛЕ всех снимков, и без этого сетка поставила бы
     её в самый низ.

     `stretch` — ростом с героя. Колонка сама по себе короткая, и раньше она
     кончалась там же, где текст. Теперь она занимает всю первую строку, а
     строку задаёт герой. Пустого места под текстом это не добавляет: место
     нужно НЕ под текст, а под ход прилипшей панели — см. правило ниже. */
  .uc-item-info {
    grid-column: 8 / -1;
    grid-row: 1;
    align-self: stretch;
  }
  /* ПАНЕЛЬ ЕДЕТ ВМЕСТЕ С ГЕРОЕМ. Первый кадр высокий, и пока он проходит
     мимо, имя, цена и кнопка не должны уезжать вверх: покупатель смотрит на
     фотографию и в этот момент как раз решает.
   *
   * Прилипает не колонка, а группа внутри неё: прилипшему элементу нужен
   * запас хода в родителе, и этот запас — разница между высотой героя
   * (её держит колонка) и высотой текста.
   *
   * `top: 0`, а не высота шапки: шапка лежит ПОВЕРХ страницы и места в
   * потоке не занимает. Отступ под неё живёт в самом блоке — к прежним
   * 10vh прибавлена высота шапки. Оба значения инлайновые из шаблона,
   * поэтому `!important`. */
  .uc-item-info > .uc-column__text {
    position: sticky;
    top: 0;
    padding-top: calc(10vh + var(--header-h, 0px)) !important;
  }
  /* Дальше — ритм референса (замеры zara.com при 1440):
     герой 58% слева, следующий снимок 47% со сдвигом ВПРАВО и паузой слева,
     дальше пары. Сетка расставляет это сама: у снимка с колонкой левее
     предыдущей курсор переходит на новую строку. */
  /* ОСТАЛЬНЫЕ СНИМКИ — В ВИДИМУЮ ОБЛАСТЬ, А НЕ В ЭКРАН. Пока покупатель
     листает, сверху уже висит шапка, а под ней липкий бар покупки: кадр в
     полный экран пришлось бы доглядывать прокруткой, хотя место под ним
     формально есть. Вычитаем оба и оставляем сотую часть на воздух — иначе
     снимок упирается в бар впритык и читается его продолжением.

     Высоты обоих приходят переменными: шапку меряет `header-height.js`,
     бар — `product-options.js`. Нет их — вычитается ноль, и правило просто
     ограничивает кадр экраном.

     ПОЧЕМУ ЗДЕСЬ `lvh`, А НЕ `dvh` (решение Bo, 20.08). `dvh` — высота
     ПРЯМО СЕЙЧАС, вместе с адресной строкой браузера. Она то появляется,
     то прячется по ходу прокрутки — и вместе с ней на каждом таком движении
     пересчитывалась высота КАЖДОГО снимка: галерея дышала, а строки сетки
     переезжали под пальцем. `lvh` — высота при УБРАННОЙ панели, величина
     постоянная: снимок посчитан один раз и больше не двигается.

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

     Не поддержан `lvh` (Safari до 15.4, Chrome до 108) — весь `calc`
     считается невалидным, и остаётся `max-height: 100dvh` из общего правила
     выше. Кадр всё равно не выше экрана, просто без вычета шапки и бара. */
  .mit-gallery__item:not(:first-child) .mit-gallery__img {
    max-height: calc((100lvh - var(--header-h, 0px) - var(--mit-bar-h, 0px)) * .99);
  }
  /* И по центру своей ячейки: ужатый по высоте кадр уже её, и прижатый к
     краю он читался бы съехавшим. Герой остаётся слева — там его край
     задаёт левое поле страницы. */
  .mit-gallery__item:not(:first-child) .mit-gallery__zoom {
    margin-inline: auto;
  }

  /* `align-self` каждому снимку, а не `align-items` контейнеру: у ядра на
     колонках своё выравнивание, и спорить с ним из-за одного свойства
     дороже, чем сказать то же самое ячейке. Без этого фигура растягивается
     на высоту строки, и под снимком остаётся пустое поле. */
  .mit-gallery__item {
    align-self: start;
    /* РЯД — ОТ СЕРВЕРА, КОЛОНКА — ОТСЮДА. Раньше ряды получались сами:
       снимок с колонкой левее предыдущего перебрасывал курсор на новую
       строку. Красиво и совершенно непрозрачно — номера ряда не знал никто,
       а блоку Product Details нужно встать ИМЕННО в ряд второго снимка.
       Порядковый номер знает сервер (`mit_sf_gs_row()`), он его и печатает.
       Нет переменной — раскладка расставляет по-старому, сама. */
    grid-row: var(--row, auto);
  }
  .mit-gallery__item:nth-child(odd) {
    grid-column: 1 / 7;
  }
  .mit-gallery__item:nth-child(even) {
    grid-column: 7 / -1;
  }
  /* Второй снимок — семь колонок, как у героя, но прижатые к правому краю.
     Он единственный в своей строке, и мерить его колонкой пары незачем:
     пара — это разговор двух снимков, а здесь снимок один. Ростом с героя и
     с паузой слева он читается ответом на первый кадр, а не остатком
     несостоявшейся пары.

     Одинок он только в ЧЁТНОМ наборе. В нечётном пар хватает на всё, второй
     снимок входит в первую из них, и правило чётности ниже его
     переопределяет.

     КОНЧАЕТСЯ НА 12, А НЕ НА `-1`, И ЭТО НЕ НЕДОСМОТР.

     Ревью (находка M-2) предлагало довести кадр до правого края, `6 / -1`:
     линия 12 — начало двенадцатой колонки, и ячейка не доставала до края
     126 пикселей, единственная на странице ни с чем не выровненная. Так и
     сделали в 1.70.3 — и это оказалось ошибкой. Мерили ЯЧЕЙКУ, а глаз видит
     СНИМОК, а снимок сюда не достаёт никогда: все кадры кроме героя ужаты по
     высоте экрана и стоят в своей ячейке по центру (см. правило с
     `margin-inline: auto` ниже). Выравнивание по правому краю на экране не
     появилось вовсе, зато снимок уехал вправо на столбец — и встал почти в
     колонку правого снимка пары, разойдясь с ней на 69 пикселей. Хуже обоих
     положений: не совпадение и не смещение, а «чуть-чуть мимо».

     Вернули на 12. Здесь снимок встаёт МЕЖДУ колонками пары ниже и читается
     отдельным шагом — тот ритм, ради которого пауза слева и задумана.
     Проверено на «Coordinates» Long Sleeve при ширине 1680: снимок 815–1278,
     пара ниже 196–658 и 1022–1484. */
  .mit-gallery__item:nth-child(2) {
    grid-column: 5 / 12;
  }
  /* Герой — семь колонок рядом с панелью. Правило последним: оно сильнее
     предыдущих при равной специфичности и не спорит с ними.
   *
   * И БЕЗ ЛЕВОГО ПОЛЯ: кадр доходит до самой кромки экрана. Поле страницы
   * задано ШАБЛОНОМ (инлайновым `padding-left: 2.5vw` у `main`), а шаблон
   * живёт в базе — снять его оттуда нельзя, можно только вычесть здесь.
   * Отрицательное поле у элемента сетки не двигает ячейку: коробка растёт
   * влево, правый край остаётся на границе седьмой колонки. Ширина при этом
   * выходит «сто процентов ячейки плюс поле» — ровно то, что нужно.
   *
   * Значение приходит переменной, а `2.5vw` — запасной путь на первый кадр,
   * пока скрипт не отработал. Мерит поле `product-gallery.js`: если менеджер
   * поправит отступ в шаблоне, герой сам встанет на место, а не разъедется
   * на разницу. */
  .mit-gallery__item:first-child {
    grid-column: 1 / 8;
    margin-left: calc(-1 * var(--mit-page-pad, 2.5vw));
    /* РОВНО ПОЛЭКРАНА. Колонки сетки на половине не заканчиваются: седьмая
       кончается на 56% ширины, шестая — на 48%, и попасть в половину набором
       колонок нельзя. Поэтому ширина задана прямо: левый край у кадра и так
       на нуле, значит правый приходится ровно на середину экрана.

       Колонки при этом за собой оставляем — `grid-column` выше никуда не
       делся. Он держит место для инфо-панели справа: без него она уехала бы
       к самому кадру. Видимая ширина и занятое в сетке место здесь
       намеренно разные вещи. */
    width: 50vw;
  }
  /* PRODUCT DETAILS — В ПАУЗУ СЛЕВА ОТ ВТОРОГО СНИМКА.
     Место это ритм оставляет пустым и без блока: второй кадр стоит на 5/12,
     колонки 1–4 свободны. Поэтому наличие блока галерею не перестраивает —
     он занимает уже готовую дыру, а без него она просто остаётся дырой.

     Отступ в колонку от края страницы и выравнивание по центру высоты —
     замер референса при 1525: текст стоял на 338 при поле страницы 197 и
     приходился на середину второго кадра.

     РЯД ВСЕГДА ВТОРОЙ, И ПЕРЕМЕННАЯ ЗДЕСЬ БОЛЬШЕ НЕ НУЖНА. Пауза бывает
     только у чётного набора и только во второй строке; у нечётного её нет
     вовсе, и в сетку этот экземпляр блока тогда просто не печатается. */
  .mit-details {
    grid-column: 2 / 5;
    grid-row: 2;
    align-self: center;
  }

  /* ГАЛЕРЕЯ И ПОХОЖИЕ ТОВАРЫ — РАЗНЫЕ РАЗГОВОРЫ. Между ними стоял зазор
     темы в 1.2rem: он был меньше, чем расстояние от заголовка «Related
     products» до его же карточек, и блок читался продолжением галереи.
     Отступ должен быть больше внутреннего — тогда видно, что тема сменилась. */
  .uc-item-page {
    padding-bottom: 8rem;
  }

  /* НЕЧЁТНЫЙ НАБОР — ПАРЫ БЕЗ ПАУЗЫ.
   *
   * После героя остаётся чётное число кадров, значит они сходятся в пары и
   * одиночки в конце не остаётся. Паузы при этом нет вовсе — и блоку
   * Product Details в сетке места нет, он уходит в инфо-колонку.
   *
   * Колонки при этом СМЕЩЕНЫ НА ОДНУ ОТНОСИТЕЛЬНО ОБЩЕГО ПРАВИЛА: пару
   * открывает второй снимок, а он по счёту чётный. Отсюда `nth-child(even)`
   * слева и `nth-child(odd)` справа — наоборот тому, что стоит выше.
   *
   * `:not(:first-child)` обязателен. У товара с ОДНИМ фото герой сам себе
   * нечётный, и без исключения он уехал бы в правую половину строки, под
   * инфо-панель. Тот же капкан уже ловили на «Sailor Hat». */
  .mit-gallery__set[data-parity="odd"] .mit-gallery__item:nth-child(even) {
    grid-column: 1 / 7;
  }
  .mit-gallery__set[data-parity="odd"] .mit-gallery__item:nth-child(odd):not(:first-child) {
    grid-column: 7 / -1;
  }
}

/* ---------- Телефон: один столбец с чередованием ---------- */

@media (max-width: 780px) {
  /* ИНФО-БЛОК — ПОСЛЕ ПЕРВОГО СНИМКА, А НЕ ПОСЛЕ ВСЕЙ ГАЛЕРЕИ.
   *
   * Порядок на телефоне: первый кадр — описание и вкладки — остальные кадры.
   * Так в референсе, и так честнее: пролистать десять фотографий, чтобы
   * добраться до состава, никто не станет, а после первого кадра человек
   * как раз хочет прочитать, на что смотрит.
   *
   * ПОЧЕМУ СЕТКА, А НЕ ПЕРЕНОС УЗЛА СКРИПТОМ. Разметку отдаёт шаблон из
   * базы, порядок в ней один на все ширины. Двигать узел скриптом значило бы
   * возвращать его назад на десктопе и ловить прыжок при первой отрисовке.
   * Здесь всё решает раскладка: обёртки растворяются `display: contents`,
   * снимки и панель становятся ячейками ОДНОЙ колонки, а `order` расставляет
   * их как надо. Шаблон не тронут, DOM не тронут.
   *
   * ПОЧЕМУ GRID, А НЕ FLEX. Ядро печатает колонкам `flex-basis: 100%
   * !important` для узкой ширины. В колоночном флексе это основной размер,
   * то есть ВЫСОТА, и панель раздувало бы на всю страницу. Элемент сетки о
   * `flex-basis` не знает вовсе — спорить не с чем.
   *
   * `nth-child` ниже считает по РАЗМЕТКЕ, а не по виду, поэтому чередование
   * «во всю ширину / в полях» после перестановки остаётся прежним. */
  .wp-block-columns.uc-item-page {
    display: grid;
    grid-template-columns: 100%;
    gap: 1rem;
  }
  .wp-block-columns.uc-item-page > .wp-block-column:not(.uc-item-info),
  .mit-gallery,
  .mit-gallery__set {
    display: contents;
  }
  .mit-gallery__item {
    order: 4;
  }
  .mit-gallery__item:first-child {
    order: 1;
  }
  .uc-item-info {
    order: 2;
  }
  /* Product Details сразу за описанием — тем же приёмом, что и сама
     инфо-панель. Отдельной вкладки на телефоне не заводим: это продолжение
     разговора о товаре, а не новый раздел. */
  .mit-details {
    order: 3;
  }
  /* Нечётные — во всю ширину экрана, без полей: снимок и есть экран.
     `50% - 50vw` выносит фигуру за поля колонки, каким бы ни было их
     значение, — считать их в пикселях не приходится. */
  .mit-gallery__item:nth-child(odd) {
    margin-inline: calc(50% - 50vw);
  }
  /* Чётные — в полях колонки, как в референсе: пауза между разворотами. */
  .mit-gallery__item:nth-child(even) {
    margin-inline: 0;
  }
  /* ОДНА ШИРИНА НА ВСЕХ. Общее правило вписывает снимок в экран по ВЫСОТЕ,
     и на телефоне вертикальный кадр упирался в неё раньше, чем в ширину:
     каждая фотография получала свою ширину — свою на каждые пропорции, — а
     обёртка по содержимому прижимала её влево. Строй разъезжался, и чем
     разнообразнее съёмка, тем заметнее.

     На телефоне ограничивать высоту незачем: кадр во всю ширину экрана в
     неё и так помещается или почти помещается, а листают телефон всё равно
     вертикально. Снимаем ограничение и отдаём ячейку снимку целиком —
     пропорции держит `height: auto` из общего правила. */
  .mit-gallery__zoom {
    width: 100%;
  }
  .mit-gallery__img {
    width: 100%;
    max-height: none;
  }
  /* ДЫРА МЕЖДУ ФОТО И ОПИСАНИЕМ. Инфо-колонка отбита сверху на 10vh — это
     дышало, пока над отступом стояли имя и цена. Мы их убрали в бар, и
     отступ повис пустым местом сразу под снимком.

     `!important` здесь не небрежность: значение задано ИНЛАЙНОМ в шаблоне,
     а шаблон живёт в базе, и база ходит только вниз. Перебить его из кода
     иначе нечем. Нижний отступ (10vh) остаётся: после перестановки он
     отделяет описание от продолжения галереи — то есть разделяет два разных
     разговора, а это ровно его работа. */
  .uc-item-info > .uc-column__text {
    padding-top: 1.5rem !important;
    /* И СНИЗУ ТОЖЕ. Прежние 10vh отделяли описание от карусели похожих —
       тогда оно стояло последним. Теперь за ним идёт Product Details, а
       следом остальные кадры, и десятая часть экрана между двумя абзацами
       одного разговора читается провалом. Расстояние до похожих товаров
       держит `padding-bottom` всей страницы ниже. */
    padding-bottom: 1.5rem !important;
  }
  /* А от последнего снимка до похожих товаров отступа не осталось вовсе:
     раньше его давал нижний отступ инфо-блока, который стоял здесь. Ставим
     свой — по той же причине, что и на десктопе: между галереей и
     рекомендациями должно быть видно, что тема сменилась. */
  .uc-item-page {
    padding-bottom: 4rem;
  }
}

/* ---------- Просмотрщик ---------- */

/* Тот же язык, что у нижнего листа размеров: белая подложка, фотография
   выцветает, а не темнеет. Скролл-лок — только через `<html>`
   (tracks/content-blocks §11). */
.mit-viewer {
  position: fixed;
  inset: 0;
  z-index: var(--mit-z-viewer, 200);
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, .96);
}
.mit-viewer[hidden] {
  display: none;
}
.mit-viewer__img {
  max-width: 100vw;
  max-height: 100dvh;
  object-fit: contain;
}
.mit-viewer__close,
.mit-viewer__nav {
  position: absolute;
  border: 0;
  background: none;
  color: var(--wp--preset--color--contrast);
  cursor: pointer;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.mit-viewer__close {
  top: 1rem;
  right: 1.25rem;
  padding: .5rem;
}
.mit-viewer__nav {
  top: 50%;
  padding: 1rem;
  transform: translateY(-50%);
}
.mit-viewer__nav_prev {
  left: 0;
}
.mit-viewer__nav_next {
  right: 0;
}
.mit-viewer__nav[disabled] {
  opacity: .25;
  cursor: default;
}

/* Прокрутку под просмотрщиком блокируем ТОЛЬКО через `<html>`: `overflow`
   на `body` делает его контейнером прокрутки, и липкая шапка начинает
   липнуть к нему вместо экрана — tracks/content-blocks §11. */
html.mit-viewer-open {
  overflow: hidden;
}

/* ---------- Видимый фокус ---------- */

/* СВОИХ СОСТОЯНИЙ ФОКУСА У ЭЛЕМЕНТОВ ТРЕКА НЕ БЫЛО: работало умолчание
   браузера, разное в каждом и заметно чужое рядом с этой типографикой. Ревью,
   находка L-4.

   Контур тот же, что уже принят в каталоге и на главной
   (`catalog-filters.css`, `home.css`): 2px сплошной цветом текста. Не своя
   выдумка — один язык на весь магазин.

   `:focus-visible`, а не `:focus`: рамка нужна тому, кто идёт с клавиатуры.
   По клику мышью браузер её не показывает, и кнопка покупки не обрастает
   контуром на каждое нажатие. */
.mit-gallery__zoom:focus-visible,
.mit-viewer__nav:focus-visible,
.mit-viewer__close:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

/* Кадр в потоке — контур внутрь: снаружи он попал бы на соседний снимок или
   за край экрана, потому что первый кадр выходит за поле страницы. */
.mit-gallery__zoom:focus-visible {
  outline-offset: -2px;
}
