/* ═══════════════════════════════════════════════════════════════════════════
   ДВИЖЕНИЕ. 31.08.2026, вторая редакция.

   Фаундер 31.08: «Необходима яркая визуальная анимация на каждой странице.
   Все важные блоки текста должны быть анимированы (прям сам текст),
   выделяясь на странице.»

   ЧТО ЗДЕСЬ ЕСТЬ
     · несущие строки набираются ПО СЛОВАМ — слово выезжает снизу
       и проявляется, соседи идут очередью;
     · по ударной строке один раз проходит световая полоса;
     · у врезки «простыми словами» вырастает боковая черта;
     · кадр наезжает и слегка идёт за прокруткой;
     · строки таблицы появляются очередью сверху вниз;
     · знак фирмы прорисовывается как росчерк пера.

   ЧТО НЕ ОБСУЖДАЕТСЯ — это не вкус, а требование:

   1. prefers-reduced-motion. У части людей движение вызывает тошноту
      и головокружение (вестибулярные нарушения). Системная настройка
      «уменьшить движение» ДОЛЖНА выключать всё. Это WCAG 2.3.3
      и требование магазинов приложений. Блок в конце файла.
   2. Ни одного бесконечного цикла. Мигание и повтор — признак дешёвой
      страницы и утомляют за минуту.
   3. Движение НИКОГДА не задерживает чтение: текст виден сразу, даже если
      скрипт не выполнился. Появление — доводка, а не условие показа.
   4. Ничего не прыгает после загрузки: у каждого кадра заранее задан
      прямоугольник, сдвига макета ноль.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── ПОЯВЛЕНИЕ ЦЕЛЫМ БЛОКОМ ──────────────────────────────────────────────
   Класс вешает скрипт. Если скрипта нет — элемент просто виден. */
.js .reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 700ms cubic-bezier(.22,.61,.36,1),
              transform 700ms cubic-bezier(.22,.61,.36,1);
  will-change: opacity, transform;
}
.js .reveal.in { opacity: 1; transform: none; }

/* Ступенька: соседние элементы появляются с задержкой друг за другом.
   Шесть шагов по 90 мс — дальше глаз перестаёт видеть очередь. */
.js .reveal[data-step="1"] { transition-delay:  90ms; }
.js .reveal[data-step="2"] { transition-delay: 180ms; }
.js .reveal[data-step="3"] { transition-delay: 270ms; }
.js .reveal[data-step="4"] { transition-delay: 360ms; }
.js .reveal[data-step="5"] { transition-delay: 450ms; }

/* ── ТЕКСТ НАБИРАЕТСЯ ПО СЛОВАМ ──────────────────────────────────────────
   Прямой ответ на «все важные блоки текста должны быть анимированы».
   Слово — свой узел, у каждого свой номер в очереди (--i). Разбивка НЕ
   рвёт предложение для переводчика: пробелы стоят отдельными узлами,
   и браузер читает фразу целиком.

   По словам набираются ТОЛЬКО несущие строки. Разбить всю страницу —
   значит превратить чтение в мельтешение. */
/* 🔴 Кусок слова неразрывен, а обычный текст переносится где угодно:
   «(case.provenancediligence.com)» занимал 485 точек при экране 305 и
   распирал страницу приватности на 200; русское «специалистами.» в
   заголовке — на семь. Куски живут в трёх местах (текст, обложка,
   заголовок документа), поэтому правило общее для всех. */
.js .wd { max-width: 100%; overflow-wrap: anywhere; }

.js .words .wd {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.5em);
  transition: opacity 520ms cubic-bezier(.22,.61,.36,1),
              transform 520ms cubic-bezier(.22,.61,.36,1);
  transition-delay: calc(var(--i, 0) * 42ms);
  will-change: opacity, transform;
}
.js .words.in .wd { opacity: 1; transform: none; }

/* ── ПЕРВЫЙ ЭКРАН: заголовок строками, внутри строк — словами ─────────── */
/* Перенос строки заголовка НЕ зависит от класса js: скрипт уже заменил
   <br> на .ln, и если страховка снимет js, строки обязаны остаться
   строками. Иначе заголовок слипается в одну — поймано на живом
   просмотре: «Вы видели бизнес.Вы не видели его прошлого.» */
.hero__text h1 .ln,
.doc__head h1 .ln { display: block; }
.js .hero__text h1 .wd,
.js .doc__head h1 .wd {
  display: inline-block; opacity: 0; transform: translateY(0.55em);
  transition: opacity 700ms cubic-bezier(.22,.61,.36,1),
              transform 700ms cubic-bezier(.22,.61,.36,1);
  transition-delay: calc(var(--i, 0) * 55ms);
}
.js .hero__text h1.in .wd,
.js .doc__head h1.in .wd { opacity: 1; transform: none; }

/* ── СВЕТОВАЯ ПОЛОСА ПО УДАРНОЙ СТРОКЕ ───────────────────────────────────
   Проходит ОДИН раз при появлении. Это и есть «выделяясь на странице»:
   строка не просто появляется, по ней проходит свет, и глаз её берёт.
   Полоса не мигает и не повторяется. */
.js .hero__text .punch { position: relative; overflow: hidden; }
.js .hero__text .punch::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(105deg,
              rgba(169,84,40,0) 30%,
              rgba(169,84,40,.16) 48%,
              rgba(169,84,40,0) 66%);
  transform: translateX(-110%);
  pointer-events: none;
}
.js .hero__text .punch.in::after {
  animation: sweep 1100ms cubic-bezier(.22,.61,.36,1) 420ms 1 both;
}
@keyframes sweep { to { transform: translateX(110%); } }

/* Боковая черта ударной строки вырастает сверху вниз. */
.js .hero__text .punch { border-left-color: transparent; }
.js .hero__text .punch::before {
  content: ""; position: absolute; left: -1.5px; top: 0; bottom: 0; width: 1.5px;
  background: var(--ink); transform: scaleY(0); transform-origin: top;
  transition: transform 620ms cubic-bezier(.22,.61,.36,1) 120ms;
}
.js .hero__text .punch.in::before { transform: scaleY(1); }

/* Врезка «простыми словами» — та же черта, цветом акцента. */
.js .plain { position: relative; border-left-color: transparent; }
.js .plain::before {
  content: ""; position: absolute; left: -1.5px; top: 0; bottom: 0; width: 1.5px;
  background: var(--accent); transform: scaleY(0); transform-origin: top;
  transition: transform 620ms cubic-bezier(.22,.61,.36,1);
}
.js .plain.in::before { transform: scaleY(1); }

/* Цена тарифа: дощёлкивает числом (скрипт) и подрастает (здесь). */
.js .tier__price { display: inline-block; }
.js .words.tier__price .wd { transition-duration: 620ms; }

/* ── КАДР: медленный наезд и лёгкий сдвиг при прокрутке ──────────────────
   Наезд идёт один раз при появлении и останавливается. Сдвиг привязан
   к прокрутке, то есть управляется человеком, а не таймером. */
.shot img { transform: scale(1.07); transition: transform 1500ms cubic-bezier(.22,.61,.36,1); }
.js .shot.in img { transform: scale(1); }
.js .shot { --par: 0px; }
.js .shot img { will-change: transform; }
.js .shot.par img { transform: scale(1.07) translateY(var(--par)); }
.js .shot.par.in img { transform: scale(1) translateY(var(--par)); }

/* ── СТРОКИ ТАБЛИЦЫ ПОЯВЛЯЮТСЯ ОЧЕРЕДЬЮ ──────────────────────────────────
   Только первые восемь: дальше очередь превращается в ожидание. */
.js .rowin { opacity: 0; transform: translateY(10px);
             transition: opacity 480ms ease, transform 480ms ease;
             transition-delay: calc(var(--i, 0) * 55ms); }
.js tbody.in .rowin { opacity: 1; transform: none; }

/* ── РЕАКЦИЯ НА НАВЕДЕНИЕ ────────────────────────────────────────────── */
.btn { transition: background 160ms ease, transform 160ms ease,
                   box-shadow 200ms ease; }
.btn:hover { transform: translateY(-2px);
             box-shadow: 0 6px 18px rgba(18,32,42,.18); }
.btn:active { transform: translateY(0); box-shadow: none; }

.nav a, .langs a { position: relative; text-decoration: none; }
.nav a::after, .langs a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -3px;
  height: 1px; background: currentColor;
  transform: scaleX(0); transform-origin: left;
  transition: transform 220ms cubic-bezier(.22,.61,.36,1);
}
.nav a:hover::after, .langs a:hover::after { transform: scaleX(1); }

.five li { transition: background 200ms ease; }
.five li:hover { background: var(--ground); }

.tbl tbody tr { transition: background 200ms ease; }
.tbl tbody tr:hover { background: var(--ground); }

.tier { transition: transform 240ms cubic-bezier(.22,.61,.36,1),
                    box-shadow 240ms ease; }
.tier:hover { transform: translateY(-3px);
              box-shadow: 0 10px 30px rgba(18,32,42,.10); }

/* Поле ввода: рамка утолщается плавно, а не прыжком. */
.field input { transition: border-color 160ms ease, box-shadow 160ms ease; }
.field input:focus { outline: none;
  box-shadow: inset 0 0 0 1.5px var(--ink); }

/* ── ЛИНИЯ-ЗНАК: рисуется один раз при загрузке ──────────────────────────
   Это подпись фирмы, и она проводится как росчерк пера. Один раз,
   без повтора. */
.js .sign path { stroke-dasharray: 1400; stroke-dashoffset: 1400;
                 transition: stroke-dashoffset 1600ms cubic-bezier(.22,.61,.36,1); }
.js .sign.in path { stroke-dashoffset: 0; }
.js .sign circle { opacity: 0; transition: opacity 400ms ease 1500ms; }
.js .sign.in circle { opacity: 1; }

/* ═══ ОБЯЗАТЕЛЬНОЕ: человек попросил меньше движения — движения нет ═══════
   Не «поменьше», а НОЛЬ. Всё видно сразу и не двигается. */
@media (prefers-reduced-motion: reduce) {
  .js .reveal,
  .js .words .wd,
  .js .hero__text h1 .wd,
  .js .doc__head h1 .wd,
  .js .rowin { opacity: 1 !important; transform: none !important;
               transition: none !important; animation: none !important; }
  .js .hero__text .punch::after { animation: none !important;
                                  opacity: 0 !important; }
  .js .hero__text .punch::before,
  .js .plain::before { transform: scaleY(1) !important;
                       transition: none !important; }
  .shot img, .js .shot.in img, .js .shot.par img, .js .shot.par.in img {
    transform: none !important; transition: none !important; }
  .btn, .btn:hover, .btn:active,
  .tier, .tier:hover { transform: none !important;
                       transition: none !important; box-shadow: none !important; }
  .nav a::after, .langs a::after { transition: none !important;
                                   transform: scaleX(1) !important; opacity: .35; }
  .js .sign path { stroke-dasharray: none !important;
                   stroke-dashoffset: 0 !important; transition: none !important; }
  .js .sign circle { opacity: 1 !important; transition: none !important; }
  .five li, .tbl tbody tr, .field input { transition: none !important; }
}
