/* ==========================================================================
   BrosMedia — движение
   Всё живёт под классом .bm-motion, который скрипт ставит на <html> только при
   prefers-reduced-motion: no-preference. Нет скрипта или человек просил покой —
   класса нет, стилей ниже нет, сайт статичен и полностью виден.
   ========================================================================== */

:root {
  --ease-out-soft: cubic-bezier(.22, .61, .36, 1);
  --ease-out-back: cubic-bezier(.34, 1.2, .48, 1);
  /* Длинный пологий выход — под неспешное движение самого снимка. */
  --ease-cine: cubic-bezier(.16, .84, .34, 1);
}

/* --- Верхний блок: вход ---------------------------------------------------- */

/* Первый такт вступления — снимок наводится на резкость, и в кадре больше
   ничего не движется. Проявляется он быстро: это самый крупный элемент экрана,
   тянуть его появление значит портить скорость отрисовки. Медленно идёт только
   сведение масштаба и резкости, причём выход нарочно пологий — основное
   движение проходит за первую треть, дальше кадр едва заметно доводится.
   К моменту, когда вступает текст, снимок уже не перетягивает взгляд. */
.bm-motion .hero__media img {
  opacity: 0;
  transform: scale(1.08);
  transition:
    opacity 1.1s var(--ease-cine),
    transform 2.4s var(--ease-cine);
}
.bm-motion .hero.is-ready .hero__media img {
  opacity: 1;
  transform: scale(1);
}

/* Расфокус только на больших экранах: на телефоне размытие крупной картинки
   стоит слишком дорого, а выигрыш незаметен. */
@media (min-width: 901px) {
  .bm-motion .hero__media img {
    filter: blur(14px);
    transition:
      opacity 1.1s var(--ease-cine),
      transform 2.4s var(--ease-cine),
      filter 1.6s var(--ease-cine);
  }
  .bm-motion .hero.is-ready .hero__media img {
    filter: blur(0);
  }
}

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

/* Заголовок раскрывается построчно из-под маски. */
.bm-motion .bm-line {
  display: block;
  overflow: hidden;
}
.bm-motion .bm-line__inner {
  display: block;
  transform: translateY(108%);
  transition: transform 1.5s var(--ease-cine);
  transition-delay: var(--bm-delay, 0s);
}
.bm-motion .hero.is-ready .bm-line__inner {
  transform: translateY(0);
}

/* Надстрочник, абзац и кнопка — подъём со смещением. */
.bm-motion .hero__brand,
.bm-motion .hero__text,
.bm-motion .hero__content .btn-primary {
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity 1.15s var(--ease-cine),
    transform 1.15s var(--ease-cine);
  transition-delay: var(--bm-delay, 0s);
}
.bm-motion .hero.is-ready .hero__brand,
.bm-motion .hero.is-ready .hero__text,
.bm-motion .hero.is-ready .hero__content .btn-primary {
  opacity: 1;
  transform: translateY(0);
}

/* Черта прочерчивается сразу после надстрочника и служит подсказкой взгляду:
   она уводит его влево-вниз, к заголовку, который в этот момент раскрывается. */
.bm-motion .hero__brand::after {
  content: '';
  display: block;
  width: 64px;
  height: 2px;
  margin-top: 14px;
  background: var(--primary);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 1.2s var(--ease-cine) 1.55s;
}
.bm-motion .hero.is-ready .hero__brand::after {
  transform: scaleX(1);
}

/* Параллакс от курсора: слой двигают скрипты, здесь только сглаживание. */
.bm-motion .hero__media {
  will-change: transform;
}

/* --- Плашка с репликами: третий такт вступления ---------------------------- */

/* Плашка — последний такт, уже после того, как текст слева замер.
   Появляется она не сразу: сперва на её месте заполняется полоса, и только
   потом вокруг неё проступает панель. Полоса и нужна затем, чтобы взгляд
   успел перейти с текста на снимок и застал набор с самого начала.
   Панель не выезжает, а проявляется на месте — иначе полоса ехала бы вместе
   с ней и переставала быть точкой, к которой приковано внимание. */
.bm-motion .hero__note {
  background-color: transparent;
  border-color: transparent;
  transition:
    background-color .85s var(--ease-cine) 3.8s,
    border-color .85s var(--ease-cine) 3.8s;
}
.bm-motion .hero.is-ready .hero__note {
  background-color: rgba(13, 13, 15, .8);
  border-color: var(--border);
  border-left-color: var(--primary);
}

/* Полоса заполнения. Разгон и торможение нарочно неравномерные — ровное
   движение читается как декоративная линия, а не как индикатор. */
.bm-motion .hero__note-bar {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
  background: var(--primary);
  transform: scaleX(0);
  transform-origin: left center;
  transition:
    transform 1s cubic-bezier(.55, .06, .2, 1) 2.85s,
    opacity .5s linear 3.9s;
}
.bm-motion .hero.is-ready .hero__note-bar {
  transform: scaleX(1);
  opacity: 0;
}

/* Текст проступает вместе с панелью, а не вместе с полосой. */
.bm-motion .hero__note-text {
  opacity: 0;
  transition: opacity .75s var(--ease-cine) 3.9s;
}
.bm-motion .hero.is-ready .hero__note-text {
  opacity: 1;
}

/* Точки набора стоят прямо в строке, за курсором, и видны только в паузе перед
   новой репликой. Вне паузы схлопываются в нулевую ширину — иначе пустое место
   в конце строки лишний раз переносило бы её. */
.bm-motion .hero__note-dots {
  display: inline-flex;
  gap: 5px;
  align-items: center;
  vertical-align: middle;
  width: 0;
  margin-left: 0;
  opacity: 0;
  transition:
    width .25s ease,
    margin-left .25s ease,
    opacity .25s ease;
  /* Без overflow: hidden — точки в анимации подпрыгивают вверх, и край
     контейнера срезал бы им макушки. Место схлопывает нулевая ширина,
     а от посторонних глаз их прячет прозрачность. */
}
.bm-motion .hero__note.is-thinking .hero__note-dots {
  width: 25px;
  margin-left: 8px;
  opacity: 1;
}
.bm-motion .hero__note-dots i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--primary);
  animation: bm-dot 1.2s ease-in-out infinite;
}
.bm-motion .hero__note-dots i:nth-child(2) { animation-delay: .18s; }
.bm-motion .hero__note-dots i:nth-child(3) { animation-delay: .36s; }
@keyframes bm-dot {
  0%, 60%, 100% { opacity: .25; transform: translateY(0); }
  30%           { opacity: 1;   transform: translateY(-3px); }
}

/* Курсор мигает скачком, а не плавно: плавное затухание читается как свечение,
   а не как каретка. */
.bm-motion .hero__note-caret {
  display: inline-block;
  width: 2px;
  height: 1.05em;
  margin-left: 3px;
  vertical-align: -.16em;
  background: var(--primary);
  animation: bm-caret 1.06s steps(1, end) infinite;
}
@keyframes bm-caret {
  0%, 50%   { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}

/* --- Появление секций при прокрутке --------------------------------------- */

.bm-motion [data-bm-reveal] {
  opacity: 0;
  transform: translateY(26px);
  transition:
    opacity .75s var(--ease-out-soft),
    transform .75s var(--ease-out-soft);
  transition-delay: var(--bm-delay, 0s);
}
.bm-motion [data-bm-reveal].is-in {
  opacity: 1;
  transform: translateY(0);
}

/* Карточки услуг и проектов приходят с лёгким масштабом — так заметнее,
   что это отдельные объекты, а не блок текста. */
.bm-motion .service-card[data-bm-reveal],
.bm-motion .project-card[data-bm-reveal] {
  transform: translateY(30px) scale(.97);
}
.bm-motion .service-card[data-bm-reveal].is-in,
.bm-motion .project-card[data-bm-reveal].is-in {
  transform: translateY(0) scale(1);
}

/* Этапы процесса — реальная последовательность, поэтому и линия между ними
   прочерчивается по порядку, а не проявляется целиком. */
.bm-motion .process-step__line {
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .85s var(--ease-out-soft);
  transition-delay: var(--bm-delay, 0s);
}
.bm-motion .process-step.is-in .process-step__line {
  transform: scaleX(1);
}

/* Цифры статистики набираются скриптом; здесь — ровная колонка при счёте. */
.bm-motion .stat__value {
  font-variant-numeric: tabular-nums;
}

/* --- Мелкая моторика ------------------------------------------------------- */

/* Блик по кнопке. */
.bm-motion .btn-primary {
  position: relative;
  overflow: hidden;
  transition: filter .2s ease, transform .25s var(--ease-out-soft);
}
.bm-motion .btn-primary::before {
  content: '';
  position: absolute;
  top: -60%;
  left: -80%;
  width: 45%;
  height: 220%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .5), transparent);
  transform: skewX(-18deg);
  pointer-events: none;
  opacity: 0;
}
.bm-motion .btn-primary:hover::before {
  animation: bm-sheen .75s var(--ease-out-soft);
}
@keyframes bm-sheen {
  from { left: -80%; opacity: 1; }
  to   { left: 130%; opacity: 0; }
}
/* Содержимое кнопки поверх блика. */
.bm-motion .btn-primary > * {
  position: relative;
  z-index: 1;
}

/* Карточка услуги приподнимается, стрелка уезжает по диагонали. */
.bm-motion .service-card {
  transition:
    transform .35s var(--ease-out-soft),
    border-color .35s ease,
    box-shadow .35s ease;
}
.bm-motion .service-card:hover {
  transform: translateY(-6px);
  border-color: rgba(188, 211, 36, .45);
  box-shadow: 0 18px 40px -24px rgba(188, 211, 36, .55);
}
.bm-motion .service-card__arrow {
  transition: transform .35s var(--ease-out-back), color .35s ease;
}
.bm-motion .service-card:hover .service-card__arrow {
  transform: translate(5px, -5px);
  color: var(--primary);
}

/* Плитка статистики подсвечивает иконку при наведении. */
.bm-motion .stat__icon {
  transition: transform .4s var(--ease-out-back), color .4s ease;
}
.bm-motion .stat:hover .stat__icon {
  transform: translateY(-4px) scale(1.08);
  color: var(--primary);
}

/* --- Страховка ------------------------------------------------------------- */

/* Даже если класс на <html> каким-то образом окажется при включённом покое —
   движения не будет. */
@media (prefers-reduced-motion: reduce) {
  .bm-motion *,
  .bm-motion *::before,
  .bm-motion *::after {
    animation: none !important;
    transition: none !important;
    transform: none !important;
    filter: none !important;
    opacity: 1 !important;
  }
}
