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

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

   Своя таблица, а не правки в style.css: длинная версия остаётся рабочей,
   пока эта обкатывается. */

@import url("/style.css?v=de4523dc");
/* Сама сетка — общая со страницами проектов, там она стоит в подвале вместо
   «Previous / Next». Лежит отдельно, чтобы копии не разошлись. */
@import url("/bento-grid.css?v=834eea49");

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

   Правил больше нет: главная берёт общую шапку из style.css, как список,
   заметки и страница для рекрутёров. Все четыре сходятся центром на 48. */

/* ── Шапка «о себе» ───────────────────────── */

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

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

   Выключка по верхнему краю, а не по центру: строка выросла в абзац на
   четыре предложения и стала заметно выше кадра, и по центру кадр повисал
   в её середине, будто прибился сбоку случайно. По верху оба начинаются
   от одной линии и читаются как подпись при фото, а не как два блока. */
.bento-intro {
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
  gap: 2.25rem;
  padding: 3rem 0 0;
  margin-bottom: 0;
}

/* На главной убираем верхний отступ у ленты, чтобы портрет прилегал к первой
   карточке без зазора. На страницах проектов он нужен — там intro нет. */
.bento-page .bento {
  padding-top: 0;
}

/* Обёртка вокруг строки-вступления и тегов под ней — сама эта пара и есть
   тот единственный элемент, который выключается по верхнему краю рядом с
   портретом (см. .bento-line ниже); max-width переехал сюда же, чтобы
   ужимался весь столбец, а не только абзац. */
.bento-intro-copy {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  max-width: 58ch;
  align-self: flex-start;
}

.bento-line {
  font-family: var(--font-serif);
  font-size: 1.1875rem;
  font-weight: 400;
  line-height: 1.7;
  letter-spacing: -0.01em;
  color: var(--ink-body);
  text-wrap: pretty;
  margin-bottom: 0;
}

.bento-intro .intro-portrait {
  float: none;
  margin: 0 0 -6px 0;
  flex: 0 0 auto;
  width: 320px;
  order: -1;
  align-self: flex-end;
}

.bento-intro .intro-portrait img {
  filter: none;
}

/* Ссылки-теги прямо под строкой вступления (внутри .bento-intro-copy) —
   фильтр витрины по ?tag=, который читает bento.js render(). Клик по ним
   не перезагружает страницу: bento.js подменяет URL через history.pushState
   и перерисовывает витрину на месте (тот же приём, что и у чекбокса
   toggleIncomplete). Плашки, а не подчёркнутые ссылки: заливка — терракота
   на просвет, не сплошным цветом, фирменный акцент вместо чужого синего.
   Гарнитура и кегль — как у строки вступления (.bento-line), но помельче
   и строчными буквами. Счётчик (bento.js .intro-tag-count) — число
   подходящих проектов, чтобы работодатель видел объём подборки до клика.
   Активная плашка (?tag= совпал, либо «all» при пустом фильтре) заливается
   терракотой сплошь, а не на просвет — тот же приём, что различает состояния
   у .bento-badge. Отступ снизу — с запасом: колонка с тегами теперь часто
   выше портрета, и без него сетка проектов подпирала бы теги вплотную. */
.intro-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 2.5rem;
}

.intro-tags a {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4em;
  padding: 0.5rem 1.05rem;
  border-radius: 999px;
  background: rgba(255, 90, 31, 0.09);
  color: var(--ink-body);
  text-decoration: none;
  font-family: var(--font-serif);
  font-size: 1rem;
  letter-spacing: -0.01em;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.intro-tags a:hover,
.intro-tags a:focus-visible {
  background: rgba(255, 90, 31, 0.18);
}

.intro-tags a.active {
  background: var(--terra);
  color: #fff;
}

.intro-tags .intro-tag-count {
  color: var(--text-neutral-500);
  font-size: 0.8em;
}

.intro-tags a.active .intro-tag-count {
  color: rgba(255, 255, 255, 0.72);
}

@media (max-width: 700px) {
  .bento-intro {
    flex-direction: column;
    align-items: flex-start;
    gap: 1.5rem;
    padding: 2rem 0 0;
    margin-bottom: 2.5rem;
  }

  .bento-intro .intro-portrait {
    width: 100%;
    max-width: none;
    align-self: auto;
  }

  .bento-intro-copy {
    max-width: none;
    align-self: auto;
  }

  .bento-line {
    text-wrap: pretty;
    margin-bottom: 0;
  }
}

/* Кнопка архива и подвал возвращаются к колонке текста — лента их не
   касается. */
/* Панорама студии: эволюция компьютеров 1990 — 2026 (внутри бенто-сетки на 4-й строке, h=660px, без бордеров) */
.bento-page .studio-panorama {
  display: block;
  width: 100%;
  margin-top: 18px;
  margin-bottom: 18px;
  position: relative;
  background: #ffffff;
  border-radius: 6px;
  overflow: hidden;
  border: none;
}

.bento-page .studio-panorama__viewport {
  width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-behavior: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: rgba(222, 93, 67, 0.3) rgba(0, 0, 0, 0.03);
  border: none;
  border-radius: 6px;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
}

.bento-page .studio-panorama__viewport.is-dragging {
  cursor: grabbing !important;
}

body.studio-panorama--dragging,
body.studio-panorama--dragging * {
  cursor: grabbing !important;
  user-select: none !important;
  -webkit-user-select: none !important;
}

.bento-page .studio-panorama__viewport::-webkit-scrollbar {
  height: 8px;
}
.bento-page .studio-panorama__viewport::-webkit-scrollbar-track {
  background: rgba(0, 0, 0, 0.02);
}
.bento-page .studio-panorama__viewport::-webkit-scrollbar-thumb {
  background: rgba(222, 93, 67, 0.3);
  border-radius: 4px;
}
.bento-page .studio-panorama__viewport::-webkit-scrollbar-thumb:hover {
  background: rgba(222, 93, 67, 0.5);
}

.bento-page .studio-panorama__svg {
  display: block;
  height: 760px;
  width: auto;
  min-width: 2294px;
  flex-shrink: 0;
}

@media (max-width: 768px) {
  .bento-page .studio-panorama {
    width: 100vw !important;
    max-width: 100vw !important;
    margin-left: calc(-1 * var(--bento-gap, 18px)) !important;
    margin-right: calc(-1 * var(--bento-gap, 18px)) !important;
    border-radius: 0 !important;
    border-left: none !important;
    border-right: none !important;
    margin-top: 12px;
    margin-bottom: 12px;
  }
  .bento-page .studio-panorama__viewport {
    border-radius: 0 !important;
    width: 100vw !important;
  }
  .bento-page .studio-panorama__svg {
    height: 520px;
    min-width: 1570px;
  }
}

/* ── Тултипы артефактов в панораме студии ─────────────────────────────── */
.bento-page .pano-artifact {
  cursor: pointer;
}

/* Фирменные брызги (Sparks) вместо свечения (Glow) */
.bento-page .pano-sparks {
  opacity: 0;
  pointer-events: none;
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(0.62);
  transition: opacity 0.16s ease,
              transform 0.24s cubic-bezier(0.18, 0.9, 0.32, 1.25);
}

.bento-page .pano-artifact:hover .pano-sparks {
  opacity: 1;
  transform: scale(1);
}

.bento-page .studio-panorama__tooltip {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, -100%) scale(0.96);
  transition: opacity 0.16s cubic-bezier(0.16, 1, 0.3, 1),
              transform 0.16s cubic-bezier(0.16, 1, 0.3, 1),
              visibility 0.16s;
  background: #de5d43;
  color: #ffffff;
  border: 1px solid #de5d43;
  border-radius: 6px;
  padding: 6px 12px;
  font-family: 'Roboto Mono', ui-monospace, monospace;
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.35;
  white-space: nowrap;
  box-shadow: 0 6px 20px rgba(222, 93, 67, 0.32), 0 2px 6px rgba(0, 0, 0, 0.12);
  z-index: 50;
}

.bento-page .studio-panorama__tooltip.is-visible {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, -100%) scale(1);
}

.bento-page .studio-panorama__tooltip::after {
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border-width: 5px 5px 0 5px;
  border-style: solid;
  border-color: #de5d43 transparent transparent transparent;
}

.bento-page .studio-panorama__tooltip.is-below {
  transform: translate(-50%, 0) scale(0.96);
}

.bento-page .studio-panorama__tooltip.is-below.is-visible {
  transform: translate(-50%, 0) scale(1);
}

.bento-page .studio-panorama__tooltip.is-below::after {
  top: auto;
  bottom: 100%;
  border-width: 0 5px 5px 5px;
  border-color: transparent transparent #de5d43 transparent;
}

.bento-page .archive-toggle-wrap {
  margin-top: 3rem;
}

/* Шапка над роликом. Ролик уже уходит под неё, но сама она почти непрозрачная
   белая — и кадр за ней не виден вовсе, получается та же белая ступенька,
   только теперь нарисованная шапкой.

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

   Только на главной: на остальных страницах за шапкой нет видео и прятать
   ей нечего. */
body.bento-page .header {
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-bottom-color: transparent;
}

body.bento-page .header.is-stuck {
  background-color: var(--bg-white);
  background-image: var(--raster-gray);
  background-size: var(--raster-step) var(--raster-step);
  border-bottom-color: var(--border-neutral-200);
}

/* ── Ролик о проектах ─────────────────────────────────────────────────────
   Ролик идёт первым и чистым, представление — под ним.

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

   Пропорция 16:9 — ровно та, в которой ролик снят, поэтому object-fit
   ничего не обрезает: кадр виден целиком, как задуман.

   Зерно поверх рисует браузер, а не кодек. Вжатое ломает сжатие (кодек честно
   тратит биты на случайный шум) и весит вдвое, а нарисованное поверх ничего
   не стоит и вдобавок живое. Здесь оно легче, чем на hire: тот ролик тёмный
   и зернистый по природе, а этот почти весь белый, и на белом шум виден
   втрое сильнее при той же плотности. */
.reel {
  position: relative;
  /* Режим наложения у зерна не должен вылезать за секцию. */
  isolation: isolate;
  overflow: hidden;
  aspect-ratio: 16 / 9;
  background: var(--bg-neutral-200, #e5e5e5);
  width: min(calc(100% - 3rem), 1160px);
  margin: 1.5rem auto 3rem auto;
  border-radius: 12px;
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.07);
}

@media (max-width: 768px) {
  .reel {
    width: calc(100% - 1.5rem);
    margin: 1rem auto 2rem auto;
    border-radius: 8px;
  }
}

.reel__media {
  position: absolute;
  z-index: 1;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Точечный полиграфический растр (Dot Screen / Halftone):
   чистый CSS без шума и JS. Даёт фактуру печати / микро-матрицы без мерцания. */
.reel__grain {
  display: block;
  position: absolute;
  z-index: 2;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(rgba(0, 0, 0, 0.16) 1px, transparent 1px);
  background-size: 3px 3px;
  mix-blend-mode: multiply;
  opacity: 0.85;
}

.reel__noise {
  display: none;
}

/* Кому движение мешает — остаётся постер и неподвижная фактура. */
@media (prefers-reduced-motion: reduce) {
  .reel__grain { animation: none }
  .reel__noise { display: none }
}


/* ── Светлая подпись на плитке ────────────────────────────────────────────
   Теперь это основной вид. Прежний тёмный возвращается адресом /?tiles=dark —
   класс вешает reel.js, правила ниже в конце файла.

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

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

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

   Плотность белого выше, чем у чёрного (68% против 62%): тёмный текст на
   светлом требует большего контраста, чем светлый на тёмном, — белый фон
   отражает и подмешивается в буквы, а чёрный только поглощает.

   Тень у текста тоже переворачивается. Оставить чёрную было нельзя: под
   чёрными буквами она даёт грязный ореол вместо отрыва от фона. */
.bento-label {
  background: linear-gradient(
    to top,
    rgb(255 255 255 / 68%) 0%,
    rgb(255 255 255 / 66%) 8%,
    rgb(255 255 255 / 61%) 18%,
    rgb(255 255 255 / 52%) 30%,
    rgb(255 255 255 / 40%) 42%,
    rgb(255 255 255 / 29%) 55%,
    rgb(255 255 255 / 18%) 68%,
    rgb(255 255 255 / 9%) 80%,
    rgb(255 255 255 / 4%) 90%,
    transparent 100%
  );
  color: var(--text-black);
  text-shadow: 0 1px 5px rgb(255 255 255 / 75%), 0 0 18px rgb(255 255 255 / 45%);
}

/* Ховер: та же кривая, умноженная целиком, — при наведении меняется плотность,
   а не форма ската. Осветление гуще покоя ровно настолько же, насколько
   затемнение гуще своего покоя. Описание набрано мягче заголовка, поэтому
   ему нужна более плотная подложка. */
@media (hover: hover) {
  .bento-card:hover .bento-label,
  .bento-card:focus-within .bento-label {
    background: linear-gradient(
      to top,
      rgb(255 255 255 / 86%) 0%,
      rgb(255 255 255 / 84%) 8%,
      rgb(255 255 255 / 77%) 18%,
      rgb(255 255 255 / 65%) 30%,
      rgb(255 255 255 / 50%) 42%,
      rgb(255 255 255 / 36%) 55%,
      rgb(255 255 255 / 22%) 68%,
      rgb(255 255 255 / 11%) 80%,
      rgb(255 255 255 / 5%) 90%,
      transparent 100%
    );
  }
}

/* Описание тоже чёрное, только мягче заголовка — как в тёмном варианте оно
   мягче белого. */
.bento-desc {
  color: rgb(0 0 0 / 78%);
}

/* Все заголовки жирные. В тёмном варианте вес отличал четыре главные работы
   от остальных, но на светлом фоне лёгкое начертание теряется само по себе:
   чёрный текст на осветлении держится хуже белого на затемнении. Читаемость
   важнее этой градации — тем более что главные работы и так крупнее. */
.bento-label {
  font-weight: 700;
  letter-spacing: -0.015em;
}

/* ── Тёмная подпись (прежний вид) ─────────────────────────────────────────
   Возвращается адресом /?tiles=dark. Оставлено не из осторожности: светлое
   держится на светлых кадрах, а витрина живая — если в неё придут тёмные
   работы, будет с чем сравнить, не поднимая всё заново. */
body.tiles-dark .bento-label {
  background: linear-gradient(
    to top,
    rgb(0 0 0 / 62%) 0%, rgb(0 0 0 / 60%) 8%, rgb(0 0 0 / 55%) 18%,
    rgb(0 0 0 / 46%) 30%, rgb(0 0 0 / 35%) 42%, rgb(0 0 0 / 25%) 55%,
    rgb(0 0 0 / 15%) 68%, rgb(0 0 0 / 7%) 80%, rgb(0 0 0 / 3%) 90%,
    transparent 100%
  );
  color: var(--bg-white);
  font-weight: 300;
  letter-spacing: 0;
  text-shadow: 0 1px 5px rgb(0 0 0 / 65%), 0 0 18px rgb(0 0 0 / 35%);
}

body.tiles-dark .bento-card--big .bento-label {
  font-weight: 700;
  letter-spacing: -0.015em;
}

body.tiles-dark .bento-desc {
  color: rgb(255 255 255 / 88%);
}

@media (hover: hover) {
  body.tiles-dark .bento-card:hover .bento-label,
  body.tiles-dark .bento-card:focus-within .bento-label {
    background: linear-gradient(
      to top,
      rgb(0 0 0 / 78%) 0%, rgb(0 0 0 / 76%) 8%, rgb(0 0 0 / 69%) 18%,
      rgb(0 0 0 / 58%) 30%, rgb(0 0 0 / 44%) 42%, rgb(0 0 0 / 31%) 55%,
      rgb(0 0 0 / 19%) 68%, rgb(0 0 0 / 9%) 80%, rgb(0 0 0 / 4%) 90%,
      transparent 100%
    );
  }
}

/* ── Звук у ролика ────────────────────────────────────────────────────────
   Ролик стартует немым — со звуком браузер автозапуска не даст, — поэтому
   звук включается кнопкой. Кнопку ставит reel.js, разметки у неё нет:
   без скрипта ролик не грузится вовсе, и кнопка вела бы в никуда.

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

   Вид сдержанный: полупрозрачная плашка на своём же кадре. Ролик почти весь
   светлый, поэтому подложка тёмная, а не наоборот, — на светлом кадре белая
   кнопка растворяется. */
.reel__sound {
  position: absolute;
  z-index: 6;
  right: 12px;
  bottom: 16px;
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.42em 0.72em;
  border: 0;
  border-radius: 999px;
  background: rgba(20, 18, 17, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  opacity: 0.72;
  transition: opacity var(--transition-fast), background var(--transition-fast);
}

.reel__sound:hover,
.reel__sound:focus-visible {
  opacity: 1;
  background: rgba(20, 18, 17, 0.78);
}

.reel__sound svg {
  width: 14px;
  height: 14px;
  fill: currentColor;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  fill-rule: evenodd;
}

/* Корпус динамика залит, дуги и крестик — только обводкой: залитые дуги
   слипаются в кляксу на четырнадцати точках. */
.reel__sound svg path + path { fill: none }

/* Выключено — крестик, включено — дуги. Рисуем одно, прячем другое: две
   иконки в разметке дороже, чем две группы в одной. */
.reel__wave { display: none }
.reel--loud .reel__wave { display: inline }
.reel--loud .reel__mute { display: none }

@media (max-width: 700px) {
  .reel__sound {
    right: 8px;
    bottom: 14px;
    font-size: 10px;
  }
  .reel__timeline {
    left: 8px;
    right: 88px;
    bottom: 14px;
    height: 24px;
  }
}

/* ── Интерактивный таймлайн и перемотка (Scrubber) ─────────────────────────
   Вместо глухой сплошной полосы по нижнему срезу кадра — парящая растровая капсула,
   стоящая в одном ряду с кнопкой звука. Нижний край видео остаётся чистым,
   а шкала живёт полиграфической точечной сеткой, как и весь сайт. */
.reel {
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  touch-action: pan-y;
}

.reel--scrubbing {
  cursor: grabbing !important;
}

.reel__timeline {
  position: absolute;
  bottom: 16px;
  left: 16px;
  right: 110px;
  height: 28px;
  display: flex;
  align-items: center;
  cursor: pointer;
  z-index: 8;
  outline: none;
  touch-action: pan-y;
  opacity: 0;
  transition: opacity 0.3s ease;
}

.reel[data-load-done] .reel__timeline {
  opacity: 1;
}

.reel__timeline-track {
  position: relative;
  width: 100%;
  height: 8px;
  border-radius: 999px;
  background-color: rgba(20, 18, 17, 0.55);
  background-image: radial-gradient(circle, rgba(255, 255, 255, 0.28) 1.1px, transparent 1.2px);
  background-size: 6px 6px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
  transition: height var(--transition-fast, 0.15s ease), background-color var(--transition-fast, 0.15s ease);
}

.reel__timeline:hover .reel__timeline-track,
.reel__timeline:focus-visible .reel__timeline-track,
.reel--scrubbing .reel__timeline-track {
  height: 12px;
  background-color: rgba(20, 18, 17, 0.72);
}

.reel__timeline-fill {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 0%;
  border-radius: 999px;
  background-color: var(--terra, #cc7c5e);
  background-image: radial-gradient(circle, rgba(255, 255, 255, 0.95) 1.4px, transparent 1.5px);
  background-size: 6px 6px;
  box-shadow: 0 0 10px rgba(204, 124, 94, 0.6), inset 0 0 4px rgba(255, 255, 255, 0.4);
  pointer-events: none;
}

.reel__timeline-thumb {
  position: absolute;
  top: 50%;
  left: 0%;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #ffffff;
  border: 2px solid var(--terra, #cc7c5e);
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.5);
  transform: translate(-50%, -50%) scale(0);
  transition: transform 0.15s ease, opacity 0.15s ease;
  opacity: 0;
  pointer-events: none;
}

.reel__timeline:hover .reel__timeline-thumb,
.reel__timeline:focus-visible .reel__timeline-thumb,
.reel--scrubbing .reel__timeline-thumb {
  transform: translate(-50%, -50%) scale(1);
  opacity: 1;
}

.reel__timeline-tooltip {
  position: absolute;
  bottom: 30px;
  left: 0;
  transform: translateX(-50%);
  padding: 3px 7px;
  border-radius: 4px;
  background: rgba(20, 18, 17, 0.88);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.15s ease;
  z-index: 9;
}

.reel__timeline:hover .reel__timeline-tooltip,
.reel--scrubbing .reel__timeline-tooltip {
  opacity: 1;
}

/* ── HUD бейдж перемотки жестом по кадру ────────────────────────────────── */
.reel__hud {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(0.92);
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 18px;
  border-radius: 999px;
  background: rgba(20, 18, 17, 0.76);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.18);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  pointer-events: none;
  z-index: 9;
  opacity: 0;
  transition: opacity 0.2s ease, transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);
  user-select: none;
}

.reel--hud-active .reel__hud {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

.reel__hud-arrows {
  font-size: 10px;
  opacity: 0.6;
  letter-spacing: -0.05em;
}

.reel__hud-time {
  font-weight: 600;
}

.reel__hud-total {
  opacity: 0.6;
}

/* Кому движение мешает, тому ролик не грузится вовсе — кнопкам и таймлайну
   нечего показывать. */
@media (prefers-reduced-motion: reduce) {
  .reel__sound,
  .reel__timeline,
  .reel__hud {
    display: none;
  }
}
