/* ==========================================================================
   Online Ads: scenes.css
   Анимированные SVG-сцены услуг, композиция в hero, кольца-мишени,
   импульсы в схеме AI и цикл Growth. Только CSS-анимации.
   Сцены играют, пока блок с атрибутом data-scene виден на экране:
   класс .is-inview ставит js/main.js.
   ========================================================================== */

@property --orbit {
  syntax: "<angle>";
  inherits: true;
  initial-value: 0deg;
}

/* ---------- Общие правила сцен ---------- */
.scene {
  display: block;
  width: 100%;
  height: auto;
}

.scene * { transform-box: fill-box; }

/* вне экрана всё стоит на паузе */
.js [data-scene]:not(.is-inview) .scene *,
.js [data-scene]:not(.is-inview) .scene-anim,
.js [data-scene]:not(.is-inview) .scene-anim *,
.js .flow:not(.is-inview) .flow__link::after,
.js .flow:not(.is-inview) .flow__ring--2,
.js .flow:not(.is-inview) .flow__item,
.js .growth__grid:not(.is-inview) .loop__sweep,
.js .growth__grid:not(.is-inview) .loop__node,
.js .growth__grid:not(.is-inview) .growth__item,
.js .growth__grid:not(.is-inview) .growth__item::before { animation-play-state: paused; }

/* Палитра сцен */
.sc-stroke { fill: none; stroke: var(--brand-ice); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.sc-dim    { fill: none; stroke: rgba(185, 198, 238, .32); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.sc-accent { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.sc-panel  { fill: var(--surface); stroke: rgba(185, 198, 238, .45); stroke-width: 1.5; }
.sc-deep   { fill: var(--bg); }
.sc-soft   { fill: rgba(185, 198, 238, .28); }
.sc-ice    { fill: var(--brand-ice); }
.sc-white  { fill: #FFFFFF; }
.sc-cyan   { fill: var(--accent); }
.sc-navy   { fill: var(--brand-navy); }
.sc-brand  { fill: url(#g-brand); }

.sc-text {
  fill: var(--brand-ice);
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.12em;
}

/* ---------- Сцена 1: приложение ---------- */
.app__row { animation: app-row 7s var(--ease) infinite; }
.app__row--1 { animation-delay: 0.3s; }
.app__row--2 { animation-delay: 0.6s; }
.app__hero   { animation: app-row 7s var(--ease) infinite; }

@keyframes app-row {
  0%       { opacity: 0; transform: translateY(12px); }
  10%, 86% { opacity: 1; transform: none; }
  94%, 100% { opacity: 0; transform: translateY(-6px); }
}

.app__push { animation: app-push 7s var(--ease) infinite; }

@keyframes app-push {
  0%, 22%   { opacity: 0; transform: translateX(-20px); }
  32%, 80%  { opacity: 1; transform: none; }
  90%, 100% { opacity: 0; transform: translateX(-10px); }
}

.app__ok { transform-origin: center; animation: app-ok 7s var(--ease) infinite; }

@keyframes app-ok {
  0%, 44%   { opacity: 0; transform: scale(.4); }
  52%       { opacity: 1; transform: scale(1.12); }
  58%, 84%  { opacity: 1; transform: scale(1); }
  92%, 100% { opacity: 0; transform: scale(.8); }
}

.app__check { stroke-dasharray: 30; stroke-dashoffset: 30; animation: app-check 7s var(--ease) infinite; }

@keyframes app-check {
  0%, 52%   { stroke-dashoffset: 30; }
  62%, 100% { stroke-dashoffset: 0; }
}

/* ---------- Сцена 2: игра ---------- */
.game__hero { animation: game-run 6s linear infinite; }

@keyframes game-run {
  0%   { transform: translate(0, 0); opacity: 1; animation-timing-function: ease-out; }
  10%  { transform: translate(16px, -22px); animation-timing-function: ease-in; }
  20%  { transform: translate(32px, 0); animation-timing-function: ease-out; }
  32%  { transform: translate(58px, -44px); animation-timing-function: ease-in; }
  44%  { transform: translate(84px, -24px); animation-timing-function: ease-out; }
  56%  { transform: translate(112px, -66px); animation-timing-function: ease-in; }
  68%  { transform: translate(138px, -44px); opacity: 1; }
  86%  { transform: translate(138px, -44px); opacity: 1; }
  92%  { transform: translate(138px, -44px); opacity: 0; }
  96%  { transform: translate(0, 0); opacity: 0; }
  100% { transform: translate(0, 0); opacity: 1; }
}

.game__coin { transform-origin: center; animation: game-coin 6s var(--ease) infinite; }
.game__coin--1 { --hit: 20%; animation-name: game-coin-1; }
.game__coin--2 { animation-name: game-coin-2; }
.game__coin--3 { animation-name: game-coin-3; }

@keyframes game-coin-1 {
  0%, 18%   { transform: scale(1); opacity: 1; }
  24%, 94%  { transform: scale(0) translateY(-12px); opacity: 0; }
  100%      { transform: scale(1); opacity: 1; }
}

@keyframes game-coin-2 {
  0%, 42%   { transform: scale(1); opacity: 1; }
  48%, 94%  { transform: scale(0) translateY(-12px); opacity: 0; }
  100%      { transform: scale(1); opacity: 1; }
}

@keyframes game-coin-3 {
  0%, 66%   { transform: scale(1); opacity: 1; }
  72%, 94%  { transform: scale(0) translateY(-12px); opacity: 0; }
  100%      { transform: scale(1); opacity: 1; }
}

.game__pip { fill: rgba(185, 198, 238, .28); animation: 6s linear infinite; }
.game__pip--1 { animation-name: game-pip-1; }
.game__pip--2 { animation-name: game-pip-2; }
.game__pip--3 { animation-name: game-pip-3; }

@keyframes game-pip-1 { 0%, 20% { fill: rgba(185, 198, 238, .28); } 24%, 94% { fill: #2DD9FF; } 100% { fill: rgba(185, 198, 238, .28); } }
@keyframes game-pip-2 { 0%, 44% { fill: rgba(185, 198, 238, .28); } 48%, 94% { fill: #2DD9FF; } 100% { fill: rgba(185, 198, 238, .28); } }
@keyframes game-pip-3 { 0%, 68% { fill: rgba(185, 198, 238, .28); } 72%, 94% { fill: #2DD9FF; } 100% { fill: rgba(185, 198, 238, .28); } }

.game__star { animation: game-star 3s ease-in-out infinite; }
.game__star:nth-of-type(2n) { animation-delay: -1.2s; }
.game__star:nth-of-type(3n) { animation-delay: -2.1s; }

@keyframes game-star { 0%, 100% { opacity: .25; } 50% { opacity: .9; } }

/* ---------- Сцена 3: сайт ---------- */
.web__part { transform-origin: left top; animation: web-build 8s var(--ease) infinite; }
.web__part--1 { animation-delay: 0s; }
.web__part--2 { animation-delay: 0.25s; }
.web__part--3 { animation-delay: 0.5s; }
.web__part--4 { animation-delay: 0.65s; }
.web__part--5 { animation-delay: 0.8s; }

@keyframes web-build {
  0%        { opacity: 0; transform: translateY(10px); }
  8%, 88%   { opacity: 1; transform: none; }
  96%, 100% { opacity: 0; transform: none; }
}

.web__cursor { animation: web-cursor 8s var(--ease) infinite; }

@keyframes web-cursor {
  0%, 16%   { transform: translate(120px, 60px); opacity: 0; }
  24%       { transform: translate(120px, 60px); opacity: 1; }
  44%, 50%  { transform: translate(0, 0); opacity: 1; }
  53%       { transform: translate(0, 0) scale(.86); opacity: 1; }
  56%, 86%  { transform: translate(0, 0); opacity: 1; }
  94%, 100% { transform: translate(0, 0); opacity: 0; }
}

.web__btn { fill: #FFFFFF; animation: web-btn 8s var(--ease) infinite; }
.web__cursor { fill: #FFFFFF; stroke: var(--bg); stroke-width: 1; stroke-linejoin: round; }

@keyframes web-btn {
  0%, 52%   { fill: #FFFFFF; }
  56%, 88%  { fill: #2DD9FF; }
  96%, 100% { fill: #FFFFFF; }
}

.web__ring { transform-origin: center; animation: web-ring 8s var(--ease) infinite; }

@keyframes web-ring {
  0%, 52%   { opacity: 0; transform: scale(.4); }
  56%       { opacity: .9; transform: scale(1); }
  66%, 100% { opacity: 0; transform: scale(2.2); }
}

/* ---------- Сцена 4: AI ---------- */
.ai__pulse {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-dasharray: 10 100;
  stroke-dashoffset: 110;
  animation: ai-pulse 3.2s linear infinite;
}

.ai__pulse--2 { animation-delay: -1.1s; }
.ai__pulse--3 { animation-delay: -2.2s; }
.ai__pulse--4 { animation-delay: -0.5s; }
.ai__pulse--5 { animation-delay: -1.6s; }
.ai__pulse--6 { animation-delay: -2.7s; }

@keyframes ai-pulse { to { stroke-dashoffset: 0; } }

.ai__ring { transform-origin: center; animation: spin 24s linear infinite; }
.ai__core { transform-origin: center; animation: ai-core 3.2s ease-in-out infinite; }

@keyframes ai-core {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.05); }
}

.ai__label {
  fill: #FFFFFF;
  font-family: var(--font);
  font-size: 20px;
  font-weight: 900;
  letter-spacing: 0.04em;
}

@keyframes spin { to { transform: rotate(360deg); } }
@keyframes spin-reverse { to { transform: rotate(-360deg); } }

/* ---------- Сцена 5: рост ---------- */
.growth__bar {
  transform-origin: center bottom;
  animation: growth-bar 7s var(--ease) infinite;
  animation-delay: calc(var(--i) * 120ms);
}

@keyframes growth-bar {
  0%        { transform: scaleY(0); opacity: 0; }
  14%, 86%  { transform: scaleY(1); opacity: 1; }
  94%, 100% { transform: scaleY(1); opacity: 0; }
}

.growth__line {
  fill: none;
  stroke: var(--accent);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  animation: growth-line 7s var(--ease) infinite;
}

@keyframes growth-line {
  0%, 12%   { stroke-dashoffset: 100; opacity: 1; }
  44%, 86%  { stroke-dashoffset: 0; opacity: 1; }
  94%, 100% { stroke-dashoffset: 0; opacity: 0; }
}

.growth__arrow { transform-origin: center; animation: growth-arrow 7s var(--ease) infinite; }

@keyframes growth-arrow {
  0%, 40%   { opacity: 0; transform: scale(.3); }
  46%, 86%  { opacity: 1; transform: scale(1); }
  94%, 100% { opacity: 0; transform: scale(1); }
}

.growth__hit { transform-origin: center; animation: growth-hit 7s var(--ease) infinite; }

@keyframes growth-hit {
  0%, 44%   { opacity: 0; transform: scale(.5); }
  48%       { opacity: .9; transform: scale(1); }
  62%, 100% { opacity: 0; transform: scale(2.4); }
}

/* ---------- Мишень: кольца, знак, чипы на орбите и комета по траектории ----------
   Стоит в блоке с призывом на страницах услуг: размещение .cta-band__target. */
.target {
  position: relative;
  aspect-ratio: 1;
  container-type: inline-size;
  pointer-events: none;
}

.target__svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.target__ring { fill: none; stroke: rgba(45, 217, 255, .28); stroke-width: 1; }
.target__ring--dashed { stroke: rgba(191, 230, 237, .4); stroke-dasharray: 2 10; stroke-linecap: round; transform-origin: center; transform-box: fill-box; animation: spin 120s linear infinite; }
.target__ring--inner { stroke: rgba(45, 217, 255, .5); }
.target__tick { stroke: var(--accent); stroke-width: 2; stroke-linecap: round; }
.target__path { fill: none; stroke: rgba(191, 230, 237, .22); stroke-width: 1.5; stroke-dasharray: 4 8; }

/* комета летит по траектории к наконечнику стрелы */
.target__comet {
  fill: none;
  stroke: var(--accent);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 16 100;
  stroke-dashoffset: 116;
  filter: drop-shadow(0 0 6px rgba(45, 217, 255, .9));
  animation: target-comet 5s cubic-bezier(.5, 0, .2, 1) infinite;
}

.target__arrow { fill: var(--accent); }

.target__glow {
  position: absolute;
  inset: 22%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(1, 49, 184, .65) 0%, rgba(0, 125, 198, .2) 50%, transparent 72%);
}

.target__mark {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 30%;
  height: auto;
  transform: translate(-50%, -50%);
  filter: drop-shadow(0 12px 40px rgba(1, 49, 184, .8));
}

.target__orbit { position: absolute; inset: 0; animation: orbit 90s linear infinite; }

/* чипы стоят на среднем кольце и остаются горизонтальными */
.target__chip {
  position: absolute;
  top: 50%;
  left: 50%;
  --a: calc(var(--i) * 60deg + var(--orbit));
  transform: translate(-50%, -50%) rotate(var(--a)) translateX(36.4cqw) rotate(calc(var(--a) * -1));
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  color: var(--text);
}

@keyframes target-comet {
  0%   { stroke-dashoffset: 116; opacity: 0; }
  8%   { opacity: 1; }
  70%  { opacity: 1; }
  80%, 100% { stroke-dashoffset: 0; opacity: 0; }
}

@keyframes orbit { to { --orbit: 360deg; } }

/* Размещение мишени: только на десктопе, на узких экранах ей нет места рядом с текстом */
.cta-band__target { display: none; }

@media (min-width: 1024px) {
  /* Блок с призывом на страницах услуг: справа по краю контента, по центру высоты,
     целиком помещается и не обрезается краем экрана */
  .cta-band__target {
    display: block;
    position: absolute;
    top: 50%;
    right: var(--gutter);
    z-index: -1;
    width: clamp(260px, 44vw - 190px, 440px);
    transform: translateY(-50%);
  }
}

/* ---------- Hero главной: логотип по частям ----------
   Сюжет: буквы o (кольцо) и a (она же глаз) появляются рядом, как инициалы Online Ads,
   затем съезжаются, и a встаёт внутрь o. После этого стрела раз за разом попадает в цель.
   Вступление занимает 2.3s, один выстрел 2.5s.
   Координаты внутри знака заданы в единицах файла логотипа (684 x 752). */
.aim {
  position: relative;
  aspect-ratio: 1;
  pointer-events: none;
}

.aim__svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* свечение за знаком отделяет его от видео */
.aim__glow {
  position: absolute;
  top: 36.6%;
  left: 60.7%;
  width: 84%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(1, 49, 184, .6) 0%, rgba(0, 125, 198, .2) 42%, transparent 68%);
  transform: translate(-50%, -50%);
  animation: aim-fade 900ms var(--ease) 300ms both;
}

/* линия прицела: продолжение стрелы в обе стороны */
.aim__path {
  stroke: rgba(191, 230, 237, .28);
  stroke-width: 1.5;
  stroke-dasharray: 4 8;
  animation: aim-fade 900ms var(--ease) 300ms both;
}

/* буквы o и a: сначала рядом, потом съезжаются в знак */
.aim__o,
.aim__a {
  transform-origin: 363px 357px;
  animation: 2s linear 300ms both;
}

.aim__o { animation-name: aim-letter-o; }
.aim__a { animation-name: aim-letter-a; }

/* стрела: прилетает, попадает, держится как в логотипе и гаснет перед следующим выстрелом */
.aim__arrow { animation: aim-arrow 2.5s linear 2.6s infinite backwards; }

/* знак чуть отдаёт назад от попадания */
.aim__nudge { animation: aim-nudge 2.5s var(--ease) 2.6s infinite backwards; }

/* зрачок следит за стрелой и расширяется в момент попадания */
.aim__pupil {
  transform-origin: 363px 357px;
  animation: aim-eye 2.5s var(--ease) 2.6s infinite backwards;
}

/* волны от попадания */
.aim__ripple {
  stroke: var(--accent);
  stroke-width: 2;
  opacity: 0;
  transform-origin: 340px 205px;
  animation: aim-ripple 2.5s var(--ease) 2.6s infinite backwards;
}

.aim__ripple--late { animation-delay: 2.82s; }

@keyframes aim-fade { from { opacity: 0; } }

/* 0-0.5s появляется o, 0.3-0.8s появляется a, до 1.1s стоят рядом, к 2s съезжаются */
@keyframes aim-letter-o {
  0%   { transform: translate(-265px, 0) scale(.6); opacity: 0; animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
  25%  { transform: translate(-265px, 0) scale(1); opacity: 1; }
  55%  { transform: translate(-265px, 0) scale(1); animation-timing-function: cubic-bezier(.6, 0, .2, 1); }
  100% { transform: translate(0, 0) scale(1); opacity: 1; }
}

@keyframes aim-letter-a {
  0%, 15% { transform: translate(265px, 0) scale(.6); opacity: 0; animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
  40%  { transform: translate(265px, 0) scale(1); opacity: 1; }
  55%  { transform: translate(265px, 0) scale(1); animation-timing-function: cubic-bezier(.6, 0, .2, 1); }
  100% { transform: translate(0, 0) scale(1); opacity: 1; }
}

@keyframes aim-arrow {
  0%   { transform: translate(-656px, 755px); opacity: 0; animation-timing-function: cubic-bezier(.3, .6, .25, 1); }
  5%   { opacity: 1; }
  18%  { transform: translate(8px, -9px); opacity: 1; animation-timing-function: ease-out; }
  25%  { transform: translate(0, 0); }
  78%  { transform: translate(0, 0); opacity: 1; animation-timing-function: ease-in; }
  90%, 100% { transform: translate(0, 0); opacity: 0; }
}

@keyframes aim-nudge {
  0%, 17%   { transform: translate(0, 0); }
  21%       { transform: translate(13px, -15px); }
  36%, 100% { transform: translate(0, 0); }
}

@keyframes aim-eye {
  0%, 12%   { transform: translate(-12px, 14px) scale(.82); }
  20%       { transform: translate(4px, -5px) scale(.9); }
  30%, 80%  { transform: translate(0, 0) scale(1); }
  96%, 100% { transform: translate(-12px, 14px) scale(.82); }
}

@keyframes aim-ripple {
  0%, 17%   { transform: scale(.97); opacity: 0; }
  19%       { transform: scale(1); opacity: .85; }
  55%, 100% { transform: scale(1.48); opacity: 0; }
}

/* Размещение в hero: справа от заголовка, под текстом по слоям. Только десктоп.
   Ширина композиции и её отступ справа заданы переменными: от них же считается фон */
.hero-aim { display: none; }

@media (min-width: 1024px) {
  .hero {
    --aim-w: min(38vw, 68vh, 540px);
    --aim-r: max(var(--gutter), calc((100vw - var(--container)) / 2));
  }

  .hero-aim {
    display: block;
    position: absolute;
    top: 50%;
    right: var(--aim-r);
    z-index: -1;
    width: var(--aim-w);
    /* центр знака лежит на 36.6% высоты композиции: он и встаёт в середину hero */
    transform: translateY(-36.6%);
  }
}

/* ---------- Hero главной: фон анимации ----------
   Слой лежит за знаком. По нему снизу вверх плывут пары слов (.fly) и мишени (.hit).
   Фон разбит на вертикальные полосы слева и справа от знака, полосы не пересекаются.
   У всех элементов одной полосы одна скорость (--dur) и равные сдвиги по времени
   (--delay), поэтому они идут друг за другом и тоже не встречаются.
   .fly: слова ads и online буквами из логотипа (шрифт Arista, контуры взяты из файла
   логотипа) стоят в разных местах полосы. На пути вверх все буквы, кроме первых,
   гаснут, а буквы o и a притягиваются друг к другу и превращаются в маленький знак.
   .hit: круглая мишень, в центр которой попадает стрела из логотипа. Мишень светлая,
   как буква a в знаке, стрела голубая: цвета разные, но оба из логотипа.
   Скорость подобрана под частицы в видео (около 4% высоты кадра в секунду).
   Параметры элемента заданы в разметке:
   --x      левый край от центра знака (у слов это край слова online), в единицах --u,
            минус значит левее знака
   --size   высота строчной буквы у слов или диаметр мишени, в единицах --u
   --dx, --dy   где стоит слово ads: смещение буквы a от буквы o, в единицах --u
   --dur, --delay   время одного прохода и сдвиг по времени
   --alpha  яркость слов
   --at     на какой доле пути в мишень прилетает стрела
   Координаты внутри слов заданы в единицах файла логотипа. */
.hero-fly { display: none; }

@media (min-width: 1024px) {
  .hero-fly {
    /* единица фона: сотая часть ширины композиции знака, фон растёт вместе со знаком */
    --u: calc(var(--aim-w) / 100);
    /* центр знака от правого края hero */
    --cx: calc(var(--aim-r) + var(--aim-w) * .393);
    display: block;
    position: absolute;
    inset: 0;
    z-index: -1;
    overflow: hidden;
    container-type: size;
    pointer-events: none;
    /* под шапкой и у нижнего края, где стоит стрелка вниз, элементы растворяются */
    -webkit-mask-image: linear-gradient(to bottom, transparent 4%, #000 16%, #000 84%, transparent 91%);
    mask-image: linear-gradient(to bottom, transparent 4%, #000 16%, #000 84%, transparent 91%);
  }
}

.hero-fly__defs { position: absolute; }

/* Состав фона зависит от ширины окна: слева мешает текст, справа край экрана.
   На узком экране слова стоят в полосе одно над другим, на широком расходятся по ширине */
.hero-fly__min-1280,
.hero-fly__min-1536,
.hero-fly__min-1800 { display: none; }

@media (min-width: 1280px) {
  .hero-fly__min-1280 { display: block; }
  .hero-fly__max-1279 { display: none; }
}

@media (min-width: 1536px) {
  .hero-fly__min-1536 { display: block; }
  .hero-fly__max-1535 { display: none; }
}

@media (min-width: 1800px) {
  .hero-fly__min-1800 { display: block; }
}

.fly,
.hit {
  position: absolute;
  top: 0;
  left: calc(100% - var(--cx) + var(--x) * var(--u));
  height: auto;
  overflow: visible;
  animation: fly-rise var(--dur) linear var(--delay) infinite;
}

/* --lift есть только у слов: он опускает путь, если слово ads иначе появилось бы сразу в кадре */
@keyframes fly-rise {
  from { transform: translateY(calc(104cqh + var(--lift, 0px))); }
  to   { transform: translateY(calc(-18cqh + var(--lift, 0px))); }
}

/* пара слов: рамка элемента совпадает со словом online, оно шире высоты строчной буквы
   в 5.79 раза. Слово ads стоит выше и в стороне. online голубое, ads светлое, как в логотипе */
.fly {
  /* смещение буквы a от буквы o в единицах файла логотипа */
  --kx: calc(var(--dx) * 226.7px / var(--size));
  --ky: calc(var(--dy) * 226.7px / var(--size));
  --lift: max(0px, calc(var(--dy) * var(--u) * -1 - 13cqh));
  width: calc(var(--size) * var(--u) * 5.792);
  fill: var(--brand-sky);
}

.fly__ads {
  fill: var(--brand-ice);
  transform: translate(var(--kx), var(--ky));
}

/* точка встречи: середина между буквами o и a */
.fly__meet { transform: translate(calc(var(--kx) / 2), calc(var(--ky) / 2)); }

.fly__rest,
.fly__o,
.fly__a,
.fly__mark {
  animation: var(--dur) linear var(--delay) infinite;
}

.fly__rest { animation-name: fly-rest; }
.fly__o { animation-name: fly-o; }
.fly__a { animation-name: fly-a; }
.fly__mark { animation-name: fly-mark; }

/* все буквы, кроме первых, гаснут на месте */
@keyframes fly-rest {
  0%, 37%   { opacity: var(--alpha); }
  42%, 100% { opacity: 0; }
}

/* буквы o и a загораются и притягиваются: сначала медленно, у точки встречи быстро.
   По дороге o растёт в диск знака, a становится его серединой */
@keyframes fly-o {
  0%, 41%   { transform: translate(0, 0) scale(1); opacity: var(--alpha); }
  44%       { transform: translate(0, 0) scale(1); opacity: .8; animation-timing-function: cubic-bezier(.7, 0, 1, .55); }
  53%       { transform: translate(calc(var(--kx) / 2), calc(var(--ky) / 2)) scale(2); opacity: .8; }
  57%, 100% { transform: translate(calc(var(--kx) / 2), calc(var(--ky) / 2)) scale(2); opacity: 0; }
}

@keyframes fly-a {
  0%, 41%   { transform: translate(0, 0) scale(1); opacity: var(--alpha); }
  44%       { transform: translate(0, 0) scale(1); opacity: .8; animation-timing-function: cubic-bezier(.7, 0, 1, .55); }
  53%       { transform: translate(calc(var(--kx) / -2), calc(var(--ky) / -2)) scale(1.314); opacity: .8; }
  57%, 100% { transform: translate(calc(var(--kx) / -2), calc(var(--ky) / -2)) scale(1.314); opacity: 0; }
}

/* маленький знак появляется в точке встречи */
@keyframes fly-mark {
  0%, 52%   { transform: scale(.85); opacity: 0; }
  55%       { transform: scale(1.1); opacity: .85; }
  59%, 100% { transform: scale(1); opacity: .85; }
}

/* мишень: --size задаёт диаметр. Стрела выступает влево вниз на треть диаметра, а в полёте
   уходит ещё дальше, поэтому слева от мишени в полосе оставлено место */
.hit { width: calc(var(--size) * var(--u)); }

.hit__ring,
.hit__ripple {
  stroke: var(--brand-ice);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
}

.hit__dot { fill: var(--brand-ice); }

/* выстрел сдвинут относительно пути на долю --at: мишени получают стрелу на разной высоте.
   Из сдвига вычтен полный круг, чтобы задержка была отрицательной и цикл шёл с первой секунды */
.hit__ring,
.hit__dot,
.hit__ripple,
.hit__arrow {
  animation: var(--dur) linear calc(var(--delay) + var(--dur) * (var(--at) - 1)) infinite;
}

.hit__ring,
.hit__dot { animation-name: hit-ring; }
.hit__ripple { transform-origin: 100px 100px; animation-name: hit-ripple; }
.hit__arrow { animation-name: hit-arrow; }

/* стрела прилетает быстро, остриём встаёт в центр, чуть отдаёт назад и остаётся
   в мишени почти до конца пути */
@keyframes hit-arrow {
  0%        { transform: translate(-131px, 151px); opacity: 0; animation-timing-function: cubic-bezier(.4, 0, .9, .7); }
  0.4%      { opacity: .95; }
  1.4%      { transform: translate(0, 0); opacity: .95; }
  1.9%      { transform: translate(-4px, 5px); }
  2.6%      { transform: translate(0, 0); }
  56%       { transform: translate(0, 0); opacity: .95; }
  62%, 100% { transform: translate(0, 0); opacity: 0; }
}

@keyframes hit-ring {
  0%, 1.3%  { opacity: .4; }
  1.8%      { opacity: 1; }
  56%       { opacity: .75; }
  62%, 100% { opacity: .4; }
}

@keyframes hit-ripple {
  0%, 1.3%  { transform: scale(1); opacity: 0; }
  1.6%      { transform: scale(1); opacity: .8; animation-timing-function: ease-out; }
  8%, 100%  { transform: scale(1.5); opacity: 0; }
}

/* ---------- Contacts главной: слова появляются на месте ----------
   Те же пары слов, что в фоне hero, но без полёта: .fly--spot. Слова ads и online
   появляются в свободном месте справа от заголовка, все буквы, кроме первых, гаснут,
   o и a притягиваются в маленький знак, знак пропадает. Потом пауза, и всё повторяется:
   у пар разная длина цикла, поэтому они возникают то тут, то там.
   Слой .contacts__fly привязан к блоку заголовка: начинается чуть выше надзаголовка
   и не доходит до карточек. Пары стоят в три ряда и не пересекаются.
   Параметры пары в разметке:
   --x      левый край слова online от правого края слоя, в единицах --u
   --y      верх пары от верха слоя, в px
   --size, --dx, --dy, --dur, --delay, --alpha   как у пар в hero
   Слева стоит текст: в двух верхних рядах пара не уходит дальше 140 единиц от правого
   края, в нижнем (рядом с абзацем) не дальше 60. */
.contacts__fly { display: none; }

@media (min-width: 1024px) {
  .contacts__fly {
    --u: min(0.37vw, 5.4px);
    display: block;
    position: absolute;
    inset: -24px 0 -40px;
    z-index: -1;
    pointer-events: none;
  }
}

/* рамка элемента совпадает со словом online: если слово ads стоит выше, рамка опускается.
   Между циклами пара немного сдвигается, место каждый раз чуть другое */
.fly--spot {
  top: calc(var(--y) + max(0, -1 * var(--dy)) * var(--u));
  left: calc(100% - var(--x) * var(--u));
  animation: spot-shift calc(var(--dur) * 3) step-end var(--delay) infinite;
}

.fly--spot .fly__rest { animation-name: spot-rest; }
.fly--spot .fly__o { animation-name: spot-o; }
.fly--spot .fly__a { animation-name: spot-a; }
.fly--spot .fly__mark { animation-name: spot-mark; }

@keyframes spot-shift {
  0%     { transform: translate(0, 0); }
  33.34% { transform: translate(calc(var(--u) * 4), calc(var(--u) * -1.5)); }
  66.67% { transform: translate(calc(var(--u) * -4), calc(var(--u) * 1.5)); }
}

/* Один цикл: слова проявляются, стоят, лишние буквы гаснут, o и a сходятся в знак,
   знак держится и пропадает. Всё это занимает первую половину цикла, дальше пауза */
@keyframes spot-rest {
  0%        { opacity: 0; }
  3%, 15%   { opacity: var(--alpha); }
  18%, 100% { opacity: 0; }
}

@keyframes spot-o {
  0%        { transform: translate(0, 0) scale(1); opacity: 0; }
  3%, 17.5% { transform: translate(0, 0) scale(1); opacity: var(--alpha); }
  20%       { transform: translate(0, 0) scale(1); opacity: .8; animation-timing-function: cubic-bezier(.7, 0, 1, .55); }
  29%       { transform: translate(calc(var(--kx) / 2), calc(var(--ky) / 2)) scale(2); opacity: .8; }
  32%, 100% { transform: translate(calc(var(--kx) / 2), calc(var(--ky) / 2)) scale(2); opacity: 0; }
}

@keyframes spot-a {
  0%        { transform: translate(0, 0) scale(1); opacity: 0; }
  3%, 17.5% { transform: translate(0, 0) scale(1); opacity: var(--alpha); }
  20%       { transform: translate(0, 0) scale(1); opacity: .8; animation-timing-function: cubic-bezier(.7, 0, 1, .55); }
  29%       { transform: translate(calc(var(--kx) / -2), calc(var(--ky) / -2)) scale(1.314); opacity: .8; }
  32%, 100% { transform: translate(calc(var(--kx) / -2), calc(var(--ky) / -2)) scale(1.314); opacity: 0; }
}

@keyframes spot-mark {
  0%, 28.5% { transform: scale(.85); opacity: 0; }
  31%       { transform: scale(1.1); opacity: .85; }
  33.5%, 44% { transform: scale(1); opacity: .85; }
  50%, 100% { transform: scale(.9); opacity: 0; }
}

/* ---------- AI: импульсы по соединителям ---------- */
.flow__link::after { animation: flow-y 2.2s linear infinite; }
.flow__link--out::after { animation-delay: 1.1s; }
.flow__ring--2 { animation: spin 40s linear infinite; }

@keyframes flow-y {
  from { transform: translateY(-100%); }
  to   { transform: translateY(100%); }
}

@keyframes flow-x {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}

@media (min-width: 640px) {
  .flow__link::after { animation-name: flow-x; }
}

/* пункты по очереди подсвечиваются цветом фона: вход, затем результат */
.flow__item { animation: flow-item 8s linear infinite; animation-delay: calc(var(--i, 0) * 1s); }

@keyframes flow-item {
  0%        { background-color: #030822; }
  3%, 10%   { background-color: #0131B8; }
  16%, 100% { background-color: #030822; }
}

/* ---------- Growth: дуга обходит узлы, узлы и пункты списка загораются по очереди ---------- */
.loop__base { fill: none; stroke: var(--border); stroke-width: 2; }
.loop__chevron { fill: none; stroke: var(--text-dim); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

.loop__sweep {
  fill: none;
  stroke: var(--accent);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 14 86;
  transform-box: fill-box;
  transform-origin: center;
  transform: rotate(-140.4deg);
  animation: loop-sweep 10s linear infinite;
}

@keyframes loop-sweep { to { transform: rotate(219.6deg); } }

.loop__node,
.growth__item,
.growth__item::before {
  animation: 10s linear infinite;
  animation-delay: calc(var(--i) * 2s);
}

.loop__node { animation-name: loop-node; }
.growth__item { animation-name: loop-item; }
.growth__item::before { animation-name: loop-node; }

@keyframes loop-node {
  0%, 18% { border-color: #2DD9FF; background-color: #2DD9FF; color: #021033; box-shadow: 0 0 0 8px rgba(45, 217, 255, .12); }
  22%, 100% { border-color: #1A2C78; background-color: #030822; color: #B9C6EE; box-shadow: 0 0 0 0 rgba(45, 217, 255, 0); }
}

@keyframes loop-item {
  0%, 18% { background-color: #0A1648; }
  22%, 100% { background-color: transparent; }
}

/* ---------- Без движения: сцены показывают итоговое состояние ---------- */
@media (prefers-reduced-motion: reduce) {
  .scene *,
  .target, .target *,
  .aim, .aim *,
  .hero-fly, .hero-fly *,
  .contacts__fly, .contacts__fly *,
  .flow *, .loop *, .growth__item, .growth__item::before {
    animation: none !important;
  }

  .hero-fly, .contacts__fly { display: none; }
  .ai__pulse, .target__comet, .web__ring, .growth__hit { opacity: 0; }
  .growth__line, .app__check { stroke-dashoffset: 0; }
}
