/* UKM — motion.css
   1) scenes — анимации технических иллюстраций (js/scenes.js), классы .sc-*
   2) reveal — каталог эффектов при прокрутке (js/motion.js): rise, rise-x, cascade, words, curtain, curtain-x,
      draw, drift, progress, panel-in, soft, header, tick, view. Полигоны карты (poly) анимирует js/map.js инлайн-стилями.
   Подключать после css/style.css. Все скрытые стартовые состояния действуют только под html.has-motion
   (класс ставит motion.js до первой отрисовки), поэтому без JS и при prefers-reduced-motion контент виден сразу. */

:root{--ease-out:cubic-bezier(.16,1,.3,1)}

/* ---------- scenes ----------
   Классы движения схем (js/scenes.js). Полный список — в MOVE ниже: гейт .is-drawn, пауза .sc-idle и reduced-motion
   применяются ко всем. Точка вращения циклов — начало координат группы (transform-box:view-box; origin 0 0),
   анимируемая группа вложена в <g transform="translate(ось)">; wheels — fill-box/center. */
.sc-svg{text-transform:uppercase}
[data-scene] svg.sc-svg{display:block;width:100%;height:auto;--sc-bg:var(--bg-2)}
.sheet [data-scene] svg.sc-svg{--sc-bg:var(--bg-up)} /* на листе схема лежит на --bg-up: плашки под текстом совпадают с фоном */

/* скорость «земли» — 40px/с: 80px за 2с; период узоров кратен 80 (или 160) */
.sc-tread{animation:sc-tread 2s linear infinite}
.sc-tread-x2{animation:sc-tread-x2 4s linear infinite}

/* вращение: период колеса = длина окружности / 40px/с */
.sc-spin-r,.sc-spin-f,.sc-spin-s,.sc-beam{transform-box:fill-box;transform-origin:center}
.sc-spin-r{animation:sc-spin 4.4s linear infinite}   /* r=28 */
.sc-spin-f{animation:sc-spin 2.6s linear infinite}   /* r=16–17 */
.sc-spin-s{animation:sc-spin 1.9s linear infinite}   /* r=12 */
.sc-beam{animation:sc-spin 1.6s linear infinite}     /* луч излучателя */

/* движение штриха по линии: поток пласта по отвалу, опорная лазерная плоскость */
.sc-flow{stroke-dasharray:3 5;animation:sc-flow 1s linear infinite}
.sc-flow-l{stroke-dasharray:6 6;animation:sc-flow-l 1.2s linear infinite}

/* полотно 40px/1с (плуг: один пласт за цикл оборота) и плитка сорняков КУ-4М (период 320) */
.sc-tread-x1{animation:sc-tread-x1 1s linear infinite}
.sc-tread-x4{animation:sc-tread-x4 8s linear infinite}

/* быстрые роторы: диски косилки (попарно навстречу), ротор КИР-1,5, вентилятор ОВХ */
.sc-spin-fan,.sc-spin-fanr{transform-box:fill-box;transform-origin:center}
.sc-spin-fan{animation:sc-spin .9s linear infinite}
.sc-spin-fanr{animation:sc-spin .9s linear infinite reverse}

/* потоки по линии: сдвиг почвы у сошников и измельчённая масса (быстро), факел капель, струя груза из кузова */
.sc-flow-f{stroke-dasharray:4 5;animation:sc-flow-f .4s linear infinite}
.sc-flow-mist{stroke-dasharray:2 6;animation:sc-flow-f .5s linear infinite}
.sc-flow-drop{stroke-dasharray:2 5;animation:sc-flow-drop .4s linear infinite,sc-tip-stream 6s linear infinite} /* струя видна только в фазе выгрузки (stroke-opacity — не opacity: та уходит на композитор и не синхронна с циклом) */

/* плуг: пласт у последнего корпуса поднимается по отвалу и ложится (1 с = шаг полотна 40px) */
.sc-plug-flip{transform-box:view-box;transform-origin:0 0;animation:sc-plug-flip 1s linear infinite}

/* планировщик: трактор идёт по исходному рельефу (4 с = период рельефа 160px), дышло качается, шток компенсирует */
.sc-bob,.sc-bob-r,.sc-bob-x{transform-box:view-box;transform-origin:0 0;animation:sc-bob 4s ease-in-out infinite}
.sc-bob-r{animation-name:sc-bob-r}
.sc-bob-x{animation-name:sc-bob-x}

/* прицеп: цикл 6 с — подъём 0–40 %, выгрузка 40–62 %, опускание 62–100 %; промежуточные положения (8/16/24/32 %)
   заданы долями угла, для гидроцилиндра — рассчитанными в scenes.js переменными --sc-r0…r5 (угол) и --sc-e0…e5 (ход) */
.sc-tip-body,.sc-tip-gate,.sc-tip-cyl,.sc-tip-ext,.sc-tip-load,.sc-tip-pile{transform-box:view-box;transform-origin:0 0}
.sc-tip-body{animation:sc-tip-body 6s linear infinite}
.sc-tip-cyl{animation:sc-tip-cyl 6s linear infinite}
.sc-tip-ext{animation:sc-tip-ext 6s linear infinite}
.sc-tip-gate{animation:sc-tip-gate 6s cubic-bezier(.2,0,0,1) infinite}
.sc-tip-load{animation:sc-tip-load 6s linear infinite}
.sc-tip-pile{animation:sc-tip-pile 6s linear infinite}

@keyframes sc-tread{to{transform:translateX(-80px)}}
@keyframes sc-tread-x1{to{transform:translateX(-40px)}}
@keyframes sc-tread-x2{to{transform:translateX(-160px)}}
@keyframes sc-tread-x4{to{transform:translateX(-320px)}}
@keyframes sc-spin{to{transform:rotate(360deg)}}
@keyframes sc-flow{to{stroke-dashoffset:-8}}
@keyframes sc-flow-l{to{stroke-dashoffset:-12}}
@keyframes sc-flow-f{to{stroke-dashoffset:-9}}
@keyframes sc-flow-drop{to{stroke-dashoffset:-7}}
@keyframes sc-plug-flip{0%{transform:rotate(0);opacity:0}10%{opacity:1}100%{transform:rotate(-110deg)}}
@keyframes sc-bob{0%,50%,100%{transform:translateY(0)}25%{transform:translateY(-3px)}75%{transform:translateY(3px)}}
@keyframes sc-bob-r{0%,50%,100%{transform:rotate(0)}25%{transform:rotate(-3deg)}75%{transform:rotate(3deg)}}
@keyframes sc-bob-x{0%,50%,100%{transform:translateX(0)}25%{transform:translateX(3px)}75%{transform:translateX(-3px)}}
@keyframes sc-tip-body{
  0%,100%{transform:rotate(0)}
  8%,94%{transform:rotate(calc(var(--sc-t,-36deg) * .12))}
  16%,86%{transform:rotate(calc(var(--sc-t,-36deg) * .38))}
  24%,78%{transform:rotate(calc(var(--sc-t,-36deg) * .68))}
  32%,70%{transform:rotate(calc(var(--sc-t,-36deg) * .9))}
  40%,62%{transform:rotate(var(--sc-t,-36deg))}
}
@keyframes sc-tip-cyl{
  0%,100%{transform:rotate(var(--sc-r0,-165deg))}
  8%,94%{transform:rotate(var(--sc-r1,-161deg))}
  16%,86%{transform:rotate(var(--sc-r2,-152deg))}
  24%,78%{transform:rotate(var(--sc-r3,-141deg))}
  32%,70%{transform:rotate(var(--sc-r4,-133deg))}
  40%,62%{transform:rotate(var(--sc-r5,-130deg))}
}
@keyframes sc-tip-ext{
  0%,100%{transform:translateX(0)}
  8%,94%{transform:translateX(calc(var(--sc-e1,14px) * var(--sc-k,1)))}
  16%,86%{transform:translateX(calc(var(--sc-e2,46px) * var(--sc-k,1)))}
  24%,78%{transform:translateX(calc(var(--sc-e3,82px) * var(--sc-k,1)))}
  32%,70%{transform:translateX(calc(var(--sc-e4,108px) * var(--sc-k,1)))}
  40%,62%{transform:translateX(calc(var(--sc-e5,120px) * var(--sc-k,1)))}
}
@keyframes sc-tip-gate{0%,22%,80%,100%{transform:rotate(0)}42%,62%{transform:rotate(80deg)}}
@keyframes sc-tip-load{0%,30%{transform:translateX(0);opacity:1}62%,94%{transform:translateX(-300px);opacity:0}96%{transform:translateX(0);opacity:0}100%{transform:translateX(0);opacity:1}}
@keyframes sc-tip-pile{0%{transform:scale(.08);opacity:0}34%{transform:scale(.08);opacity:1}62%,90%{transform:scale(1);opacity:1}100%{transform:scale(1);opacity:0}}
@keyframes sc-tip-stream{0%,33%,64%,100%{stroke-opacity:0}40%,58%{stroke-opacity:1}}

/* движущиеся части схемы (протектор, колёса, луч, поток, циклы) проявляются после того, как нарисованы линии:
   motion.js ставит .is-drawn на [data-scene] в момент старта draw (с учётом data-draw-delay) */
html.has-motion [data-scene] :is(.sc-tread,.sc-tread-x1,.sc-tread-x2,.sc-tread-x4,.sc-spin-r,.sc-spin-f,.sc-spin-s,.sc-spin-fan,.sc-spin-fanr,.sc-beam,.sc-flow,.sc-flow-l,.sc-flow-f,.sc-flow-mist,.sc-flow-drop,.sc-tip-pile){transition:opacity .6s var(--ease-out) .45s}
html.has-motion [data-scene]:not(.is-drawn) :is(.sc-tread,.sc-tread-x1,.sc-tread-x2,.sc-tread-x4,.sc-spin-r,.sc-spin-f,.sc-spin-s,.sc-spin-fan,.sc-spin-fanr,.sc-beam,.sc-flow,.sc-flow-l,.sc-flow-f,.sc-flow-mist,.sc-flow-drop,.sc-tip-pile){opacity:0}

/* сцена вне вьюпорта — анимации на паузе (класс ставит motion.js) */
[data-scene].sc-idle :is(.sc-tread,.sc-tread-x1,.sc-tread-x2,.sc-tread-x4,.sc-spin-r,.sc-spin-f,.sc-spin-s,.sc-spin-fan,.sc-spin-fanr,.sc-beam,
.sc-flow,.sc-flow-l,.sc-flow-f,.sc-flow-mist,.sc-flow-drop,.sc-plug-flip,.sc-bob,.sc-bob-r,.sc-bob-x,
.sc-tip-body,.sc-tip-gate,.sc-tip-cyl,.sc-tip-ext,.sc-tip-load,.sc-tip-pile){animation-play-state:paused}

/* без движения: статичный чертёж — кузов опущен, груз в кузове и куча видны, струя и пласт на отвале скрыты */
@media (prefers-reduced-motion:reduce){
  .sc-tread,.sc-tread-x1,.sc-tread-x2,.sc-tread-x4,.sc-spin-r,.sc-spin-f,.sc-spin-s,.sc-spin-fan,.sc-spin-fanr,.sc-beam,
  .sc-flow,.sc-flow-l,.sc-flow-f,.sc-flow-mist,.sc-flow-drop,.sc-plug-flip,.sc-bob,.sc-bob-r,.sc-bob-x,
  .sc-tip-body,.sc-tip-gate,.sc-tip-cyl,.sc-tip-ext,.sc-tip-load,.sc-tip-pile{animation:none}
  .sc-tip-stream,.sc-plug-flip{opacity:0}
}

/* ---------- rise / rise-x / cascade ----------
   [data-reveal]                   rise: opacity 0→1, translateY(24px)→0, 700 мс   (data-reveal-delay="ms")
   [data-reveal="x"]               rise-x: translateX(24px)→0
   [data-reveal="fade"]            только opacity
   [data-reveal-group]             cascade: rise для прямых детей, задержка i×step (data-reveal-step, по умолчанию 60,
                                   не больше 8×step); [data-reveal-group="x"|"fade"] или сочетание с data-reveal="x"
                                   задаёт направление детям; сам контейнер при этом не анимируется */
html.has-motion [data-reveal]:not(.is-done),
html.has-motion [data-reveal-group]:not(.is-done)>*{
  opacity:0;transform:translateY(24px);
  transition:opacity .7s var(--ease-out),transform .7s var(--ease-out);
  transition-delay:var(--sc-delay,0ms)
}
/* soft — мягкий каскад для мелких элементов (чипы hero, пилюли phead): сдвиг 8px, 500 мс, шаг 40 мс */
html.has-motion [data-reveal-group="soft"]:not(.is-done)>*{transform:translateY(8px);transition-duration:.5s}
html.has-motion [data-reveal="x"]:not(.is-done),
html.has-motion [data-reveal-group="x"]:not(.is-done)>*,
html.has-motion [data-reveal-group][data-reveal="x"]:not(.is-done)>*{transform:translateX(24px)}
html.has-motion [data-reveal="fade"],
html.has-motion [data-reveal-group="fade"]>*,
html.has-motion [data-reveal-group][data-reveal="fade"]>*,
html.has-motion .partners[data-reveal-group]>*{transform:none}
/* контейнер каскада и заголовок с пословной анимацией сами не прячутся */
html.has-motion [data-reveal-group][data-reveal],
html.has-motion [data-reveal][data-split]{opacity:1;transform:none;transition:none}
html.has-motion [data-reveal].is-in:not(.is-done),
html.has-motion [data-reveal-group].is-in:not(.is-done)>*{opacity:1;transform:none}

/* ---------- words ----------
   [data-split] на заголовке: motion.js оборачивает слова в .w > .w__i; внутренний span выезжает снизу из маски.
   Отступы маски — чтобы не срезать верх «Й», «б» и хвосты «р», «у», «д» при line-height < 1. */
html.has-motion [data-split]:not(.is-split){opacity:0}
[data-split] .w{display:inline-block;overflow:hidden;vertical-align:top;padding:.12em 0 .14em;margin:-.12em 0 -.14em}
[data-split] .w__i{display:inline-block}
html.has-motion [data-split] .w__i{
  transform:translateY(120%);
  transition:transform .9s var(--ease-out);transition-delay:var(--sc-delay,0ms)
}
html.has-motion [data-split].is-in .w__i{transform:none}

/* ---------- curtain / curtain-x ----------
   [data-curtain] на .frame (или .tmap__stage): наблюдается контейнер, шторка — на внутреннем img/picture/.tmap__zoom.
   Радиус шторки — --r-curtain (motion.js берёт его из вычисленного border-radius контейнера, если CSS не задал),
   поэтому шторка повторяет скругление маски, включая усиленный угол .frame--tl/tr/br/bl.
   data-curtain-dur="ms", data-curtain-delay="ms" (или data-reveal-delay). Одновременно img: scale(1.08)→1, +200 мс. */
html.has-motion [data-curtain]{--sc-dur-def:1s}
html.has-motion [data-curtain="x"]{--sc-dur-def:1.1s}
html.has-motion [data-curtain]:not(.is-done)>:is(img,picture,.tmap__zoom,[data-curtain-target]){
  clip-path:inset(0 0 100% 0 round var(--r-curtain,var(--r,28px)));
  transform:scale(1.08);
  transition:clip-path var(--sc-dur,var(--sc-dur-def)) var(--ease-out),transform calc(var(--sc-dur,var(--sc-dur-def)) + .2s) var(--ease-out);
  transition-delay:var(--sc-delay,0ms)
}
html.has-motion [data-curtain="x"]:not(.is-done)>:is(img,picture,.tmap__zoom,[data-curtain-target]){clip-path:inset(0 100% 0 0 round var(--r-curtain,var(--r,28px)))}
html.has-motion [data-curtain]>.tmap__zoom{transform:none} /* сцену карты не масштабируем: у неё свой зум */
html.has-motion [data-curtain].is-in:not(.is-done)>:is(img,picture,.tmap__zoom,[data-curtain-target]){clip-path:inset(0 round var(--r-curtain,var(--r,28px)));transform:none}
html.has-motion [data-curtain].is-done>.tmap__zoom{clip-path:none;transition:transform .7s var(--ease,cubic-bezier(.2,0,0,1))}

/* ---------- drift ----------
   [data-drift="32"] на .frame: --p от −1 до 1 по положению фрейма в окне (ставит motion.js в rAF), только ≥1024 (html.has-drift).
   После шторки транзишн снимается, чтобы сдвиг следовал за прокруткой без запаздывания. */
html.has-motion.has-drift [data-drift]:not([data-curtain])>:is(img,picture),
html.has-motion.has-drift [data-drift][data-curtain].is-in>:is(img,picture){
  transform:translateY(calc(var(--p,0) * var(--drift,32) * -1px)) scale(var(--drift-scale,1.06))
}
html.has-motion.has-drift [data-drift][data-curtain].is-done>:is(img,picture){transition:none}

/* ---------- draw ----------
   [data-draw] (svg, g, фигура или контейнер схемы): dasharray/dashoffset выставляет motion.js по getTotalLength();
   data-draw-dur="1100" data-draw-step="30" data-draw-delay="250" (на .scheme ставит сам motion.js) */
html.has-motion .sc-draw{transition:stroke-dashoffset var(--sc-draw,900ms) var(--ease-out)}

/* ---------- progress ----------
   [data-progress]: --p 0…1 (сколько блока пройдено), li внутри получают .is-past по мере прокрутки */
[data-progress] li{transition:color .3s var(--ease,cubic-bezier(.2,0,0,1))}

/* ---------- header ----------
   шапка въезжает сверху после первой инициализации (motion.js ставит .hdr.is-in в rAF после refresh) */
html.has-motion .hdr{transition:opacity .6s var(--ease-out),transform .6s var(--ease-out)}
html.has-motion .hdr:not(.is-in){opacity:0;transform:translateY(-8px)}
html.has-motion .hdr.is-in{opacity:1;transform:none}

/* ---------- view ----------
   смена вида карты: уходящий кадр держится, пока новый проявляется (crossfade без «просвета» фона) */
.tmap__view{transition:opacity 0s linear .4s}
.tmap__view.is-active{transition:opacity .4s var(--ease,cubic-bezier(.2,0,0,1));z-index:1}

/* ---------- tick ----------
   счётчики лент (about.js: история, схемы на главной): при смене номера цифры «набираются» — короткий сдвиг снизу */
html.has-motion [data-tl-count],html.has-motion [data-schemes-count]{display:inline-block}
@keyframes tick{from{opacity:0;transform:translateY(6px)}}

/* ---------- panel-in ----------
   панель документа, панель объекта карты, мобильное меню и лайтбокс: появление при открытии */
@media (prefers-reduced-motion:no-preference){
  .docpanel.is-active,.tmap__panel.is-open{animation:panel-in .45s var(--ease-out) both}
  .mnav.is-open{animation:panel-in .35s var(--ease-out) both}
  .lb.is-open{animation:fade-in .3s var(--ease-out)}
  .lb.is-open .lb__img{animation:lb-in .45s var(--ease-out)} /* без fill: после анимации действует инлайн-transform зума */
  @keyframes panel-in{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
  @keyframes fade-in{from{opacity:0}}
  @keyframes lb-in{from{opacity:0;transform:translateY(12px) scale(.98)}}
}

/* ---------- mobile (js/mobile.js, css/mobile.css) ----------
   Нижние листы едут transform-переходом .m-sheet (400 мс ease-out); panel-in на панели объекта и docpanel-in в аккордеоне
   на мобильном отключены (animation:none — в mobile.css §9 и §11). Свайп листа: инлайн transform без перехода (ставит mobile.js), возврат — 200 мс. */
@media (max-width:767px){
  html.has-motion .m-objlist>.m-obj{transition:transform var(--t,.2s) var(--ease,cubic-bezier(.2,0,0,1))}
  .m-obj:active{transform:scale(.98)}
}
