/* Brain Motion 1.0 — общая библиотека анимаций экосистемы.
   Подключение: <link rel="stylesheet" href="brain-motion.css"> + <script src="brain-motion.js" defer></script>
   Использование: <div data-bm="fade-up">…</div>, группа: <ul data-bm-stagger="60"> <li data-bm="pop">…
   Всё уважает prefers-reduced-motion. */

:root {
  /* Длительности */
  --bm-instant: 90ms;
  --bm-fast: 160ms;
  --bm-base: 260ms;
  --bm-slow: 420ms;
  --bm-slower: 680ms;
  --bm-epic: 1100ms;
  /* Кривые */
  --bm-ease: cubic-bezier(.2, .0, .0, 1);          /* стандарт (Material 3 emphasized) */
  --bm-ease-out: cubic-bezier(.16, 1, .3, 1);      /* expo out — появление */
  --bm-ease-in: cubic-bezier(.7, 0, .84, 0);       /* уход */
  --bm-ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --bm-back: cubic-bezier(.34, 1.56, .64, 1);      /* с перелётом */
  --bm-spring: linear(0, .009, .035 2.1%, .141, .281 6.7%, .723 12.9%, .938 16.7%, 1.017, 1.077, 1.121 24.1%, 1.149 26.6%, 1.159, 1.163 30.4%, 1.154, 1.129 36.2%, 1.051 42.7%, 1.017 46.4%, .991 50.6%, .977 55.3%, .975 58.6%, .981 64.6%, .997 76.5%, 1.003 87.9%, 1);
  --bm-bounce: linear(0, .004, .016, .035, .063, .098, .141 13.6%, .25, .391, .563, .765, 1, .891 40.9%, .848, .813, .785, .766, .754, .75, .754, .766, .785, .813, .848, .891 68.2%, 1 72.7%, .973, .953, .941, .938, .941, .953, .973, 1, .988, .984, .988, 1);
  /* Дистанции */
  --bm-shift: 18px;
  --bm-shift-lg: 48px;
}

/* ---------- Ключевые кадры ---------- */
@keyframes bm-fade { from { opacity: 0 } }
@keyframes bm-fade-up { from { opacity: 0; transform: translateY(var(--bm-shift)) } }
@keyframes bm-fade-down { from { opacity: 0; transform: translateY(calc(var(--bm-shift) * -1)) } }
@keyframes bm-fade-left { from { opacity: 0; transform: translateX(var(--bm-shift-lg)) } }
@keyframes bm-fade-right { from { opacity: 0; transform: translateX(calc(var(--bm-shift-lg) * -1)) } }
@keyframes bm-zoom { from { opacity: 0; transform: scale(.92) } }
@keyframes bm-zoom-out { from { opacity: 0; transform: scale(1.08) } }
@keyframes bm-pop { 0% { opacity: 0; transform: scale(.6) } 60% { opacity: 1; transform: scale(1.06) } 100% { transform: scale(1) } }
@keyframes bm-blur { from { opacity: 0; filter: blur(14px); transform: scale(1.03) } }
@keyframes bm-flip { from { opacity: 0; transform: perspective(900px) rotateX(-70deg); transform-origin: top } }
@keyframes bm-flip-y { from { opacity: 0; transform: perspective(900px) rotateY(80deg) } }
@keyframes bm-rise { from { opacity: 0; transform: translateY(110%) } }
@keyframes bm-clip-up { from { clip-path: inset(100% 0 0 0) } to { clip-path: inset(0 0 0 0) } }
@keyframes bm-clip-left { from { clip-path: inset(0 100% 0 0) } to { clip-path: inset(0 0 0 0) } }
@keyframes bm-clip-circle { from { clip-path: circle(0% at 50% 50%) } to { clip-path: circle(75% at 50% 50%) } }
@keyframes bm-swing { 20% { transform: rotate(12deg) } 40% { transform: rotate(-8deg) } 60% { transform: rotate(4deg) } 80% { transform: rotate(-2deg) } 100% { transform: rotate(0) } }
@keyframes bm-shake { 10%, 90% { transform: translateX(-1px) } 20%, 80% { transform: translateX(3px) } 30%, 50%, 70% { transform: translateX(-6px) } 40%, 60% { transform: translateX(6px) } }
@keyframes bm-wobble { 15% { transform: translateX(-12%) rotate(-5deg) } 30% { transform: translateX(9%) rotate(3deg) } 45% { transform: translateX(-6%) rotate(-3deg) } 60% { transform: translateX(4%) rotate(2deg) } 75% { transform: translateX(-2%) rotate(-1deg) } 100% { transform: none } }
@keyframes bm-jelly { 30% { transform: scale(1.25, .75) } 40% { transform: scale(.75, 1.25) } 50% { transform: scale(1.15, .85) } 65% { transform: scale(.95, 1.05) } 75% { transform: scale(1.05, .95) } 100% { transform: scale(1) } }
@keyframes bm-heartbeat { 0%, 28%, 70% { transform: scale(1) } 14%, 42% { transform: scale(1.18) } }
@keyframes bm-pulse { 50% { opacity: .55 } }
@keyframes bm-ping { 75%, 100% { transform: scale(2.2); opacity: 0 } }
@keyframes bm-spin { to { transform: rotate(360deg) } }
@keyframes bm-float { 50% { transform: translateY(-10px) } }
@keyframes bm-breathe { 50% { transform: scale(1.04) } }
@keyframes bm-bounce-y { 0%, 100% { transform: translateY(-22%); animation-timing-function: cubic-bezier(.8, 0, 1, 1) } 50% { transform: none; animation-timing-function: cubic-bezier(0, 0, .2, 1) } }
@keyframes bm-shimmer { from { background-position: 150% 0 } to { background-position: -50% 0 } }
@keyframes bm-gradient { 0%, 100% { background-position: 0% 50% } 50% { background-position: 100% 50% } }
@keyframes bm-marquee { to { transform: translateX(-50%) } }
@keyframes bm-blink { 50% { opacity: 0 } }
@keyframes bm-draw { to { stroke-dashoffset: 0 } }
@keyframes bm-ripple { to { transform: scale(4); opacity: 0 } }
@keyframes bm-dots { 0%, 80%, 100% { transform: scale(0); opacity: .3 } 40% { transform: scale(1); opacity: 1 } }
@keyframes bm-bar { 0% { left: -40%; right: 100% } 60% { left: 100%; right: -90% } 100% { left: 100%; right: -90% } }
@keyframes bm-aurora { 0% { transform: translate(0, 0) rotate(0) scale(1) } 33% { transform: translate(8%, -6%) rotate(60deg) scale(1.15) } 66% { transform: translate(-6%, 6%) rotate(140deg) scale(.95) } 100% { transform: translate(0, 0) rotate(360deg) scale(1) } }
@keyframes bm-glow { 50% { box-shadow: 0 0 0 6px color-mix(in oklab, var(--bm-glow, #7c5cff) 25%, transparent), 0 0 32px color-mix(in oklab, var(--bm-glow, #7c5cff) 45%, transparent) } }
@keyframes bm-toast-in { from { opacity: 0; transform: translateY(16px) scale(.96) } }
@keyframes bm-toast-out { to { opacity: 0; transform: translateY(8px) scale(.96) } }

/* ---------- Появление (data-bm) ---------- */
[data-bm] {
  --bm-d: var(--bm-slow);
  --bm-delay: 0ms;
  --bm-curve: var(--bm-ease-out);
}
/* Пока JS не пометил элемент видимым — скрыт. Без JS (класс bm-js не поставлен) всё видно. */
.bm-js [data-bm]:not(.bm-in):not([data-bm-loop]) { opacity: 0 }
.bm-in[data-bm], [data-bm][data-bm-now] {
  animation: var(--bm-name, bm-fade-up) var(--bm-d) var(--bm-curve) var(--bm-delay) both;
}
[data-bm="fade"] { --bm-name: bm-fade }
[data-bm="fade-up"] { --bm-name: bm-fade-up }
[data-bm="fade-down"] { --bm-name: bm-fade-down }
[data-bm="fade-left"] { --bm-name: bm-fade-left }
[data-bm="fade-right"] { --bm-name: bm-fade-right }
[data-bm="zoom"] { --bm-name: bm-zoom }
[data-bm="zoom-out"] { --bm-name: bm-zoom-out }
[data-bm="pop"] { --bm-name: bm-pop; --bm-curve: var(--bm-ease) }
[data-bm="blur"] { --bm-name: bm-blur; --bm-d: var(--bm-slower) }
[data-bm="flip"] { --bm-name: bm-flip; --bm-d: var(--bm-slower) }
[data-bm="flip-y"] { --bm-name: bm-flip-y; --bm-d: var(--bm-slower) }
[data-bm="clip-up"] { --bm-name: bm-clip-up; --bm-d: var(--bm-slower); --bm-curve: var(--bm-ease-in-out) }
[data-bm="clip-left"] { --bm-name: bm-clip-left; --bm-d: var(--bm-slower); --bm-curve: var(--bm-ease-in-out) }
[data-bm="clip-circle"] { --bm-name: bm-clip-circle; --bm-d: var(--bm-epic); --bm-curve: var(--bm-ease-in-out) }
[data-bm="spring"] { --bm-name: bm-zoom; --bm-d: 900ms; --bm-curve: var(--bm-spring) }
[data-bm="drop"] { --bm-name: bm-fade-down; --bm-shift: 60px; --bm-d: 900ms; --bm-curve: var(--bm-bounce) }

/* Разбитый на слова/буквы текст (BM.split) */
.bm-word, .bm-char { display: inline-block; white-space: pre }
.bm-mask { display: inline-block; overflow: hidden; vertical-align: bottom; padding-bottom: .08em }
.bm-js .bm-split:not(.bm-in) .bm-piece { opacity: 0 }
.bm-split.bm-in .bm-piece {
  animation: var(--bm-name, bm-rise) var(--bm-slower) var(--bm-ease-out) calc(var(--bm-i) * var(--bm-step, 35ms) + var(--bm-delay, 0ms)) both;
}

/* ---------- Постоянные эффекты (классы) ---------- */
.bm-spin { animation: bm-spin 1s linear infinite }
.bm-float { animation: bm-float 3.2s var(--bm-ease-in-out) infinite }
.bm-breathe { animation: bm-breathe 3s var(--bm-ease-in-out) infinite }
.bm-pulse { animation: bm-pulse 1.8s var(--bm-ease-in-out) infinite }
.bm-heartbeat { animation: bm-heartbeat 1.4s ease-in-out infinite }
.bm-bounce { animation: bm-bounce-y 1s infinite }
.bm-glow { animation: bm-glow 2.4s var(--bm-ease-in-out) infinite; border-radius: inherit }
.bm-blink { animation: bm-blink 1s steps(1) infinite }
/* Разовые «внимание»: BM.play(el, 'shake') */
.bm-shake { animation: bm-shake .5s var(--bm-ease) both }
.bm-swing { animation: bm-swing .8s var(--bm-ease) both; transform-origin: top center }
.bm-wobble { animation: bm-wobble .8s var(--bm-ease) both }
.bm-jelly { animation: bm-jelly .8s both }
.bm-tada { animation: bm-pop .6s var(--bm-back) both }

/* Точка-«пинг» (уведомление, онлайн) */
.bm-ping { position: relative; display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: var(--bm-ping, #22c55e) }
.bm-ping::after { content: ""; position: absolute; inset: 0; border-radius: inherit; background: inherit; animation: bm-ping 1.4s cubic-bezier(0, 0, .2, 1) infinite }

/* ---------- Загрузка ---------- */
.bm-spinner { width: 28px; height: 28px; border-radius: 50%; border: 3px solid color-mix(in oklab, currentColor 18%, transparent); border-top-color: currentColor; animation: bm-spin .8s linear infinite }
.bm-dots { display: inline-flex; gap: 6px }
.bm-dots > i { width: 8px; height: 8px; border-radius: 50%; background: currentColor; animation: bm-dots 1.2s infinite var(--bm-ease-in-out) }
.bm-dots > i:nth-child(2) { animation-delay: .16s }
.bm-dots > i:nth-child(3) { animation-delay: .32s }
.bm-progress { position: relative; height: 4px; overflow: hidden; border-radius: 4px; background: color-mix(in oklab, currentColor 14%, transparent) }
.bm-progress::before { content: ""; position: absolute; top: 0; bottom: 0; background: currentColor; border-radius: inherit; animation: bm-bar 1.6s var(--bm-ease-in-out) infinite }
.bm-skeleton {
  border-radius: 10px; color: transparent !important;
  background: linear-gradient(100deg, var(--bm-sk-a, #e8e8ef) 40%, var(--bm-sk-b, #f6f6fa) 50%, var(--bm-sk-a, #e8e8ef) 60%) 0 0 / 200% 100%;
  animation: bm-shimmer 1.4s linear infinite;
}
@media (prefers-color-scheme: dark) { :root { --bm-sk-a: #24242c; --bm-sk-b: #31313b } }

/* ---------- Текст и фон ---------- */
.bm-gradient-text {
  background: linear-gradient(90deg, var(--bm-g1, #7c5cff), var(--bm-g2, #00d4ff), var(--bm-g3, #ff5ca8), var(--bm-g1, #7c5cff)) 0 0 / 300% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: bm-gradient 6s linear infinite;
}
.bm-shine-text {
  background: linear-gradient(110deg, currentColor 40%, #fff 50%, currentColor 60%) 0 0 / 250% 100%;
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
  animation: bm-shimmer 2.8s linear infinite;
}
.bm-caret::after { content: "▍"; margin-left: 2px; animation: bm-blink 1s steps(1) infinite }
.bm-aurora { position: relative; overflow: hidden; isolation: isolate }
.bm-aurora::before, .bm-aurora::after {
  content: ""; position: absolute; z-index: -1; width: 55%; aspect-ratio: 1; border-radius: 50%; filter: blur(80px); opacity: var(--bm-aurora-o, .32);
  animation: bm-aurora 18s linear infinite;
}
.bm-aurora::before { background: var(--bm-g1, #7c5cff); top: -30%; left: -10% }
.bm-aurora::after { background: var(--bm-g2, #00d4ff); bottom: -35%; right: -15%; animation-duration: 24s; animation-direction: reverse }

/* Бегущая строка: <div class="bm-marquee"><div class="bm-marquee-track">…контент дважды…</div></div> (BM.marquee дублирует сам) */
.bm-marquee { overflow: hidden; mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent) }
.bm-marquee-track { display: flex; width: max-content; gap: var(--bm-gap, 48px); animation: bm-marquee var(--bm-speed, 30s) linear infinite }
.bm-marquee:hover .bm-marquee-track { animation-play-state: paused }

/* Рисование SVG-линий: <svg class="bm-draw"> … path/line … */
.bm-draw :is(path, line, polyline, circle, rect, polygon) { stroke-dasharray: var(--bm-len, 1000); stroke-dashoffset: var(--bm-len, 1000) }
.bm-draw.bm-in :is(path, line, polyline, circle, rect, polygon), .bm-draw[data-bm-now] :is(path, line, polyline, circle, rect, polygon) { animation: bm-draw var(--bm-epic) var(--bm-ease-in-out) forwards }

/* ---------- Взаимодействие ---------- */
.bm-press { transition: transform var(--bm-fast) var(--bm-ease), box-shadow var(--bm-base) var(--bm-ease) }
.bm-press:active { transform: scale(.96) }
.bm-lift { transition: transform var(--bm-base) var(--bm-ease-out), box-shadow var(--bm-base) var(--bm-ease-out) }
.bm-lift:hover { transform: translateY(-4px); box-shadow: 0 14px 34px -12px rgb(0 0 0 / .28) }
.bm-grow { transition: transform var(--bm-base) var(--bm-back) }
.bm-grow:hover { transform: scale(1.05) }
.bm-underline { background: linear-gradient(currentColor, currentColor) 0 100% / 0 2px no-repeat; transition: background-size var(--bm-base) var(--bm-ease-out); text-decoration: none }
.bm-underline:hover { background-size: 100% 2px }
.bm-ripple-host { position: relative; overflow: hidden }
.bm-ripple-dot { position: absolute; border-radius: 50%; pointer-events: none; background: currentColor; opacity: .28; transform: scale(0); animation: bm-ripple .6s var(--bm-ease-out) forwards }
.bm-tilt { transition: transform var(--bm-base) var(--bm-ease-out); transform-style: preserve-3d; will-change: transform }
.bm-magnetic { transition: transform var(--bm-slow) var(--bm-ease-out) }
.bm-spotlight { position: relative; isolation: isolate }
.bm-spotlight::before { content: ""; position: absolute; inset: 0; border-radius: inherit; z-index: -1; opacity: 0; transition: opacity var(--bm-base);
  background: radial-gradient(420px circle at var(--bm-x, 50%) var(--bm-y, 50%), color-mix(in oklab, var(--bm-g1, #7c5cff) 22%, transparent), transparent 60%) }
.bm-spotlight:hover::before { opacity: 1 }

/* Плавное раскрытие высоты: <div class="bm-collapse" data-open> <div>контент</div> </div> */
.bm-collapse { display: grid; grid-template-rows: 0fr; transition: grid-template-rows var(--bm-slow) var(--bm-ease) }
.bm-collapse > * { overflow: hidden; min-height: 0 }
.bm-collapse[data-open] { grid-template-rows: 1fr }

/* Тосты (BM.toast) */
.bm-toasts { position: fixed; z-index: 9999; left: 50%; bottom: 24px; translate: -50% 0; display: flex; flex-direction: column; gap: 8px; align-items: center; pointer-events: none }
.bm-toast { pointer-events: auto; padding: 12px 18px; border-radius: 14px; background: #16161c; color: #fff; font: 500 14px/1.3 system-ui, sans-serif; box-shadow: 0 12px 30px -10px rgb(0 0 0 / .5); animation: bm-toast-in var(--bm-slow) var(--bm-spring) both }
.bm-toast.bm-out { animation: bm-toast-out var(--bm-base) var(--bm-ease-in) forwards }

/* Переходы страниц (View Transitions API — BM.transition) */
::view-transition-old(root) { animation: bm-toast-out var(--bm-base) var(--bm-ease-in) both }
::view-transition-new(root) { animation: bm-fade-up var(--bm-slow) var(--bm-ease-out) both }

/* ---------- Доступность ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 1ms !important; animation-iteration-count: 1 !important; transition-duration: 1ms !important; scroll-behavior: auto !important }
  .bm-js [data-bm]:not(.bm-in), .bm-js .bm-split:not(.bm-in) .bm-piece { opacity: 1 }
}
