/* ==========================================================================
   ALUMIRROR — анимации сайта (направление D). Подключается после style.css и shop.css.
   Пара к site/assets/js/motion.js. API атрибутов — PLATFORM.md, раздел «Анимации (D)».

   Принципы:
   - состояния «до появления» действуют только под html.js (ставит строка в <head>);
     если motion.js не запустился за 2,5 с — страховка показывает всё;
   - анимируются только opacity / translate / scale / clip-path / filter (без перерасчёта
     раскладки); независимые свойства translate/scale/rotate не мешают transform из style.css;
   - после появления элемент получает .m-done, и правила отсюда к нему больше не применяются —
     переходы наведения из style.css работают как задуманы;
   - уровни: html[data-motion="full|reduced|off"] (токен темы), prefers-reduced-motion;
     длительности умножаются на --motion-speed.
   ========================================================================== */

:root {
  --m-speed: var(--motion-speed, 1);
  --m-ease: cubic-bezier(.16, 1, .3, 1);       /* expo out — появления, мягкая остановка */
  --m-ease-quart: cubic-bezier(.25, 1, .5, 1); /* quart out — отклики на действия */
  --m-ease-io: cubic-bezier(.65, 0, .35, 1);   /* in-out — шторки, блики, слайды */
  --m-shift: 24px;                             /* смещение при появлении */
  --m-dur: calc(1000ms * var(--m-speed));
  --m-dur-fade: calc(900ms * var(--m-speed));
  --m-dur-slow: calc(1400ms * var(--m-speed));
  --m-dur-s: calc(220ms * var(--m-speed));     /* короткие отклики */
}

@media (prefers-reduced-motion: no-preference) {
  html:not([data-motion="off"]):not([data-motion="reduced"]) { scroll-behavior: smooth; }
}
/* Якоря не прячутся под шапкой (высоту шапки ставит motion.js) */
html { scroll-padding-top: calc(var(--header-h, 0px) + 12px); }

/* --------------------------------------------------------------------------
   1. Появление при прокрутке — исходные состояния (только под html.js)
   Цели: [data-reveal]; дети [data-stagger] без своих атрибутов; секции конструктора с явно
   выбранной анимацией [data-anim] — выбор дизайнера главнее: «Подъём», «Проявление» и т. п.
   двигают секцию целиком (внутренние data-reveal показываются сразу), «Шторка» и «Наезд фото»
   забирают фото, «По строкам» — заголовки. Секция с [data-intro] (hero) — всегда своё вступление.
   -------------------------------------------------------------------------- */

html.js :is(
  [data-reveal]:not([data-reveal="curtain"]),
  :is([data-anim="fade-up"], [data-anim="fade"], [data-anim="zoom"], [data-anim="left"], [data-anim="right"], [data-anim="blur"]):not(.cb):not(:has([data-intro])),
  [data-stagger]:not(:has([data-reveal])) > *
):not(.m-in):not(.m-split) {
  opacity: 0;
}

html.js :is([data-reveal="up"], [data-reveal=""], [data-anim="fade-up"]:not(.cb):not(:has([data-intro])), [data-stagger]:not([data-stagger-reveal]):not(:has([data-reveal])) > *, [data-stagger-reveal="up"]:not(:has([data-reveal])) > *):not(.m-in) {
  translate: 0 var(--m-shift);
}
html.js :is([data-reveal="scale"], [data-anim="zoom"]:not(.cb):not(:has([data-intro])), [data-stagger-reveal="scale"]:not(:has([data-reveal])) > *):not(.m-in) {
  scale: .96;
}
html.js :is([data-reveal="left"], [data-anim="left"]:not(.cb):not(:has([data-intro])), [data-stagger-reveal="left"]:not(:has([data-reveal])) > *):not(.m-in) {
  translate: calc(var(--m-shift) * -1) 0;
}
html.js :is([data-reveal="right"], [data-anim="right"]:not(.cb):not(:has([data-intro])), [data-stagger-reveal="right"]:not(:has([data-reveal])) > *):not(.m-in) {
  translate: var(--m-shift) 0;
}
html.js :is([data-reveal="blur"], [data-anim="blur"]:not(.cb):not(:has([data-intro]))):not(.m-in) {
  filter: blur(12px);
  scale: 1.02;
}
/* Секция с явной общей анимацией (или «Без анимации»): внутренние появления не двигаются */
html.js :is([data-anim="none"], :is([data-anim="fade-up"], [data-anim="fade"], [data-anim="zoom"], [data-anim="left"], [data-anim="right"], [data-anim="blur"]):not(:has([data-intro]))):not(.cb) :is([data-reveal], [data-stagger]:not(:has([data-reveal])) > *, .m-line__in, .m-word__in) {
  opacity: 1 !important; translate: none !important; scale: none !important; clip-path: none !important; filter: none !important;
}

/* Шторка: фото открывается снизу вверх, а снимок внутри медленно «садится» на место.
   В секции-пресете цели — [data-media], а если их нет — сами фото. */
html.js :is(
  [data-reveal="curtain"],
  [data-anim="curtain"]:has([data-media]) [data-media],
  [data-anim="curtain"]:not(:has([data-media])) :is(picture, video, img:not(picture img))
):not(.m-in) {
  clip-path: inset(100% 0 0 0);
}
html.js :is([data-reveal="curtain"], [data-anim="curtain"] [data-media]):not(.m-in) :is(img, video) {
  scale: 1.16;
}

/* Наезд фото: кадр проявляется, снимок уменьшается 1.12 → 1 (контейнер обрезает края) */
html.js :is([data-reveal="zoom-out"], [data-anim="zoom-out"] [data-media]):not(.m-done) { overflow: hidden; }
html.js :is(
  [data-reveal="zoom-out"],
  [data-anim="zoom-out"]:has([data-media]) [data-media],
  [data-anim="zoom-out"]:not(:has([data-media])) :is(picture, video, img:not(picture img))
):not(.m-in) {
  opacity: 0;
}
html.js :is([data-reveal="zoom-out"], [data-anim="zoom-out"]:has([data-media]) [data-media]):not(.m-in) :is(img, video),
html.js :is(img, video):is([data-reveal="zoom-out"], [data-anim="zoom-out"]:not(:has([data-media])) :is(picture img, video, img)):not(.m-in) {
  scale: 1.12;
}

/* Заголовки по строкам / словам: до разбиения элемент прозрачен, после — прячутся строки */
html.js :is([data-reveal="lines"], [data-reveal="words"], [data-anim="lines"] :is(h1, h2, h3, [data-split])):not(.m-split):not(.m-in) {
  opacity: 0;
}

/* --------------------------------------------------------------------------
   2. Появление — переход в видимое состояние (.m-in), затем .m-done снимает правила
   Задержку ставит motion.js в --m-delay (очередь, data-reveal-delay, «Задержка» блока).
   -------------------------------------------------------------------------- */

html.js .m-in:not(.m-done):not(.cb) {
  transition:
    opacity var(--m-dur-fade) cubic-bezier(.33, 1, .68, 1) var(--m-delay, 0ms),
    translate var(--m-dur) var(--m-ease) var(--m-delay, 0ms),
    scale var(--m-dur) var(--m-ease) var(--m-delay, 0ms),
    filter var(--m-dur) var(--m-ease) var(--m-delay, 0ms),
    clip-path var(--m-dur-slow) var(--m-ease-io) var(--m-delay, 0ms);
}
/* clip-path переходит только между одинаковыми функциями: на время появления — явный inset(0) */
html.js .m-in:not(.m-done):is([data-reveal="curtain"], [data-anim="curtain"] :is([data-media], picture, video, img)) {
  clip-path: inset(0 0 0 0);
}
html.js .m-in:not(.m-done):is([data-reveal="curtain"], [data-reveal="zoom-out"], [data-media]) :is(img, video) {
  transition: scale calc(1800ms * var(--m-speed)) var(--m-ease) var(--m-delay, 0ms);
}
html.js :is(img, video).m-in:not(.m-done):is([data-reveal="zoom-out"], [data-m-kind="zoom-out"]) {
  transition: opacity var(--m-dur-fade) ease var(--m-delay, 0ms), scale calc(1800ms * var(--m-speed)) var(--m-ease) var(--m-delay, 0ms);
}
/* Мгновенно (элемент уже выше экрана — возврат назад, переход по якорю, поздний запуск) */
html.js .m-instant, html.js .m-instant :is(.m-line__in, .m-word__in, img, video) { transition: none !important; }

/* Строки и слова (motion.js оборачивает: .m-line > .m-line__in, .m-word > .m-word__in) */
.m-line {
  display: block;
  overflow: hidden;
  /* запас под выносные элементы и Й/Ё, чтобы маска их не срезала */
  padding: .08em 0 .14em;
  margin: -.08em 0 -.14em;
}
.m-line__in { display: block; }
.m-word { display: inline-block; vertical-align: top; overflow: hidden; padding: .08em 0 .14em; margin: -.08em 0 -.14em; }
.m-word__in { display: inline-block; }
html.js .m-split:not(.m-in) :is(.m-line__in, .m-word__in) { translate: 0 108%; opacity: 0; }
html.js .m-split.m-in:not(.m-done) .m-line__in {
  transition:
    translate calc(1100ms * var(--m-speed)) var(--m-ease) calc(var(--m-delay, 0ms) + var(--m-li, 0) * 95ms * var(--m-speed)),
    opacity calc(700ms * var(--m-speed)) ease calc(var(--m-delay, 0ms) + var(--m-li, 0) * 95ms * var(--m-speed));
}
html.js .m-split.m-in:not(.m-done) .m-word__in {
  transition:
    translate calc(900ms * var(--m-speed)) var(--m-ease) calc(var(--m-delay, 0ms) + var(--m-li, 0) * 42ms * var(--m-speed)),
    opacity calc(600ms * var(--m-speed)) ease calc(var(--m-delay, 0ms) + var(--m-li, 0) * 42ms * var(--m-speed));
}

/* --------------------------------------------------------------------------
   3. Вступление на hero ([data-intro]) — последовательность ставит motion.js
   Явные метки: data-intro-line, data-intro-title, data-intro-item, data-intro-media;
   без меток находятся сами: линия .eyebrow__line, заголовок h1, .eyebrow, абзацы, кнопки,
   фото в .hero__media / .hero__bg / .hero__image.
   -------------------------------------------------------------------------- */

html.js [data-intro] :is([data-intro-line], .eyebrow__line, .hero__line) { transform-origin: 0 50%; }
html.js [data-intro]:not(.m-intro) :is([data-intro-line], .eyebrow__line, .hero__line) { scale: 0 1; }
html.js [data-intro]:not(.m-intro) :is([data-intro-item], .eyebrow, .hero__eyebrow, p, .btn, .lead, .hero__actions > *, .hero__tagline):not([data-intro-title]):not(h1):not([data-reveal]) {
  opacity: 0;
  translate: 0 16px;
}
html.js [data-intro]:not(.m-intro) :is([data-intro-title], h1):not(.m-split):not([data-reveal]) { opacity: 0; }
html.js [data-intro] :is([data-intro-media], .hero__media, .hero__bg, .hero__image) :is(img, video),
html.js [data-intro] :is(img, video)[data-intro-media] { scale: 1.08; }
html.js [data-intro].m-intro :is([data-intro-media], .hero__media, .hero__bg, .hero__image) :is(img, video),
html.js [data-intro].m-intro :is(img, video)[data-intro-media] {
  scale: 1;
  transition: scale calc(2600ms * var(--m-speed)) cubic-bezier(.22, 1, .36, 1);
}
/* фото hero, у которого ещё и параллакс: наезд идёт поверх запаса увеличения */
html.js [data-intro] :is(img, video)[data-intro-media][data-parallax] { scale: calc(var(--m-pscale, 1.1) * 1.08); }
html.js [data-intro].m-intro :is(img, video)[data-intro-media][data-parallax] { scale: var(--m-pscale, 1.1); }
html.js [data-intro].m-intro :is([data-intro-line], .eyebrow__line, .hero__line) {
  scale: 1 1;
  transition: scale calc(900ms * var(--m-speed)) var(--m-ease-io) var(--m-line-delay, 150ms);
}
/* Мягкий свет, однажды проходящий по фото hero (data-intro="light") */
.m-intro-light { position: absolute; inset: 0; z-index: 1; pointer-events: none; overflow: hidden; }
.m-intro-light::before {
  content: ""; position: absolute; top: -30%; bottom: -30%; left: -60%; width: 45%;
  background: linear-gradient(100deg, rgba(255, 246, 228, 0) 0%, rgba(255, 246, 228, .16) 42%, rgba(255, 246, 228, .3) 50%, rgba(255, 246, 228, .16) 58%, rgba(255, 246, 228, 0) 100%);
  rotate: 8deg; opacity: 0;
}
[data-intro].m-intro .m-intro-light::before { animation: m-sweep calc(2800ms * var(--m-speed)) var(--m-ease-io) calc(900ms * var(--m-speed)) both; }
/* Шапка спускается при первом визите (motion.js ставит .m-header-intro один раз за сеанс) */
html.js [data-header].m-header-intro { animation: m-header-in calc(1000ms * var(--m-speed)) var(--m-ease) calc(100ms * var(--m-speed)) both; }
@keyframes m-header-in { from { opacity: 0; translate: 0 -12px; } }

/* --------------------------------------------------------------------------
   4. Шапка [data-header]: .is-top / .is-scrolled / .is-hidden / .is-up (вид плашки — style.css)
   -------------------------------------------------------------------------- */

[data-header] {
  transition:
    translate calc(520ms * var(--m-speed)) var(--m-ease),
    background-color calc(380ms * var(--m-speed)) ease,
    box-shadow calc(380ms * var(--m-speed)) ease,
    backdrop-filter calc(380ms * var(--m-speed)) ease,
    color calc(380ms * var(--m-speed)) ease,
    border-color calc(380ms * var(--m-speed)) ease;
  view-transition-name: site-header;
}
[data-header].is-hidden { translate: 0 -100%; }

/* --------------------------------------------------------------------------
   5. Параллакс, счётчики, тени листвы, бегущая строка
   -------------------------------------------------------------------------- */

[data-parallax] { translate: 0 var(--m-py, 0px); }
/* Фото с параллаксом (или обёртка, где фото — прямой потомок) слегка увеличено с первого кадра,
   чтобы при сдвиге не открывались края; сдвиг motion.js ограничивает этим запасом */
:is(img, video, picture, [data-parallax-media])[data-parallax],
[data-parallax]:has(> img, > picture, > video) { scale: var(--m-pscale, 1.1); }
[data-parallax].m-p-active { will-change: translate; }

[data-count] { font-variant-numeric: tabular-nums; }

[data-sway] {
  transform-origin: 32% 0%;
  animation:
    m-sway var(--m-sway-dur, 11s) ease-in-out var(--m-sway-delay, 0s) infinite alternate,
    m-breathe calc(var(--m-sway-dur, 11s) * 1.37) ease-in-out var(--m-sway-delay, 0s) infinite alternate;
}
[data-sway].m-paused { animation-play-state: paused; }
@keyframes m-sway {
  0%   { rotate: calc(var(--m-sway-k, 1) * -1.1deg); translate: 0 0; }
  35%  { rotate: calc(var(--m-sway-k, 1) * .6deg);   translate: calc(var(--m-sway-k, 1) * 5px) calc(var(--m-sway-k, 1) * -2px); }
  70%  { rotate: calc(var(--m-sway-k, 1) * -.4deg);  translate: calc(var(--m-sway-k, 1) * -3px) calc(var(--m-sway-k, 1) * 3px); }
  100% { rotate: calc(var(--m-sway-k, 1) * 1deg);    translate: calc(var(--m-sway-k, 1) * 7px) calc(var(--m-sway-k, 1) * 1px); }
}
@keyframes m-breathe { from { opacity: var(--m-sway-o1, .8); } to { opacity: 1; } }

[data-marquee] { overflow: hidden; }
.m-marquee__track { display: flex; width: max-content; gap: var(--m-marquee-gap, 48px); padding-right: var(--m-marquee-gap, 48px); }
.m-marquee__track > * { flex: none; }
[data-marquee].m-marquee-on .m-marquee__track { animation: m-marquee var(--m-marquee-dur, 40s) linear infinite; }
[data-marquee][data-marquee-dir="right"].m-marquee-on .m-marquee__track { animation-direction: reverse; }
[data-marquee].m-marquee-on:is(:hover, :focus-within) .m-marquee__track,
[data-marquee].m-paused .m-marquee__track { animation-play-state: paused; }
html:is([data-motion="reduced"], [data-motion="off"]) [data-marquee] { overflow-x: auto; }
@keyframes m-marquee { to { translate: -50% 0; } }

/* --------------------------------------------------------------------------
   6. Блик «зеркала» [data-shine], наклон [data-tilt], магнитная кнопка [data-magnetic]
   motion.js добавляет внутрь <span class="m-shine">: полоса света проходит при наведении
   (на сенсорных экранах — один раз при появлении), за курсором — мягкий отсвет.
   -------------------------------------------------------------------------- */

:where([data-shine]) { position: relative; overflow: hidden; isolation: isolate; }
.m-shine { position: absolute; inset: 0; z-index: 2; pointer-events: none; overflow: hidden; border-radius: inherit; }
.m-shine::before {
  content: ""; position: absolute; top: -25%; bottom: -25%; left: -55%; width: 42%;
  background: linear-gradient(100deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, .1) 38%, rgba(255, 255, 255, .3) 50%, rgba(255, 255, 255, .1) 62%, rgba(255, 255, 255, 0) 100%);
  rotate: 12deg; opacity: 0;
}
.m-shine-run > .m-shine::before { animation: m-sweep calc(1300ms * var(--m-speed)) var(--m-ease-io) both; }
@keyframes m-sweep {
  0%   { translate: 0 0; opacity: 0; }
  18%  { opacity: 1; }
  100% { translate: 360% 0; opacity: 0; }
}
.m-shine::after {
  content: ""; position: absolute; inset: 0; opacity: 0;
  background: radial-gradient(circle at var(--m-gx, 50%) var(--m-gy, 35%), rgba(255, 255, 255, .24), rgba(255, 255, 255, 0) 46%);
  mix-blend-mode: soft-light;
  transition: opacity calc(450ms * var(--m-speed)) ease;
}
@media (hover: hover) and (pointer: fine) {
  [data-shine]:hover > .m-shine::after { opacity: 1; }
}

[data-tilt].m-tilting { transform: perspective(1100px) rotateX(var(--m-rx, 0deg)) rotateY(var(--m-ry, 0deg)); }

[data-magnetic].m-mag { translate: var(--m-mx, 0px) var(--m-my, 0px); transition: translate calc(380ms * var(--m-speed)) var(--m-ease-quart); }
[data-magnetic].m-mag > * { translate: calc(var(--m-mx, 0px) * .35) calc(var(--m-my, 0px) * .35); transition: translate calc(380ms * var(--m-speed)) var(--m-ease-quart); }
[data-magnetic].m-mag-release, [data-magnetic].m-mag-release > * { transition-duration: calc(700ms * var(--m-speed)); }

/* --------------------------------------------------------------------------
   7. Микровзаимодействия общих классов style.css (только переходы; цвета — из style.css)
   -------------------------------------------------------------------------- */

.btn {
  transition:
    background-color var(--m-dur-s) ease, color var(--m-dur-s) ease, border-color var(--m-dur-s) ease,
    background-size calc(560ms * var(--m-speed)) var(--m-ease), box-shadow var(--m-dur-s) ease,
    scale calc(160ms * var(--m-speed)) var(--m-ease-quart);
  /* заливка «волной» слева: у тёмной кнопки — --brand-2, у светлой — --surface-2 */
  background-image: linear-gradient(var(--m-btn-fill, var(--brand-2, #163d35)), var(--m-btn-fill, var(--brand-2, #163d35)));
  background-repeat: no-repeat;
  background-position: 0 0;
  background-size: 0% 100%;
}
.btn--light { --m-btn-fill: var(--surface-2, #e6d6c3); }
.btn :is(svg, [class*="icon"], [class*="arrow"], [data-arrow]) { transition: translate calc(420ms * var(--m-speed)) var(--m-ease); }
@media (hover: hover) {
  .btn:hover { background-size: 100% 100%; }
  .btn:hover :is(svg, [class*="icon"], [class*="arrow"], [data-arrow]) { translate: 4px 0; }
}
.btn:active { scale: .98; }

.link-arrow {
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-origin: border-box;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size calc(620ms * var(--m-speed)) var(--m-ease), color var(--m-dur-s) ease, border-color var(--m-dur-s) ease;
}
.link-arrow :is(svg, [class*="icon"], [class*="arrow"], [data-arrow]) { transition: translate calc(420ms * var(--m-speed)) var(--m-ease); }
@media (hover: hover) {
  .link-arrow:hover { background-size: 100% 1px; }
  .link-arrow:hover :is(svg, [class*="icon"], [class*="arrow"], [data-arrow]) { translate: 2px -2px; }
}

:is(.input, .textarea, .field input, .field textarea, .field select) {
  transition: border-color var(--m-dur-s) ease, background-color var(--m-dur-s) ease, box-shadow calc(320ms * var(--m-speed)) var(--m-ease-quart);
}
.field__label { transition: color var(--m-dur-s) ease; }

.chip { transition: background-color var(--m-dur-s) ease, color var(--m-dur-s) ease, border-color var(--m-dur-s) ease, scale calc(160ms * var(--m-speed)) var(--m-ease-quart); }
.chip:active { scale: .97; }

.icon-btn { transition: color var(--m-dur-s) ease, background-color var(--m-dur-s) ease, opacity var(--m-dur-s) ease; }
.icon-btn :is(svg, img) { transition: translate calc(300ms * var(--m-speed)) var(--m-ease-quart), scale calc(300ms * var(--m-speed)) var(--m-ease-quart); }
@media (hover: hover) {
  .icon-btn:hover :is(svg, img) { translate: 0 -1px; scale: 1.06; }
}
.icon-btn:active :is(svg, img) { scale: .94; }

/* Счётчики в шапке «подпрыгивают» при изменении (motion.js следит за их текстом) */
.m-bump { animation: m-bump calc(520ms * var(--m-speed)) var(--m-ease-quart); }
@keyframes m-bump {
  0% { scale: 1; }
  30% { scale: 1.32; }
  60% { scale: .94; }
  100% { scale: 1; }
}

/* --------------------------------------------------------------------------
   8. Окна, выпадающие панели, мобильное меню — появление при показе
   Окно: [data-modal] в состоянии [open] / .is-open / [aria-hidden="false"]; панель внутри —
   [data-modal-panel] или .modal__panel / .modal__dialog / .modal__box.
   Панели: [data-motion-pop] (выпадающий каталог, подсказки) и [data-motion-menu] (мобильное
   меню) показываются снятием hidden / display:none или классом .is-open; пункты по очереди —
   [data-motion-item] (номер --m-i ставит motion.js).
   -------------------------------------------------------------------------- */

[data-modal]:is([open], .is-open, .open, .is-active, [aria-hidden="false"], [data-state="open"]) {
  animation: m-fade calc(360ms * var(--m-speed)) ease;
}
[data-modal]:is([open], .is-open, .open, .is-active, [aria-hidden="false"], [data-state="open"]) :is([data-modal-panel], .modal__panel, .modal__dialog, .modal__box) {
  animation: m-rise calc(620ms * var(--m-speed)) var(--m-ease);
}
dialog[data-modal]::backdrop { transition: background-color calc(360ms * var(--m-speed)) ease, backdrop-filter calc(360ms * var(--m-speed)) ease; }
@starting-style { dialog[data-modal][open]::backdrop { background-color: transparent; backdrop-filter: none; } }
[data-modal].is-closing { animation: m-fade-out calc(260ms * var(--m-speed)) ease forwards; }
[data-modal].is-closing :is([data-modal-panel], .modal__panel, .modal__dialog, .modal__box) { animation: m-sink calc(260ms * var(--m-speed)) ease forwards; }

[data-motion-pop]:is(.is-open, [open], :not([hidden]):not(.is-closed)) {
  animation: m-pop calc(420ms * var(--m-speed)) var(--m-ease);
}
[data-motion-menu]:is(.is-open, [open], :not([hidden]):not(.is-closed)) {
  animation: m-menu calc(560ms * var(--m-speed)) var(--m-ease);
}
:is([data-motion-pop], [data-motion-menu]):is(.is-open, [open], :not([hidden]):not(.is-closed)) [data-motion-item] {
  animation: m-item calc(640ms * var(--m-speed)) var(--m-ease) both;
  animation-delay: calc((90ms + var(--m-i, 0) * 45ms) * var(--m-speed));
}

@keyframes m-fade { from { opacity: 0; } }
@keyframes m-fade-out { to { opacity: 0; } }
@keyframes m-rise { from { opacity: 0; translate: 0 18px; scale: .985; } }
@keyframes m-sink { to { opacity: 0; translate: 0 10px; } }
@keyframes m-pop { from { opacity: 0; translate: 0 -6px; clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes m-menu { from { opacity: 0; translate: 0 -10px; } }
@keyframes m-item { from { opacity: 0; translate: 0 12px; } }

/* --------------------------------------------------------------------------
   9. Слайдеры [data-slider]: переходы между кадрами (логика — app.js или almMotion.slide)
   Режим «fade»: <div data-slider="fade"><div data-slider-track><img data-slide class="is-active">…
   -------------------------------------------------------------------------- */

[data-slider="fade"] [data-slider-track] { display: grid; }
[data-slider="fade"] [data-slider-track] > [data-slide] { grid-area: 1 / 1; }
[data-slider] [data-slide] {
  transition:
    opacity calc(760ms * var(--m-speed)) var(--m-ease-io),
    scale calc(1400ms * var(--m-speed)) var(--m-ease),
    translate calc(900ms * var(--m-speed)) var(--m-ease);
}
[data-slider="fade"] [data-slide]:not(.is-active):not(.is-leaving) { opacity: 0; visibility: hidden; }
[data-slider="fade"] [data-slide].is-active { opacity: 1; visibility: visible; z-index: 2; }
[data-slider="fade"] [data-slide].is-leaving { opacity: 0; visibility: visible; z-index: 1; }
[data-slider="fade"] [data-slide].is-entering { scale: 1.045; translate: 2.5% 0; transition: none; }
[data-slider="fade"][data-dir="prev"] [data-slide].is-entering { translate: -2.5% 0; }
[data-slider] [data-slider-track] { touch-action: pan-y; } /* горизонтальный свайп — листание, вертикальный — прокрутка */
[data-slider] [data-slider-count].m-tick { animation: m-tick calc(420ms * var(--m-speed)) var(--m-ease-quart); }
@keyframes m-tick { from { opacity: 0; translate: 0 6px; } }

/* --------------------------------------------------------------------------
   10. «Полёт» в корзину / избранное (almMotion.flyTo)
   -------------------------------------------------------------------------- */

.m-fly { position: fixed; z-index: 2147483000; pointer-events: none; left: 0; top: 0; will-change: transform; }
.m-fly__in { width: 100%; height: 100%; overflow: hidden; box-shadow: 0 18px 40px rgba(40, 28, 20, .22); will-change: transform, opacity; background: var(--surface, #f0ebe3); }
.m-fly__in img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* --------------------------------------------------------------------------
   11. Переходы между страницами (View Transitions; Chrome 126+, Safari 18.2+)
   Шапка неподвижна, страница мягко сменяется, фото товара «перелетает» из списка в карточку:
   на карточке E ставит data-vt="product-photo" на главное фото; в списке имя ставит motion.js
   на фото той карточки, по которой щёлкнули (и при возврате назад).
   -------------------------------------------------------------------------- */

@view-transition { navigation: auto; }
::view-transition-old(root) { animation: m-vt-out calc(240ms * var(--m-speed)) cubic-bezier(.4, 0, 1, 1) both; }
::view-transition-new(root) { animation: m-vt-in calc(560ms * var(--m-speed)) var(--m-ease) calc(60ms * var(--m-speed)) both; }
::view-transition-group(site-header) { animation-duration: 0s; }
::view-transition-group(product-photo) { animation-duration: calc(620ms * var(--m-speed)); animation-timing-function: var(--m-ease); }
::view-transition-old(product-photo), ::view-transition-new(product-photo) { animation-duration: calc(620ms * var(--m-speed)); height: 100%; object-fit: cover; }
[data-vt="product-photo"] { view-transition-name: product-photo; }
@keyframes m-vt-out { to { opacity: 0; } }
@keyframes m-vt-in { from { opacity: 0; translate: 0 10px; } }

/* --------------------------------------------------------------------------
   12. Страховка и уровни движения
   -------------------------------------------------------------------------- */

/* motion.js не запустился за 2,5 с — показать всё (класс .m-ready ставит движок) */
html.js:not(.m-ready) :is(
  [data-reveal], [data-anim]:not(.cb), [data-stagger] > *,
  :is([data-anim="curtain"], [data-anim="zoom-out"]) :is([data-media], picture, video, img), [data-anim="lines"] :is(h1, h2, h3, [data-split]),
  [data-intro] :is([data-intro-item], [data-intro-title], [data-intro-line], [data-intro-media], .eyebrow, .hero__eyebrow, .eyebrow__line, .hero__line, p, .btn, .lead, .hero__actions > *, .hero__tagline, h1, img, video)
) {
  animation: m-failsafe 1ms linear 2.5s forwards;
}
@keyframes m-failsafe { to { opacity: 1; translate: none; scale: none; clip-path: none; filter: none; } }

/* Сниженное движение: без сдвигов, параллакса, качания и бегущей строки — только короткое проявление */
@media (prefers-reduced-motion: reduce) {
  html.js :is(
    [data-reveal], [data-anim]:not(.cb), [data-stagger] > *, :is([data-anim="curtain"], [data-anim="zoom-out"]) :is([data-media], picture, video, img),
    [data-intro] :is([data-intro-item], [data-intro-line], [data-intro-media], .eyebrow, .eyebrow__line, .hero__line, p, .btn, .lead, .hero__actions > *, .hero__tagline, img, video)
  ) { translate: none !important; scale: none !important; clip-path: none !important; filter: none !important; }
  html.js .m-in:not(.m-done):not(.cb) { transition: opacity calc(320ms * var(--m-speed)) ease !important; }
  [data-parallax] { translate: none !important; scale: none !important; }
  [data-sway], .m-marquee__track, .m-shine::before, .m-intro-light::before, [data-header].m-header-intro { animation: none !important; }
  [data-marquee] { overflow-x: auto; }
  .btn, .link-arrow { background-size: 0 0 !important; }
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}
html[data-motion="reduced"].js :is(
  [data-reveal], [data-anim]:not(.cb), [data-stagger] > *, :is([data-anim="curtain"], [data-anim="zoom-out"]) :is([data-media], picture, video, img),
  [data-intro] :is([data-intro-item], [data-intro-line], [data-intro-media], .eyebrow, .eyebrow__line, .hero__line, p, .btn, .lead, .hero__actions > *, .hero__tagline, img, video)
) { translate: none !important; scale: none !important; clip-path: none !important; filter: none !important; }
html[data-motion="reduced"].js .m-in:not(.m-done):not(.cb) { transition: opacity calc(320ms * var(--m-speed)) ease !important; }
html[data-motion="reduced"] [data-parallax] { translate: none !important; scale: none !important; }
html[data-motion="reduced"] :is([data-sway], .m-marquee__track, [data-header].m-header-intro) { animation: none !important; }
html[data-motion="reduced"] :is(.m-shine, .m-intro-light) { display: none; }
html[data-motion="reduced"]::view-transition-old(root), html[data-motion="reduced"]::view-transition-new(root) { animation-duration: calc(180ms * var(--m-speed)); }

/* Анимации выключены (тема «Без анимаций», предпросмотр без движения): всё сразу видно */
html[data-motion="off"] :is(
  [data-reveal], [data-anim]:not(.cb), [data-stagger]:not(:has([data-reveal])) > *,
  :is([data-anim="curtain"], [data-anim="zoom-out"]) :is([data-media], picture, video, img), [data-anim="lines"] :is(h1, h2, h3, [data-split]),
  [data-intro] :is([data-intro-item], [data-intro-title], [data-intro-line], [data-intro-media], .eyebrow, .hero__eyebrow, .eyebrow__line, .hero__line, p, .btn, .lead, .hero__actions > *, .hero__tagline, h1, img, video),
  .m-line__in, .m-word__in
) {
  opacity: 1 !important; translate: none !important; scale: none !important; clip-path: none !important; filter: none !important; transition: none !important;
}
html[data-motion="off"] [data-parallax] { translate: none !important; scale: none !important; }
html[data-motion="off"] :is([data-sway], .m-marquee__track, [data-modal], [data-motion-pop], [data-motion-menu], [data-motion-item], .m-bump, [data-header].m-header-intro) { animation: none !important; }
html[data-motion="off"] [data-modal] :is([data-modal-panel], .modal__panel, .modal__dialog, .modal__box) { animation: none !important; }
html[data-motion="off"] :is(.m-shine, .m-intro-light) { display: none; }
html[data-motion="off"]::view-transition-group(*), html[data-motion="off"]::view-transition-old(*), html[data-motion="off"]::view-transition-new(*) { animation: none !important; }

/* Печать: без скрытых состояний */
@media print {
  :is([data-reveal], [data-anim], [data-stagger] > *, .m-line__in, .m-word__in) { opacity: 1 !important; translate: none !important; scale: none !important; clip-path: none !important; filter: none !important; }
}
