  /* ===== Mobile (<768px) =====================================================
     Figma: страница MOBILE, канвас 402×874 (логический размер iPhone 16 Pro),
     хедер 68px, послайдовое листание свайпом (js/mobile-slides.js).

     ПЕРЕВЁРСТАНО 2026-08-04 под новый макет. Пользователь привёл ВСЕ фреймы к
     одной технической структуре:
         colorBack  +  header-mobile (402×68)  +
         full-content-wrapper > content (0, 105, 402×664)
     то есть зона контента у всех экранов теперь одна и та же — 105…769.
     Всё, что вне неё (colorBack, стикеры, кольцо частиц, тёмные плашки), —
     фон и иллюстрации, которым по замыслу можно уходить за край экрана.
     Прежняя версия этого файла жила на индивидуальных границах каждого
     экрана; из-за этого масштаб всей мобилки задавал один самый рослый экран.

     МАСШТАБИРОВАНИЕ — ключевое отличие от desktop. На десктопе scale берётся
     как min(1, w/1440, h/760): композиция гарантированно влезает целиком, а
     лишняя высота добавляется пустым полем снизу. Для мобилки так нельзя:
     874 — это ПОЛНАЯ высота экрана iPhone 16 Pro, а реальный вьюпорт всегда
     меньше (браузерные панели), и на Android вроде 360×640 min() дал бы
     scale≈0.73 — контент 294px шириной с жёлтыми полями по бокам и нечитаемо
     мелким текстом. Поэтому здесь scale считается по ширине (innerWidth/402),
     а лишний вертикальный "воздух" ОБРЕЗАЕТСЯ — сначала симметрично, а когда
     сверху уже нечего снимать, только снизу (см. M_SAFE_BAND и cropTop в
     js/stage.js: сверху над зоной контента гарантированно остаётся 12px).

     Вся вёрстка ниже — в ДИЗАЙН-пикселях канваса 402×874, 1:1 с Figma.
     Реальный масштаб накладывается одним transform:scale() на #m-stage
     (и отдельно на .m-menubar, см. ниже). ============================== */

  /* ----- Хедер -------------------------------------------------------------
     В отличие от десктопного .menubar (настоящие реальные px, не
     масштабируется) мобильный хедер МАСШТАБИРУЕТСЯ вместе с канвасом — иначе
     на 360px-телефоне 402-пиксельная шапка просто не влезла бы по ширине.
     Приём тот же, что у #m-stage: внутри всё в дизайн-px, снаружи один
     transform:scale(). Обёртке при этом выставляется УЖЕ отмасштабированная
     высота (--m-header-h из js/stage.js), чтобы она занимала в реальном
     layout ровно столько, сколько занимает визуально.

     ПРОГРЕССИВНЫЙ БЛЮР (правка пользователя 2026-08-04: «чтобы красиво было
     при уходе слайдов при переходах»). Раньше у шапки не было ни заливки, ни
     блюра — контент просто просвечивал насквозь. Теперь под ней тот же
     многослойный блюр, что и на десктопе.

     Почему слоёв пять, а не один backdrop-filter: CSS не умеет менять радиус
     размытия по пространству внутри одного фильтра. Стандартный обход —
     несколько наложенных слоёв с РАЗНЫМ blur(), каждый замаскирован
     linear-gradient'ом так, чтобы гаснуть на своей глубине. У самого верха
     непрозрачны все пять, их размытия складываются (каждый следующий
     backdrop-filter размывает уже размытый результат предыдущих) — там блюр
     максимальный. Ниже слои гаснут по очереди, начиная с самого сильного, и
     эффективный радиус тает ступеньками, которые глаз читает как градиент.

     Радиусы уменьшены против десктопных пропорционально высоте шапки
     (68 против 80). Область размытия крошечная — 402×68 дизайн-px, — поэтому
     цена на мобильном GPU невелика; но если профайлер (?perf=1) покажет
     обратное, первым делом убирать слои с конца, начиная с --5. */
  /* ШАПКА МАСШТАБИРУЕТСЯ СВОИМ КОЭФФИЦИЕНТОМ (--m-header-scale), а не общим
     --m-scale. Это не мелочь: когда срабатывает M_SAFE_BAND (низкий экран,
     см. js/stage.js), общий масштаб становится МЕНЬШЕ, чем innerWidth/402,
     канвас честно сужается — а вместе с ним сужалась и шапка, и лого с
     иконкой меню отъезжали от физических краёв экрана. Замерено на 412×730
     (близко к Galaxy A54 с видимой адресной строкой): отступ иконки справа
     получался 57.1px вместо 16. Пользователь это заметил первым же взглядом,
     и правильно: шапка — это UI-хром, он обязан прижиматься к краям экрана,
     а не к краям иллюстрации. Поэтому у неё честный innerWidth/402 и
     transform-origin:left top — она всегда ровно во всю ширину. */
  .m-menubar-wrap{
    position:fixed; left:0; top:0; width:100%; height:var(--m-header-h,68px);
    z-index:100; pointer-events:none;
  }
  .m-menubar-tint, .m-menubar-blur{ position:absolute; inset:0; pointer-events:none; }
  /* Тон уходит в 0 ровно там же, где и блюр, иначе шов был бы заметен по
     цвету. Двумя слоями (светлый/тёмный) вместо одного перекрашиваемого —
     кросс-фейд по opacity композитится, перерисовка градиента нет. */
  .m-menubar-tint--light{
    background:linear-gradient(to bottom, rgba(255,227,0,0.92) 0%, rgba(255,227,0,0.8) 40%, rgba(255,227,0,0) 100%);
  }
  .m-menubar-tint--dark{
    background:linear-gradient(to bottom, rgba(26,26,28,0.92) 0%, rgba(26,26,28,0.8) 40%, rgba(26,26,28,0) 100%);
    opacity:0;
  }
  .m-menubar-blur--1{
    backdrop-filter:blur(15px); -webkit-backdrop-filter:blur(15px);
    -webkit-mask-image:linear-gradient(to bottom, #000 0%, #000 5%, transparent 38%);
    mask-image:linear-gradient(to bottom, #000 0%, #000 5%, transparent 38%);
  }
  .m-menubar-blur--2{
    backdrop-filter:blur(8.5px); -webkit-backdrop-filter:blur(8.5px);
    -webkit-mask-image:linear-gradient(to bottom, #000 0%, #000 5%, transparent 55%);
    mask-image:linear-gradient(to bottom, #000 0%, #000 5%, transparent 55%);
  }
  .m-menubar-blur--3{
    backdrop-filter:blur(5px); -webkit-backdrop-filter:blur(5px);
    -webkit-mask-image:linear-gradient(to bottom, #000 0%, #000 5%, transparent 70%);
    mask-image:linear-gradient(to bottom, #000 0%, #000 5%, transparent 70%);
  }
  .m-menubar-blur--4{
    backdrop-filter:blur(2.5px); -webkit-backdrop-filter:blur(2.5px);
    -webkit-mask-image:linear-gradient(to bottom, #000 0%, #000 5%, transparent 85%);
    mask-image:linear-gradient(to bottom, #000 0%, #000 5%, transparent 85%);
  }
  .m-menubar-blur--5{
    backdrop-filter:blur(1.2px); -webkit-backdrop-filter:blur(1.2px);
    -webkit-mask-image:linear-gradient(to bottom, #000 0%, #000 5%, transparent 100%);
    mask-image:linear-gradient(to bottom, #000 0%, #000 5%, transparent 100%);
  }
  /* --m-header-bleed (js/stage.js) — поля по бокам канваса В ДИЗАЙН-ПИКСЕЛЯХ,
     ненулевые только в планшетном режиме. Там шапка масштабируется тем же
     коэффициентом, что и канвас (иначе на iPad она была бы на 36% крупнее
     контента), и до физических краёв экрана дотягивается уже не масштабом, а
     шириной. Внутри flex со space-between и padding:16, поэтому лого и правая
     группа сами прижимаются к новым краям — пересчитывать координаты не
     пришлось. На телефоне переменная 0 и правило вырождается в прежние 402. */
  .m-menubar{
    position:absolute; left:0; top:0; height:68px;
    width:calc(402px + 2 * var(--m-header-bleed, 0px));
    transform:scale(var(--m-header-scale,1)); transform-origin:left top;
    display:flex; align-items:center; justify-content:space-between;
    padding:8px 16px; box-sizing:border-box;
    pointer-events:auto;
  }
  /* Тёмная версия лого лежит ПОВЕРХ светлой и проявляется на тёмных слайдах —
     кросс-фейд, а не подмена src: подмена дала бы моргание на перерисовке, а
     оба файла и так уже в кеше. Прозрачностями (как и цветами пилюли и иконки
     меню) управляет js/mobile-slides.js — НЕПРЕРЫВНО по позиции трека, а не
     переключением класса с CSS-transition: класс перекрашивал бы шапку
     скачком в середине свайпа, отдельно от всего остального на экране. */
  /* cursor:pointer — лого кликабельно, ведёт на первый экран (js/mobile-overlays.js). */
  .m-logo-stack{ position:relative; width:64px; height:52px; flex-shrink:0; cursor:pointer; }
  .m-logo{ position:absolute; left:0; top:0; width:64px; height:52px; display:block; }
  .m-logo--dark{ opacity:0; }

  .m-menubar__right{ display:flex; align-items:center; gap:16px; padding:5px 0; }
  /* Пилюля "Демонстрация" — тот же паттерн, что .menu-demo-btn/.btn-demo/
     .demo-cta по всему проекту. На тёмных слайдах инвертируется (жёлтая
     плашка + тёмный текст). */
  .m-demo-btn{
    display:flex; align-items:center; justify-content:center;
    height:40px; padding:12px 20px; box-sizing:border-box;
    background:var(--ink); border:none; border-radius:100px; cursor:pointer;
    font-family:'Source Sans Pro',sans-serif; font-weight:600; font-size:16px;
    letter-spacing:0.7143px; text-transform:uppercase; color:#fff;
    white-space:nowrap;
  }

  /* Иконка-меню 2×2 (Figma "menu 1", 32×32). Реализована ЧЕТЫРЬМЯ CSS-
     квадратами, а не SVG-ассетом: это чистая геометрия без визуального
     содержания, ровно как треугольник-указатель активного пункта десктопного
     меню (см. .menu li.is-active::after в css/menubar.css). Если понадобится
     пиксель-в-пиксель как в Figma — берём настоящий SVG и меняем на <img>. */
  .m-menu-btn{
    display:grid; grid-template-columns:repeat(2,13px); grid-template-rows:repeat(2,13px);
    gap:6px; width:32px; height:32px; padding:0; box-sizing:border-box;
    background:none; border:none; cursor:pointer;
  }
  .m-menu-btn span{
    display:block; width:13px; height:13px; border-radius:4px;
    background:var(--ink);
  }

  /* ----- Сцена -------------------------------------------------------------
     .m-stage-wrap — настоящий fixed-блок под хедером.
     touch-action:none + overscroll-behavior:none — гасят нативный скролл,
     pull-to-refresh в Chrome Android и резиновый оверскролл; без этого
     свайп-джек дерётся с браузером за жест. */
  .m-stage-wrap{
    position:fixed; left:0; top:0; right:0; bottom:0;
    padding-top:var(--m-header-h,68px); box-sizing:border-box;
    display:flex; align-items:flex-start; justify-content:center;
    background:var(--yellow); overflow:hidden;
    touch-action:none; overscroll-behavior:none;
    -webkit-user-select:none; user-select:none; -webkit-touch-callout:none;
  }
  /* Картинки НЕ ПЕРЕТАСКИВАЮТСЯ — иначе браузер на pointerdown по иллюстрации
     запускает свой нативный drag и шлёт pointercancel, а наш жест на этом
     обрывается. Поймано на длинной ленте: свайп, начатый с картинки, двигал
     её ровно на один кадр и вставал намертво. На тач-устройствах тем же
     правилом снимается долгий тап «сохранить изображение». */
  .m-stage-wrap img{ -webkit-user-drag:none; user-drag:none; pointer-events:none; }
  /* Высота #m-stage выставляется из js/stage.js под фактическую доступную
     высоту экрана (делённую на scale), 874 здесь — только запасное значение
     до первого fitStage(). */
  #m-stage{
    position:relative; width:402px; height:874px;
    transform:scale(var(--m-scale,1)); transform-origin:center top;
    flex-shrink:0;
  }

  /* ----- Сквозные слои -----------------------------------------------------
     Живут ВНЕ .m-slide-секций и переезжают между слайдами через JS — ровно
     тот же приём, что .phone-frame/.color-back на десктопе (см.
     js/phone-shared.js).

     ПОРЯДОК В DOM ЗНАЧИМ (см. комментарий в index.html): стикеры лежат ВЫШЕ
     телефона (на 2-2 они по макету накрывают его), но НИЖЕ точки Question и
     лупы (на 3-1 они по макету под лупой и приглушены до 50%). Так ни одному
     слою не приходится переключать z-index на лету.

     z-index:1 против 2 у трека — как на десктопе, и переключать его на лету не
     приходится ни на одном экране. */
  #m-shared{ position:absolute; inset:0; z-index:1; pointer-events:none; }
  /* overflow:hidden ОБЯЗАТЕЛЕН и ставится именно здесь, а не на .m-stage-wrap.
     У .m-stage-wrap отступ под шапку сделан через padding-top, а overflow
     режет по PADDING-боксу, то есть полоса под шапкой остаётся видимой — на
     десктопе это сделано намеренно (там .color-back должен подтекать под
     размытую шапку, ей надо что-то размывать). Но на мобилке шапка прозрачная,
     и в этой полосе проступал нижний край ПРЕДЫДУЩЕГО слайда: на 2-1 сверху
     висел хвост заголовка с 1-1. Клип на #m-slide-viewport режет ровно по
     границе сцены, при этом сквозной слой (#m-shared) снаружи и по-прежнему
     свободно подтекает под шапку. */
  /* ПО ГОРИЗОНТАЛИ клип раздвинут на поля по бокам канваса (--m-bleed), а по
     вертикали остаётся ровно по границе сцены. Иллюстрации 6-1/7-1 (и разлёт
     стикеров на 2-3) по макету намеренно вылезают за канвас, и на телефоне это
     безобидно: канвас занимает всю ширину экрана, лишнее уходит за физический
     край. На планшете же канвас у'же экрана — и клип обрубал картинку ровной
     вертикальной линией посреди жёлтого поля, что читалось как брак вёрстки
     (замечание пользователя про «обрезы» на 6-1/7-1). Раздвигаем именно клип,
     а не картинки: замысел «иллюстрация выходит за панель» сохраняется.
     Трек при этом обязан остаться в СВОЕЙ системе координат — отсюда
     компенсирующий left и жёсткие 402px ширины вместо 100%. */
  #m-slide-viewport{
    position:absolute; top:0; bottom:0; z-index:2; overflow:hidden;
    left:calc(-1 * var(--m-bleed, 0px));
    right:calc(-1 * var(--m-bleed, 0px));
  }
  #m-slide-track{ position:absolute; left:var(--m-bleed, 0px); top:0; width:402px; }

  /* ----- Слайды ПОД шапкой (класс ставит js/stage.js, см. UNDER_HEADER) -----
     Клип трека поднимается до верха ЭКРАНА, а сам трек компенсирующе
     опускается на высоту шапки — контент остаётся на прежнем месте, но при
     листании проезжает под полупрозрачной шапкой, и её прогрессивный блюр
     наконец получает что размывать (раньше под шапкой всегда был чистый фон).
     Работает это потому, что overflow у .m-stage-wrap режет по PADDING-боксу:
     полоса под шапкой физически внутри области клипа, просто до сих пор в неё
     ничего не попадало.

     Плата — ровно тот эффект, от которого когда-то избавлялись: в стоячем
     положении под шапкой видна нижняя кромка предыдущего экрана. Теперь это
     осмысленно (её и размывает блюр с тонировкой), но если решим, что мешает —
     откат в одну строку, см. UNDER_HEADER в js/stage.js. */
  html.m-under-topbar #m-slide-viewport{ top:calc(-1 * var(--m-header-h-design, 0px)); }
  html.m-under-topbar #m-slide-track{ top:var(--m-header-h-design, 0px); }
  /* Поднятого клипа ТРЕКА мало: у каждого слайда свой overflow:hidden, и он
     по-прежнему обрубал бы контент по верхней кромке слайда. Для соседних
     экранов это незаметно (в зоне шапки виден предыдущий слайд, а он — другой
     элемент), но лента 8/9/10 прокручивается ВНУТРИ своего слайда, и её
     контент упирался в эту кромку ровной линией под шапкой вместо того, чтобы
     уходить под неё (замечание пользователя). Поэтому сам слайд поднимается
     вверх и на столько же становится выше — числа пишет fitMobile в
     js/stage.js, — а его канвас компенсирующе опускается здесь. */
  html.m-under-topbar .m-slide > .m-canvas,
  html.m-under-topbar .m-slide > .m-long-canvas{ top:var(--m-header-h-design, 0px); }
  /* Из-за подъёма слайды перекрываются на эту же полосу, и верхняя (пустая)
     кромка следующего слайда легла бы на низ предыдущего, перехватывая клики
     по тому, что там окажется. Канваса в этой полосе нет — он опущен, — поэтому
     достаточно снять перехват с самого слайда и вернуть его канвасу. */
  html.m-under-topbar .m-slide{ pointer-events:none; }
  /* 🔴 Перехват возвращается канвасу ТОЛЬКО у живого слайда.
     Канвас соседа — 874px высотой, и на невысоком экране он СВЕШИВАЕТСЯ на низ
     текущего, накрывая то, что там стоит. Пользователь поймал это на кнопке
     «Получить демонстрацию» на 5-2: на 402×874 запаса хватало, на 412×730 и
     360×640 кнопка переставала нажиматься. Прозрачность соседа не помогает —
     невидимый элемент всё равно ловит касание.
     Класс `is-live` вешает renderAt ровно на один слайд, ближайший к позиции
     трека (см. js/mobile-slides.js).
     ⚠️ Селектор с `html.m-under-topbar` обязан быть В КАЖДОЙ строке: правило
     без него слабее по специфичности (три класса против трёх классов и типа),
     и прежний безусловный `auto` перебивал бы его — на этом я и споткнулся,
     первый вариант правки не сработал вообще. */
  html.m-under-topbar .m-slide.is-live > .m-canvas,
  html.m-under-topbar .m-slide.is-live > .m-long-canvas{ pointer-events:auto; }
  /* Тот же смысл для режима без UNDER_HEADER (слайды там не перекрываются, но
     правило дешёвое и держит инвариант «кликабелен только живой слайд»). */
  .m-slide:not(.is-live){ pointer-events:none; }
  /* overflow:hidden обязателен: композиция внутри слайда — бокс 874px, и на
     низких экранах он ФИЗИЧЕСКИ выше самого слайда (см. отрицательный
     --m-center-offset). Без обрезки контент соседних экранов вылезал бы друг
     на друга — на десктопе такой проблемы нет, там slideH всегда >= 760. */
  /* По ГОРИЗОНТАЛИ клип слайда раздвинут на поля по бокам канваса — та же
     причина и та же пара «раздвинуть контейнер, компенсировать потомка», что у
     #m-slide-viewport выше: иначе иллюстрации 6-1/7-1, которым положено
     выходить за канвас, обрубались бы ровной линией посреди жёлтого поля.
     Компенсация висит на .m-slide > .m-canvas, а не на самом .m-canvas: этот
     же класс носит и сквозной слой, а он лежит вне .m-slide и сдвигать его
     нельзя — уехал бы относительно контента. */
  .m-slide{
    position:absolute; overflow:hidden;
    left:calc(-1 * var(--m-bleed, 0px));
    width:calc(100% + 2 * var(--m-bleed, 0px));
  }
  /* Оба канваса слайда: обычный 402×874 и длинный 402×2908.65 у ленты 8/9/10.
     Забыть второй легко — он свой класс, — и тогда вся лента уезжает влево
     ровно на поле по боку (поймано пользователем на планшете). */
  .m-slide > .m-canvas,
  .m-slide > .m-long-canvas{ left:var(--m-bleed, 0px); }

  /* Композиция каждого слайда свёрстана в боксе 402×874 и сдвигается по
     вертикали на --m-center-offset (= −cropTop из js/stage.js). На экранах
     ниже 874 дизайн-px offset ОТРИЦАТЕЛЬНЫЙ — это и есть обрезка воздуха.
     Один и тот же класс используют и слайды, и сквозной слой — иначе они
     разъехались бы относительно друг друга на любом экране, отличном от 874. */
  .m-canvas{
    position:absolute; left:0; top:0; width:402px; height:874px;
    transform:translateY(var(--m-center-offset,0px));
  }

  /* colorBack — SVG с тремя feGaussianBlur внутри. По уроку из
     feedback_yourhotelapp_perf_safari его геометрию НЕЛЬЗЯ анимировать через
     width/height (переразмер размытого слоя = перерисовка блюра каждый кадр,
     худший кадр уходил в сотни мс). Базовый бокс задан здесь один раз, любое
     движение между слайдами — только transform.
     РАЗМЕР — 719.559×899 НА ВСЕХ ЭКРАНАХ (правка пользователя 2026-08-04:
     «сделай размер пятна везде как на 8/9/10»). В макете так только у длинного
     экрана, у остальных пятно 452×565; но у маленького на светлых экранах
     видно нижнюю границу градиента, а у большого она уходит за пределы
     композиции. Центр при этом остался на месте: бокс вырос вокруг прежнего
     центра (201, 142.5), поэтому композиция не поехала.

     Размер задан БОКСОМ, а не scale: у SVG есть viewBox и preserveAspectRatio
     none, поэтому в новом боксе он рисуется в натуральную величину, а не
     растягивается растром — и блюр внутри масштабируется вместе с ним. Это
     разовая CSS-величина, а не анимация: правило «размытое не масштабировать
     размером» (см. feedback_yourhotelapp_perf_safari) запрещает менять
     width/height КАЖДЫЙ КАДР, и оно тут не нарушено — движение по-прежнему
     только transform'ом.

     База — положение на 1-1…2-3. На 4-1…7-1 и 11-1 макет опускает пятно на
     +140 по Y, на длинном экране — на +291. transform-origin:0 0 обязателен
     по общему правилу сквозных слоёв. */
  /* 🔴 ПЯТНО РИСУЕТСЯ CSS-ГРАДИЕНТАМИ, А НЕ КАРТИНКОЙ (правка 2026-08-07).
     Живой баг: на телефоне в Safari пятно пропало СО ВСЕХ ЭКРАНОВ. Причина —
     `images/color-back.svg`: три feGaussianBlur со stdDeviation 64. В боксе
     719.559×899 при DPR 3 буфер фильтра выходит за две тысячи пикселей по
     каждой стороне, и Safari просто не рисует результат — молча, без ошибок.
     На десктопе и в Chrome тот же файл рисуется нормально, поэтому баг
     выглядел мистикой; заметен он стал только когда телефон перестал
     показывать вчерашний кеш (см. project_yourhotelapp_demo_delivery).
     ⚠️ Заодно это объясняет, почему пятно НЕ надо возвращать «как было, но
     поменьше»: сам приём — большой размытый SVG на весь экран — на телефоне
     ненадёжен в принципе.

     Градиенты не выдуманы на глаз: профиль каждого размытого круга СНЯТ
     численно с того же SVG (скрипты /tmp/profile.js и /tmp/cbdiff.js в
     сессии), сверка попиксельная — максимум расхождения 9/255 при среднем
     0.6, глазом неразличимо. Эллипсы, а не круги, потому что исходный SVG
     стоит с preserveAspectRatio="none" и растягивается неравномерно:
     657→719.559 по X (×1.0952) и 757→899 по Y (×1.1876).
     Порядок слоёв в CSS ОБРАТНЫЙ порядку в SVG: первый фон — верхний. */
  .m-color-back{
    position:absolute; left:-158.78px; top:-307px; width:719.559px; height:899px;
    transform-origin:0 0; will-change:transform;
    background-repeat:no-repeat;
    background-image:
      radial-gradient(299.0px 324.2px at 229.4px 247.6px, rgba(255,253,224,0.569) 0.0%, rgba(255,253,224,0.553) 7.1%, rgba(255,253,224,0.502) 14.3%, rgba(255,253,224,0.426) 21.4%, rgba(255,253,224,0.343) 28.6%, rgba(255,253,224,0.260) 35.7%, rgba(255,253,224,0.178) 42.9%, rgba(255,253,224,0.110) 50.0%, rgba(255,253,224,0.064) 57.1%, rgba(255,253,224,0.000) 64.3%),
      radial-gradient(345.0px 374.1px at 444.7px 600.9px, rgba(96,211,218,0.875) 0.0%, rgba(96,211,218,0.855) 7.1%, rgba(96,211,218,0.798) 14.3%, rgba(96,211,218,0.708) 21.4%, rgba(96,211,218,0.588) 28.6%, rgba(96,211,218,0.457) 35.7%, rgba(96,211,218,0.331) 42.9%, rgba(96,211,218,0.222) 50.0%, rgba(96,211,218,0.128) 57.1%, rgba(96,211,218,0.065) 64.3%, rgba(96,211,218,0.029) 71.4%, rgba(96,211,218,0.000) 78.6%),
      radial-gradient(391.0px 424.0px at 320.9px 447.7px, rgba(255,142,140,0.988) 0.0%, rgba(255,142,140,0.978) 7.1%, rgba(255,142,140,0.945) 14.3%, rgba(255,142,140,0.880) 21.4%, rgba(255,142,140,0.783) 28.6%, rgba(255,142,140,0.654) 35.7%, rgba(255,142,140,0.500) 42.9%, rgba(255,142,140,0.345) 50.0%, rgba(255,142,140,0.214) 57.1%, rgba(255,142,140,0.114) 64.3%, rgba(255,142,140,0.051) 71.4%, rgba(255,142,140,0.016) 78.6%, rgba(255,142,140,0.004) 85.7%, rgba(255,142,140,0.000) 92.9%);
  }

  /* ----- Тёмная плашка (сквозная, ОДНА на все экраны) ----------------------
     Раньше их было три: половина экрана на 2-3, весь экран на 3-1 и блок
     320px со скруглённым низом на 4-1 — и они кросс-фейдились друг в друга,
     что на живом свайпе читалось как мигание. Теперь это ОДИН прямоугольник,
     у которого JS двигает верхнее и нижнее ребро (поля dark.t / dark.b в
     STATES, см. js/mobile-slides.js):
         2-2  1000 … 1000   схлопнута за нижним краем
         2-3   437 … 1000   верхнее ребро поднялось до середины экрана
         3-1  −200 … 1000   поднялось дальше и накрыло весь экран
         4-1  −200 …  320   опустилось НИЖНЕЕ ребро, остался блок сверху
         5-1  −200 … −200   нижнее ребро ушло за верхний край, плашки нет
     Ни одного кросс-фейда: все четыре перехода — непрерывное движение рёбер.

     Геометрия задаётся через top/height, а не translate+scaleY: scaleY
     раздавил бы скруглённые нижние углы (они видны на 4-1). Это layout на
     каждый кадр, но у пустого абсолютно спозиционированного div'а без
     потомков он копеечный.

     --m-bleed (из js/stage.js) — половина ширины жёлтых полей, которые
     появляются по бокам канваса, когда срабатывает M_SAFE_BAND. Плашка
     расширяется ровно на неё, поэтому дотягивается до физических краёв
     экрана на любом телефоне, а скруглённые углы при этом остаются ровно на
     краях экрана, а не внутри него.

     Скругление 32 по ВСЕМ четырём углам, хотя одновременно видны максимум два:
     верхние — только на 2-3 (там верхнее ребро на 437, в кадре), нижние —
     только на 4-1 (нижнее на 320). На 3-1 оба ребра за краями экрана, там
     скругления не видно вовсе. Так одна плашка закрывает оба случая макета
     без переключений. */
  .m-dark{
    position:absolute; top:1000px; height:0;
    left:calc(-1 * var(--m-bleed, 0px));
    width:calc(402px + 2 * var(--m-bleed, 0px));
    background:var(--ink); border-radius:32px;
  }

  /* transform-origin:0 0 — ОБЯЗАТЕЛЬНО у всех сквозных слоёв. js/mobile-slides.js
     задаёт их положение как translate(dx,dy) scale(s), где dx/dy — буквальная
     разница координат Figma между экранами. При дефолтном origin 50% 50%
     масштаб считался бы от центра, и элемент уезжал бы на половину разницы
     размеров: рамка на 2-1 оказывалась правее на 45px и ниже на 88px (ровно
     это и было видно — рамка не совпадала со своей же начинкой).

     РАМКА ТЕЛЕФОНА — ИСКЛЮЧЕНИЕ, у неё не scale, а честные width/height.
     Сначала было иначе: 1-1 → 2-1 → 5-2 это чистый scale, и он бесплатно тянул
     за собой толщину бордера и радиус. Но на 6-1/7-1 рамка по макету
     разворачивается в ПАНЕЛЬ 370×664 — пропорция 0.557 против 0.514 у
     телефона, — а на 11-1 сжимается до иконки 26.4×51.4, где и бордер, и
     радиус заданы дизайнером отдельно (2.359 и 4.717 вместо пропорциональных
     0.77 и 3.36). Неравномерный scale раздавил бы скругления в эллипсы,
     поэтому x/y/w/h/радиус/бордер/заливка — семь независимых чисел в STATES
     (поля frame.*), а сюда попадают только стартовые значения экрана 1-1.
     Layout на каждый кадр здесь такой же копеечный, как у .m-dark: элемент
     абсолютный и без потомков. */
  .m-phone-frame{
    position:absolute; left:87.911px; top:105px; width:226.177px; height:440px;
    border:6.594px solid var(--ink); border-radius:28.793px; box-sizing:border-box;
    transform-origin:0 0;
  }
  /* Точка Question. На 3-1/4-1 она разворачивается в лупу: масштаб ×5.333
     переводит её 12px ровно в 64px лупы, а сдвиг (−27, −13) — ровно в её
     координаты (169, 105). То есть это не «две разные штуки, которые
     кросс-фейдятся», а один элемент в двух формах, и в момент подмены обе
     геометрически совпадают. */
  .m-question{
    position:absolute; left:196px; top:118px; width:12px; height:12px;
    border-radius:50%; background:var(--ink); transform-origin:0 0;
  }

  /* ----- Начинка телефона (сквозной слой, видна на 2-1 и 2-2) --------------
     Координаты — абсолютные в канвасе 402×874, 1:1 с Figma. Лежит ПОВЕРХ
     .m-phone-frame, потому что карта МИР по дизайну свисает за нижнюю границу
     телефона и перекрывает его рамку.
     opacity:0 — стартовое значение до того, как отработает renderAt(): скрипт
     подключён с defer, и без этого начинка успевала мигнуть на первом кадре. */
  .m-phone-top{ position:absolute; inset:0; opacity:0; }
  .m-phone-back{
    position:absolute; left:120.29px; top:111.822px; width:161.737px; height:326.896px;
    border-radius:18px; object-fit:cover;
  }
  .m-push{
    position:absolute; left:122.702px; width:157.387px; height:33.899px;
    box-sizing:border-box;
    display:flex; align-items:center; gap:4.843px;
    padding:5.448px 8.475px 5.448px 5.448px; border-radius:9.685px;
    background:rgba(26,26,28,0.8);
    backdrop-filter:blur(9.08px); -webkit-backdrop-filter:blur(9.08px);
  }
  .m-push img{ width:23.003px; height:23.003px; border-radius:50%; flex-shrink:0; }
  .m-push p{
    margin:0; color:var(--push-text);
    font-family:'SF Pro Text','Source Sans Pro',sans-serif;
    font-size:9.08px; letter-spacing:-0.454px; line-height:1.15;
  }
  .m-push--1{ top:129.789px; }
  .m-push--2{ top:167.320px; }
  .m-push--3{ top:204.851px; }

  /* Наклон карты — −11.68° (точное значение из Figma, то же, что у
     .tablet-credit-card-wrap). Он задаётся НЕ ЗДЕСЬ, а из JS через data-rot
     на самой обёртке (см. index.html и phoneTopEls в js/mobile-slides.js):
     renderAt каждый кадр переписывает transform обёртки целиком, поэтому
     CSS-rotate тут просто стирался бы — карта на 2-1 стояла ровно. Ровно та
     же ловушка, что была со стикерами. */
  /* top 227.355, а не 307.355 из макета: правка пользователя — «на 2-1/2-2
     подними карточку на 80px вверх». */
  .m-card-wrap{
    position:absolute; left:73.13px; top:227.355px; width:251.002px; height:185.558px;
    display:flex; align-items:center; justify-content:center;
  }
  .m-card{
    position:relative; width:226.830px; height:142.578px;
    border-radius:13.251px; overflow:hidden;
    box-shadow:5.184px 7.777px 7.777px rgba(207,103,0,0.4);
    background-image:linear-gradient(-90deg, rgb(43,170,172) 0%, rgb(201,89,80) 64.9%, rgb(252,80,110) 100%);
  }
  .m-card-masks img{ position:absolute; inset:0; width:100%; height:100%; }
  .m-card-logo{ position:absolute; left:76.25%; top:12.3%; width:17.84%; height:7.9%; }
  .m-card-number{
    position:absolute; left:5.14%; top:46.82%;
    font-family:'Source Sans Pro',sans-serif; font-size:11.661px; color:#fff; letter-spacing:0.585px;
  }
  .m-card-number span{ position:absolute; top:0; white-space:nowrap; }
  .m-card-number span:nth-child(1){ left:0; }
  .m-card-number span:nth-child(2){ left:36.96px; }
  .m-card-number span:nth-child(3){ left:74.54px; }
  .m-card-number span:nth-child(4){ left:110.21px; }
  .m-card-name{ position:absolute; left:5.14%; top:81.82%; font-family:'Source Sans Pro',sans-serif; font-size:7.774px; color:#fff; }
  .m-card-expiry{ position:absolute; right:6.06%; top:82.16%; font-family:'Source Sans Pro',sans-serif; font-size:7.774px; color:#fff; }

  /* Лого внутри телефона — тоже сквозное: живёт на 1-1, пропадает на 2-1…4-1
     и возвращается на 5-1 (на 11px ниже) и 5-2 (в общем зуме ×1.30879). */
  .m-logo-big{
    position:absolute; left:124px; top:202px; width:154px; height:126px;
    transform-origin:0 0;
  }

  /* ----- Кольцо частиц (сквозное) ------------------------------------------
     Растровое, а не canvas: частицы отрисованы десктопной логикой RINGS в
     headless-Chromium. На мобильных GPU canvas с тысячами точек — лишний
     риск, а статичная картинка идеально ложится на зум между 5-1 и 5-2.
     Намеренно шире канваса: кольцо по построению уходит за края.

     ПОЛОЖЕНИЕ: центр кольца стоит ровно в центре рамки телефона (правка
     пользователя 2026-08-04 «подними его до центра телефона») — на 5-1 это
     (201, 276.15), на 5-2 (201, 329). Раньше оно стояло по эллипсу-гайду ORB
     из макета, то есть заметно ниже.
     Бокс: центр картинки приходится на её (50.0%, 50.05%), отсюда левый
     верхний угол.

     ТРИ ЧАСТИ — одна картинка, разные clip-path (см. комментарий в
     index.html): l и r показывают её целиком слева и справа от рамки
     телефона, mid — только ниже линии центра эллипса, внутри полосы рамки.
     Так верхняя дужка «уходит за телефон», а нижняя идёт по нему. Значения
     insets пишет js/mobile-slides.js: полоса рамки в координатах картинки
     разная на 5-1 и 5-2, потому что телефон и кольцо растут с разными
     коэффициентами. Все три части лежат ВЫШЕ телефона — переключать z-index
     на лету не нужно, вырез делает всю работу. */
  .m-rings{
    position:absolute; left:-9.799px; top:191.453px; width:421.656px; height:169.23px;
    transform-origin:0 0; opacity:0; pointer-events:none;
  }
  /* Картинка колец — ФОНОМ, а не <img> (правка 2026-08-08). Тег <img>
     браузер качает всегда, в том числе внутри display:none, а на десктопе
     мобильная ветка скрыта целиком — 326 КБ на каждой загрузке тратились на
     картинку, которую там физически невозможно увидеть (11% веса первой
     загрузки). Фон внутри display:none не запрашивается вообще, а это
     правило живёт внутри мобильного медиазапроса.
     background-size:100% 100% воспроизводит прежние width/height:100% у
     <img> — то есть картинка ТЯНЕТСЯ по боксу, пропорции не сохраняются;
     так было и раньше, вырез частей считает js/mobile-slides.js. */
  .m-rings__part{
    position:absolute; inset:0;
    background-image:url(../images/rings-mobile.png);
    background-size:100% 100%; background-repeat:no-repeat;
  }

  /* ----- Стикеры (сквозной слой) -------------------------------------------
     Восемь штук с ДЕСКТОПА (в мобильной Figma их шесть-семь и с повторами —
     пользователь прямо сказал, что там приблизительный набросок и брать надо
     десктопные). Раскладка тоже наша: стикеры летят через три экрана подряд
     (2-2 → 2-3 → 3-1) одной траекторией, поэтому позиции для каждого экрана
     заданы таблицами в js/mobile-slides.js, а не вёрсткой.
     Разметкой задано только состояние 2-2 (атрибуты left/top у .m-sticker-shell),
     остальные считаются от него.
     opacity:0 — стартовое значение до первого renderAt(), см. .m-phone-top. */
  .m-stickers{ position:absolute; inset:0; opacity:0; }
  .m-sticker-shell{ position:absolute; width:0; height:0; }
  .m-sticker{
    position:absolute; left:0; top:0; width:137.330px; height:110.279px;
    box-shadow:4.8px 11.1px 15.7px rgba(60,30,10,0.18);
    overflow:hidden;
  }
  .m-sticker .strip{ position:absolute; left:0; top:0; width:100%; height:19.826px; }
  .m-sticker p{
    position:absolute; margin:0;
    font-family:'Caveat',cursive; color:var(--purple); line-height:1.1;
  }
  .m-sticker--md p{ left:10.75px; top:33.02px; font-size:19.024px; letter-spacing:-0.952px; }
  .m-sticker--lg p{ left:19.83px; top:28.53px; font-size:22.194px; letter-spacing:-1.110px; }
  .m-sticker--pink{ background:#F8D7E6; }
  .m-sticker--pink .strip{ background:linear-gradient(180deg,#F8D7E6,#F0CEDD); }
  .m-sticker--blue{ background:#D2E0ED; }
  .m-sticker--blue .strip{ background:linear-gradient(180deg,#D2E0ED,#C7D6E5); }
  .m-sticker--yellow{ background:#FDF2B6; }
  .m-sticker--yellow .strip{ background:linear-gradient(180deg,#FDF2B6,#F5E697); }

  /* ----- Лупа (сквозная) ----------------------------------------------------
     Развёрнутая версия точки Question: на 1-1…2-3 это чёрная точка-камера на
     рамке телефона, на 3-1 и 4-1 — белая лупа 64×64 в одном и том же месте
     (169, 105) на обоих экранах. Два DOM-узла, но геометрия у них в каждом
     состоянии СОВПАДАЕТ (см. комментарий у .m-question), поэтому кросс-фейд
     читается как морфинг, а не как подмена.
     Сама иконка — тот же inline-SVG, что у десктопной поисковой строки
     (см. #cost-searchbar-icon в index.html). */
  .m-magnifier{
    position:absolute; left:169px; top:105px; width:64px; height:64px;
    transform-origin:0 0; opacity:0;
  }
  .m-magnifier svg{ display:block; width:100%; height:100%; }

  /* ========================================================================
     ЭКРАНЫ. Ниже — только собственный контент каждого слайда: всё, что
     переезжает между экранами, живёт в сквозных слоях выше.
     Координаты абсолютные в канвасе 402×874, зона контента везде 105…769.
     ======================================================================== */

  /* ----- 1-1 Hero (Figma 2924:4323) ----------------------------------------
     Бабл с лирикой: ширина 303 против 226 у рамки телефона — бабл НАМЕРЕННО
     шире, вылезает за неё с обеих сторон «чтобы создать объём» (прямые слова
     пользователя), это не ошибка вёрстки.
     Высота зафиксирована (127px), а не auto: от неё отсчитываются пузырьки-
     хвостик ниже, и если бы текст в браузере лёг в другое число строк, вся
     цепочка поехала бы. */
  .m-hero-bubble{
    position:absolute; left:49px; top:399px; width:303px; height:127px;
    box-sizing:border-box; padding:32px 10px;
    display:flex; align-items:center; justify-content:center;
    background:#fff; border-radius:100px;
  }
  /* position:relative — чтобы текст рисовался ПОВЕРХ пузырьков: они
     absolute-потомки того же бабла и по правилам покраски легли бы на
     непозиционированный <p> сверху, закрыв часть строк (самый крупный
     пузырёк заходит внутрь бабла на 52px). */
  .m-hero-bubble p{
    position:relative; z-index:1; margin:0; width:283px;
    font-family:'Unbounded',sans-serif; font-weight:500; font-size:16px;
    line-height:1.3; letter-spacing:0.48px; text-align:center; color:var(--ink);
  }
  /* Цепочка пузырьков-хвостик. Координаты — от бабла (он родитель), точка
     отсчёта по вертикали — низ логотипа: самый мелкий пузырёк начинается ровно
     под ним и цепочка ведёт вниз к баблу. Белые круги на белом бабле — самый
     крупный наполовину утоплен в него и сливается, это и даёт форму «облака». */
  .m-hero-bubble__dot{ position:absolute; background:#fff; border-radius:50%; }
  .m-hero-bubble__dot--1{ left:182px; top:-65px; width:14px; height:14px; }
  .m-hero-bubble__dot--2{ left:188px; top:-46px; width:26px; height:26px; }
  .m-hero-bubble__dot--3{ left:192px; top:-19px; width:71px; height:71px; }

  /* Составной заголовок в две ступени — крупная строка «что это» и мелкая
     «какая выгода». Нижняя граница 742 — внутри зоны контента (769). */
  .m-hero-title{
    position:absolute; left:16px; top:585px; width:370px;
    display:flex; flex-direction:column; gap:8px;
    /* margin:0 — контейнер стал <h1>, у него есть собственные отступы от
       браузера. На position:absolute они в раскладке не участвуют, но пусть
       не мешаются, если блок когда-нибудь снимут с абсолюта. Кегль и
       начертание возвращаем к наследуемым по той же причине, что и у
       .sec-heading: браузерные h1-ские 32px/bold здесь ничего не красят
       (обе строки задают своё), но достались бы любому будущему тексту. */
    margin:0; font-size:inherit; font-weight:inherit;
  }
  /* Селектор по классам, а не по тегу p: строки заголовка переехали на <span>
     (2026-08-07, расстановка уровней — <p> внутри заголовка стандарт не
     разрешает). Внутри flex-контейнера спаны всё равно блокифицируются, так
     что раскладка не меняется ни на пиксель. */
  .m-hero-title__lead, .m-hero-title__sub{ margin:0; width:370px; text-align:center; color:var(--ink); }
  .m-hero-title__lead{
    font-family:'Unbounded',sans-serif; font-weight:600; font-size:30px;
    line-height:1.1; letter-spacing:0.9px;
  }
  .m-hero-title__sub{
    font-family:'Unbounded',sans-serif; font-weight:500; font-size:18px;
    line-height:1.4;
  }

  /* ----- 2-1 «МИР изменился» (Figma 2924:4176) -----------------------------
     bottom-of-slide: (16, 463.3) 370×305.7, контент прижат к верху с
     отступом 24 (в макете flex-col + pt-24), НЕ центрируется по высоте.
     Телефон, его начинка, colorBack и точка Question — сквозные слои: начинка
     на 2-1 и 2-2 СТОИТ НА МЕСТЕ, меняется только текст под ним и налетают
     стикеры. Именно поэтому .m-phone-top не может принадлежать слайду —
     иначе при переходе 2-1→2-2 он бы гас и появлялся заново. */
  .m-s2-text{
    position:absolute; left:16px; top:463.3px; width:370px;
    padding-top:24px; box-sizing:border-box;
    display:flex; flex-direction:column; gap:16px; align-items:center;
    color:var(--ink);
  }
  .m-s2-text p{ margin:0; }
  .m-s2-heading{ display:flex; flex-direction:column; margin:0; font-size:inherit; font-weight:inherit; }
  /* Кегль 65.507 — не круглое число из Figma, оставлено как есть: заголовок
     «МИР» подогнан там по оптической ширине под «изменился», а не набран
     ступенью шкалы. */
  .m-s21-heading{ align-items:center; white-space:nowrap; }
  .m-s21-heading__mir, .m-s21-heading__izm{ font-family:'Unbounded',sans-serif; font-weight:600; line-height:0.8; }
  .m-s21-heading__mir{ font-size:65.507px; text-transform:uppercase; }
  .m-s21-heading__izm{ font-size:44px; }
  .m-s2-para{
    width:100%; text-align:center;
    font-family:'Unbounded',sans-serif; font-weight:500; font-size:16px; line-height:1.5;
  }

  /* ----- 2-2 «НО приезжая в гостиницу» (Figma 2924:4001) ------------------- */
  .m-s22-heading{ align-items:flex-start; width:100%; text-align:center; }
  .m-s22-heading__no, .m-s22-heading__rest{ font-family:'Unbounded',sans-serif; font-weight:600; width:370px; }
  .m-s22-heading__no{ font-size:65.507px; line-height:0.8; text-transform:uppercase; }
  .m-s22-heading__rest{ font-size:40px; line-height:0.9; }

  /* ----- 2-3 «Ожидания гостей изменились» (Figma 2924:3829) ----------------
     Зона контента 105…769 делится на две равные половины по 324 с зазором 16;
     тёмная плашка (сквозная .m-dark) встаёт верхним ребром на 437 — это центр
     КАНВАСА, а не центр зоны контента, и так в макете.
     Блок «Большинство гостиниц —» намеренно на всю ширину 402 (в макете он
     выходит за 16px-поля контента), поэтому у него свои координаты. */
  .m-s23-top{
    position:absolute; left:16px; top:105px; width:370px; height:324px;
    display:flex; align-items:center; justify-content:center;
  }
  .m-s23-bottom{
    margin:0; font-size:inherit; font-weight:inherit;
    position:absolute; left:0; top:445px; width:402px; height:324px;
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:16px;
  }
  .m-s23-top p, .m-s23-line{
    margin:0; width:100%; text-align:center;
    font-family:'Unbounded',sans-serif; font-weight:600; font-size:40px; line-height:1;
  }
  .m-s23-top p{ color:var(--ink); }
  .m-s23-line{ color:var(--yellow); }
  /* Бейдж «нет». В Figma к тексту применён text-box-trim (обрезка по
     капитальной высоте), в CSS это пока нестабильно поддерживается — вместо
     него подобраны асимметричные паддинги 6.691/13.383 из того же макета,
     они дают тот же визуальный результат на непрозрачной плашке. */
  .m-s23-badge{
    display:flex; align-items:center; justify-content:center;
    padding:6.691px 10.037px 13.383px; background:var(--yellow);
  }
  .m-s23-badge span{
    font-family:'Unbounded',sans-serif; font-weight:600; font-size:53.531px;
    line-height:1.2; color:var(--ink); white-space:nowrap;
  }

  /* ----- 3-1 «Что это стоит гостинице?» + три потери (Figma 2924:3711) -----
     СЛИТЫЙ ЭКРАН: пользователь объединил прежние 3-1 и 3-2 в один, поэтому
     на одном экране и вопрос с лупой, и весь список потерь.
     Лупа и тёмный фон — сквозные слои.
     Верхний блок: лупа (169, 105) 64×64 + заголовок (17, 185) 368×88.
     Список: (16, 305) 370×464, три позиции, распределённые justify-between —
     в макете зазоры между ними получаются по 30. */
  .m-s31-title{
    position:absolute; left:17px; top:185px; width:368px; margin:0;
    font-family:'Unbounded',sans-serif; font-weight:600; font-size:40px;
    line-height:1.1; text-align:center; color:#fff;
  }
  .m-s31-list{
    position:absolute; left:16px; top:305px; width:370px; height:464px;
    display:flex; flex-direction:column; justify-content:space-between;
  }
  .m-s31-item{
    display:flex; align-items:center; gap:16px;
    width:370px; padding-right:16px; box-sizing:border-box;
  }
  .m-s31-item--1, .m-s31-item--2{ height:128px; }
  .m-s31-item--3{ height:148px; }
  .m-s31-item img{ width:128px; height:128px; flex-shrink:0; object-fit:cover; }
  .m-s31-item__text{
    margin:0; font-size:inherit; font-weight:inherit;
    flex:1 0 0; min-width:0;
    display:flex; flex-direction:column; gap:6px; align-items:flex-start;
  }
  /* Текст на этом экране БЕЛЫЙ, а не жёлтый — так в новом макете (в прежнем
     3-2 он был жёлтым). Полоска-разделитель тоже белая и тонкая, 1px. */
  /* Селектор по классам, а не по тегу p: подводка и вывод переехали на span
     (2026-08-08, «версия для чтения» — контейнер .m-s31-item__text стал
     абзацем, чтобы фраза «Когда … — вы теряете …» читалась целиком). Оставь
     тут `p`, и правило поймало бы САМ контейнер вместо своих двух строк:
     ширина и цвет достались бы не тому элементу. */
  .m-s31-item__lead, .m-s31-item__loss{ margin:0; width:100%; color:#fff; font-family:'Unbounded',sans-serif; }
  .m-s31-item__lead{ font-weight:400; font-size:12px; line-height:1.4; }
  .m-s31-item__loss{ font-weight:600; font-size:18px; line-height:1.2; }
  .m-s31-item__bar{ width:100%; height:1px; background:#fff; flex-shrink:0; }

  /* ----- 4-1 «Какое же решение?» (Figma 2924:3499) -------------------------
     Тёмный блок сверху — сквозная .m-dark (нижнее ребро на 320, углы
     скруглены). Лупа стоит на том же месте, что и на 3-1, — не двигается.
     bottom-of-slide (16, 418) 370×351, содержимое распределено
     justify-between: текстовый блок сверху, кнопка внизу. */
  .m-s41-question{
    position:absolute; left:74px; top:185px; width:254px; margin:0;
    font-family:'Unbounded',sans-serif; font-weight:500; font-size:40px;
    line-height:1.1; text-align:center; color:#fff;
  }
  /* Правка макета 2026-08-07: текстовый блок поднялся (418 → 358) и перестал
     делить место с кнопкой — низ экрана теперь занимает блок media5. Заодно
     поменялись веса и кегли: «цифровой сервис» стал Medium (был SemiBold), а
     абзац — Regular 16 (был Medium 21). */
  .m-s41-text{
    margin:0; font-size:inherit; font-weight:inherit;
    position:absolute; left:16px; top:358px; width:370px;
    display:flex; flex-direction:column; gap:16px;
  }
  .m-s41-top{ display:flex; flex-direction:column; gap:8px; width:100%; }
  .m-s41-lead, .m-s41-big, .m-s41-para{ margin:0; width:100%; text-align:center; color:var(--ink); font-family:'Unbounded',sans-serif; }
  .m-s41-lead{ font-weight:600; font-size:18px; line-height:0.9; }
  .m-s41-big{ font-weight:500; font-size:48px; line-height:0.9; }
  .m-s41-para{ font-weight:400; font-size:16px; line-height:1.2; }

  /* ----- Блок media5 внизу 4-1 (Figma 2977:1783) ---------------------------
     Координаты макета: сам блок (16, 588.409) 370×180.591 — его низ ровно
     совпадает с нижней границей зоны контента (769). Внутри: подпись 24/1.2 в
     две строки (58), зазор 11, лого 146×32.591, зазор 11 + верхний отступ
     обёртки 16, кнопка 322×52 — итого низ кнопки приходится на те же 769.
     Перенос строки в подписи ЖЁСТКИЙ (<br>): в макете «И он уже здесь —» и
     «продукт от компании» стоят двумя строками, автоперенос по ширине 370
     ломал бы фразу в другом месте. */
  .m-s41-media5{
    position:absolute; left:16px; top:588.409px; width:370px;
    display:flex; flex-direction:column; align-items:center; gap:11px;
  }
  .m-s41-here{
    margin:0; width:100%; text-align:center; color:var(--ink);
    font-family:'Unbounded',sans-serif; font-weight:500; font-size:24px; line-height:1.2;
  }
  /* Тот же media5-logo.svg, что в попапе и в меню, но там он лежит на чёрном и
     потому сам белый. Здесь фон жёлтый — красим в чёрный тем же приёмом, что
     и на десктопном Solution (.sol-block__logo): brightness(0) гасит любой
     цвет, прозрачность не трогает. Второй файл ради одного цвета не заводим. */
  .m-s41-logo{ display:block; width:146px; height:32.591px; filter:brightness(0); }
  .m-s41-about-wrap{ width:100%; padding:16px 24px 0; box-sizing:border-box; }
  /* Кнопка ПУНКТИРНАЯ и прозрачная — не CTA, а «узнать больше»: в макете она
     специально тише жёлто-чёрных пилюль на 5-2 и в ленте. */
  .m-s41-about{
    display:flex; align-items:center; justify-content:center;
    width:100%; height:52px; padding:12px 20px; box-sizing:border-box;
    background:none; border:1px dashed var(--ink); border-radius:100px; cursor:pointer;
    font-family:'Unbounded',sans-serif; font-weight:500; font-size:18px; line-height:1.3;
    color:var(--ink); white-space:nowrap;
  }

  /* Пилюля-кнопка — тот же паттерн, что .m-demo-btn в шапке и .demo-cta на
     десктопе. Ширина всегда по контейнеру: и на 4-1, и на 5-2 обёртка даёт
     370 − 2×24 = 322, ровно как в макете. */
  .m-cta{
    display:flex; align-items:center; justify-content:center;
    width:100%; height:52px; padding:12px 20px; box-sizing:border-box;
    background:var(--ink); border:none; border-radius:100px; cursor:pointer;
    font-family:'Source Sans Pro',sans-serif; font-weight:600; font-size:16px;
    letter-spacing:0.7143px; text-transform:uppercase; color:#fff; white-space:nowrap;
  }
  /* Вариант с Unbounded вместо Source Sans Pro и без капса — так набрана
     кнопка на 5-2 (на 4-1 остаётся базовый вариант). */
  .m-cta--unb{
    font-family:'Unbounded',sans-serif; font-weight:500; font-size:18px;
    line-height:1.3; letter-spacing:normal; text-transform:none;
  }

  /* ----- 5-1 «Без замены PMS…» (Figma 2924:3067) ---------------------------
     Телефон, лого и кольцо — сквозные слои, здесь только сетка.
     Список стал СЕТКОЙ 2×2 из карточек с пунктирной рамкой (в прежнем макете
     это был вертикальный список). Ряды разной высоты — 135 и 152, как в
     макете; align-content:start, чтобы сетка не растягивалась на все 305.7. */
  .m-s51-grid{
    position:absolute; left:16px; top:463.3px; width:370px; height:305.7px;
    display:grid; grid-template-columns:1fr 1fr; grid-template-rows:135px 152px;
    gap:10px; align-content:start;
  }
  /* Пунктирная рамка БЕЛАЯ, а кружок со стрелкой наоборот тёмный с белым
     шевроном — правка макета 2026-08-04, до неё было ровно наоборот. */
  .m-s51-li{
    display:flex; flex-direction:column; align-items:center; gap:16px;
    padding:16px 8px; box-sizing:border-box;
    border:1px dashed #fff; border-radius:16px;
  }
  .m-s51-li__title{
    margin:0; width:100%; text-align:center; color:var(--ink);
    font-family:'Unbounded',sans-serif; font-weight:600; font-size:13px; line-height:1.3;
  }
  /* Кружок со стрелкой. В макете это SVG-компонент, повёрнутый так, что
     стрелка смотрит ВНИЗ — на текст под ней. Здесь собран из CSS: белый круг
     + шеврон на бордерах — та же логика, что у треугольника-указателя
     десктопного меню. */
  .m-s51-pointer{
    position:relative; width:36px; height:36px; flex-shrink:0;
    border-radius:50%; background:var(--ink);
  }
  .m-s51-pointer::after{
    content:''; position:absolute; left:50%; top:50%;
    width:9px; height:9px; margin:-7px 0 0 -4.5px;
    border-right:2.6px solid #fff; border-bottom:2.6px solid #fff;
    transform:rotate(45deg);
  }

  /* ----- 5-2 «Единая цифровая среда» (Figma 2924:3399) ---------------------
     Table (16, 569) 370×200: заголовок с отступом 24 сверху, дальше зазор 24
     и кнопка. Нижняя граница 769 — ровно край зоны контента. */
  .m-s52-text{
    position:absolute; left:16px; top:569px; width:370px;
    padding-top:24px; box-sizing:border-box;
    display:flex; flex-direction:column; gap:24px; align-items:flex-start;
  }
  /* 18/1.4 вместо 21/1.2 — правка 2026-08-07, следствие дописанного слова
     «Приложение». На 21px строка «Приложение объединяет гостя,» занимает 419px
     при контейнере 370 и переносится, ломая заголовок на пять строк с висячим
     «гостя,». На 18px она укладывается в 359px.
     Интерлиньяж поднят ровно настолько, чтобы ВЫСОТА БЛОКА НЕ ИЗМЕНИЛАСЬ:
     18×1.4 = 25.2 = 21×1.2, четыре строки как были — значит кнопка под
     заголовком осталась на своём месте, а нижняя граница блока — на 769,
     ровно по краю зоны контента, как в макете. */
  .m-s52-title{
    margin:0; width:100%;
    font-family:'Unbounded',sans-serif; font-weight:500; font-size:18px;
    line-height:1.4; text-align:center; color:var(--ink);
  }
  .m-s52-cta-wrap{ width:100%; padding:0 24px; box-sizing:border-box; }

  /* ----- 6-1 / 7-1 — экраны-панели (Figma 2922:1870 / 2922:2100) ----------
     Сама панель — это СКВОЗНАЯ рамка телефона, развёрнутая до 370×664 с
     заливкой (поля frame.w/h/c/f в STATES). Здесь только её содержимое.
     Разница между экранами (правка 2026-08-05): 6-1 — ПУСТАЯ чёрная рамка
     без заливки, весь контент тёмный (переопределения .m-s61-* ниже); 7-1 —
     бирюзовая заливка с тёмными галочками и белым текстом. Базовые правила
     ниже написаны под 7-1 (белый текст), 6-1 их перекрывает. */
  /* Правка макета 2026-08-07: поля контента стали 48 (были 32 у заголовка и
     31.5 у списка — раньше список центрировался в канвасе сам по себе, теперь
     оба блока стоят на одной левой границе), подзаголовок подрос до Medium 15,
     пункты — до Regular 13. Ширина 306 = 402 − 2×48. */
  .m-panel-head{
    position:absolute; left:48px; top:129px; width:306px;
    display:flex; flex-direction:column; gap:10px;
    text-align:center; color:#fff;
  }
  .m-panel-title{
    margin:0; font-family:'Unbounded',sans-serif; font-weight:600;
    font-size:28px; line-height:1.2;
  }
  .m-panel-sub{
    margin:0; font-family:'Unbounded',sans-serif; font-weight:500;
    font-size:15px; line-height:1.5;
  }
  .m-panel-list{
    position:absolute; left:48px; width:306px;
    display:flex; flex-direction:column; gap:16px;
  }
  .m-s61-list{ top:280px; }
  .m-s71-list{ top:308px; }
  .m-panel-li{ display:flex; gap:16px; align-items:flex-start; }
  /* Отдельные пункты в макете выровнены галочкой ПО ЦЕНТРУ строки, а не по
     верху (на 7-1 это второй и пятый) — в Figma это видно по сдвинутой на
     6px галочке. Разницу держим модификатором, а не общим правилом: у
     трёхстрочных пунктов центрирование увело бы галочку на середину абзаца. */
  .m-panel-li--mid{ align-items:center; }
  .m-panel-li p{
    margin:0; flex:1 0 0; min-width:0; color:#fff;
    font-family:'Unbounded',sans-serif; font-weight:400; font-size:13px; line-height:1.4;
  }

  /* Галочка в кружке — тот же смысловой элемент, что .receive-check/.guest-check
     на десктопе, и так же собрана инлайновым SVG, а не ассетом: из песочницы
     Figma-иконки не скачиваются, а это одна ломаная. */
  .m-check{
    display:flex; align-items:center; justify-content:center;
    width:24px; height:24px; border-radius:50%; flex-shrink:0;
  }
  .m-check svg{ display:block; width:16px; height:11.762px; }
  .m-check polyline{ fill:none; stroke:#fff; stroke-width:2.4; stroke-linecap:round; stroke-linejoin:round; }
  .m-check--teal{ background:#10ABB5; }
  .m-check--ink{ background:var(--ink); }

  /* 6-1 — переопределения на тёмный контент (правка 2026-08-05: панель стала
     пустой рамкой, белый текст на жёлтом фоне читаться перестал). Держим их
     тут, рядом с базовыми правилами панели, а не отдельным блоком — иначе при
     следующей правке цвета 7-1 легко забыть про пару. */
  .m-s61-head{ color:var(--ink); }
  .m-s61-list .m-panel-li p{ color:var(--ink); }
  /* Интерлиньяж у 6-1 плотнее, чем у 7-1: 1.3 против 1.5 в подзаголовке и 1.3
     против 1.4 в пунктах. Так в макете — на 6-1 пунктов шесть, и они иначе бы
     не уместились над иллюстрацией. */
  .m-s61-head .m-panel-sub{ line-height:1.3; }
  .m-s61-list .m-panel-li p{ line-height:1.3; }

  /* Иллюстрации по макету вылезают за панель — влево, вправо и вниз за край
     канваса. Это намеренно, не ошибка вёрстки. Размеры строго макетные и
     МАСШТАБИРОВАТЬ ИХ ПОД ШИРИНУ ЭКРАНА НЕ НАДО — пробовал (растягивал бокс, а
     потом масштабировал пропорционально), пользователь отверг оба варианта:
     картинка раздувалась на весь экран, а просьба была ровно противоположная —
     не обрезать её. От обреза лечит расширенный клип слайда (см. .m-slide и
     #m-slide-viewport выше): на планшете картинка просто видна целиком, с
     жёлтым полем по бокам. */
  .m-s61-img{ position:absolute; left:-36px; top:622px; width:474px; height:316px; object-fit:cover; }
  .m-s71-img{ position:absolute; left:-19.676px; top:567.563px; width:459.503px; height:306.335px; object-fit:cover; }

  /* ----- Декоративные кружки (обновление макета 2026-08-07) ----------------
     Раньше были ВПЕЧАТАНЫ в растровые иллюстрации, теперь вынесены дизайнером
     отдельными слоями — и здесь, и на десктопе (см. память проекта).

     ⚠️ Кружки лежат в СЛОЯХ-контейнерах, а не поштучно, и это не про
     аккуратность разметки. Их 39 на всю мобилку, а параллакс на этой версии
     настоящий: renderAt пишет transform каждый кадр прокрутки. Двигать 39
     элементов = 39 записей за кадр; двигать два слоя на группу = две. Заодно
     слои дают саму глубину: `--far` (крупные пятна) отстаёт сильнее, чем
     `--near` (мелкие точки).

     Слой не имеет своей геометрии — только transform от JS. Кружки внутри
     позиционированы абсолютно в координатах канваса слайда.

     Порядок слоёв в разметке = порядок наложения. Там, где макет кладёт часть
     кружков ПОВЕРХ иллюстрации, слой стоит после <img> (`--over`). */
  .m-circ-layer{ position:absolute; left:0; top:0; width:402px; height:100%; pointer-events:none; will-change:transform; }
  .m-circ{ position:absolute; border-radius:50%; }
  .m-circ--y{ background:#FFE300; }
  .m-circ--r{ background:#E6195B; }
  .m-circ--b{ background:#10ABB5; }

  /* 6-1: два крупных пятна под зданием, шесть акцентов поверх фасада.
     Фрейм иллюстрации в макете стоит на (-36, 622), локальные числа Figma к
     нему прибавлены. */
  .m-s61-c1{ left:6.985px;   top:622.581px; width:181.235px; height:181.235px; }
  .m-s61-c2{ left:248.051px; top:653.949px; width:117.919px; height:117.919px; }
  .m-s61-c3{ left:159.176px; top:780px;     width:43.566px;  height:43.566px; }
  .m-s61-c4{ left:1.757px;   top:849.125px; width:48.794px;  height:48.794px; }
  .m-s61-c5{ left:106.897px; top:742.824px; width:21.493px;  height:21.493px; }
  .m-s61-c6{ left:368.875px; top:661.5px;   width:14.522px;  height:14.522px; }
  .m-s61-c7{ left:331.699px; top:780px;     width:34.272px;  height:34.272px; }
  .m-s61-c8{ left:166.147px; top:810.787px; width:14.522px;  height:14.522px; }

  /* 7-1: фрейм иллюстрации на (-19.676, 553). */
  .m-s71-c1{ left:169px;     top:566px;     width:191px;    height:191px; }
  .m-s71-c2{ left:132.632px; top:622.783px; width:77.064px; height:77.064px; }
  .m-s71-c3{ left:173.288px; top:782.979px; width:50.972px; height:50.972px; }
  .m-s71-c4{ left:300.110px; top:773.877px; width:60.074px; height:60.074px; }
  .m-s71-c5{ left:129.598px; top:679.215px; width:22.452px; height:22.452px; }
  .m-s71-c6{ left:329.844px; top:656.157px; width:15.170px; height:15.170px; }
  .m-s71-c7{ left:372.320px; top:686.497px; width:15.170px; height:15.170px; }
  .m-s71-c8{ left:45.252px;  top:742.930px; width:15.170px; height:15.170px; }

  /* ----- 8/9/10 — единственный экран со скроллом (Figma 2922:2276) --------
     Канвас 402×2908.65 — в 3.3 раза выше остальных. Три десктопных слайда
     («Почему нас выбирают», «Как проходит внедрение», «Покажем») идут одной
     лентой: решение пользователя.

     Прокрутку держит НЕ браузер: у .m-stage-wrap стоит touch-action:none, а
     touch-action пересекается по всей цепочке предков — нативный pan-y внутри
     всё равно бы не заработал, пришлось бы ослаблять защиту от pull-to-refresh
     на всей сцене. Поэтому лента едет тем же обработчиком жестов, что и трек:
     палец сначала прокручивает её, и только упершись в край — листает
     (longY в js/mobile-slides.js). Transform ленте пишет JS целиком, поэтому
     --m-center-offset здесь НЕ в CSS.

     Секции разбиты по вертикали и НЕ перекрываются — иначе верхняя пустая
     секция ловила бы клики по кнопке нижней.

     ⚠️ Канвас ВЫРОС до 3116 (было 2908.65) с обновлением макета 2026-08-07:
     иллюстрации сменились на квадратных консьержей и стали выше, из-за чего
     весь контент секций 2 и 3 переехал вниз. Высота продублирована в
     LONG_CANVAS_H (js/mobile-slides.js) — от неё считается longMax, предел
     прокрутки; поправить надо ОБА места. */
  .m-long-canvas{ position:absolute; left:0; top:0; width:402px; height:3077px; }
  .m-long-sec{ position:absolute; left:0; width:402px; }
  .m-long-sec--1{ top:0; height:1413px; }
  .m-long-sec--2{ top:1413px; height:871px; }
  .m-long-sec--3{ top:2284px; height:793px; }

  /* Все три иллюстрации теперь квадратные 370×370 — те же файлы, что на
     десктопе. У секции 2 фрейм в макете выше картинки (409 против 370),
     поэтому она смещена внутри него на 9.994. */
  /* Клип по «Ellipse 61» из макета — та же дуга, что на десктопе: персонаж
     срезан снизу, и на срез садится тень-подставка. Без неё консьерж выглядит
     наклеенным (пользователь заметил сразу: «отсутствуют нижние чёрные срезы»).
     Эллипс в макете 697.573×404.533, поэтому радиусы 348.787×202.267; центр
     смещён по вертикали у второй секции — её фрейм выше (409 против 370). */
  .m-long-clip{ position:absolute; left:16px; width:370px; overflow:hidden; }
  .m-long-clip--1{ top:105px; height:370px; clip-path:ellipse(348.787px 202.267px at 185px 137.640px); }
  .m-long-clip--2{ top:0;     height:409px; clip-path:ellipse(348.787px 202.267px at 185px 186.640px); }
  .m-long-clip--3{ top:0;     height:370px; clip-path:ellipse(348.787px 202.267px at 185px 137.640px); }

  .m-long-img{ position:absolute; left:0; width:370px; height:370px; display:block; object-fit:cover; }
  .m-long-img--1{ top:0; }
  .m-long-img--2{ top:9.994px; }
  .m-long-img--3{ top:0; }

  /* Подставки («Subtract» в макете). У первой секции узкая дуга, у второй и
     третьей — широкая; это те же два path, что на десктопе, растянутые
     preserveAspectRatio="none" в макетный бокс. */
  .m-long-stand{ position:absolute; display:block; }
  .m-long-stand--1{ left:71.112px; top:430.416px; width:259.774px; height:14.490px; }
  .m-long-stand--2{ left:22.074px; top:360.299px; width:357.852px; height:28.607px; }
  .m-long-stand--3{ left:22.074px; top:311.299px; width:357.852px; height:28.607px; }

  /* ----- Кружки ленты ------------------------------------------------------
     Координаты локальные для своей секции (см. .m-long-sec--* выше). Слои
     `--far` / `--near` и зачем они — у .m-circ-layer.
     Секция 1: фрейм иллюстрации на (16, 105) внутри секции. */
  .m-l1-c1{ left:80.133px;  top:187.387px; width:204.733px; height:204.733px; }
  .m-l1-c2{ left:238.987px; top:234.007px; width:111.987px; height:111.987px; }
  .m-l1-c3{ left:108.253px; top:196.267px; width:37.987px;  height:37.987px; }
  .m-l1-c4{ left:115.653px; top:308.253px; width:23.187px;  height:23.187px; }
  .m-l1-c5{ left:300.160px; top:177.027px; width:12.333px;  height:12.333px; }
  .m-l1-c6{ left:334.693px; top:349.693px; width:12.333px;  height:12.333px; }
  .m-l1-c7{ left:112.693px; top:305.293px; width:12.333px;  height:12.333px; }

  /* Секция 2: фрейм иллюстрации на (16, 0) внутри секции, но он растянут по
     вертикали (409 против 370), поэтому кружки здесь ЭЛЛИПСЫ — ширина и
     высота отличаются ровно в 1.1054 раза. Так в макете, это не описка. */
  .m-l2-c1{ left:90px;      top:118.338px; width:204.733px; height:226.313px; }
  .m-l2-c2{ left:247.867px; top:47.444px;  width:90.773px;  height:100.341px; }
  .m-l2-c3{ left:253.787px; top:213.498px; width:111.987px; height:123.791px; }
  .m-l2-c4{ left:108.253px; top:100.887px; width:37.987px;  height:41.991px; }
  .m-l2-c5{ left:115.653px; top:126.517px; width:23.187px;  height:25.631px; }
  .m-l2-c6{ left:270.560px; top:79.618px;  width:12.333px;  height:13.633px; }
  .m-l2-c7{ left:339.627px; top:205.045px; width:12.333px;  height:13.633px; }
  .m-l2-c8{ left:78.160px;  top:166.872px; width:12.333px;  height:13.633px; }

  /* Секция 3: фрейм иллюстрации на (16, 0) внутри секции. Последний кружок
     в макете вынесен ЗА masking-illustration — он поверх персонажа, как и на
     десктопе, поэтому живёт в отдельном слое после <img>. */
  .m-l3-c1{ left:104.800px; top:82.387px;  width:204.733px; height:204.733px; }
  .m-l3-c2{ left:238.987px; top:94.473px;  width:111.987px; height:111.987px; }
  .m-l3-c3{ left:104.800px; top:82.387px;  width:78.440px;  height:78.440px; }
  .m-l3-c4{ left:162.520px; top:86.333px;  width:18.253px;  height:18.253px; }
  .m-l3-c5{ left:300.160px; top:72.027px;  width:12.333px;  height:12.333px; }
  .m-l3-c6{ left:334.693px; top:96.693px;  width:12.333px;  height:12.333px; }
  .m-l3-c7{ left:112.693px; top:195.360px; width:12.333px;  height:12.333px; }
  .m-l3-c8{ left:309.533px; top:201.773px; width:23.187px;  height:23.187px; }

  .m-long-h1, .m-long-h2{
    position:absolute; left:32px; width:338px; margin:0; text-align:center;
    font-family:'Unbounded',sans-serif; font-weight:600; font-size:40px;
    line-height:1.1; color:var(--ink);
  }
  .m-long-h1{ top:507px; }
  .m-long-h2{ top:441px; }

  .m-para{
    position:absolute; left:32px; width:338px;
    display:flex; flex-direction:column; gap:24px;
  }
  .m-para--1{ top:627px; }
  .m-para--2{ top:873px; }
  .m-para--3{ top:1077px; }
  /* Локальная координата внутри своей секции: 2018 − 1413. */
  .m-para--4{ top:605px; gap:8px; }
  .m-para__title{ display:flex; gap:16px; align-items:flex-start; }
  /* Компенсатор из макета: кружок галочки опущен на 2px, чтобы оптически
     сесть на первую строку заголовка, а точка списка — на 4px. */
  .m-para__title .m-check{ margin-top:2px; }
  .m-para--4 .m-para__title{ gap:10px; }
  .m-para__title p{
    margin:0; flex:1 0 0; min-width:0; color:var(--ink);
    font-family:'Unbounded',sans-serif; font-weight:500; font-size:20px; line-height:1.2;
  }
  /* Правка макета 2026-08-07: список больше НЕ выровнен по тексту заголовка.
     Точка съехала к левому краю абзаца (pl 5 вместо 39), а расстояние от неё
     до текста выросло до 25 — в макете текст пункта начинается на 40px от
     края, ровно под текстом заголовка. Кегль пунктов 13 (был 12). */
  .m-para__list{
    display:flex; flex-direction:column; gap:16px; padding-left:5px;
  }
  .m-para__li{ display:flex; gap:25px; align-items:flex-start; }
  .m-para__li p{
    margin:0; flex:1 0 0; min-width:0; color:var(--ink);
    font-family:'Unbounded',sans-serif; font-weight:400; font-size:13px; line-height:1.4;
  }
  /* Абзац секции 2 — без галочки и без точки, весь по центру (в макете это
     единственный такой блок: у Title там нет иконки вообще). */
  .m-para--4 .m-para__title p{ text-align:center; }
  .m-para--4 .m-para__list{ padding-left:0; }
  .m-para--4 .m-para__li p{ text-align:center; }
  .m-dot{ width:10px; height:10px; border-radius:50%; background:var(--ink); flex-shrink:0; margin-top:4px; }

  /* Обёртка-<h2> над двумя строками заголовка (см. комментарий в разметке).
     Ни position, ни высоты, ни отступов — в раскладке её нет вообще, обе
     строки как стояли на своих абсолютных координатах, так и стоят. */
  .m-long-h3{ margin:0; font-weight:inherit; font-size:inherit; }
  .m-long-h3__lead, .m-long-h3__big, .m-long-h3__para{
    position:absolute; left:32px; width:338px; margin:0; text-align:center; color:var(--ink);
    font-family:'Unbounded',sans-serif;
  }
  .m-long-h3__lead{ top:402px; font-weight:600; font-size:21px; line-height:1.3; }
  .m-long-h3__big{ top:483px; font-weight:600; font-size:30px; line-height:1.1; }
  /* Между «в вашем объекте» и абзацем в макете стоит отдельный separator16 —
     здесь это просто +16 к координате: 483 + 33 + 16. */
  .m-long-h3__para{ top:532px; font-weight:400; font-size:13px; line-height:1.4; }

  /* Кнопки на ленте — 330×52 с радиусом 26 (у экранных 4-1/5-2 радиус 100
     и ширина по контейнеру, поэтому переопределяем оба). */
  .m-long-cta{ position:absolute; left:36px; width:330px; height:52px; border-radius:26px; }
  .m-long-cta--1{ top:1265px; }
  .m-long-cta--2{ top:636px; }

  /* ----- 11-1 Контакты (Figma 2924:2875) ---------------------------------- */
  .m-c11-head{
    position:absolute; left:16px; top:129px; width:370px;
    display:flex; flex-direction:column; gap:10px;
    text-align:center; color:var(--ink);
  }
  .m-c11-title{ margin:0; font-family:'Unbounded',sans-serif; font-weight:600; font-size:24px; line-height:1.2; }
  .m-c11-sub{ margin:0; font-family:'Unbounded',sans-serif; font-weight:400; font-size:16px; line-height:1.5; }

  .m-c11-list{
    position:absolute; left:16px; top:330px; width:370px;
    display:flex; flex-direction:column; gap:8px;
  }
  .m-c11-pill{
    display:flex; align-items:center; gap:16px;
    width:370px; padding:8px; box-sizing:border-box;
    background:var(--ink); border-radius:100px; text-decoration:none;
  }
  .m-c11-icon{
    position:relative; display:flex; align-items:center; justify-content:center;
    width:64px; height:64px; border-radius:50%; background:var(--yellow); flex-shrink:0;
  }
  .m-c11-icon img{ display:block; width:45.714px; height:45.714px; }
  .m-c11-icon--phone{ width:62.33px; height:62.33px; }
  /* Иконка кнопки «Получить демонстрацию» — 46×46 на (9, 8.67) внутри кружка
     64: в макете она стоит НЕ по центру, поэтому позиционируем числами, а не
     флексом. Фон, а не <img>, — см. комментарий в index.html. */
  .m-c11-icon--demo::before{
    content:''; position:absolute; left:9px; top:8.67px; width:46px; height:46px;
    background:url(../images/demo-icon.svg) center/contain no-repeat;
  }
  /* Телефончик внутри жёлтого кружка — статичная иконка (см. index.html):
     та же рамка с точкой-камерой, но своими числами из макета, а не приехавший
     сюда сквозной слой. Координаты — от кружка.
     Правка макета 2026-08-07: бордер стал 3px (был 2.359). */
  .m-c11-phone{
    position:absolute; left:17.583px; top:5.241px; width:26.417px; height:51.42px;
    box-sizing:border-box; border:3px solid var(--ink); border-radius:4.717px;
  }
  /* Точка-камера тоже переехала и подросла: 5×5 на (29, 10) — правка макета
     2026-08-07 (было 3.774 и правее-ниже). Числа отсчитываются ОТ КРУЖКА, а
     не от рамки телефона, поэтому и висит она на кружке: у рамки свой бордер,
     и координаты внутри неё пришлось бы каждый раз пересчитывать на его
     толщину — ровно та арифметика, в которой легко ошибиться при следующей
     правке макета. */
  .m-c11-icon--phone::after{
    content:''; position:absolute; left:29px; top:10px;
    width:5px; height:5px; border-radius:50%; background:var(--ink);
  }
  /* Текстовый блок НЕ растягивается на всю оставшуюся ширину и НЕ центрируется
     в ней: по макету он начинается сразу за иконкой (правка пользователя —
     «левое выравнивание, как на макете»). Подпись прижата влево, само
     значение отцентровано внутри блока — так в Figma. */
  .m-c11-text{ display:flex; flex-direction:column; align-items:stretch; gap:4px; min-width:0; }
  .m-c11-label{
    font-family:'Source Sans Pro',sans-serif; font-weight:600; font-size:14px;
    letter-spacing:0.5714px; text-transform:uppercase; color:#fff; text-align:left;
  }
  .m-c11-value{
    font-family:'Unbounded',sans-serif; font-weight:500; font-size:18px;
    line-height:1.3; text-align:center; color:#fff;
  }
  .m-c11-cta{
    position:absolute; left:16px; top:528.33px; width:370px; height:80px;
    padding:8px; box-sizing:border-box;
    display:flex; align-items:center; gap:16px;
    background:var(--ink); border:none; border-radius:40px; cursor:pointer;
  }
  .m-c11-cta__text{
    font-family:'Unbounded',sans-serif; font-weight:500; font-size:18px;
    line-height:1.3; color:#fff; text-align:left;
  }
  .m-c11-address{
    position:absolute; left:58.5px; top:640.33px; width:285px;
    display:flex; flex-direction:column; align-items:center; gap:4px;
    text-align:center;
  }
  .m-c11-address .m-c11-label, .m-c11-address .m-c11-value{ color:var(--ink); }

  /* ===== Мобильные оверлеи: меню, форма, попап о компании =================
     Живут СНАРУЖИ .m-stage-wrap (см. разметку) и потому свободны от её
     touch-action:none и клипа — форма может нативно скроллиться, а затемнение
     накрывает в том числе шапку.

     Масштаб — ШАПОЧНЫЙ (--m-header-scale): это UI-хром, он обязан занимать всю
     ширину экрана. Высота канваса задаётся в дизайн-px через --m-vh-design
     (реальная высота вьюпорта, делённая на тот же масштаб) — так вёрстка
     внутри остаётся в дизайн-координатах, а привязка «прижать к низу экрана»
     работает на любом телефоне. */
  /* touch-action:pan-y — вертикальную прокрутку браузеру оставляем (форма и
     карточка попапа прокручиваются нативно), а щипок и двойной тап забираем:
     любое значение, кроме auto/manipulation, отключает и pinch-zoom, и
     double-tap-zoom. Внутри сцены то же самое даёт touch-action:none, но
     оверлеи лежат СНАРУЖИ неё и это правило до них не доставало — форму можно
     было случайно растянуть пальцами. */
  /* touch-action:manipulation на всём, что нажимается: убирает у Chrome на
     Android ожидание второго тапа (double-tap-to-zoom) перед тем, как отдать
     click. Вместе с реакцией на pointerup в js/mobile-overlays.js это и лечит
     жалобу «кнопка срабатывает только со второго раза». */
  .m-menu-btn, .m-demo-btn, .m-logo-stack, .m-ov__close,
  #m-menu [data-nav-group], #m-menu [data-action], .m-menu__logo,
  .m-s41-about, .m-s52-cta, .m-long-cta, .m-c11-cta, .m-menu-cta,
  .m-last__links button, .m-last__contacts a{
    touch-action:manipulation;
  }

  .m-ov{
    position:fixed; inset:0; z-index:300;
    opacity:0; visibility:hidden; pointer-events:none;
    background:var(--ink); touch-action:pan-y;
  }
  .m-ov.is-open{ opacity:1; visibility:visible; pointer-events:auto; }
  /* Попап о компании — не сплошной экран, а карточка на затемнении. */
  #m-lastpopup{ background:rgba(0,0,0,0.8); }
  /* ⚠️ touch-action:none у попапа — не перестраховка, а лечение живого бага:
     свайп вниз закрывал попап на iOS в Safari и НЕ работал на Android
     (пользователь проверил на обоих). Причина — унаследованный от .m-ov
     `pan-y`: Chrome считает вертикальный жест своей прокруткой, забирает его
     и рвёт поток pointer-событий (нам прилетает pointercancel, дальше тишина).
     Safari в этой же ситуации события отдавал, поэтому баг выглядел
     «случайным». Прокручивать здесь всё равно нечего — карточка помещается
     целиком; исключение ниже.
     Сама карточка тоже none: touch-action ПЕРЕСЕКАЕТСЯ по цепочке предков,
     значит ребёнку строже родителя быть можно, а свободнее — нет, и писать
     правило нужно там, где начинается жест. */
  #m-lastpopup{ touch-action:none; }
  .m-last__card{ touch-action:none; }
  /* Исключение: на коротком экране контент не влезает и карточка становится
     настоящим скроллером (класс вешает fitLast в js/mobile-overlays.js).
     Тогда вертикаль отдаём браузеру — прокрутка важнее жеста, а закрыть
     попап всегда можно крестиком или тапом мимо. */
  .m-last__card.is-scrollable{ touch-action:pan-y; }
  #m-demo{ background:rgba(0,0,0,0.8); }

  .m-ov__canvas{
    position:absolute; left:0; top:0;
    width:calc(402px + 2 * var(--m-header-bleed, 0px));
    height:var(--m-vh-design, 874px);
    transform:scale(var(--m-header-scale,1)); transform-origin:left top;
  }
  /* Форма выше экрана (961 дизайн-px), поэтому её канвас живёт в нативном
     скроллере. overscroll-behavior:none — чтобы дотяг за край не уводил
     страницу под ним и не давал резинку. */
  /* overflow-x:hidden — не косметика, а лечение реального бага, видимого
     только на ДЕСКТОПЕ в узком окне. Канвас масштабируется transform'ом, а его
     LAYOUT-ширина остаётся 402 дизайн-px. На телефоне это безобидно
     (скроллбары там overlay и места не занимают), а в десктопном Chrome
     вертикальный скроллбар формы отъедает у скроллера ~15px, и при окне около
     400px клиентская ширина становится меньше 402 — вылезала вторая, уже
     горизонтальная полоса. Скрывать сами полосы тоже приходится здесь: на
     мобильном устройстве их всё равно не видно, а в десктопной проверке
     мобильной вёрстки они читаются как поломка макета. */
  .m-ov--scroll .m-ov__scroller{
    position:absolute; inset:0; overflow-y:auto; overflow-x:hidden;
    -webkit-overflow-scrolling:touch; overscroll-behavior:none;
    scrollbar-width:none; -ms-overflow-style:none;
  }
  .m-ov--scroll .m-ov__scroller::-webkit-scrollbar{ width:0; height:0; }
  /* САЙЗЕР — не декорация, а лечение конкретного бага: канвас масштабируется
     transform'ом, а transform НЕ участвует в раскладке. Скроллер мерил бы
     немасштабированную высоту канваса и при --m-header-scale ≈ 0.9 давал ход
     прокрутки на ~11% больше нужного — снизу вылезала полоса фона (жёлтая, по
     цвету страницы). Высоту скроллируемой области теперь задаёт этот пустой
     блок, а js/mobile-overlays.js пишет ему ФАКТИЧЕСКУЮ высоту (высота канваса
     × масштаб). */
  .m-ov--scroll .m-ov__sizer{ position:relative; width:100%; height:100%; }
  /* Полоса с крестиком: лежит ПОВЕРХ скроллера и не прокручивается вместе с
     формой. Высота нулевая — она только задаёт систему координат в
     дизайн-пикселях (тот же шапочный масштаб, что у канваса). */
  .m-ov__topbar{
    position:absolute; left:0; top:0; height:0; z-index:5;
    width:calc(402px + 2 * var(--m-header-bleed, 0px));
    transform:scale(var(--m-header-scale,1)); transform-origin:left top;
    pointer-events:none;
  }
  .m-ov__topbar .m-ov__close{ pointer-events:auto; }
  /* На время выезда панели снизу прячем переполнение, иначе уехавшая вниз
     панель на миг добавляет скроллеру лишний ход. */
  .m-ov--scroll.is-anim .m-ov__scroller{ overflow:hidden; }
  .m-ov--scroll .m-ov__canvas{ height:auto; }

  /* Крестик. Два варианта: в меню — просто линии в углу (как в макете),
     у формы и попапа — в жёлтом круге по центру над карточкой. */
  .m-ov__close{
    position:absolute; right:16px; top:18px; width:32px; height:32px;
    background:none; border:none; padding:0; cursor:pointer; z-index:2;
  }
  .m-ov__close span{
    position:absolute; left:50%; top:50%; width:26px; height:2.5px;
    margin:-1.25px 0 0 -13px; background:#fff; border-radius:2px;
  }
  .m-ov__close span:first-child{ transform:rotate(45deg); }
  .m-ov__close span:last-child{ transform:rotate(-45deg); }
  .m-ov__close--round{
    left:50%; right:auto; top:24px; margin-left:-24px; width:48px; height:48px;
    background:var(--yellow); border-radius:50%;
  }
  .m-ov__close--round span{ width:17.6px; margin:-1.25px 0 0 -8.8px; background:var(--ink); }

  /* ----- Меню (Figma 2924:4470) -------------------------------------------
     Геометрия макета (канвас 402×874):
       шапка 0…68   лого 64×52 на (16, 8), крестик 32×32 на (354, 18)
       пункты 105…395   шаг: строка + 32 (пятая строка кончается на 395)
       кнопки 443…613   две 270.4×64, зазор 10, по центру
       Media5 621…874   ручка 42×4 на y 14, лого-строка на y 52…84,
                        стрелка 16×9 на y 123 — всё по центру канваса

     Раскладка привязана к РЕАЛЬНОЙ высоте экрана, а не к 874-канвасу: блок
     Media5 прижат к низу, пункты с кнопками занимают всё, что осталось между
     шапкой и им. На коротком телефоне это единственный способ не получить
     обрезанное меню — поэтому у Media5 разрешено ужиматься (flex-shrink) до
     152px, ниже которых начинается уже его пустой чёрный хвост. */
  #m-menu .m-ov__canvas{ display:flex; flex-direction:column; }
  .m-menu__logo{
    position:absolute; left:16px; top:8px; width:64px; height:52px;
    display:block; z-index:2; cursor:pointer;
  }
  /* Четыре размера ниже задаёт fitMenu() в js/mobile-overlays.js — иначе на
     коротком вьюпорте (в Safari панели съедают заметную часть высоты) пункты
     не влезали и наезжали на кнопки. Значения по умолчанию — макетные, они и
     остаются на экранах, где всё помещается. */
  /* Пункты НЕ растягиваются на весь свободный остаток. Зазор до жёлтой кнопки
     И зазор от пунктирной кнопки до чёрной плашки — оба в ПОЛТОРА раза больше
     зазора между пунктами (правка пользователя: на маленьком айфоне блоки
     слипались). Излишек высоты забирает margin-top:auto у Media5: авто-margin
     в флексе съедает свободное место, а margin-bottom у кнопок остаётся
     жёстким минимумом и не схлопывается, когда места впритык. */
  .m-menu__nav{
    flex:0 0 auto;
    display:flex; flex-direction:column; align-items:center;
    gap:var(--m-menu-gap, 32px);
    padding:var(--m-menu-top, 105px) 16px 0;
  }
  .m-menu__nav button{
    width:100%; padding:0; background:none; border:none; cursor:pointer;
    font-family:'Unbounded',sans-serif; font-weight:500;
    font-size:var(--m-menu-fs, 21px);
    line-height:1.3; text-transform:uppercase; text-align:center; color:#fff;
  }
  .m-menu__buttons{
    flex:0 0 auto; display:flex; flex-direction:column; align-items:center; gap:10px;
    margin-top:calc(var(--m-menu-gap, 32px) * 1.5);
    margin-bottom:calc(var(--m-menu-gap, 32px) * 1.5);
    padding:0 32px;
  }
  .m-menu-cta{
    display:flex; align-items:center; gap:13.6px;
    width:270.4px; height:64px; padding:0 6.4px; box-sizing:border-box;
    border-radius:32px; border:none; cursor:pointer;
    font-family:'Unbounded',sans-serif; font-weight:500; font-size:14px; line-height:1.3;
    text-align:left;
  }
  .m-menu-cta__icon{
    display:flex; align-items:center; justify-content:center;
    width:51.2px; height:51.2px; border-radius:50%; background:var(--ink); flex-shrink:0;
  }
  /* Глиф маской, а не картинкой: mail.svg и settings-icon.svg чёрные без
     собственного fill. Конверт раньше выбеливали filter:invert(1) — он должен
     быть ЖЁЛТЫМ; шестерёнка вообще пропадала, потому что чёрное на чёрном.

     ⚠️ SVG ВСТРОЕН data-URI, а не взят по ссылке — и это не оптимизация, а
     необходимость. mask-image, в отличие от background-image, подчиняется
     CORS: при открытии сайта по file:// origin равен null, и браузер молча
     блокирует внешний файл маски. Клиент, распаковавший архив и открывший
     index.html двойным щелчком, видел пустые кружки вместо иконок. Тот же
     урок, что был со шрифтами: всё, что нужно для отрисовки, живёт внутри
     CSS. Схема data: разрешена явно, ей CORS не мешает. */
  .m-menu-cta__glyph{
    display:block; background-color:var(--yellow);
    -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
    -webkit-mask-size:contain; mask-size:contain;
    -webkit-mask-position:center; mask-position:center;
  }
  .m-menu-cta--filled{ background:var(--yellow); color:var(--ink); }
  .m-menu-cta--filled .m-menu-cta__glyph{
    width:36.571px; height:36.571px;
    -webkit-mask-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJDYXBhXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgNTEyIDUxMiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNTEyIDUxMjsiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPGc+DQoJPGc+DQoJCTxwYXRoIGQ9Ik00NjcsNzZINDVDMjAuMTM3LDc2LDAsOTYuMjYyLDAsMTIxdjI3MGMwLDI0Ljg4NSwyMC4yODUsNDUsNDUsNDVoNDIyYzI0LjY1NSwwLDQ1LTIwLjAzLDQ1LTQ1VjEyMQ0KCQkJQzUxMiw5Ni4zMDYsNDkxLjk0Myw3Niw0NjcsNzZ6IE00NjAuNjk4LDEwNmMtOS4xOTQsOS4xNDUtMTY3LjQxNSwxNjYuNTMzLTE3Mi44NzgsMTcxLjk2N2MtOC41LDguNS0xOS44LDEzLjE4LTMxLjgyLDEzLjE4DQoJCQlzLTIzLjMyLTQuNjgxLTMxLjg0OC0xMy4yMDhDMjIwLjQ3OCwyNzQuMjg0LDY0LjAwMywxMTguNjM0LDUxLjMwMiwxMDZINDYwLjY5OHogTTMwLDM4NC44OTRWMTI3LjEyNUwxNTkuNjM4LDI1Ni4wOEwzMCwzODQuODk0eg0KCQkJIE01MS4zMjEsNDA2bDEyOS41ODctMTI4Ljc2M2wyMi4wNTksMjEuOTQzYzE0LjE2NiwxNC4xNjYsMzMsMjEuOTY3LDUzLjAzMywyMS45NjdjMjAuMDMzLDAsMzguODY3LTcuODAxLDUzLjAwNS0yMS45MzkNCgkJCWwyMi4wODctMjEuOTcxTDQ2MC42NzksNDA2SDUxLjMyMXogTTQ4MiwzODQuODk0TDM1Mi4zNjIsMjU2LjA4TDQ4MiwxMjcuMTI1VjM4NC44OTR6Ii8+DQoJPC9nPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPC9zdmc+DQo=);
    mask-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJDYXBhXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgNTEyIDUxMiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNTEyIDUxMjsiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPGc+DQoJPGc+DQoJCTxwYXRoIGQ9Ik00NjcsNzZINDVDMjAuMTM3LDc2LDAsOTYuMjYyLDAsMTIxdjI3MGMwLDI0Ljg4NSwyMC4yODUsNDUsNDUsNDVoNDIyYzI0LjY1NSwwLDQ1LTIwLjAzLDQ1LTQ1VjEyMQ0KCQkJQzUxMiw5Ni4zMDYsNDkxLjk0Myw3Niw0NjcsNzZ6IE00NjAuNjk4LDEwNmMtOS4xOTQsOS4xNDUtMTY3LjQxNSwxNjYuNTMzLTE3Mi44NzgsMTcxLjk2N2MtOC41LDguNS0xOS44LDEzLjE4LTMxLjgyLDEzLjE4DQoJCQlzLTIzLjMyLTQuNjgxLTMxLjg0OC0xMy4yMDhDMjIwLjQ3OCwyNzQuMjg0LDY0LjAwMywxMTguNjM0LDUxLjMwMiwxMDZINDYwLjY5OHogTTMwLDM4NC44OTRWMTI3LjEyNUwxNTkuNjM4LDI1Ni4wOEwzMCwzODQuODk0eg0KCQkJIE01MS4zMjEsNDA2bDEyOS41ODctMTI4Ljc2M2wyMi4wNTksMjEuOTQzYzE0LjE2NiwxNC4xNjYsMzMsMjEuOTY3LDUzLjAzMywyMS45NjdjMjAuMDMzLDAsMzguODY3LTcuODAxLDUzLjAwNS0yMS45MzkNCgkJCWwyMi4wODctMjEuOTcxTDQ2MC42NzksNDA2SDUxLjMyMXogTTQ4MiwzODQuODk0TDM1Mi4zNjIsMjU2LjA4TDQ4MiwxMjcuMTI1VjM4NC44OTR6Ii8+DQoJPC9nPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPC9zdmc+DQo=);
  }
  .m-menu-cta--ghost{
    background:none; color:var(--yellow);
    border:0.8px dashed var(--yellow);
  }
  .m-menu-cta--ghost .m-menu-cta__icon{ border:0.8px dashed var(--yellow); box-sizing:border-box; }
  .m-menu-cta--ghost .m-menu-cta__glyph{
    width:32px; height:32px;
    -webkit-mask-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzIiIGhlaWdodD0iNzIiIHZpZXdCb3g9IjAgMCA3MiA3MiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzI4OThfMTMyOSkiPgo8cGF0aCBkPSJNMzYuMDAwMSA1NS42MjU2QzI1LjE3ODYgNTUuNjI1NiAxNi4zNzQ1IDQ2LjgyMTcgMTYuMzc0NSAzNkMxNi4zNzQ1IDI1LjE3ODQgMjUuMTc4NiAxNi4zNzQ0IDM2LjAwMDEgMTYuMzc0NEM0Ni44MjE3IDE2LjM3NDQgNTUuNjI1OCAyNS4xNzg0IDU1LjYyNTggMzZDNTUuNjI1OCA0Ni44MjE3IDQ2LjgyMTcgNTUuNjI1NiAzNi4wMDAxIDU1LjYyNTZaTTM2LjAwMDEgMjAuNTkzMUMyNy41MDQ4IDIwLjU5MzEgMjAuNTkzMyAyNy41MDQ2IDIwLjU5MzMgMzZDMjAuNTkzMyA0NC40OTU1IDI3LjUwNDggNTEuNDA2OSAzNi4wMDAxIDUxLjQwNjlDNDQuNDk1NCA1MS40MDY5IDUxLjQwNyA0NC40OTUzIDUxLjQwNyAzNkM1MS40MDcgMjcuNTA0NyA0NC40OTU0IDIwLjU5MzEgMzYuMDAwMSAyMC41OTMxWiIgZmlsbD0iIzFBMUExQyIvPgo8cGF0aCBkPSJNMzMuNzk0MSA0My42MjMxTDI3LjU4MTUgMzcuNDEwNEwzMC41NjQ2IDM0LjQyNzNMMzMuNzk0MSAzNy42NTY5TDQxLjU4MjkgMjkuODY4M0w0NC41NjYgMzIuODUxNUwzMy43OTQxIDQzLjYyMzFaIiBmaWxsPSIjMUExQTFDIi8+CjxwYXRoIGQ9Ik00MS44MjE3IDcySDMwLjE3ODFMMjguMDg5MyA2NC44MDg5QzI1LjY5NDkgNjQuMTUxIDIzLjM5NzMgNjMuMTk2MiAyMS4yMzIzIDYxLjk1OTFMMTQuNjYwNyA2NS41NzI1TDYuNDI3NDEgNTcuMzM5MUwxMC4wNDA2IDUwLjc2NzVDOC44MDM1NSA0OC42MDI0IDcuODQ4NyA0Ni4zMDQ5IDcuMTkwODYgNDMuOTEwNkwwIDQxLjgyMTlWMzAuMTc4MUw3LjE5MTE0IDI4LjA4OTRDNy44NDg5OCAyNS42OTUxIDguODAzODMgMjMuMzk3NiAxMC4wNDA5IDIxLjIzMjVMNi40Mjc2OSAxNC42NjA5TDE0LjY2MSA2LjQyNzU1TDIxLjIzMjUgMTAuMDQwOUMyMy4zOTc2IDguODAzODMgMjUuNjk1IDcuODQ5MTMgMjguMDg5NiA3LjE5MTE0TDMwLjE3ODMgMEg0MS44MjE5TDQzLjkxMDcgNy4xOTExNEM0Ni4zMDUxIDcuODQ4OTggNDguNjAyNyA4LjgwMzgzIDUwLjc2NzcgMTAuMDQwOUw1Ny4zMzkzIDYuNDI3NTVMNjUuNTcyNiAxNC42NjA5TDYxLjk1OTQgMjEuMjMyNUM2My4xOTY1IDIzLjM5NzYgNjQuMTUxMyAyNS42OTUxIDY0LjgwOTEgMjguMDg5NEw3MiAzMC4xNzgxVjQxLjgyMTlMNjQuODA4OSA0My45MTA2QzY0LjE1MSA0Ni4zMDQ5IDYzLjE5NjIgNDguNjAyNCA2MS45NTkxIDUwLjc2NzVMNjUuNTcyMyA1Ny4zMzkxTDU3LjMzOSA2NS41NzI1TDUwLjc2NzUgNjEuOTU5MUM0OC42MDI0IDYzLjE5NjIgNDYuMzA1IDY0LjE1MDkgNDMuOTEwNCA2NC44MDg5TDQxLjgyMTcgNzJaTTMzLjM0NTggNjcuNzgxMkgzOC42NTQyTDQwLjU0MiA2MS4yODE0TDQxLjc0OTcgNjEuMDAzOEM0NC41Mjg5IDYwLjM2NTEgNDcuMTcwNCA1OS4yNjc0IDQ5LjYwMDggNTcuNzQwOUw1MC42NTE3IDU3LjA4MUw1Ni41OTYxIDYwLjM0OTRMNjAuMzQ5NiA1Ni41OTU4TDU3LjA4MTIgNTAuNjUxNEw1Ny43NDEgNDkuNjAwNUM1OS4yNjc0IDQ3LjE3IDYwLjM2NTIgNDQuNTI4NSA2MS4wMDQgNDEuNzQ5M0w2MS4yODE2IDQwLjU0MThMNjcuNzgxMiAzOC42NTQyVjMzLjM0NThMNjEuMjgxNCAzMS40NThMNjEuMDAzOCAzMC4yNTA0QzYwLjM2NTEgMjcuNDcxMiA1OS4yNjcyIDI0LjgyOTcgNTcuNzQwOSAyMi4zOTkyTDU3LjA4MTEgMjEuMzQ4M0w2MC4zNDk1IDE1LjQwMzlMNTYuNTk1OSAxMS42NTA1TDUwLjY1MTYgMTQuOTE4OUw0OS42MDA3IDE0LjI1OUM0Ny4xNzAzIDEyLjczMjYgNDQuNTI4OCAxMS42MzQ4IDQxLjc0OTYgMTAuOTk2TDQwLjU0MTkgMTAuNzE4NEwzOC42NTQyIDQuMjE4NzVIMzMuMzQ1OEwzMS40NTggMTAuNzE4NkwzMC4yNTAzIDEwLjk5NjJDMjcuNDcxMSAxMS42MzQ5IDI0LjgyOTYgMTIuNzMyNiAyMi4zOTkyIDE0LjI1OTFMMjEuMzQ4MyAxNC45MTlMMTUuNDA0MSAxMS42NTA1TDExLjY1MDUgMTUuNDA0MUwxNC45MTg5IDIxLjM0ODRMMTQuMjU5MSAyMi4zOTkzQzEyLjczMjggMjQuODI5OSAxMS42MzQ5IDI3LjQ3MTQgMTAuOTk2MiAzMC4yNTA1TDEwLjcxODYgMzEuNDU4MUw0LjIxODc1IDMzLjM0NThWMzguNjU0MkwxMC43MTg2IDQwLjU0MkwxMC45OTYyIDQxLjc0OTZDMTEuNjM0OSA0NC41Mjg4IDEyLjczMjggNDcuMTcwMyAxNC4yNTkxIDQ5LjYwMDhMMTQuOTE4OSA1MC42NTE3TDExLjY1MDUgNTYuNTk1OUwxNS40MDQxIDYwLjM0OTVMMjEuMzQ4NCA1Ny4wODExTDIyLjM5OTMgNTcuNzQxQzI0LjgyOTcgNTkuMjY3NCAyNy40NzEyIDYwLjM2NTIgMzAuMjUwNCA2MS4wMDRMMzEuNDU4MSA2MS4yODE2TDMzLjM0NTggNjcuNzgxMloiIGZpbGw9IiMxQTFBMUMiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF8yODk4XzEzMjkiPgo8cmVjdCB3aWR0aD0iNzIiIGhlaWdodD0iNzIiIGZpbGw9IndoaXRlIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==);
    mask-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzIiIGhlaWdodD0iNzIiIHZpZXdCb3g9IjAgMCA3MiA3MiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzI4OThfMTMyOSkiPgo8cGF0aCBkPSJNMzYuMDAwMSA1NS42MjU2QzI1LjE3ODYgNTUuNjI1NiAxNi4zNzQ1IDQ2LjgyMTcgMTYuMzc0NSAzNkMxNi4zNzQ1IDI1LjE3ODQgMjUuMTc4NiAxNi4zNzQ0IDM2LjAwMDEgMTYuMzc0NEM0Ni44MjE3IDE2LjM3NDQgNTUuNjI1OCAyNS4xNzg0IDU1LjYyNTggMzZDNTUuNjI1OCA0Ni44MjE3IDQ2LjgyMTcgNTUuNjI1NiAzNi4wMDAxIDU1LjYyNTZaTTM2LjAwMDEgMjAuNTkzMUMyNy41MDQ4IDIwLjU5MzEgMjAuNTkzMyAyNy41MDQ2IDIwLjU5MzMgMzZDMjAuNTkzMyA0NC40OTU1IDI3LjUwNDggNTEuNDA2OSAzNi4wMDAxIDUxLjQwNjlDNDQuNDk1NCA1MS40MDY5IDUxLjQwNyA0NC40OTUzIDUxLjQwNyAzNkM1MS40MDcgMjcuNTA0NyA0NC40OTU0IDIwLjU5MzEgMzYuMDAwMSAyMC41OTMxWiIgZmlsbD0iIzFBMUExQyIvPgo8cGF0aCBkPSJNMzMuNzk0MSA0My42MjMxTDI3LjU4MTUgMzcuNDEwNEwzMC41NjQ2IDM0LjQyNzNMMzMuNzk0MSAzNy42NTY5TDQxLjU4MjkgMjkuODY4M0w0NC41NjYgMzIuODUxNUwzMy43OTQxIDQzLjYyMzFaIiBmaWxsPSIjMUExQTFDIi8+CjxwYXRoIGQ9Ik00MS44MjE3IDcySDMwLjE3ODFMMjguMDg5MyA2NC44MDg5QzI1LjY5NDkgNjQuMTUxIDIzLjM5NzMgNjMuMTk2MiAyMS4yMzIzIDYxLjk1OTFMMTQuNjYwNyA2NS41NzI1TDYuNDI3NDEgNTcuMzM5MUwxMC4wNDA2IDUwLjc2NzVDOC44MDM1NSA0OC42MDI0IDcuODQ4NyA0Ni4zMDQ5IDcuMTkwODYgNDMuOTEwNkwwIDQxLjgyMTlWMzAuMTc4MUw3LjE5MTE0IDI4LjA4OTRDNy44NDg5OCAyNS42OTUxIDguODAzODMgMjMuMzk3NiAxMC4wNDA5IDIxLjIzMjVMNi40Mjc2OSAxNC42NjA5TDE0LjY2MSA2LjQyNzU1TDIxLjIzMjUgMTAuMDQwOUMyMy4zOTc2IDguODAzODMgMjUuNjk1IDcuODQ5MTMgMjguMDg5NiA3LjE5MTE0TDMwLjE3ODMgMEg0MS44MjE5TDQzLjkxMDcgNy4xOTExNEM0Ni4zMDUxIDcuODQ4OTggNDguNjAyNyA4LjgwMzgzIDUwLjc2NzcgMTAuMDQwOUw1Ny4zMzkzIDYuNDI3NTVMNjUuNTcyNiAxNC42NjA5TDYxLjk1OTQgMjEuMjMyNUM2My4xOTY1IDIzLjM5NzYgNjQuMTUxMyAyNS42OTUxIDY0LjgwOTEgMjguMDg5NEw3MiAzMC4xNzgxVjQxLjgyMTlMNjQuODA4OSA0My45MTA2QzY0LjE1MSA0Ni4zMDQ5IDYzLjE5NjIgNDguNjAyNCA2MS45NTkxIDUwLjc2NzVMNjUuNTcyMyA1Ny4zMzkxTDU3LjMzOSA2NS41NzI1TDUwLjc2NzUgNjEuOTU5MUM0OC42MDI0IDYzLjE5NjIgNDYuMzA1IDY0LjE1MDkgNDMuOTEwNCA2NC44MDg5TDQxLjgyMTcgNzJaTTMzLjM0NTggNjcuNzgxMkgzOC42NTQyTDQwLjU0MiA2MS4yODE0TDQxLjc0OTcgNjEuMDAzOEM0NC41Mjg5IDYwLjM2NTEgNDcuMTcwNCA1OS4yNjc0IDQ5LjYwMDggNTcuNzQwOUw1MC42NTE3IDU3LjA4MUw1Ni41OTYxIDYwLjM0OTRMNjAuMzQ5NiA1Ni41OTU4TDU3LjA4MTIgNTAuNjUxNEw1Ny43NDEgNDkuNjAwNUM1OS4yNjc0IDQ3LjE3IDYwLjM2NTIgNDQuNTI4NSA2MS4wMDQgNDEuNzQ5M0w2MS4yODE2IDQwLjU0MThMNjcuNzgxMiAzOC42NTQyVjMzLjM0NThMNjEuMjgxNCAzMS40NThMNjEuMDAzOCAzMC4yNTA0QzYwLjM2NTEgMjcuNDcxMiA1OS4yNjcyIDI0LjgyOTcgNTcuNzQwOSAyMi4zOTkyTDU3LjA4MTEgMjEuMzQ4M0w2MC4zNDk1IDE1LjQwMzlMNTYuNTk1OSAxMS42NTA1TDUwLjY1MTYgMTQuOTE4OUw0OS42MDA3IDE0LjI1OUM0Ny4xNzAzIDEyLjczMjYgNDQuNTI4OCAxMS42MzQ4IDQxLjc0OTYgMTAuOTk2TDQwLjU0MTkgMTAuNzE4NEwzOC42NTQyIDQuMjE4NzVIMzMuMzQ1OEwzMS40NTggMTAuNzE4NkwzMC4yNTAzIDEwLjk5NjJDMjcuNDcxMSAxMS42MzQ5IDI0LjgyOTYgMTIuNzMyNiAyMi4zOTkyIDE0LjI1OTFMMjEuMzQ4MyAxNC45MTlMMTUuNDA0MSAxMS42NTA1TDExLjY1MDUgMTUuNDA0MUwxNC45MTg5IDIxLjM0ODRMMTQuMjU5MSAyMi4zOTkzQzEyLjczMjggMjQuODI5OSAxMS42MzQ5IDI3LjQ3MTQgMTAuOTk2MiAzMC4yNTA1TDEwLjcxODYgMzEuNDU4MUw0LjIxODc1IDMzLjM0NThWMzguNjU0MkwxMC43MTg2IDQwLjU0MkwxMC45OTYyIDQxLjc0OTZDMTEuNjM0OSA0NC41Mjg4IDEyLjczMjggNDcuMTcwMyAxNC4yNTkxIDQ5LjYwMDhMMTQuOTE4OSA1MC42NTE3TDExLjY1MDUgNTYuNTk1OUwxNS40MDQxIDYwLjM0OTVMMjEuMzQ4NCA1Ny4wODExTDIyLjM5OTMgNTcuNzQxQzI0LjgyOTcgNTkuMjY3NCAyNy40NzEyIDYwLjM2NTIgMzAuMjUwNCA2MS4wMDRMMzEuNDU4MSA2MS4yODE2TDMzLjM0NTggNjcuNzgxMloiIGZpbGw9IiMxQTFBMUMiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF8yODk4XzEzMjkiPgo8cmVjdCB3aWR0aD0iNzIiIGhlaWdodD0iNzIiIGZpbGw9IndoaXRlIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==);
  }

  /* Блок Media5 — триггер попапа о компании. Чёрный (не --ink), скруглён
     сверху на 32, прижат к низу экрана. Внутри всё позиционируется абсолютно
     по макету: ручка, строка «Продукт компании + media5» и стрелка — по
     центру канваса, лого и подпись выровнены по ОДНОЙ горизонтальной оси. */
  .m-menu__media5{
    position:relative; flex:0 0 var(--m-menu-m5, 252px); margin-top:auto;
    background:#000; border-radius:32px 32px 0 0;
    cursor:pointer;
    /* Свайп вверх по плашке открывает попап о компании — жест наш, браузеру
       его отдавать нельзя. */
    touch-action:none;
  }
  /* Ручка/лого/шеврон центрируются через 50%, а не фиксированным left от
     402-канваса: на планшете канвас оверлея расширен до ширины экрана
     (--m-header-bleed, см. .m-ov__canvas), и макетные left:180/0/193 оставляли
     всю начинку плашки прижатой влево, хотя сама плашка тянулась во всю
     ширину. Числа — те же центры, что в макете (201 = 402/2). */
  .m-menu__grip{
    position:absolute; left:50%; margin-left:-21px; top:14px; width:42px; height:4px;
    background:rgba(255,255,255,0.3); border-radius:100px;
  }
  /* Строка лого: центр подписи и центр знака media5 на одной оси y=68
     (правка пользователя «выровняй по центру лого и подпись»). */
  .m-menu__media5-logo{
    position:absolute; left:0; top:52px; width:100%; height:32px;
    display:flex; align-items:center; justify-content:center; gap:12px;
  }
  .m-menu__media5-logo p{
    margin:0; width:75px; text-align:right; color:#fff;
    font-family:'Unbounded',sans-serif; font-weight:400; font-size:12px; line-height:1.1;
  }
  .m-menu__media5-logo img{ width:143.353px; height:32px; display:block; }
  /* Шеврон вниз — тот же приём, что у указателя на 5-1. Цвет ТОТ ЖЕ, что у
     ручки: пользователь отметил, что они должны быть одним цветом. */
  .m-menu__chev{
    position:absolute; left:50%; margin-left:-8px; top:123px; width:16px; height:9px;
  }
  .m-menu__chev::after{
    content:''; position:absolute; left:3.5px; top:-2px; width:9px; height:9px;
    border-right:2px solid rgba(255,255,255,0.3); border-bottom:2px solid rgba(255,255,255,0.3);
    transform:rotate(45deg);
  }

  /* ----- Форма-заявка (Figma 2924:4595) -----------------------------------
     Геометрия макета (канвас 402×961, координаты от верха канваса):
       0…24     прозрачная полоса — сквозь неё и 60%-затемнение виден слайд
       24       верх панели, скругление 24 сверху; крестик 48 сидит НА кромке
       48…140   заголовок + подзаголовок (16 по бокам, ширина 362)
       156…602  пять полей: высота 48, шаг 96 (последнее — textarea, 62)
       626…752  чекбокс согласия
       800…856  кнопка 178×56
       856…961  нижнее поле 105 — то же, что у всех экранов

     Поля — плавающая подпись поверх линии, тот же паттерн, что у десктопной
     .demo-field: подпись поднимается, когда поле в фокусе или непустое
     (:not(:placeholder-shown)), поэтому в разметке у input стоит placeholder=" ". */

  /* 60% вместо сплошного: пользователь заметил, что в макете верхушка залита
     на 60% — то есть форма ложится ПОВЕРХ текущего слайда и он должен
     просвечивать. Сплошная заливка это съедала. */
  #m-demo{ background:rgba(26,26,28,0.6); }
  .m-demo__canvas{ background:none; }
  /* Отступ сверху: 24 от сейф-зоны до крестика (правка пользователя), дальше
     половина крестика — и кромка панели. --m-safe-top-design приходит из
     js/mobile-overlays.js: env(safe-area-inset-*) отдаёт CSS-пиксели, а внутри
     масштабированного канваса нужны дизайн-пиксели. */
  .m-demo__panel{
    position:relative; margin-top:calc(var(--m-safe-top-design, 0px) + 48px);
    min-height:calc(var(--m-vh-design, 874px) - var(--m-safe-top-design, 0px) - 48px);
    background:var(--ink); border-radius:24px 24px 0 0;
    padding-bottom:105px; box-sizing:border-box;
  }
  /* Крестик формы центром сидит ровно на кромке панели (в макете круг 48
     наполовину заходит на прозрачную полосу). */
  #m-demo .m-ov__close--round{ top:calc(var(--m-safe-top-design, 0px) + 24px); }

  .m-demo__form{ padding:48px 20px 0; display:flex; flex-direction:column; }
  .m-demo__title p{
    margin:0; color:#fff; font-family:'Unbounded',sans-serif; font-weight:600;
    font-size:24px; line-height:1.3; text-align:center;
  }
  .m-demo__subtitle{ padding-top:10px; }
  .m-demo__title .m-demo__subtitle{
    font-weight:400; font-size:14px; line-height:1.4;
  }
  .m-demo__fields{ padding-top:16px; display:flex; flex-direction:column; gap:48px; }
  .m-field{ position:relative; display:block; padding-top:18px; }
  /* Введённый текст — ЖЁЛТЫЙ (правка пользователя), включая шаблон маски
     телефона. Плавающая подпись остаётся приглушённо-белой, пока поле не в
     фокусе. */
  .m-field input, .m-field textarea{
    width:100%; box-sizing:border-box; display:block;
    background:none; border:none; border-bottom:1px solid rgba(255,255,255,0.4);
    padding:0 0 8px; margin:0; resize:none;
    font-family:'Unbounded',sans-serif; font-weight:400; font-size:14px; line-height:1.4;
    color:var(--yellow); outline:none; caret-color:var(--yellow);
  }
  .m-field textarea{ min-height:44px; }
  .m-field__label{
    position:absolute; left:0; top:18px; pointer-events:none;
    font-family:'Unbounded',sans-serif; font-weight:400; font-size:14px; line-height:1.4;
    color:rgba(255,255,255,0.6);
    transition:transform 0.18s ease, color 0.18s ease, font-size 0.18s ease;
    transform-origin:0 0;
  }
  .m-field input:focus + .m-field__label,
  .m-field input:not(:placeholder-shown) + .m-field__label,
  .m-field textarea:focus + .m-field__label,
  .m-field textarea:not(:placeholder-shown) + .m-field__label{
    transform:translateY(-18px) scale(0.72); color:var(--yellow);
  }
  .m-field input:focus, .m-field textarea:focus{ border-bottom-color:var(--yellow); }

  .m-checkbox{ display:flex; gap:16px; align-items:flex-start; cursor:pointer; margin-top:24px; }
  .m-checkbox input{ position:absolute; opacity:0; width:0; height:0; }
  .m-checkbox__box{
    position:relative; width:24px; height:24px; flex-shrink:0;
    border:1px solid rgba(255,255,255,0.5); border-radius:4px; box-sizing:border-box;
  }
  .m-checkbox input:checked + .m-checkbox__box{ background:var(--yellow); border-color:var(--yellow); }
  .m-checkbox input:checked + .m-checkbox__box::after{
    content:''; position:absolute; left:8px; top:3.5px; width:6px; height:12px;
    border-right:2.4px solid var(--ink); border-bottom:2.4px solid var(--ink);
    transform:rotate(45deg);
  }
  .m-checkbox__text{
    font-family:'Unbounded',sans-serif; font-weight:400; font-size:11px; line-height:1.5;
    color:rgba(255,255,255,0.75);
  }
  .m-checkbox__text a{ color:var(--yellow); }
  .m-demo__submit-wrap{ display:flex; justify-content:center; padding-top:48px; }
  .m-demo__submit{
    min-width:178px; height:56px; padding:0 24px; border:none; border-radius:28px; cursor:pointer;
    background:var(--yellow); color:var(--ink);
    font-family:'Unbounded',sans-serif; font-weight:600; font-size:16px;
    text-transform:uppercase; letter-spacing:0.5px;
  }

  /* Сообщение об отправке — ПО ЦЕНТРУ панели (правка пользователя), а не
     абзацем сверху. Буквы разбиты на span'ы в js/mobile-overlays.js и
     проявляются из размытия; .m-ch выставлен inline-block, иначе transform и
     filter к нему не применялись бы, а .m-word держит слово целым при
     переносе строки. */
  .m-demo__success{
    display:none; position:absolute; left:0; top:0; width:100%; height:100%;
    align-items:center; justify-content:center; padding:0 32px; box-sizing:border-box;
  }
  .m-demo__success-text{
    margin:0; text-align:center; color:var(--yellow);
    font-family:'Unbounded',sans-serif; font-weight:500; font-size:20px; line-height:1.5;
  }
  .m-demo__success-text .m-word{ display:inline-block; white-space:nowrap; }
  .m-demo__success-text .m-ch{ display:inline-block; will-change:filter, transform, opacity; }
  #m-demo.is-sent .m-demo__form{ display:none; }
  #m-demo.is-sent .m-demo__success{ display:flex; }

  /* ----- Попап о компании (Figma 2928:5109) --------------------------------
     Карточка по макету 370×664 на (16, 105), крестик 48 центром сидит ровно на
     её верхней кромке (в макете фрейм close стоит на y −24 относительно
     контента, то есть ровно наполовину выше).

     max-height вместо жёсткой высоты — правка пользователя «снизу отступ 16px
     гарантированно»: на коротком экране 664 не влезали и низ карточки уходил
     под строку браузера. Теперь карточка не может быть ниже, чем
     (высота экрана − 105 сверху − 16 снизу), а лишний контент прокручивается
     внутри неё. */
  /* top и height карточки считает fitLast() в js/mobile-overlays.js: на
     коротком экране макетные 105 сверху + 664 высоты не влезали, низ уходил
     под строку браузера и появлялся внутренний скролл, хотя сверху места было
     полно. Значения ниже — макетные, они и остаются там, где всё помещается. */
  /* left через 50%, а не макетные 16: на планшете канвас оверлея расширен до
     ширины экрана, и карточка при фиксированном left оставалась прижатой к
     левому краю (16 + поле по боку). 185 = 370/2. */
  .m-last__card{
    position:absolute; left:50%; margin-left:-185px; top:105px; width:370px; height:664px;
    box-sizing:border-box; padding:48px 16px 24px;
    background:var(--ink); border-radius:32px;
    overflow-y:auto; overflow-x:hidden; overscroll-behavior:contain;
    scrollbar-width:none; -ms-overflow-style:none;
    display:flex; flex-direction:column; align-items:center; gap:16px;
  }
  .m-last__card::-webkit-scrollbar{ width:0; height:0; }
  /* Крестик центром сидит на верхней кромке карточки (в макете фрейм close
     стоит на y −24 относительно контента). */
  #m-lastpopup .m-ov__close--round{ top:calc(var(--m-last-top, 105px) - 24px); }
  .m-last__logo{ width:200px; height:44.645px; flex-shrink:0; }
  .m-last__title{
    margin:0; width:338px; text-align:center; color:#fff;
    font-family:'Unbounded',sans-serif; font-weight:400; font-size:16px; line-height:1.4;
  }
  .m-last__clients{ width:338px; flex-shrink:0; padding-top:24px; display:flex; flex-direction:column; gap:32px; }
  .m-last__clients-label{
    margin:0; text-align:center; color:#fff; opacity:0.6;
    font-family:'Source Sans Pro',sans-serif; font-weight:600; font-size:14px;
    letter-spacing:0.5714px; text-transform:uppercase;
  }
  .m-last__links{ padding-top:24px; display:flex; flex-direction:column; align-items:center; gap:12px; }
  .m-last__links button{
    background:none; border:none; padding:0; cursor:pointer; color:#fff;
    font-family:'Unbounded',sans-serif; font-weight:400; font-size:12px; line-height:1.4;
  }
  .m-last__contacts{ padding-top:24px; display:flex; justify-content:center; gap:32px; }
  .m-last__contacts a{
    display:flex; align-items:center; gap:12px; text-decoration:none; color:#fff;
    font-family:'Unbounded',sans-serif; font-weight:400; font-size:12px; line-height:1.4;
  }
  .m-last__ico{ display:flex; width:16px; height:16px; flex-shrink:0; }
  .m-last__ico img{ width:16px; height:16px; display:block; filter:invert(1); }
  .m-last__legal{
    margin-top:auto; opacity:0.5; text-align:center;
    display:flex; flex-direction:column; gap:4px;
  }
  .m-last__legal p, .m-last__legal a{
    margin:0; color:#fff; text-decoration:none;
    font-family:'Unbounded',sans-serif; font-weight:400; font-size:11px; line-height:1.4;
  }

  /* Карусель клиентов на мобилке — один слот в кадре, стрелки по краям.
     Общие правила лежат в css/lastpopup.css (там же десктопный вариант). */
  #m-lastpopup .clients-carousel__arrow{ width:8px; height:13.946px; }
  #m-lastpopup .clients-carousel__slot{ height:32px; }

  /* ----- Отладочная панель (?debug=1) -------------------------------------
     По образцу js/perf-overlay.js: без параметра в URL скрипт вообще ничего
     не создаёт. Нужна независимо от chrome://inspect — в частности, чтобы
     смотреть в Samsung Internet, который стоит по умолчанию на самсунгах и
     в chrome://inspect не появляется. */
  #m-debug{
    position:fixed; left:0; right:0; bottom:0; z-index:9999;
    background:rgba(0,0,0,0.82); color:#0f0;
    font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:10px; line-height:1.35;
    padding:6px 8px calc(6px + env(safe-area-inset-bottom,0px));
    max-height:45vh; overflow:auto; -webkit-overflow-scrolling:touch;
  }
  #m-debug.is-collapsed{ max-height:26px; overflow:hidden; }
  #m-debug b{ color:#ff0; font-weight:normal; }
  #m-debug .m-debug__bar{ display:flex; gap:6px; align-items:center; margin-bottom:4px; }
  #m-debug button{
    font:inherit; color:#000; background:#0f0; border:none; border-radius:3px;
    padding:2px 6px; cursor:pointer;
  }
  #m-debug .m-debug__log{ white-space:pre-wrap; word-break:break-word; color:#9f9; }

  /* ----- Брейкпоинт --------------------------------------------------------
     Скрытие мобильной ветки вне её диапазона — ОБЯЗАНО стоять после всех
     правил выше (тот же порядок, что был в прежней версии файла).

     С 2026-08-05 граница проходит не по ширине, а по ФОРМЕ экрана: мобильная
     ветка обслуживает всё, кроме широкого ландшафта, — включая планшеты в
     портрете (там она просто масштабируется крупнее, см. fitMobile в
     js/stage.js). Условие зеркально тому, что в css/breakpoints.css скрывает
     десктоп, и тому, что считает YHA.isDesktopLayout(); менять его нужно
     во всех трёх местах разом. */
  @media (min-width:1024px) and (orientation:landscape){
    .m-menubar-wrap, .m-stage-wrap, .m-ov, #m-debug{ display:none; }
  }
  /* Прежнее исключение "html,body{overflow:visible} для мобильных ширин"
     УБРАНО вместе со сплошной лентой: страница снова никуда не скроллится
     нативно ни на одном брейкпоинте, переходы держит js/mobile-slides.js. */

  /* ===== Зум пальцами на мобилке ===========================================
     Композиция мобилки — фиксированный канвас 402×874, который сам
     подгоняется под экран; браузерный зум её только ломает. На слайдах щипок
     и так не проходил (у .m-stage-wrap touch-action:none), а вот на всём
     остальном — шапке, оверлеях, пустых полях — проходил.

     ПОЧЕМУ ИМЕННО touch-action, а не user-scalable=no. Safari на iOS с 10-й
     версии намеренно игнорирует user-scalable и maximum-scale для ЖЕСТА
     пользователя: Apple не даёт странице запрещать зум ради доступности.
     А touch-action он уважает — это не запрет зума, а указание, какие жесты
     страница обрабатывает сама.

     Правило стоит на body, а не на отдельных блоках: touch-action
     ПЕРЕСЕКАЕТСЯ по цепочке предков, поэтому более строгие значения ниже
     (none у сцены и у плашки Media5) продолжают работать. */
  @media (max-width:1023px), (orientation:portrait){
    body{ touch-action:pan-y; }
  }

  /* ===== Заглушка "поверните телефон" (Figma 2943:1433) =====================
     Ландшафт на телефоне не поддерживается сознательно: макеты вертикальные,
     и уместить их в 360–430 px высоты можно только полностью перерисовав всё
     заново. Запретить поворот программно нельзя — screen.orientation.lock()
     по спецификации работает лишь в полноэкранном режиме, а Safari на iOS не
     поддерживает его совсем, — поэтому заглушка.

     УСЛОВИЕ ПОКАЗА — пять частей, и каждая нужна:
       orientation:landscape  — собственно повод;
       max-width:1023px       — планшет в ландшафте показывает ДЕСКТОПНУЮ
                                версию и прекрасно себя чувствует, ему
                                заглушка была бы вредна;
       max-height:600px       — иначе узкое окно на десктопе (ширина <1024,
                                ландшафт) получало бы «поверните телефон».
                                Телефон в ландшафте — это 360–430 px высоты,
                                окно десктопа почти всегда выше;
       pointer:coarse         — ОСНОВНОЕ устройство ввода — палец, а не мышь;
       hover:none             — им нельзя навести курсор, не нажимая.
     Последние две отсекают ровно тот случай, на который пожаловался
     пользователь: десктоп со сплющенным окном. Размеры окна человек меняет
     как хочет, а вот подменить мышь пальцем — нет: pointer/hover описывают
     ЖЕЛЕЗО, а не геометрию. Пара, а не одна: тачскрин-ноутбук в Windows
     отдаёт hover:none при работе пальцем, но pointer у него остаётся fine,
     пока подключена мышь. Режим эмуляции устройства в DevTools подделывает
     обе — и правильно делает, там как раз проверяют телефон.

     ЧЕТВЁРТЫЙ РУБЕЖ — класс html.not-phone, его ставит скрипт в <head>
     index.html по признакам, которых у CSS нет вообще: userAgentData.mobile,
     maxTouchPoints, физический размер ЭКРАНА (не окна). Он работает только на
     ВЫЧИТАНИЕ: не поставился (скрипт не отработал, старый браузер) — остаётся
     чистое поведение медиазапроса. Ошибиться в сторону «не показали» тут
     дешевле, чем в сторону «показали на десктопе».

     В ПОРТРЕТЕ заглушки нет ни при какой высоте — прямое решение пользователя:
     на телефоне с раскрытой клавиатурой вьюпорт становится очень низким, и
     заглушка накрывала бы поля ввода формы. */
  #m-rotate{
    position:fixed; inset:0; z-index:400; display:none;
    align-items:center; justify-content:center; overflow:hidden;
    background:var(--yellow);
    touch-action:none; -webkit-user-select:none; user-select:none;
  }
  @media (max-width:1023px) and (orientation:landscape) and (max-height:600px)
     and (pointer:coarse) and (hover:none){
    html:not(.not-phone) #m-rotate{ display:flex; }
  }
  /* Канвас ландшафтного телефона из макета. Тот же приём, что у сцены и
     оверлеев: внутри всё в дизайн-px, снаружи один transform:scale
     (--m-rotate-scale считает fitMobile в js/stage.js). */
  .m-rotate__canvas{
    position:relative; width:874px; height:402px; flex:none;
    transform:scale(var(--m-rotate-scale, 1));
  }
  /* Цветовое пятно — тот же color-back.svg, что и везде, положенный на бок
     (в макете бокс 452×565 повёрнут на 90°). Внутренние инсеты — запас под
     размытие, 1:1 из Figma.

     ФЛИП И TOP ПОДОБРАНЫ ГЛАЗАМИ по скриншоту макета, а не взяты из его чисел,
     и это не лень: у экспортированного SVG своя ориентация градиента, поэтому
     буквальные rotate(90deg) и top:211 давали зеркальную картинку (бирюзовое
     ядро уезжало влево-вниз вместо правого нижнего угла). Перебрал ±90° и оба
     флипа со скриншотами — совпало на этой паре. */
  .m-rotate__back{
    position:absolute; left:50%; top:80px; margin-left:-282.5px;
    width:565px; height:452px;
    display:flex; align-items:center; justify-content:center;
  }
  .m-rotate__back > span{
    position:relative; display:block; flex:none;
    width:452px; height:565px; transform:rotate(90deg) scaleY(-1);
  }
  .m-rotate__back img{ position:absolute; top:-26.08%; right:-21.54%; bottom:-43.28%; left:-32.6%; }
  .m-rotate__logo{ position:absolute; left:24px; top:24px; width:97.778px; height:80px; display:block; }
  /* Группа по центру канваса: иконка, отступ 16, текст в три строки. */
  .m-rotate__center{
    position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
    display:flex; flex-direction:column; align-items:center; gap:16px;
  }
  .m-rotate__icon{ width:52.185px; height:52.185px; display:block; }
  .m-rotate__text{
    margin:0; text-align:center; color:var(--ink);
    font-family:'Unbounded',sans-serif; font-weight:500;
    font-size:16px; line-height:1.1; letter-spacing:0.48px;
  }
