/* ВЁРСТКА САЙТА: то, что нельзя выразить инлайном.

   Источник - `handoff-site-editor-wp/kit/siteedit.css` из передаточного пакета
   дизайна, срез 23 августа 2026.

   ПОЧЕМУ ЗДЕСЬ ТАК МАЛО. Цвета сайта принадлежат палитре КЛИЕНТА и приходят
   инлайновым стилем: в CSS их нет и быть не должно, иначе показанный сайт сольётся
   с интерфейсом, который его правит. В классы вынесено ровно то, что инлайном не
   выражается: наведение, фокус, движение, состояние полки.

   ОДИН ФАЙЛ НА ОБЕ СТОРОНЫ. Его подключает и опубликованный сайт, и холст
   редактора. Второй файл завёл бы второй источник правды и сайт, который в
   редакторе выглядит иначе, чем у посетителя.
*/

/* --- КОРЕНЬ САЙТА: КОНТЕЙНЕР И СВОЁ ДВИЖЕНИЕ ---

   ДВИЖЕНИЕ ОБЪЯВЛЯЕТСЯ ЗДЕСЬ И ПОД СВОИМИ ИМЕНАМИ. Файл подключается и на сайте, и в
   кабинете. Блок `:root{--sc-dur-fast:...}`, идущий после `tokens/motion.css`, переписал
   бы движение ВСЕГО кабинета - ровно так `parts/navigation.css` первой строкой
   переопределял `.sc-app`. На `.ls-page` значения существуют только внутри сайта и
   приходят вниз наследованием.

   Имена `--ls-*`, а не `--sc-*`: систем две, и смешивать их запрещено. Читая
   `var(--ls-ease)` внутри вёрстки сайта, нельзя сказать, чей это ease; а сайт обязан
   выглядеть одинаково опубликованным и в редакторе, а не одинаково с оболочкой,
   которая его правит. Имена кита - в скобках рядом.

   ДО ЭТОГО БЛОКА ФАЙЛ БЫЛ ПОЛОМАН. Строка перехода полки ссылалась на
   `--sc-dur-screen`, которого нет НИ В ОДНОЙ теме: по правилам CSS всё объявление
   `transition` при этом отбрасывается целиком и становится `none`. Полка не
   анимировалась бы и после подключения файла. Отсюда правило: этот файл не имеет права
   ссылаться на переменную, которой сам не объявляет.

   КОНТЕЙНЕР ИМЕНОВАН, И ЭТО НЕ КОСМЕТИКА. Безымянный `@container` в редакторе
   подписался бы на `.sc-se` - корень редактора, который тоже контейнер, - а не на
   бумагу сайта. Именованный запрос с безымянным контейнером связаться не может ни при
   каких условиях: защита конструктивная, а не по внимательности. */
.ls-page{
  container-type:inline-size;
  container-name:ls;

  /* ВЫРАВНИВАНИЕ ЗАДАЁТ САМ САЙТ, А НЕ ТОТ, КТО ЕГО ВСТАВИЛ (06.10.2026, снимок владельца).
     Миниатюра каталога - кнопка, а у кнопки по умолчанию `text-align:center`: заголовок и
     абзац секции наследовали центр, а ряд кнопок (flex) оставался слева, и миниатюра не
     совпадала с сайтом. У посетителя спасало `body{text-align:start}` - то есть правило жило
     у хозяина страницы, а не у сайта. Раскладки, которые центрируют нарочно, объявляют это
     сами и этим правилом не задеты. */
  text-align:start;

  /* ОДНА ШИРИНА СОДЕРЖИМОГО НА ВСЕ СЕКЦИИ, И У НЕЁ ОДИН ХОЗЯИН.

     Владелец: «давай по дефолту зададим какую-то стандартную ширину контента для всех
     секций, потому что сейчас все секции гуляют: где-то они тянутся на все 100%, где-то
     фиксированные». Замерено 01.09.2026: обложка и показатели держали 1440, отзывы 1536, у
     предложения и подвала предела не было вовсе.

     Число выбрано владельцем - 1536, то есть то, что уже стояло у отзывов: тогда один пакет
     из трёх не двигается вовсе, и сверка с его китом остаётся точной.

     СУЖАЕТСЯ ТОЛЬКО СОДЕРЖИМОЕ - тоже его решение. Фоновые снимки, завесы, кольца орбиты и
     цветные полосы остаются во всю ширину: сузь мы их, и у фотографии первого экрана на
     широком мониторе появились бы белые поля по бокам.

     Пакеты читают токен ЧЕРЕЗ СВОЮ переменную (`--ls-hero-max` и родня): своя ручка у
     каждого остаётся - раскладка вправе сказать «а я во всю ширину», как это делает B6, -
     а общее умолчание теперь одно. */
  --ls-max:1536px;

  /* ОТСТУП ПОД ЗАКРЕПЛЁННОЙ ШАПКОЙ ЗДЕСЬ БОЛЬШЕ НЕ ЖИВЁТ, И ЭТО НЕ ПОТЕРЯ.
     Стояли два имени одного смысла - `--ls-stats-top` и `--ls-a4-top`, оба 105, - и число
     было СЛИТЫМ: 81 замер шапки плюс 24 зазор в одном литерале, разложить его было нечем.
     Пакет шапки разложил: высоту считает формула `--ls-bar-h` на `.ls-site` (`header.css`),
     зазор остался у читателя (`calc(var(--ls-bar-h,80px) + 24px)`). Хозяин по-прежнему
     один, но теперь он СЧИТАЕТ высоту из полей и цели нажатия, а не помнит замер: поменяется
     поле полосы - приклеенные колонки поедут за ним сами. */

  /* БОКОВОЕ ПОЛЕ САЙТА. Читает его кит подвала: по правилу рамки предел содержимого и
     боковое поле общие у шапки, содержимого и подвала - своей ширины подвал не заводит.

     ДОЛГ НАЗЫВАЮ ВСЛУХ: сегодня общее оно только по имени. Шапка носит своё число
     (`--ls-bar-pad`), у каждого зеркала секции своё поле, и свести их в это имя - работа
     по всему слою, а не по подвалу. Пока писателя два: здесь и узкая ветка ниже. */
  --ls-page-gut:24px;

  /* ШКАЛА ДВИЖЕНИЯ СЛОЯ САЙТА, И ОНА НЕ КАБИНЕТНАЯ. Прежние значения были сняты с токенов
     кабинета (`--sc-dur-*`), то есть через границу двух систем, которые в этом проекте
     не смешиваются; у `--ls-dur-screen` рядом честно стояло «ИСТОЧНИК НЕ СВЕРЕН». Пакет
     первого экрана объявляет слою САЙТА собственную шкалу (`site-hero/kit/hero.css` на
     `.ls-w, .ls-hero`) - её и берём, иначе одно имя означало бы два числа: внутри первого
     экрана китовое, снаружи наше, и различие в 20мс глазами неразличимо, а замером видно. */
  --ls-dur-fast:140ms;
  --ls-dur-base:220ms;
  --ls-dur-screen:320ms;
  --ls-ease:cubic-bezier(.2,.6,.3,1);
  --ls-ease-enter:cubic-bezier(.2,.8,.3,1);
  --ls-focus-w:2px;
  /* Шаг задержки: пункты выпадающего меню приходят волной. Суммарно не дольше 350мс.
     ЗДЕСЬ МЫ С КИТОМ РАСХОДИМСЯ НАМЕРЕННО: он объявляет 60мс и не потребляет их НИ РАЗУ,
     а у нашего значения есть потребитель ниже по файлу и объявленный бюджет - при 60мс
     волна вылезет за 350мс уже на шести пунктах. Мёртвое объявление кита снимается
     отступлением в `tools/adopt-hero.php`, чтобы оно не перекрыло это внутри `.ls-w`. */
  --ls-stagger:14ms;
}

/* --- ССЫЛКИ И КНОПКИ ---
   Наведение сделано ПРОЗРАЧНОСТЬЮ и подчёркиванием: цвет здесь чужой. */
.ls-link{transition:opacity var(--ls-dur-fast) var(--ls-ease)}
.ls-link:hover{opacity:.62;text-decoration:underline;text-underline-offset:3px}
.ls-link:focus-visible,.ls-btn:focus-visible,.ls-soc:focus-visible,.ls-sheetRow:focus-visible{
  /* Радиус кольца не задаётся: `outline` берёт скругление самого органа, а `4px` здесь
     плющил и пилюли, и прямоугольные плитки к одной форме. Отступ у кнопок и ссылок
     оставлен - вплотную к заливке кольцо почти не видно (решение владельца 09.09.2026). */
  outline:var(--ls-focus-w) solid currentColor;outline-offset:3px}
/* Подчёркивание снимается ЗДЕСЬ, у одного хозяина, а не в каждом ките: `main.css`
   объявляет `a` без `text-decoration`, то есть браузерное подчёркивание остаётся у любой
   кнопки-ссылки, чей кит его не снял (снимали четыре кита из одиннадцати - замерено). */
.ls-btn{text-decoration:none;transition:filter var(--ls-dur-fast) var(--ls-ease),opacity var(--ls-dur-fast) var(--ls-ease)}
.ls-btn:hover{text-decoration:none}
.ls-btn:hover{filter:brightness(1.07) saturate(1.05)}
.ls-btn:active{filter:brightness(.96)}

/* ФОРМА И КЕГЛЬ КНОПКИ - ОДИН НАБОР ВЕЛИЧИН НА ВСЕ СЕКЦИИ.
   Замерено 08.09.2026 по объявлениям китов: обложка, показатели и отзывы уже совпадали
   (52px, поле 28, угол 14, кегль --ls-btn, вес 500), а галерея шла с полем 18, углом 18
   и без высоты и веса вовсе, цены - 48/20/600. Владелец: «все кнопки на сайте должны быть
   в одном стиле». Эталоном взято то, что уже у трёх слоёв из пяти, а не новое число.
   ЗАЛИВКА И РАМКА ЗДЕСЬ НЕ ОБЪЯВЛЯЮТСЯ: они несут роль (главная или обводочная), и у
   галереи это законное различие - её обводочная кнопка светлая по замыслу кита.
   СПЕЦИФИЧНОСТЬ УДВОЕНА САМОССЫЛКОЙ, а не предком `.ls-page`: этого узла нет в архивах
   (сказано в `site-render.php` у самого печатника), и правило молча не сработало бы ровно
   там, где его труднее всего заметить. Киты объявляются одиночным классом (0,1,0) и
   грузятся ПОСЛЕ - одиночного класса здесь не хватило бы.
   ШАПКА ВОШЛА СЮДА 15.09.2026, И ПРЕЖНИЙ ДОВОД БЫЛ ОПРОВЕРГНУТ ЗАМЕРОМ. Здесь стояло
   «кнопка высотой 52 сломала бы её высоту», и число 44 читалось как высота полосы - на деле
   44 это её ВНУТРЕННИЙ ряд, а сама полоса 68. Прямой опыт 15.09.2026: форма свода даёт кнопку
   150x52 и полосу 76, то есть рост на восемь точек, а не поломку. Решение владельца принято
   после предъявления этого числа; свои рост, поле и угол полоса больше не объявляет, а кегль
   объявляет по-прежнему - см. ниже, почему он сюда не входит.

   КОММЕНТАРИЙ ЗДЕСЬ ЗАКРЫВАЛСЯ ДВАЖДЫ, И ЭТО СЪЕДАЛО САМО ПРАВИЛО. До 15.09.2026 на этом
   месте стояла закрывающая пара (звёздочка и косая - написать её здесь нельзя, она закроет
   и этот комментарий; на этом я наступил, пока описывал), а пять строк ниже шли уже как КОД:
   браузер выбрасывал мусор вместе с
   идущим следом `.ls-btn.ls-btn`, то есть общий свод кнопки не применялся НИ К ОДНОЙ кнопке
   сайта. Замерено в браузере: у кнопки обложки `min-block-size` давал `.ls-hero__btn` из
   `hero.css`, а свода в списке правил не было вовсе. Совпадение кнопок держалось только на
   том, что киты секций объявляют те же числа сами, - и разошлось бы при первой правке кита.
   Записанная грабля проекта, второй случай: «правка шапки закрыла комментарий строкой
   раньше, хвост объяснения стал мусорным CSS».

   КЕГЛЬ ЗДЕСЬ НЕ ОБЪЯВЛЯЕТСЯ, и это не забывчивость: у секций он и так 16px у всех пяти
   (замерено), а имена токенов у них РАЗНЫЕ - `--ls-btn` у обложки, `--ls-role-body-sm` у
   отзывов. Сослаться на чужой токен этот файл не вправе: он обязан быть самодостаточным,
   и сторож набора `site-v2-test` это ловит. Угол считается через `--ls-r-k` - её печатает
   PHP с корня, она объявлена своей и подчиняется Customize. */
.ls-btn.ls-btn{
  display:inline-flex;align-items:center;justify-content:center;
  min-block-size:52px;padding-inline:28px;
  border-radius:calc(14px * var(--ls-r-k,1));
  font-weight:500;line-height:1.4}

/* Значок соцсети. Цвет из палитры сайта приходит инлайном, поэтому наведение -
   прозрачностью. */
.ls-soc{opacity:.62;transition:opacity var(--ls-dur-fast) var(--ls-ease)}
.ls-soc:hover{opacity:1}

/* ЦЕЛЬ НАЖАТИЯ У ССЫЛОК. Видимый рост строки может быть меньше 44, цель - никогда.
   Замерено на 375: ссылки подвала выходили 36x22 и 48x22.

   Поле добирается ТОЛЬКО ПО ВЕРТИКАЛИ. По строке ссылки стоят в ряд с зазором 24, и
   поле шире половины зазора перекрыло бы соседа - нажатие по краю одной ссылки
   попадало бы в другую. Правило пишется на класс, а не на каждое место: перечисление
   по одному пропускает вновь добавленное. */
.ls-link{position:relative}
.ls-link::after{content:"";position:absolute;inset-block:-11px;inset-inline:0}

/* --- УЗКАЯ ПОЛОСА: БУРГЕР И ПОЛКА ---

   Полка печатается СЕРВЕРОМ в закрытом виде, со всеми пунктами внутри: скрипт только
   ставит признак. Так меню достаётся диктору и работает без единой строки JS -
   пункты остаются ссылками.

   Рост по содержимому, а не на весь экран: меню из трёх пунктов, растянутое на
   страницу, читается как ошибка. Едет вниз из-под полосы, поэтому видно, откуда
   взялось. */
.ls-sheet{transition:grid-template-rows var(--ls-dur-screen) var(--ls-ease-enter),
  opacity var(--ls-dur-fast) linear,
  visibility 0s linear var(--ls-dur-screen)}
.ls-bar[data-open="true"] .ls-sheet{grid-template-rows:1fr;opacity:1;pointer-events:auto;
  transition-delay:0s}
.ls-scrim{transition:opacity .22s linear}
.ls-bar[data-open="true"] .ls-scrim{block-size:100vh;opacity:1;pointer-events:auto}

/* Три черты складываются в крест НА МЕСТЕ: отдельного крестика нет, он читался бы
   как вторая кнопка. Черта 18x2, как в макете. */
.ls-burger__i,.ls-burger__i::before,.ls-burger__i::after{content:"";display:block;
  inline-size:18px;block-size:2px;background:currentColor;border-radius:calc(2px * var(--ls-r-k,1));
  transition:transform var(--ls-dur-base) var(--ls-ease),opacity var(--ls-dur-fast) linear}
.ls-burger__i{position:relative}
.ls-burger__i::before{position:absolute;inset-block-start:-6px;inset-inline-start:0}
.ls-burger__i::after{position:absolute;inset-block-start:6px;inset-inline-start:0}
.ls-bar[data-open="true"] .ls-burger__i{background:transparent}
.ls-bar[data-open="true"] .ls-burger__i::before{transform:translateY(6px) rotate(45deg)}
.ls-bar[data-open="true"] .ls-burger__i::after{transform:translateY(-6px) rotate(-45deg)}

/* --- ДВА МЕНЮ В РАЗМЕТКЕ, ОДНО НА ЭКРАНЕ ---

   Сервер печатает И строчное меню, И бургер с полкой; лишнее убирает ширина. Печатать
   что-то одно по серверному признаку нельзя: разметка приезжает один раз, а телефон
   поворачивают.

   Прячет `display:none`, и это правильный ответ, а не ленивый: такой узел вынут И из
   дерева доступности, И из порядка обхода табом. Диктор в любой момент слышит ровно
   один набор ссылок. `aria-hidden` не годится - он убирает из дерева, но оставляет
   фокусируемость, то есть фокус проваливается в объявленное несуществующим.

   `display` - единственное, что НЕ уходит в переменную: `display:var(--x, none)`
   означал бы «не пришёл файл - меню нет вовсе». Здесь отказ файла оставляет ОБА меню
   видимыми: некрасиво, но всё работает и всё доступно. */
.ls-menu{display:flex}
.ls-barSoc{display:inline-flex;align-items:center;gap:12px}
.ls-burger,.ls-scrim,.ls-sheet{display:none}

/* ЗАКРЫТАЯ ПОЛКА НЕ ДОЛЖНА БЫТЬ ФОКУСИРУЕМОЙ. Ростом ноль и прозрачностью ноль ссылки
   внутри остаются в обходе табом - человек с клавиатуры проваливается в невидимое меню.
   Это дефект уже сегодня; узкая раскладка просто делает его достижимым. `visibility`
   убирает и из дерева, и из обхода, и при этом дружит с переходом: открытие - видимость
   сразу, закрытие - в конце переезда. */
.ls-sheet{visibility:hidden}
.ls-bar[data-open="true"] .ls-sheet{visibility:visible}

/* --- УЗКАЯ РАСКЛАДКА САЙТА ---

   ПОРОГ ОДИН: 700 и уже. Число ЗАМЕРЕНО В ПРОТОТИПЕ, а не взято из README: там стоит
   `paperEl.clientWidth <= 700` (`design/v4/site-editor/source/SiteEditor.jsx:1812`), и
   этот же признак уходит в шапку сайта - секции перестраиваются в одну колонку, ссылки
   убираются под кнопку меню.

   Прежде здесь стояло 640 со ссылкой на README пакета передачи. README говорит
   неправду: между 640 и 700 макет уже показывает бургер, а мы ещё показывали меню.

   ЗАПРОС К КОНТЕЙНЕРУ, А НЕ К ОКНУ, И КОНТЕЙНЕР ИМЕНОВАН. В редакторе тот же сайт
   стоит на бумаге в 390 точек внутри окна в 1440; безымянный запрос подписался бы на
   `.sc-se` - корень редактора, который тоже контейнер, - и показал бы десктоп.

   МЕЖФАЙЛОВЫЙ ИНВАРИАНТ: 390 < 700 <= 834. Пределы бумаги по кнопкам устройства
   объявлены в `sc-theme/assets/css/siteedit.css`; поставь здесь 380 - и кнопка
   «телефон» молча перестанет переключать раскладку. Сторожится проверкой.

   ЗДЕСЬ ТОЛЬКО УЗКИЕ ЗНАЧЕНИЯ. Широкое живёт запасным значением в `var()`, который
   печатает PHP, и потому может быть своим у каждой секции (у одной галереи три
   колонки, у другой четыре) - общее правило в CSS этого дать не смогло бы. Отсюда же
   отказоустойчивость: не пришёл этот файл - остаётся широкая раскладка, а не пустота. */
@container ls (max-width:700px){
  /* Общее у всех шести видов. */
  /* ОТСТУП ОДИН, И ВЫБИРАТЬ ЕГО НЕЧЕМ - решение владельца, пункт 18. Здесь стояли три
     значения под орган «Vertical padding»; орган снят, писателей у ключа не осталось, и
     `compact` со `spacious` объявлялись бы тут, не будучи напечатанными никогда. */
  .ls-sec{--ls-h2:26px;
    --ls-pad-cosy:32px 20px}

  /* Обложка складывается: фото уходит подложкой под карточку.
     Сброс `--ls-hero-pic-min` в ноль обязателен - иначе подложка тянет 380 внутри
     секции 320 и вылезает на шестьдесят точек. */
  /* ИМЯ РАЗВЕДЕНО С КИТОМ ПЕРВОГО ЭКРАНА: `.ls-hero` теперь принадлежит пакету
     `design/v4/site-hero`, а прежняя обложка печатается как `ls-sec ls-hero-legacy`
     (`site-render.php`, там же довод целиком). Оставить общее имя значило бы накрыть
     прежнюю вёрстку на каждом сгенерированном сайте молча. */
  .ls-hero-legacy{--ls-hero-cols:1fr;
    --ls-hero-min:320px;
    --ls-hero-h1:28px;
    --ls-hero-card-m:32px 16px;
    --ls-hero-card-p:22px;
    --ls-hero-pic-pos:absolute;
    --ls-hero-pic-inset:0;
    --ls-hero-pic-min:0;
    --ls-hero-pic-area:1 / 1}

  /* ФОТО СБОКУ СКЛАДЫВАЕТСЯ СТОПКОЙ: снимок первым во всю ширину, карточка с текстом под ним
     (решение владельца 14.10.2026). Подложка остаётся у раскладок «карточка на фото» и «по
     центру» - у них признака `--split` нет. */
  .ls-hero-legacy--split{--ls-hero-min:0;
    --ls-hero-pic-pos:relative;
    --ls-hero-pic-inset:auto;
    --ls-hero-pic-area:1 / 1;
    --ls-hero-pic-h:auto;
    --ls-hero-pic-ar:4 / 3;
    --ls-hero-card-area:2 / 1;
    --ls-hero-card-m:0;
    --ls-hero-card-p:28px 20px 32px}

  /* Сетки схлопываются в одну колонку. */
  .ls-offer{--ls-offer-split:1fr}
  .ls-gallery{--ls-gal-cols:1fr;--ls-gal-first:auto}
  .ls-stats-legacy{--ls-stats-cols:1fr}
  .ls-cta{--ls-cta-h2:26px}

  /* Строчное меню уходит, приходит бургер. Правила `[data-open]` живут ЗДЕСЬ же,
     внутри узкого блока: тогда «открыл меню и растянул окно» разрешается само, без
     слушателя `resize` и без второго хозяина у состояния. */
  .ls-menu,.ls-barSoc{display:none}
  .ls-burger{display:inline-grid}
  .ls-scrim{display:block}
  .ls-sheet{display:grid}

  /* Полоса. Подвал свою узкую ветку получил вместе с китом раскладок и здесь её больше
     не имеет: строка `.ls-foot{--ls-foot-pad:24px 20px}` СНЯТА. Она была двухзначным
     сокращением под `padding` целиком, а кит объявляет `padding-block` - там два значения
     означают верх и низ, то есть узкая ветка тихо дала бы подвалу отступ снизу 20 вместо
     бокового поля. Мёртвой она была не сразу: до кита её читало инлайновое `padding`. */
  /* ДВЕ ВЕЛИЧИНЫ КНОПКИ ОТСЮДА СНЯТЫ 15.09.2026, И ПРИЧИНЫ У НИХ РАЗНЫЕ.
     Обе читала ПРЕЖНЯЯ полоса - печатник `sc_site_v2_header()` ставил их инлайном; в CSS
     читателя у `--ls-cta-pad` нет вовсе (правило новой полосы читает `--ls-cta-pad-inline`,
     имя другое). Прежняя полоса переведена на литералы с теми же числами: вид её не менялся
     ни на точку, а объявления стояли ОДНИ на обе полосы - `--ls-cta-fs:14px` уводила кегль
     новой кнопки в 14 на узкой ширине, где кнопка секции остаётся 16 (замерено на 375), то
     есть возвращала на телефоне ровно то расхождение, ради снятия которого кнопка полосы и
     вошла в общий свод. */
  .ls-bar{--ls-bar-gap:12px;--ls-bar-pad:14px 20px;--ls-bar-name:19px}
  /* ПОТОМКАМ СТРАНИЦЫ, А НЕ САМОЙ СТРАНИЦЕ. `.ls-page` объявлен контейнером `ls` выше, а
     контейнерный запрос СВОЙ КОНТЕЙНЕР НЕ СТИЛИЗУЕТ - правило `.ls-page{...}` здесь не
     совпало бы никогда. Замерено: боковое поле подвала держалось 24 на бумаге 390, где
     пакет ждёт 20, при полностью исправной с виду строке. Соседние правила блока живы
     ровно потому, что целят в потомков (`.ls-menu`, `.ls-burger`, `.ls-sheet`). */
  .ls-page > *{--ls-page-gut:20px}
}

@media (prefers-reduced-motion:reduce){
  .ls-link,.ls-btn,.ls-soc,.ls-sheet,.ls-scrim,
  .ls-burger__i,.ls-burger__i::before,.ls-burger__i::after{transition:none}
}

/* --- ВЫПАДАЮЩЕЕ МЕНЮ В ШАПКЕ ---

   Строка меню приходит парой «имя, вложенные». У кого вложенные есть - тот раскрывается
   по-настоящему: наведением, нажатием, с закрытием по Escape и по нажатию мимо.

   Правила перенесены из `kit/siteedit.css` макета и переведены на СВОИ токены: файл
   кабинета на опубликованной странице не подключается, а `--sc-*` там объявлять некому.
   Оставить их у кабинета значило бы получить меню, которое работает в редакторе и стоит
   раскрытым у посетителя. */

.ls-dd{position:relative;white-space:nowrap}

.ls-dd__btn{display:inline-flex;align-items:center;gap:3px;border:0;padding:0;background:none;
  font:inherit;cursor:pointer}

/* Шеврон - РИСУНОК, а не лигатура шрифта значков: у темы клиентских сайтов такого шрифта
   нет вовсе, и `<span class="sc-icon">expand_more</span>` напечатал бы СЛОВО. В редакторе
   этого не видно - там подключён шрифт кабинета. */
.ls-dd__chev{display:block;inline-size:16px;block-size:16px;flex:none;
  transition:rotate var(--ls-dur-base) var(--ls-ease)}
.ls-dd[data-open] .ls-dd__chev{rotate:180deg}

.ls-dd__menu{position:absolute;inset-block-start:calc(100% + 10px);inset-inline-start:0;z-index:30;
  min-inline-size:200px;display:flex;flex-direction:column;padding:6px;border-radius:calc(12px * var(--ls-r-k,1));
  box-shadow:0 20px 44px -18px rgba(18,19,23,.34);
  transform-origin:12px 0;opacity:0;scale:.94;translate:0 -10px;pointer-events:none;
  /* Закрытое меню вынуто из обхода табом: `opacity:0` прячет его от глаз, но не от
     клавиатуры, а `aria-hidden` убирает из дерева доступности и НЕ убирает из табуляции -
     фокус уходил бы в объявленное несуществующим. Видимость снимается в конце переезда. */
  visibility:hidden;
  transition:opacity var(--ls-dur-fast) var(--ls-ease),scale var(--ls-dur-fast) var(--ls-ease),
    translate var(--ls-dur-fast) var(--ls-ease),visibility 0s linear var(--ls-dur-fast)}
[dir="rtl"] .ls-dd__menu{transform-origin:calc(100% - 12px) 0} /* rtl-ok: точка роста зеркалится вручную, логического значения у transform-origin нет */
.ls-dd[data-open] .ls-dd__menu{opacity:1;scale:1;translate:0 0;pointer-events:auto;visibility:visible;
  transition:opacity var(--ls-dur-base) var(--ls-ease-enter),scale var(--ls-dur-screen) var(--ls-ease-enter),
    translate var(--ls-dur-screen) var(--ls-ease-enter),visibility 0s}

/* Полоса под кнопкой: без неё курсор по дороге к меню выходит из органа и меню закрывается. */
.ls-dd__menu::before{content:"";position:absolute;inset-block-start:-12px;inset-inline:0;block-size:12px}

.ls-dd__it{display:block;padding:9px 12px;border-radius:calc(8px * var(--ls-r-k,1));font-size:15px;text-decoration:none;
  opacity:0;translate:0 -6px;
  transition:background var(--ls-dur-fast) var(--ls-ease),opacity var(--ls-dur-fast) var(--ls-ease),
    translate var(--ls-dur-fast) var(--ls-ease)}
.ls-dd[data-open] .ls-dd__it{opacity:1;translate:0 0;
  transition:background var(--ls-dur-fast) var(--ls-ease),
    opacity var(--ls-dur-base) var(--ls-ease-enter),translate var(--ls-dur-base) var(--ls-ease-enter);
  transition-delay:0s,calc(var(--ls-stagger) * var(--i,0)),calc(var(--ls-stagger) * var(--i,0))}
.ls-dd__it:hover{background:color-mix(in oklab,currentColor 8%,transparent)}
.ls-dd__btn:focus-visible,.ls-dd__it:focus-visible{outline:var(--ls-focus-w) solid currentColor;
  outline-offset:3px;border-radius:4px /* kit-free: кольцо фокуса, форма не предмет вкуса */}

@media (prefers-reduced-motion:reduce){
  .ls-dd__menu,.ls-dd__chev,.ls-dd__it{transition:none}
  .ls-dd__menu{scale:1;translate:0 0}
  .ls-dd__it{opacity:1;translate:0 0}
}

/* --- ЗНАЧКИ САЙТА ---

   Вёрстка сайта печатает значки лигатурами Material Symbols. Своего шрифта у темы
   клиентских сайтов не было вовсе: в редакторе глиф вставал на место (там подключён
   шрифт кабинета), а у ПОСЕТИТЕЛЯ печаталось СЛОВО - шесть слов на демо-странице,
   замерено. Глазами в редакторе это не видно ни одним способом.

   Файл кладёт `tools/fetch-icons.php` - тот же самый, что в тему сервиса, побайтово.
   Ключ в адресе - отпечаток файла: число знаков ключом быть не может, тот же набор
   имён с другой осью даёт другой файл при том же числе. */
@font-face{
  font-family:"Material Symbols Rounded";
  font-style:normal;
  font-weight:300;
  font-display:block;
  src:url("../fonts/symbols/material-symbols-rounded-subset.woff2?v=53770be4") format("woff2");
}

/* ЭТО УМОЛЧАНИЕ, И ОНО ОБЪЯВЛЕНО КАК УМОЛЧАНИЕ. Починка живого дефекта.

   Правило было обычным - `:where(.sc-icon){...}`, вес (0,1,0). Файл подключается не только на
   опубликованной странице, но и в редакторе сайта, то есть ВНУТРИ КАБИНЕТА, и приходит в
   очередь ПОЗЖЕ `parts/icons.css` и `cabinet.css` темы сервиса. Вес тот же - значит решал
   порядок, и выигрывал он.

   Что натворил, замерено на разделе «Website»: кнопка сворачивания полосы печатала ДВА
   глифа вместо одного (`display:inline-block` перебивал гашение того же веса), и все 115
   значков экрана шли с `FILL 0` - то есть `.sc-icon--fill` темы сервиса переставал
   заливать, и отмеченный пункт отличался от неотмеченного ОДНИМ ЦВЕТОМ. Этот дефект уже
   стоил проекту пяти звёзд рейтинга, читавшихся как пустой.

   `:where()` даёт вес (0,0,0) и НЕ МЕНЯЕТ МНОЖЕСТВО СОВПАДЕНИЙ. Отсюда обе стороны:
   у посетителя конкурента нет вовсе, и правило работает ровно как прежде; в кабинете
   любое кабинетное правило значка выигрывает без борьбы. Умолчание и есть то, чем это
   правило было задумано - «своего шрифта у темы клиентских сайтов не было, добавляем».

   ПОЧЕМУ НЕ СУЖЕНИЕ ПО `.ls-page`, хотя оно напрашивалось. Проверить его на настоящем
   сайте клиента на этой установке НЕЧЕМ: активна тема сервиса, опубликованные страницы
   дела рендерит она, и `site-v2.css` там не подключается вовсе - замерено, ноль узлов
   `.ls-page` и ноль ссылок на файл. Ошибка в сужении печатает посетителю СЛОВО вместо
   значка (контрольный замер: несложившаяся лигатура даёт 408 точек ширины вместо 24), и
   увидеть это здесь было бы нечем. Смена веса такого риска не несёт по построению. */
:where(.sc-icon){
  font-family:"Material Symbols Rounded";
  font-weight:normal;
  font-style:normal;
  line-height:1;
  letter-spacing:normal;
  text-transform:none;
  display:inline-block;
  white-space:nowrap;
  word-wrap:normal;
  direction:ltr; /* rtl-ok: имя лигатуры читается слева направо всегда, это не текст страницы */
  font-variation-settings:"FILL" 0,"wght" 300,"GRAD" 0,"opsz" 24;
  -webkit-font-feature-settings:"liga";
  font-feature-settings:"liga";
  -webkit-font-smoothing:antialiased;
}

/* РАЗМЕРЫ ЗНАКА ВНУТРИ ТЕКСТОВОГО СЛОТА - ДОЛИ ОТ ЕГО СОБСТВЕННОГО КЕГЛЯ.

   Их ставит панель форматирования редактора, а видит ПОСЕТИТЕЛЬ: таблицы кабинета у него
   нет вовсе, и без этих четырёх строк размер, выбранный владельцем, работал бы только в
   редакторе. Ровно так уже было со шрифтом значков: в редакторе глиф, у посетителя слово.

   Второй копии в таблице кабинета НЕТ, и это сторожится проверкой с обеих сторон: правила
   обязаны быть здесь и обязаны отсутствовать в зеркале редактора (`adopt-siteedit.php`,
   отступление про размеры). Прежде здесь стояло обещание «числа те же, что в siteedit.css»
   - оно устарело в тот день, когда копию оттуда убрали, и молча звало её вернуть. */
.ls-fs--xs{font-size:.75em}
.ls-fs--sm{font-size:.875em}
.ls-fs--md{font-size:1.25em}
.ls-fs--lg{font-size:1.5em}

/* СНЯТИЕ ЖИРНОСТИ, НАЗНАЧЕННОЙ САМОЙ РАСКЛАДКОЙ.

   Замечание владельца 09.09.2026: «жирность не отключается в части заголовков». Ставится
   жирность тегом `strong`, а снять вес, пришедший из кита (у заголовка обложки он 600),
   тегом нечем вовсе - для этого и заведён класс.

   ПОЧЕМУ ЭТОГО ХВАТАЕТ БЕЗ ПРАВКИ КИТОВ. Вес НАСЛЕДУЕТСЯ, а объявление на самом элементе
   бьёт наследование при любой специфичности родителя - специфичность сравнивает правила,
   применённые к ОДНОМУ элементу, и правило кита к нашему `span` не относится вовсе.
   Замерено по всем таблицам сайта: `font-weight` с `!important` - ноль вхождений, правил
   веса на потомках два, и оба целят в `b`, а не в `span`.

   400, а не `normal`: у пары гарнитур обычное начертание бывает 300 или 450, и словом мы
   молча выбрали бы за макет другое число. */
.ls-fw--n{font-weight:400}

/* НАВИГАЦИЯ КАРУСЕЛИ ИСЧЕЗАЕТ, КОГДА ЛИСТАТЬ НЕЧЕГО.

   Владелец спросил дословно: «зачем вообще тут навигация, если у меня 2 слайда и они
   отображены на экране? почему навигация отображается как рабочая». Погасшая стрелка
   отвечает «дальше нельзя» - а правильный ответ «идти некуда», и его даёт отсутствие
   органа. Счётчик уходит вместе со стрелками: «1 / 2» при обоих слайдах на экране - это
   не подсказка, а загадка.

   ПРИЗНАК СТАВИТ СКРИПТ, И ИНАЧЕ НЕЛЬЗЯ. Ответ зависит от того, влезли слайды в ряд или
   нет, то есть от ширины бумаги и от длины подписей; сервер не знает ни того, ни другого.
   Считает Swiper (`isLocked`), скрипт только переносит признак на корень.

   ПРАВИЛО ЖИВЁТ ЗДЕСЬ, А НЕ В ЗЕРКАЛЕ КИТА. У кита такого состояния нет вовсе - у него
   слайдов всегда столько, сколько нарисовал холст. Дописывать за макет в его копию
   запрещено; наш собственный файл для этого и есть. */
.ls-b1[data-sc-lock] .ls-b1__tabsWrap,
.ls-b2[data-sc-lock] .ls-b2__foot,
.ls-b3[data-sc-lock] .ls-b3__foot,
.ls-b4[data-sc-lock] .ls-b4__count,
.ls-b4[data-sc-lock] .ls-b4__arrows,
.ls-b5[data-sc-lock] .ls-b5__dots { display: none; }

/* КУРСОР ТЯГИ - ТОЛЬКО У ПОСЕТИТЕЛЯ. В редакторе тяга выключена (`allowTouchMove:false`),
   и ладонь на карточке обещала бы движение, которого не будет. Swiper ставит `grabCursor`
   сам, но класс он вешает на КОРОБКУ, а рука нужна на карточке - там же, где кит её и
   объявил. */
.sc-se .ls-b2__card,
.sc-se .ls-b2__card:active { cursor: default; }

/* СЛАЙД НЕ РЕЖЕТ СВОЮ ТЕНЬ И КОЛЬЦО ФОКУСА. У Swiper слайды стоят вплотную, а кольцо
   фокуса кита выходит за коробку на 3 точки: без запаса оно обрезалось бы соседом. */
.swiper-slide:focus-visible { z-index: 1; }

/* ЛЕНТА SWIPER РАЗДУВАЛА КОРЕНЬ РАСКЛАДКИ ВШЕСТЕРО НА КАЖДЫЙ ПЕРЕСЧЁТ.

   Замерено: сцена B1 сначала 1040, после первого `update()` 37440, после второго 224640 -
   ровно умножение на число слайдов. Причина в двух словах: у корня раскладки кит объявляет
   `display:grid` БЕЗ колонок, значит колонка неявная и размером `auto`, то есть по
   max-content содержимого. А max-content ленты Swiper круговой: слайд сто процентов от
   ленты, лента сто процентов от коробки. Браузер разрешает круг содержимым и запоминает
   результат, следующий пересчёт берёт его за основу - и так до бесконечности.

   Правил ТРИ, и каждое проверено отдельно. `minmax(0,1fr)` делает колонку определённой.
   `min-inline-size:0` снимает у коробки её собственный `min-width:auto`. И решает дело
   третье - явная `inline-size:100%`: без неё коробка всё равно бралась по содержимому
   (замерено 6240 сразу после завода, при верных слайдах по 1040), а с ней три пересчёта
   подряд дают 1040 и не двигаются. Определённая колонка сама по себе элемент не удержала.

   ПРАВИЛА ЗДЕСЬ, А НЕ В ЗЕРКАЛЕ КИТА, потому что чинят они не китовское правило, а
   столкновение кита с библиотекой: у холста ленты нет, и раздуваться там нечему. Ни одно
   число макета они не трогают - колонка как была шириной в ряд, так и осталась. */
.ls-b1, .ls-b2, .ls-b3, .ls-b4, .ls-b5 { grid-template-columns: minmax(0, 1fr); }
.ls-off .swiper { min-inline-size: 0; inline-size: 100%; }

/* ПОДПИСЬ B5 - ТОЛЬКО У ЦЕНТРА, И ГАСНЕТ ОНА, А НЕ ПРОПАДАЕТ.

   Холст рисует подпись у одного элемента, потому что он статичен; продукт печатает её у
   каждого - иначе после первого же шага новый центр остался бы без подписи, а создавать
   узлы скрипту запрещено.

   `display:none` здесь был бы повторением той самой ошибки, из-за которой всё это
   переписывается: подпись возникала бы рывком посреди плавного приезда соседа. Гаснет она
   прозрачностью, а `visibility` уходит с задержкой в длину перехода - иначе диктор и
   табуляция видели бы подпись у приглушённого соседа. */
.ls-b5__it .ls-b5__cap {
	opacity: 0;
	visibility: hidden;
	transition: opacity var(--ls-dur-screen, 260ms) var(--ls-ease, ease),
		visibility 0s var(--ls-dur-screen, 260ms);
}
.ls-b5__it[data-on] .ls-b5__cap {
	opacity: 1;
	visibility: visible;
	transition-delay: 0s;
}

/*
 * ЗДЕСЬ БЫЛИ ЗНАЧОК ЛУПЫ И СЛОЙ ПРОСМОТРА - ОНИ УЕХАЛИ В `gallery.css`.
 *
 * Стили ходят парой со своим скриптом: просмотрщик стал галереей и переехал в `gallery.js`,
 * а разорванная пара «скрипт там, правила тут» - это ровно тот случай, когда починка одного
 * конца не достаёт до второго. Записанная грабля: помощник печатает разметку, а стили её
 * остаются в чужом файле.
 */

/* СТРОКИ-МАРКЕРЫ НА КАРТОЧКЕ ПРЕЖНЕЙ ОБЛОЖКИ. Печатает их тот же `sc_site_hero_pts()`, что у
   нового слоя, а вид объявлен в `hero.css`; здесь только посадка: карточка сама красит текст
   под свою бумагу, абзац у неё 16, поэтому строки на ступень мельче и с его отступом. */
.ls-hero-legacy .ls-hero__pts{color:inherit;font-size:15px;gap:8px;margin-block-start:16px}
.ls-hero-legacy .ls-hero__pt-i{font-size:18px}

/*
 * СЛОВО В ЗАГОЛОВКЕ НЕ ВЫХОДИТ ЗА СВОЮ КОЛОНКУ (находка проверщика UI 25.09.2026: у широкой
 * гарнитуры слово обложки заезжало на фотографию). Первым уступает кегль - его ужимает
 * `fit.js`; этот перенос - вторая уступка, для слова, которому не хватило и нижней ступени,
 * и страховка там, где скрипт не доехал.
 *
 * ИМЕННО `anywhere`, А НЕ `break-word`, и разница замерена. Видимый перенос у них одинаков:
 * слово рвётся, только когда не помещается в строку целиком. Но `break-word` оставляет
 * минимальной шириной заголовка ширину самого длинного слова, и контейнер, который растёт
 * по содержимому, растёт вместе с ним: на старой обложке заголовок стал 472 при экране 390,
 * и страница уехала вбок на 142 точки. `anywhere` этот минимум снимает.
 */
.ls-page :is(h1, h2, h3) {
	overflow-wrap: anywhere;
}

/*
 * МЕТКА «MADE WITH SITECREATORENGINE» У ДЕЛА НА БЕСПЛАТНОМ ТАРИФЕ (SCRUM-505). Цвет - чернило
 * подвала по наследству, оно уже проверено на контраст к фону подвала; своего цвета у метки нет,
 * иначе на тёмном подвале она пропала бы. Переменных подвала файл не читает - он самодостаточен
 * (`site-v2-test.php`). Только логические свойства - сайт бывает справа налево.
 */
.ls-foot .sc-made {
	margin: 0;
	margin-block-start: clamp(16px, 2cqi, 24px);
	font-size: 13px;
	line-height: 1.5;
	text-align: center;
	color: inherit;
}

.ls-foot .sc-made a {
	display: inline-block;
	min-block-size: 24px;
	padding-block: 2px;
	color: inherit;
	text-decoration: none;
}

.ls-foot .sc-made a:hover,
.ls-foot .sc-made a:focus-visible {
	text-decoration: underline;
}

.ls-foot .sc-made b {
	font-weight: 600;
}

/* ВИДЕО В СЕКЦИИ (SCRUM-542). Кит рисует значок «Video» надписью без нажатия
   (`pointer-events:none`, зеркало `offer.css`); у нас это кнопка, которая открывает лист
   ссылки и загрузки. Зеркало руками не правится - поэтому поправка здесь, после него. */
.ls-d6__kind[data-sc-act] {
	pointer-events: auto;
	cursor: pointer;
	border: 0;
	font-family: inherit;
}

/* Значок внутри кнопки - её размера: правило пустой коробки кита красит и растит ВСЕ значки
   внутри неё, включая этот. */
.ls-d6__box .ls-d6__kind .sc-icon {
	font-size: 17px;
	color: inherit;
	opacity: 1;
}

.ls-d6__ph b {
	font-size: 18px;
	font-weight: 600;
}

/* Перетаскивание над пустым местом: рамка уплотняется - «сюда можно бросить». */
.ls-d6__box[data-sc-video-drop][data-over] {
	outline-width: 2px;
	outline-style: dashed;
	outline-color: currentColor;
}

/* Свой файл играет наш `<video>` во всю коробку. */
.ls-d6__file {
	display: block;
	inline-size: 100%;
	block-size: 100%;
	object-fit: contain;
	background: #000;
}
