/* ═══════════════════════════════════════════════════════════════
   НОРМА · движение (07.10.2026): «вылет» и индикаторы ожидания по теме

   Четвёртый лист, подключается ПОСЛЕ tokens → base → v12 и ничего в них
   не правит. Два независимых механизма:

   1. html[data-motion="fly"] — экраны, карточки и реплики вылетают
      каскадом. Атрибут ставит сборка (webpack SKINS: только norm и norma)
      и переключатель «Появление» в настройках (app/motion.ts,
      localStorage norma-motion). БЕЗ атрибута ни одно правило блока не
      действует: finhelp и pravo остаются с прежним плавным входом.

   2. .spn-* — сюжетные индикаторы ожидания (ui/spinners.ts): монета,
      песочные часы, телефон, лупа, щит, весы, сердце, корзина, машина,
      документ, орбита. Рисуются только там, где их вставил клиент
      (индикатор «думает», открытие раздела, настройки).

   Правила слоя:
   · только transform / opacity (+ stroke-dashoffset у индикаторов) —
     ничего, что вызывает перекладку; prefers-reduced-motion глушит всё
     общим правилом базы;
   · кейфреймы входа описывают ТОЛЬКО начальное состояние (from) и идут
     с fill-mode backwards: конечное состояние — собственные стили
     элемента (так .ask.answered остаётся приглушённым, а строка-черновик
     со своей opacity .75 не прыгает в конце);
   · каскад — переменная --fly-d: контейнер получает задержку по своему
     номеру среди соседей, дети её наследуют и прибавляют свой шаг;
   · длительности и кривые — токены norma-tokens.css (--dur-fly*,
     --e-fly, --e-pop), магических миллисекунд здесь нет;
   · пружина нажатия (useTapEffect) идёт через Web Animations, а не
     через свойство animation, — иначе она перебивала бы вход и
     запускала его заново после каждого тапа.
   ═══════════════════════════════════════════════════════════════ */

@keyframes fadeIn{from{opacity:0}}
@keyframes flyScr{from{opacity:0;transform:translate3d(var(--fly-x,0px),var(--fly-y,12px),0)}}
@keyframes flyUp{from{opacity:0;transform:translate3d(0,18px,0)}}
@keyframes flyItem{from{opacity:0;transform:translate3d(-16px,10px,0)}}
@keyframes flyUser{from{opacity:0;transform:translate3d(22px,8px,0) scale(.96)}}
@keyframes flyPop{from{opacity:0;transform:translate3d(0,14px,0) scale(.95)}}
@keyframes flyTile{from{opacity:0;transform:translate3d(-20px,22px,0) scale(.93)}}
@keyframes flyTileR{from{opacity:0;transform:translate3d(20px,22px,0) scale(.93)}}
@keyframes flyChip{from{opacity:0;transform:translate3d(0,8px,0) scale(.9)}}
@keyframes flyDown{from{opacity:0;transform:translate3d(0,-10px,0)}}
@keyframes artSettle{from{opacity:0;transform:scale(1.05)}}
@keyframes sheetUp{from{opacity:0;transform:translate3d(0,44px,0)}}
@keyframes popIn{from{opacity:0;transform:translate3d(0,12px,0) scale(.94)}}

/* ── 1. Экран: въезжает по направлению перехода (data-nav на #view, shellStore.navDir):
   вперёд — справа, назад — слева, корневой — снизу. overflow-x, чтобы сдвиг не давал
   горизонтальной прокрутки в .view (у него overflow-y:auto, и x считался бы auto). ── */
html[data-motion="fly"] .view{overflow-x:hidden}
html[data-motion="fly"] #view[data-nav="push"]{--fly-x:36px;--fly-y:0px}
html[data-motion="fly"] #view[data-nav="back"]{--fly-x:-36px;--fly-y:0px}
html[data-motion="fly"] #view[data-nav="root"]{--fly-x:0px;--fly-y:16px}
html[data-motion="fly"] .screen.on{animation:flyScr var(--dur-fly) var(--e-fly) backwards}

/* ── 2. Каскад блоков экрана. Контейнеры, чьи прямые дети вылетают один за другим:
   сам экран, обёртка главной (.home-hero) и тело разбора (.artp). ── */
html[data-motion="fly"] .screen.on > *,
html[data-motion="fly"] #scr-home .home-hero > *,
html[data-motion="fly"] #scr-art .artp > *{
  --fly-d:0ms;animation:flyUp var(--dur-fly) var(--e-fly) backwards;animation-delay:var(--fly-d)}
html[data-motion="fly"] .screen.on > :nth-child(2),html[data-motion="fly"] #scr-home .home-hero > :nth-child(2),html[data-motion="fly"] #scr-art .artp > :nth-child(2){--fly-d:calc(var(--dur-fly-step) * 1)}
html[data-motion="fly"] .screen.on > :nth-child(3),html[data-motion="fly"] #scr-home .home-hero > :nth-child(3),html[data-motion="fly"] #scr-art .artp > :nth-child(3){--fly-d:calc(var(--dur-fly-step) * 2)}
html[data-motion="fly"] .screen.on > :nth-child(4),html[data-motion="fly"] #scr-home .home-hero > :nth-child(4),html[data-motion="fly"] #scr-art .artp > :nth-child(4){--fly-d:calc(var(--dur-fly-step) * 3)}
html[data-motion="fly"] .screen.on > :nth-child(5),html[data-motion="fly"] #scr-home .home-hero > :nth-child(5),html[data-motion="fly"] #scr-art .artp > :nth-child(5){--fly-d:calc(var(--dur-fly-step) * 4)}
html[data-motion="fly"] .screen.on > :nth-child(6),html[data-motion="fly"] #scr-home .home-hero > :nth-child(6),html[data-motion="fly"] #scr-art .artp > :nth-child(6){--fly-d:calc(var(--dur-fly-step) * 5)}
html[data-motion="fly"] .screen.on > :nth-child(7),html[data-motion="fly"] #scr-home .home-hero > :nth-child(7),html[data-motion="fly"] #scr-art .artp > :nth-child(7){--fly-d:calc(var(--dur-fly-step) * 6)}
html[data-motion="fly"] .screen.on > :nth-child(8),html[data-motion="fly"] #scr-home .home-hero > :nth-child(8),html[data-motion="fly"] #scr-art .artp > :nth-child(8){--fly-d:calc(var(--dur-fly-step) * 7)}
html[data-motion="fly"] .screen.on > :nth-child(9),html[data-motion="fly"] #scr-home .home-hero > :nth-child(9),html[data-motion="fly"] #scr-art .artp > :nth-child(9){--fly-d:calc(var(--dur-fly-step) * 8)}
html[data-motion="fly"] .screen.on > :nth-child(10),html[data-motion="fly"] #scr-home .home-hero > :nth-child(10),html[data-motion="fly"] #scr-art .artp > :nth-child(10){--fly-d:calc(var(--dur-fly-step) * 9)}
html[data-motion="fly"] .screen.on > :nth-child(n+11),html[data-motion="fly"] #scr-home .home-hero > :nth-child(n+11),html[data-motion="fly"] #scr-art .artp > :nth-child(n+11){--fly-d:calc(var(--dur-fly-step) * 10)}
/* обёртки не летят сами — летят их дети; декоративные слои главной (сияние, гравюры) стоят */
html[data-motion="fly"] #scr-home > .home-hero,
html[data-motion="fly"] #scr-art > .artp,
html[data-motion="fly"] #scr-dialog > .thread,
html[data-motion="fly"] #scr-home .home-hero > .aurora,
html[data-motion="fly"] #scr-home .home-hero > .eng,
html[data-motion="fly"] #scr-home .home-hero > .eng-hero{animation:none}
/* арт-плита раздела и каталога: не подъезжает, а проявляется с лёгким отъездом камеры */
html[data-motion="fly"] .screen.on > .plate-gen{animation-name:artSettle;animation-duration:calc(var(--dur-fly) * 1.6)}

/* ── 3. Плитки каталога (главная, «Право»): слетаются к центру с двух сторон, каждая
   со своей задержкой поверх задержки самой сетки; перелёт ~3 % — --e-pop. ── */
html[data-motion="fly"] .cat > .cat-i{animation:flyTile var(--dur-fly-tile) var(--e-pop) backwards;animation-delay:var(--fly-d)}
html[data-motion="fly"] .cat > .cat-i:nth-child(even){animation-name:flyTileR}
html[data-motion="fly"] .cat > .cat-i:nth-child(2){animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 1)}
html[data-motion="fly"] .cat > .cat-i:nth-child(3){animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 2)}
html[data-motion="fly"] .cat > .cat-i:nth-child(4){animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 3)}
html[data-motion="fly"] .cat > .cat-i:nth-child(5){animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 4)}
html[data-motion="fly"] .cat > .cat-i:nth-child(6){animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 5)}
html[data-motion="fly"] .cat > .cat-i:nth-child(7){animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 6)}
html[data-motion="fly"] .cat > .cat-i:nth-child(n+8){animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 7)}

/* ── 4. Лента диалога. Реплики и карточки вылетают по мере появления: ассистент —
   слева, человек — справа, оценка — с перелётом. Каскад — только первые шесть
   записей (открытие сохранённого диалога); дальше каждая новая запись появляется
   сразу, без очереди, — ответ не должен ждать своей задержки. ── */
html[data-motion="fly"] .thread > *,
html[data-motion="fly"] .step > *{
  --fly-d:0ms;animation:flyItem var(--dur-fly) var(--e-fly) backwards;animation-delay:var(--fly-d)}
html[data-motion="fly"] .thread > :nth-child(2),html[data-motion="fly"] .step > :nth-child(2){--fly-d:calc(var(--dur-fly-step) * 1)}
html[data-motion="fly"] .thread > :nth-child(3),html[data-motion="fly"] .step > :nth-child(3){--fly-d:calc(var(--dur-fly-step) * 2)}
html[data-motion="fly"] .thread > :nth-child(4),html[data-motion="fly"] .step > :nth-child(4){--fly-d:calc(var(--dur-fly-step) * 3)}
html[data-motion="fly"] .thread > :nth-child(5),html[data-motion="fly"] .step > :nth-child(5){--fly-d:calc(var(--dur-fly-step) * 4)}
html[data-motion="fly"] .thread > :nth-child(6),html[data-motion="fly"] .step > :nth-child(6){--fly-d:calc(var(--dur-fly-step) * 5)}
html[data-motion="fly"] .thread > :nth-child(n+7),html[data-motion="fly"] .step > :nth-child(n+7){--fly-d:0ms}
html[data-motion="fly"] .thread > .step{animation:none}
html[data-motion="fly"] .thread > .msg-u,html[data-motion="fly"] .step > .msg-u{animation-name:flyUser}
html[data-motion="fly"] .thread > .verdict,html[data-motion="fly"] .step > .verdict{animation:flyPop var(--dur-fly-tile) var(--e-pop) backwards;animation-delay:var(--fly-d)}
/* варианты ответа и подсказки «что дальше» — один за другим вслед за карточкой */
html[data-motion="fly"] .ask .chips > .chip,
html[data-motion="fly"] .chips.followups > .chip{animation:flyChip calc(var(--dur-fly) * .8) var(--e-pop) backwards;animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 3)}
html[data-motion="fly"] .ask .chips > .chip:nth-child(2),html[data-motion="fly"] .chips.followups > .chip:nth-child(2){animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 4)}
html[data-motion="fly"] .ask .chips > .chip:nth-child(3),html[data-motion="fly"] .chips.followups > .chip:nth-child(3){animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 5)}
html[data-motion="fly"] .ask .chips > .chip:nth-child(4),html[data-motion="fly"] .chips.followups > .chip:nth-child(4){animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 6)}
html[data-motion="fly"] .ask .chips > .chip:nth-child(5),html[data-motion="fly"] .chips.followups > .chip:nth-child(5){animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 7)}
html[data-motion="fly"] .ask .chips > .chip:nth-child(n+6),html[data-motion="fly"] .chips.followups > .chip:nth-child(n+6){animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 8)}
/* внутри оценки: строки расчёта и шаги рекомендации проявляются по очереди */
html[data-motion="fly"] .verdict .calc > .calc-r,
html[data-motion="fly"] .verdict .v-steps > li{animation:fadeIn calc(var(--dur-fly) * .7) ease-out backwards;animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 4)}
html[data-motion="fly"] .verdict .calc > .calc-r:nth-child(2),html[data-motion="fly"] .verdict .v-steps > li:nth-child(2){animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 5)}
html[data-motion="fly"] .verdict .calc > .calc-r:nth-child(3),html[data-motion="fly"] .verdict .v-steps > li:nth-child(3){animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 6)}
html[data-motion="fly"] .verdict .calc > .calc-r:nth-child(4),html[data-motion="fly"] .verdict .v-steps > li:nth-child(4){animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 7)}
html[data-motion="fly"] .verdict .calc > .calc-r:nth-child(n+5),html[data-motion="fly"] .verdict .v-steps > li:nth-child(n+5){animation-delay:calc(var(--fly-d) + var(--dur-fly-step) * 8)}
/* открытие раздела: индикатор показывается только если приветствие задержалось */
html[data-motion="fly"] .thread > .opening{animation:fadeIn calc(var(--dur-fly) * .6) ease-out backwards;animation-delay:calc(var(--dur-fly-step) * 7)}

/* ── 5. Панель диалогов: группы выезжают каскадом при каждом открытии
   (правило включается атрибутом data-drawer и потому перезапускается). ── */
html[data-motion="fly"] .app[data-drawer="1"] .dw-list > *{animation:flyItem var(--dur-fly) var(--e-fly) backwards;animation-delay:calc(var(--dur-fly-step) * 2)}
html[data-motion="fly"] .app[data-drawer="1"] .dw-list > :nth-child(2){animation-delay:calc(var(--dur-fly-step) * 4)}
html[data-motion="fly"] .app[data-drawer="1"] .dw-list > :nth-child(3){animation-delay:calc(var(--dur-fly-step) * 6)}
html[data-motion="fly"] .app[data-drawer="1"] .dw-list > :nth-child(n+4){animation-delay:calc(var(--dur-fly-step) * 8)}

/* ── 6. Листы и всплывающее: нижний лист «На чём это основано» выезжает снизу,
   подтверждение удаления — всплывает, плашка связи и установки — съезжают. ── */
html[data-motion="fly"] .sheet:not([hidden]){animation:sheetUp calc(var(--dur-fly) * .9) var(--e-fly) backwards}
html[data-motion="fly"] .sheet-scrim:not([hidden]){animation:fadeIn var(--dur-base) ease-out backwards}
html[data-motion="fly"] .confirm-bg{animation:fadeIn var(--dur-base) ease-out backwards}
html[data-motion="fly"] .confirm{animation:popIn calc(var(--dur-fly) * .7) var(--e-pop) backwards}
html[data-motion="fly"] .net-pill{animation:flyDown var(--dur-fly) var(--e-fly) backwards}
html[data-motion="fly"] .pwa-banner{animation:sheetUp calc(var(--dur-fly) * .9) var(--e-fly) backwards}

/* ── 7. Вступление: кадр проявляется с отъездом камеры, текст — каскадом снизу. ── */
html[data-motion="fly"] .islide.on{animation:fadeIn var(--dur-base) ease-out backwards}
html[data-motion="fly"] .islide.on .intro-art{animation:artSettle calc(var(--dur-fly) * 1.8) var(--e-fly) backwards}
html[data-motion="fly"] .islide.on .intro-body > *,
html[data-motion="fly"] .islide.on .consent,
html[data-motion="fly"] .islide.on .intro-foot{animation:flyUp var(--dur-fly) var(--e-fly) backwards;animation-delay:calc(var(--dur-fly-step) * 2)}
html[data-motion="fly"] .islide.on .intro-body > :nth-child(2){animation-delay:calc(var(--dur-fly-step) * 4)}
html[data-motion="fly"] .islide.on .intro-body > :nth-child(3){animation-delay:calc(var(--dur-fly-step) * 6)}
html[data-motion="fly"] .islide.on .intro-body > :nth-child(n+4){animation-delay:calc(var(--dur-fly-step) * 8)}
html[data-motion="fly"] .islide.on .consent,
html[data-motion="fly"] .islide.on .intro-foot{animation-delay:calc(var(--dur-fly-step) * 10)}

/* ═══ Индикаторы ожидания по теме (ui/spinners.ts) — не зависят от data-motion ═══
   Один цвет (--au — акцент раздела), штрих 1.5, размер 22. Подвижные части —
   группы с transform-origin в единицах viewBox. */
.tsp{display:inline-flex;flex:none;align-items:center}
.spn{display:block;width:22px;height:22px;color:var(--au);fill:none;stroke:currentColor;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round;overflow:visible}
.spn *{transform-box:view-box}
.think .tsp{margin:0 -1px}
/* Открытие раздела: индикатор и подпись на месте будущего приветствия. Задержка
   появления — чтобы не мигать, когда приветствие приходит мгновенно. */
.opening{display:flex;align-items:center;gap:10px;padding:2px 0 8px;font-family:var(--f-ui);
  font-size:0.75rem;color:var(--tx-3);animation:fadeIn var(--dur-base) ease-out backwards;animation-delay:calc(var(--dur-fly-step) * 7)}
.opening .spn{width:24px;height:24px}

/* монета (займы, кредит): переворачивается — на одной стороне ₽, на другой % */
.spn-coin .k-flip{transform-origin:12px 12px;animation:spnFlip calc(var(--dur-spin) * .9) ease-in-out infinite alternate}
.spn-coin .k-front{animation:spnFront calc(var(--dur-spin) * .9) linear infinite alternate}
.spn-coin .k-back{animation:spnBack calc(var(--dur-spin) * .9) linear infinite alternate}
@keyframes spnFlip{from{transform:scaleX(1)}to{transform:scaleX(-1)}}
@keyframes spnFront{0%,44%{opacity:1}50%,100%{opacity:0}}
@keyframes spnBack{0%,50%{opacity:0}56%,100%{opacity:1}}

/* песочные часы (просрочка): песок пересыпается, в конце часы переворачиваются */
.spn-hourglass .k-glass{transform-origin:12px 12px;animation:spnGlass calc(var(--dur-spin) * 2) var(--e) infinite}
.spn-hourglass .k-sand-top{fill:currentColor;stroke:none;transform-origin:12px 8.5px;animation:spnSandTop calc(var(--dur-spin) * 2) linear infinite}
.spn-hourglass .k-sand-bot{fill:currentColor;stroke:none;transform-origin:12px 19.5px;animation:spnSandBot calc(var(--dur-spin) * 2) linear infinite}
.spn-hourglass .k-stream{animation:spnStream calc(var(--dur-spin) * 2) linear infinite}
@keyframes spnGlass{0%,78%{transform:rotate(0)}100%{transform:rotate(180deg)}}
@keyframes spnSandTop{0%{transform:scaleY(1)}74%,100%{transform:scaleY(.08)}}
@keyframes spnSandBot{0%{transform:scaleY(.08)}74%,100%{transform:scaleY(1)}}
@keyframes spnStream{0%{stroke-dashoffset:0;opacity:1}72%{stroke-dashoffset:-14.4;opacity:1}76%,100%{stroke-dashoffset:-14.4;opacity:0}}

/* телефон (коллекторы, взыскание): звонит — трубка дрожит, расходятся волны */
.spn-phone .k-hand{transform-origin:12px 12px;animation:spnRing calc(var(--dur-spin) * 1.25) ease-in-out infinite}
.spn-phone .k-wave{animation:spnWave calc(var(--dur-spin) * 1.25) ease-out infinite}
.spn-phone .k-w2{animation-delay:.12s}
@keyframes spnRing{0%,42%,100%{transform:rotate(0)}5%{transform:rotate(-9deg)}10%{transform:rotate(8deg)}15%{transform:rotate(-8deg)}20%{transform:rotate(7deg)}25%{transform:rotate(-5deg)}30%{transform:rotate(3deg)}35%{transform:rotate(-1deg)}}
@keyframes spnWave{0%,6%{opacity:0}18%{opacity:1}44%,100%{opacity:0}}

/* лупа (отказы и кредитная история): просматривает строки записи */
.spn-search .k-lines{opacity:.45}
.spn-search .k-lens{animation:spnLens calc(var(--dur-spin) * 1.5) ease-in-out infinite}
.spn-search .k-glint{opacity:.7}
@keyframes spnLens{0%{transform:translate(-1.5px,-2px)}25%{transform:translate(2.5px,-1px)}50%{transform:translate(1px,2.5px)}75%{transform:translate(-2px,1.5px)}100%{transform:translate(-1.5px,-2px)}}

/* щит (доп. услуги и страховки): рисуется галочка, расходится контур */
.spn-shield .k-echo{transform-origin:12px 12px;animation:spnEcho calc(var(--dur-spin) * 1.5) ease-out infinite}
.spn-shield .k-check{stroke-dasharray:1;stroke-dashoffset:1;animation:spnCheck calc(var(--dur-spin) * 1.5) ease-in-out infinite}
@keyframes spnCheck{0%,10%{stroke-dashoffset:1;opacity:1}40%,80%{stroke-dashoffset:0;opacity:1}92%,100%{stroke-dashoffset:0;opacity:0}}
@keyframes spnEcho{0%,38%{transform:scale(1);opacity:0}42%{opacity:.55}100%{transform:scale(1.45);opacity:0}}

/* весы (жалобы и защита прав): коромысло качается, чаши остаются отвесными */
.spn-scale .k-beam{transform-origin:12px 4.5px;animation:spnBeam calc(var(--dur-spin) * 1.6) ease-in-out infinite alternate}
.spn-scale .k-pan{animation:spnPan calc(var(--dur-spin) * 1.6) ease-in-out infinite alternate}
.spn-scale .k-pan-l{transform-origin:5px 5px}
.spn-scale .k-pan-r{transform-origin:19px 5px}
@keyframes spnBeam{from{transform:rotate(-7deg)}to{transform:rotate(7deg)}}
@keyframes spnPan{from{transform:rotate(7deg)}to{transform:rotate(-7deg)}}

/* сердце (семья): бьётся, от удара расходится контур */
.spn-heart .k-beat{transform-origin:12px 13.5px;animation:spnBeat calc(var(--dur-spin) * .95) ease-in-out infinite}
.spn-heart .k-echo{transform-origin:12px 13.5px;animation:spnHeartEcho calc(var(--dur-spin) * .95) ease-out infinite}
@keyframes spnBeat{0%,56%,100%{transform:scale(1)}14%{transform:scale(1.1)}28%{transform:scale(1)}42%{transform:scale(1.06)}}
@keyframes spnHeartEcho{0%,14%{transform:scale(1);opacity:0}18%{opacity:.5}70%,100%{transform:scale(1.5);opacity:0}}

/* корзина (права потребителей): едет по дороге, в неё падает покупка */
.spn-cart .k-body{animation:spnBob calc(var(--dur-spin) * .7) ease-in-out infinite}
.spn-cart .k-road{opacity:.6;animation:spnRoadCart calc(var(--dur-spin) * .6) linear infinite}
.spn-cart .k-item{fill:currentColor;stroke:none;animation:spnDrop calc(var(--dur-spin) * 1.4) ease-in infinite}
@keyframes spnBob{0%,100%{transform:translateY(0)}50%{transform:translateY(-.6px)}}
@keyframes spnRoadCart{from{stroke-dashoffset:0}to{stroke-dashoffset:-9.6}}
@keyframes spnDrop{0%,10%{transform:translateY(0);opacity:0}14%{opacity:1}42%{transform:translateY(8px);opacity:1}50%,100%{transform:translateY(8px);opacity:0}}

/* машина (автоюрист): едет — колёса крутятся, разметка бежит назад */
.spn-car .k-body{animation:spnBob calc(var(--dur-spin) * .6) ease-in-out infinite}
.spn-car .k-wheel{animation:spnWheel calc(var(--dur-spin) * .55) linear infinite}
.spn-car .k-wheel-l{transform-origin:8.2px 16.5px}
.spn-car .k-wheel-r{transform-origin:15.8px 16.5px}
.spn-car .k-road{opacity:.6;animation:spnRoadCar calc(var(--dur-spin) * .55) linear infinite}
@keyframes spnWheel{to{transform:rotate(360deg)}}
@keyframes spnRoadCar{from{stroke-dashoffset:0}to{stroke-dashoffset:-12}}

/* документ (трудовое право): строки пишутся одна за другой */
.spn-doc .k-line{stroke-dasharray:1;stroke-dashoffset:1;animation:spnWrite calc(var(--dur-spin) * 1.6) ease-in-out infinite}
.spn-doc .k-l2{animation-delay:.35s}
.spn-doc .k-l3{animation-delay:.7s}
@keyframes spnWrite{0%{stroke-dashoffset:1;opacity:1}30%,70%{stroke-dashoffset:0;opacity:1}82%,100%{stroke-dashoffset:0;opacity:0}}

/* орбита (общий вопрос, неизвестный раздел): два кольца навстречу, ядро дышит */
.spn-orbit .k-r1{transform-origin:12px 12px;animation:spnSpin calc(var(--dur-spin) * 1.1) linear infinite}
.spn-orbit .k-r2{transform-origin:12px 12px;opacity:.7;animation:spnSpin calc(var(--dur-spin) * .75) linear infinite reverse}
.spn-orbit .k-core{fill:currentColor;stroke:none;transform-origin:12px 12px;animation:spnCore calc(var(--dur-spin) * .75) ease-in-out infinite alternate}
@keyframes spnSpin{to{transform:rotate(360deg)}}
@keyframes spnCore{from{transform:scale(.8);opacity:.6}to{transform:scale(1.15);opacity:1}}
