/* Экран выбора и сборки песни. Отдельный файл: разметку песни правят
   параллельно, и общий файл стилей — ровно то место, где две сессии затирают
   друг друга. Базовые классы (.ls-item, .ls-find) остаются в learn.html. */

.ls-item.sp-artist { border-color: rgba(194,134,90,.55) }
.ls-item.sp-artist b { font-weight: 700 }
.ls-item.sp-artist .ls-item-p { color: var(--ls-kr); font-size: 15px }

.ls-item.sp-have .ls-item-p, .ls-item.sp-have small { color: #3E8E5A }

/* Песня без синхронного текста: гасим, но НЕ прячем. Пустое место в списке
   человек читает как «у группы нет такой песни», а это неправда. */
.ls-item.sp-no { opacity: .42; cursor: default; box-shadow: none; background: var(--bg-1) }
.ls-item.sp-no:active { transform: none }
.ls-item.sp-no .ls-item-p { color: var(--dim) }

/* Песня на выравнивании: ЖИВОЙ КРУЖОК вместо песочных часов. Статичная эмодзи ⏳
   неотличима от «сломалось и висит» — вращение единственное, что отделяет
   ожидание от поломки. Строка ярче обычной погашенной: она не отказ, а обещание. */
.ls-item.sp-no:has(.sp-spin) { opacity: .72 }
.ls-item-p.sp-spin { display: inline-block; position: relative; flex: 0 0 auto; width: 15px; height: 15px }
.ls-item-p.sp-spin::before {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  border: 2px solid var(--line-strong); border-top-color: #C2865A;
  animation: sp-spin .8s linear infinite;
}
html[data-theme="dark"] .ls-item-p.sp-spin::before { border-top-color: #E9C48E }
@media (prefers-reduced-motion: reduce) { .ls-item-p.sp-spin::before { animation: none } }

/* КАРТОЧКА «ГОТОВИМ ДЛЯ ТЕБЯ» — сразу под строкой поиска. Отвечает на вопрос,
   ради которого человек вернулся в список: где моя песня и жива ли она. Кадр из
   клипа доказывает, что готовится именно ЭТА песня. */
.sp-work { margin: 0 0 var(--s5); padding: var(--s4); border-radius: 14px;
  border: 1px solid rgba(194,134,90,.42);
  background: linear-gradient(180deg, rgba(246,222,200,.30), rgba(246,222,200,.06) 78%); }
.sp-work-h { display: flex; align-items: center; gap: var(--s3);
  font-size: 12px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--accent2) }
.sp-work-h .sp-spin { display: inline-block; position: relative; width: 13px; height: 13px; flex: 0 0 auto }
.sp-work-h .sp-spin::before { content: ""; position: absolute; inset: 0; border-radius: 50%;
  border: 2px solid rgba(194,134,90,.32); border-top-color: #C2865A;
  animation: sp-spin .8s linear infinite }
.sp-work-row { display: flex; align-items: center; gap: var(--s4); margin-top: var(--s4) }
.sp-work-pic { flex: 0 0 auto; width: 72px; height: 41px; border-radius: 8px; object-fit: cover;
  background: var(--bg-3); border: 1px solid var(--line) }
.sp-work-nopic { display: flex; align-items: center; justify-content: center; color: var(--dim); font-size: 17px }
.sp-work-t { min-width: 0 }
.sp-work-t b { display: block; font-size: 15.5px; font-weight: 700; line-height: 1.25;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.sp-work-t small { display: block; margin-top: 2px; color: var(--dim); font-size: 12px }
.sp-work-p { margin: var(--s4) 0 0; color: var(--mut); font-size: 13px; line-height: 1.5 }
/* Блок «застряла» шкафом sp-work-stuck убран 08.09 (правка Сармата — на его
   месте теперь «Новые релизы», см. новыеРелизыHtml в song-picker.js). Само
   состояние gaveUp никуда не делось: сдавшаяся песня по-прежнему видна внутри
   папки своей группы приглушённой строкой (sp-work-warn ниже — он оттуда, не
   от шкафа, поэтому остаётся). */
.sp-work-warn { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 15px; height: 15px; border-radius: 50%; border: 2px solid var(--line-strong);
  color: var(--mut); font-size: 10px; font-weight: 800; line-height: 1 }

html[data-theme="dark"] .sp-work { border-color: rgba(233,196,142,.34);
  background: linear-gradient(180deg, rgba(233,196,142,.14), rgba(233,196,142,.03) 78%) }
html[data-theme="dark"] .sp-work-h { color: #E9C48E }
html[data-theme="dark"] .sp-work-h .sp-spin::before { border-top-color: #E9C48E }
@media (prefers-reduced-motion: reduce) { .sp-work-h .sp-spin::before { animation: none } }

/* Длинное название не переносится в три строки и не выпихивает год за край. */
.ls-item.sp-row b { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.ls-item.sp-row small { flex: 0 1 auto; max-width: 52%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
#spChk { color: var(--dim) }

/* ============ ПАПКА ГРУППЫ И ЕЁ ПЕСНИ — РАЗНЫЙ МАТЕРИАЛ (31.07) ============
   Жалоба: «раскрытый список песен и блоки групп по стилю одно и то же, всё
   сливается». Раньше разница держалась на одном отступе с тонкой линейкой —
   а отступ работает только пока список короткий: на пятой группе глаз уже не
   помнит, что сдвинуто, а что нет.
   Теперь разница материальная и работает без счёта отступов:
     ПАПКА  — хром. Литая плашка серебром, розово-золотая кромка слева, число
              песен на хромовом жетоне. Это «прибор», по нему нажимают.
     ПЕСНИ  — бумага. Матовые карточки без металлической грани, тоньше кромка,
              меньше скругление, каждая пришвартована к розово-золотой рейке
              короткой поперечиной. Это содержимое, его читают.
   Раскрытая связка вдобавок стоит на своей подложке — видно, где группа
   кончилась и началась следующая. Цветовых семейств по-прежнему два: розовое
   золото знака и хром корпуса, третьего не заводим. */
.sp-group { margin-bottom: 10px; border-radius: 14px;
  transition: background var(--d-base) var(--ease) }
.sp-group.open { background: linear-gradient(180deg, rgba(220,226,236,.55), rgba(220,226,236,0) 72%);
  padding-bottom: 2px }

/* Хромовая плашка. Диагональный отлив — это и есть «металл»: одна светлая
   полоса поперёк, а не равномерная заливка. */
.ls-item.sp-folder { position: relative; overflow: hidden; margin-bottom: 0;
  border-color: rgba(194,134,90,.5);
  background:
    linear-gradient(180deg, rgba(255,255,255,.96), rgba(255,255,255,.30) 46%, rgba(224,230,240,.85)),
    linear-gradient(100deg, #EEF1F6, #FFFFFF 26%, #E3E8F0 52%, #FBFCFE 74%, #E9EDF4);
  box-shadow: inset 0 1px 0 #fff, inset 0 -1px 0 rgba(23,32,56,.07), 0 3px 12px rgba(23,32,56,.10) }
.sp-group.open .ls-item.sp-folder { border-bottom-left-radius: 4px; border-bottom-right-radius: 4px }
/* Розово-золотая кромка по левому ребру плашки — знак продукта на металле. */
.ls-item.sp-folder::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: linear-gradient(180deg, #F6DEC8, #DFAE86 45%, #C2865A) }
.ls-item.sp-folder b { font-weight: 800; letter-spacing: .01em; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
/* Число песен — жетон, а не подпись: у папки это показание прибора. */
.ls-item.sp-folder small { flex: 0 0 auto; padding: 3px 9px; border-radius: 999px;
  color: #8A5620; background: linear-gradient(180deg, #FFFFFF, #ECEFF5);
  border: 1px solid rgba(194,134,90,.32); box-shadow: inset 0 1px 0 #fff }
.ls-item.sp-folder .ls-item-p { color: #C2865A }
/* Шеврон вместо ＋/−: разворот показывает состояние движением, а не сменой знака. */
.ls-item .sp-fold-x { position: relative; flex: 0 0 auto; width: 22px; height: 22px }
.ls-item .sp-fold-x::before { content: ""; position: absolute; left: 6px; top: 6px;
  width: 8px; height: 8px; border-right: 2px solid #C2865A; border-bottom: 2px solid #C2865A;
  transform: rotate(45deg); transition: transform var(--d-base) var(--ease) }
.sp-group.open .sp-fold-x::before { top: 9px; transform: rotate(-135deg) }
@media (prefers-reduced-motion: reduce) { .ls-item .sp-fold-x::before { transition: none } }

/* Бумага на рейке. Рейка не доходит до низа: она ведёт от плашки к последней
   песне и обрывается — так видно, что связка кончилась.

   ПЛАВНОЕ РАСКРЫТИЕ (09.09, правка Сармата: «резкое» вместо hidden-атрибута
   в один кадр). display:none у [hidden] не анимируется в принципе — сама
   .sp-folder-songs теперь grid-контейнер с одной строкой, чья высота едет
   0fr→1fr по .sp-group.open; настоящее содержимое и его паддинг/рейка/карточки
   переехали во внутренний .sp-folder-songs-in с overflow:hidden — это и есть
   тот classic-приём, который сжимает «auto»-высоту без JS-замера scrollHeight. */
/* ЕЩЁ ПЛАВНЕЕ — ЗА СЧЁТ КАДРОВ, А НЕ ДЛИТЕЛЬНОСТИ (10.09.2026, правка Сармата,
   п.6: «уже плавно, но сделать ещё плавнее именно частотой кадров»).
   Длительность НЕ увеличена намеренно: медленнее не значит плавнее, а на
   раскрытии списка медленнее значит «тормозит».

   ЧЕСТНО О ПОТОЛКЕ. grid-template-rows — свойство РАСКЛАДКИ: каждый кадр
   браузер пересчитывает геометрию папки и всего, что под ней, в главном
   потоке. На композитор это не уходит ни при каком will-change, и обещать
   здесь 120 Гц было бы враньём. Поэтому взято три настоящих рычага:
   1. `contain: layout paint` на содержимом папки — пересчёт раскладки
      ограничен поддеревом папки вместо всего документа. Это прямая экономия
      миллисекунд на кадр, то есть больше кадров, укладывающихся в бюджет;
      именно для этого contain и существует.
   2. Само движение отдано КОМПОЗИТОРУ: содержимое дополнительно приезжает
      transform+opacity (sp-slide ниже) — эти два свойства анимируются вне
      главного потока и идут с частотой дисплея. Глаз читает плавность именно
      по ним, а высота лишь освобождает место.
   3. Кривая набрана linear() из 25 точек (шаг 4.17% ≈ 13ms при 320ms) вместо
      одной cubic-bezier: браузер интерполирует между точками линейно, и такой
      шаг заведомо мельче кадра даже на 120 Гц. cubic-bezier оставлен первой
      строкой как откат для движков без linear(). */
.sp-folder-songs { display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows .32s cubic-bezier(.4,0,.2,1);
  transition: grid-template-rows .32s linear(0 0%, 0.1273 4.17%, 0.243 8.33%,
    0.3477 12.5%, 0.442 16.67%, 0.5265 20.83%, 0.6017 25%, 0.6683 29.17%,
    0.7268 33.33%, 0.7778 37.5%, 0.8218 41.67%, 0.8594 45.83%, 0.8912 50%,
    0.9176 54.17%, 0.9393 58.33%, 0.9567 62.5%, 0.9703 66.67%, 0.9806 70.83%,
    0.9882 75%, 0.9934 79.17%, 0.9968 83.33%, 0.9987 87.5%, 0.9996 91.67%,
    1 95.83%, 1 100%) }
.sp-group.open .sp-folder-songs { grid-template-rows: 1fr }
@media (prefers-reduced-motion: reduce) { .sp-folder-songs { transition: none } }
/* ОТСТУПЫ — МАРЖОЙ ДЕТЕЙ, А НЕ ПАДДИНГОМ (17.10.2026). Паддинг 10+4 px ряд 0fr сжать
   не может, и у КАЖДОЙ закрытой папки висела пустая полоса 14 px: просвет под папкой
   выходил 24 px против 10 px между песнями. Маржа первой/последней песни живёт внутри
   содержимого (contain: layout — свой контекст, маржа не выпадает наружу), поэтому 0fr
   сжимает папку в ноль, а у открытой геометрия та же, что с паддингом. */
.sp-folder-songs-in { position: relative; overflow: hidden; min-height: 0; margin: 0; padding: 0 0 0 18px;
  contain: layout paint;
  /* Тот же приём, что у пружины кнопок: слой на GPU живёт ТОЛЬКО пока папка
     открыта или закрывается, а не постоянно на каждой из двадцати папок. */
  transform: translateY(-8px); opacity: 0;
  transition: transform .3s cubic-bezier(.2,.7,.3,1), opacity .22s linear }
.sp-group.open .sp-folder-songs-in { transform: none; opacity: 1; will-change: transform, opacity }
@media (prefers-reduced-motion: reduce) {
  .sp-folder-songs-in { transition: none; transform: none; opacity: 1 } }
.sp-folder-songs-in::before { content: ""; position: absolute; left: 7px; top: 0; bottom: 14px; width: 2px;
  border-radius: 2px; background: linear-gradient(180deg, #DFAE86, rgba(223,174,134,.18)) }
.sp-folder-songs-in .ls-item { position: relative; margin-bottom: 8px; border-radius: 10px;
  border-color: rgba(194,134,90,.24); background: #CDD3DC;
  box-shadow: 0 1px 5px rgba(23,32,56,.07) }
.sp-folder-songs-in > :first-child { margin-top: 10px }
.sp-folder-songs-in .ls-item:last-child, .sp-folder-songs-in > :last-child { margin-bottom: 4px }
/* Поперечина от рейки к карточке — «песня пришвартована к своей группе». */
.sp-folder-songs-in .ls-item::before { content: ""; position: absolute; left: -11px; top: 50%;
  width: 11px; height: 1px; background: rgba(194,134,90,.45) }
.sp-folder-songs-in .ls-item b { font-weight: 600 }
.sp-folder-songs-in .ls-item:active { box-shadow: 0 1px 3px rgba(23,32,56,.09) }

/* Заголовок «Уже собраны» получает розово-золотую черту: раздел начинается
   явно, а не просто следующей карточкой. Флекс — ради кнопки «раскрыть всё»
   рядом с надписью (правка Сармата 08.09), а не только текст один в столбик. */
#spHave .ls-have-h { position: relative; padding-bottom: 8px;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3) }
#spHave .ls-have-h::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg, #DFAE86, rgba(223,174,134,0) 62%) }
/* «Раскрыть всё» — открывает разом треки каждой группы (SP.раскрыто получает
   все ключи). Обводка, а не заливка: рядом с золотой чертой заливка спорила
   бы с ней за внимание, а тут нужна тихая вторичная кнопка. */
.sp-expand-all { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap); min-width: 44px; border: 1px solid rgba(194,134,90,.45); background: transparent;
  color: #C2865A; font: inherit; font-size: 11px; font-weight: 700; letter-spacing: .04em;
  padding: 0 11px; border-radius: 999px; cursor: pointer }
.sp-expand-all:active { background: rgba(194,134,90,.14) }
html[data-theme="dark"] .sp-expand-all { border-color: rgba(233,196,142,.42); color: #E9C48E }
html[data-theme="dark"] .sp-expand-all:active { background: rgba(233,196,142,.16) }

/* ТЁМНАЯ ТЕМА — здесь же, а не в theme-dark.css. Правило файла: экран выбора
   правят параллельно с песней, и общий файл стилей ровно то место, где две
   сессии затирают друг друга. Специфичности хватает (0,3,1 против 0,2,1 у
   общих тёмных правил), поэтому порядок подключения роли не играет.
   Металл на тёмном другой: хром становится графитом с холодным отливом,
   розовое золото светлеет до #E9C48E — иначе кромка тонет в фоне. */
html[data-theme="dark"] .sp-group.open {
  background: linear-gradient(180deg, rgba(243,217,172,.07), rgba(243,217,172,0) 72%) }
html[data-theme="dark"] .ls-item.sp-folder {
  border-color: rgba(243,217,172,.34);
  background:
    linear-gradient(180deg, rgba(255,255,255,.10), rgba(255,255,255,.02) 46%, rgba(0,0,0,.20)),
    linear-gradient(100deg, #241B31, #31263F 26%, #1F1729 52%, #352943 74%, #221A2E);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.10), 0 3px 12px rgba(0,0,0,.50) }
html[data-theme="dark"] .ls-item.sp-folder::before {
  background: linear-gradient(180deg, #FBEBD6, #E9C48E 45%, #C89A66) }
html[data-theme="dark"] .ls-item.sp-folder small {
  color: #F3D9AC; border-color: rgba(243,217,172,.30);
  background: linear-gradient(180deg, rgba(255,255,255,.10), rgba(255,255,255,.03));
  box-shadow: inset 0 1px 0 rgba(255,255,255,.10) }
html[data-theme="dark"] .ls-item.sp-folder .ls-item-p { color: #E9C48E }
html[data-theme="dark"] .ls-item .sp-fold-x::before { border-color: #E9C48E }
html[data-theme="dark"] .sp-folder-songs-in::before {
  background: linear-gradient(180deg, #E9C48E, rgba(233,196,142,.15)) }
html[data-theme="dark"] .sp-folder-songs-in .ls-item {
  background: var(--bg-1); border-color: rgba(243,217,172,.18);
  box-shadow: 0 1px 5px rgba(0,0,0,.45) }
html[data-theme="dark"] .sp-folder-songs-in .ls-item::before { background: rgba(243,217,172,.35) }
html[data-theme="dark"] #spHave .ls-have-h::after {
  background: linear-gradient(90deg, #E9C48E, rgba(233,196,142,0) 62%) }

/* --------------------------- ЭКРАН СБОРКИ ----------------------------- */
/* Занимает экран целиком. Это и есть защита от «я тыкал другие песни»:
   тыкать больше не во что. */

/* Экран сборки — «идёт работа над твоей песней», и это должно ощущаться.
   Композиция по центру: эквалайзер живёт всегда (правило UX: при ожидании
   дольше 300мс что-то обязано двигаться), под ним имя песни, ниже стэппер
   с золотой нитью прогресса. Палитра — родной металл продукта. */
.sp-build { padding: var(--s7, 40px) var(--s4); max-width: 520px; margin: 0 auto; text-align: center }

/* Эквалайзер: пять золотых столбиков дышат вразнобой. Музыкальный продукт —
   музыкальный индикатор, а не безликая крутилка. */
.sp-eq { display: flex; justify-content: center; align-items: flex-end; gap: 5px;
         height: 34px; margin-bottom: var(--s5) }
.sp-eq i { width: 6px; border-radius: 3px;
  background: linear-gradient(180deg, #F6DEC8, #DFAE86 55%, #C2865A);
  box-shadow: 0 0 10px rgba(223,174,134,.35);
  animation: sp-eq 1.05s ease-in-out infinite }
.sp-eq i:nth-child(1) { animation-delay: 0s }
.sp-eq i:nth-child(2) { animation-delay: .18s }
.sp-eq i:nth-child(3) { animation-delay: .36s }
.sp-eq i:nth-child(4) { animation-delay: .09s }
.sp-eq i:nth-child(5) { animation-delay: .27s }
@keyframes sp-eq { 0%,100% { height: 30% } 40% { height: 100% } 70% { height: 55% } }

.sp-build-song { margin-bottom: var(--s6) }
.sp-build-song b { display: block; font-size: 23px; font-weight: 800; line-height: 1.25 }
.sp-build-song small { display: block; margin-top: var(--s2); color: var(--dim); font-size: 12px;
  font-family: ui-monospace,"SFMono-Regular","JetBrains Mono","Cascadia Code",Consolas,"Noto Sans Thai","Noto Sans TC",monospace;
  letter-spacing: .18em; text-transform: uppercase }

/* Стэппер: кружки соединены нитью, нить наливается золотом по мере готовности.
   Состояние читается одним взглядом: пустой — не начали, кольцо бежит — идёт,
   золотая точка с галкой — сделано. */
.sp-steps { list-style: none; margin: 0 auto; padding: 0; width: fit-content; text-align: left }
.sp-steps li {
  position: relative; display: flex; align-items: center; gap: var(--s4);
  padding: var(--s3) 0; color: var(--dim); font-size: 15px; min-height: 46px;
  transition: color var(--d-base) var(--ease);
}
/* Нить между кружками. У сделанного шага — золотая. */
.sp-steps li:not(:last-child)::before {
  content: ""; position: absolute; left: 10px; top: calc(50% + 15px); height: 18px;
  width: 2px; background: var(--line-strong); border-radius: 1px;
  transition: background var(--d-base) var(--ease);
}
.sp-steps li.done:not(:last-child)::before { background: #C2865A }
.sp-steps i {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%; box-sizing: border-box;
  border: 2px solid var(--line-strong); position: relative;
  transition: border-color var(--d-base) var(--ease), background var(--d-base) var(--ease);
}
.sp-steps li.now { color: var(--ink); font-weight: 600 }
.sp-steps li.now span { animation: sp-breathe 1.6s ease-in-out infinite }
/* Бегущее кольцо вокруг текущего шага — непрерывное движение вместо пульса. */
.sp-steps li.now i { border-color: rgba(194,134,90,.4) }
.sp-steps li.now i::before {
  content: ""; position: absolute; inset: -6px; border-radius: 50%;
  border: 2px solid transparent; border-top-color: #DFAE86;
  animation: sp-spin .9s linear infinite;
}
.sp-steps li.now i::after {
  content: ""; position: absolute; inset: 4px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #F6DEC8, #C2865A);
  animation: sp-breathe 1.6s ease-in-out infinite;
}
.sp-steps li.done { color: var(--mut) }
.sp-steps li.done i {
  border-color: #C2865A;
  background: linear-gradient(160deg, #F0CDA9, #C2865A);
  box-shadow: 0 0 8px rgba(223,174,134,.4);
}
.sp-steps li.done i::after {
  content: ""; position: absolute; left: 6px; top: 3px;
  width: 4px; height: 9px; border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
@keyframes sp-spin { to { transform: rotate(360deg) } }
@keyframes sp-breathe { 0%,100% { opacity: 1 } 50% { opacity: .55 } }
@media (prefers-reduced-motion: reduce) {
  .sp-eq i, .sp-steps li.now i::before, .sp-steps li.now i::after, .sp-steps li.now span { animation: none }
}

.sp-hint { margin-top: var(--s6); margin-bottom: var(--s2); color: var(--dim); font-size: 12.5px; line-height: 1.5 }
.sp-wait { margin: 0; color: var(--dim); font-size: 13px; line-height: 1.5 }
.sp-wait b { color: var(--mut); font-variant-numeric: tabular-nums }

/* Плеер-проверяльщик. Не display:none — скрытый iframe ютюб не инициализирует
   и события об ошибке не приходят. Поэтому он есть, но его не видно. */
.sp-probe { position: absolute; width: 200px; height: 120px; left: -9999px; top: 0; opacity: .01; pointer-events: none }

/* КЛИП ФОНОМ НА ВРЕМЯ СБОРКИ. Сборка идёт минуты, и пустой экран со списком
   шагов читается как зависший. z-index 0 с прозрачностью, а НЕ -1: при -1 кадр
   уходит под непрозрачный фон страницы и не виден вовсе. Пропорции ютюба 16:9 с
   телефоном не совпадают — кадр растягиваем по большей стороне и центрируем. */
.sp-build { position: relative; z-index: 1 }
.sp-build-bg {
  position: fixed; inset: 0; z-index: 0; overflow: hidden; pointer-events: none;
  opacity: .22; filter: saturate(1.1);
  /* Центр ВЫБЕЛЕН: текст шагов стоит там же, и кадр под ним сделал бы его
     нечитаемым. Движение остаётся по краям — этого хватает, чтобы экран не
     выглядел мёртвым. */
  -webkit-mask-image: radial-gradient(closest-side circle at 50% 42%, transparent 0%, transparent 46%, #000 100%);
          mask-image: radial-gradient(closest-side circle at 50% 42%, transparent 0%, transparent 46%, #000 100%);
}
.sp-build-bg iframe {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 100vw; height: 56.25vw;            /* 16:9 по ширине… */
  min-width: 177.78vh; min-height: 100vh;   /* …и по высоте: что больше, то и берёт */
  border: 0;
}
@media (prefers-reduced-motion: reduce) { .sp-build-bg { display: none } }

/* ---------------------------- ЭКРАН ОТКАЗА ---------------------------- */

.sp-fail { padding: var(--s6) var(--s4); max-width: 520px; margin: 0 auto }
.sp-fail h2 { margin: 0 0 var(--s3); font-size: 20px; font-weight: 800 }
.sp-fail p { margin: 0 0 var(--s5); color: var(--mut); font-size: 14.5px; line-height: 1.55 }
.sp-fail .ls-guest-cta { display: inline-block; margin: 0 var(--s2) var(--s2) 0 }
.sp-again { border: 1px solid var(--line-strong); background: var(--bg-2); color: var(--ink);
            font: inherit; font-size: 14px; font-weight: 600; padding: 0 var(--s4);
            min-height: 44px; cursor: pointer }

/* --------------------------- ЗНАЧОК «ТАНЕЦ» --------------------------- */
/* Метка в строке каталога: у этой песни есть разбор танца. Не цветная плашка —
   в списке уже есть «уже собрана» и «нет текста», а четвёртый цветовой код на
   экране перебирает потолок [FHWA-RD-98-057]. Отличается рамкой и разрядкой. */
/* СТРОКА С ДВУМЯ ДВЕРЯМИ — И ТОЛЬКО ДВУМЯ (правка Сармата 17.08). Название
   слева — текст, не ссылка: `.sp-word` теперь `<span>`, тап по нему и по
   пустой середине (`.sp-fill`) ничего не делает. Открывают только капсулы
   справа — «танец» (если есть) и «песня» (всегда). Обе настоящие ссылки,
   поэтому работают долгий тап, открытие в новой вкладке и кнопка «назад».
   Зона нажатия у каждой не меньше пальца. Причина: строка-ссылка раздувалась
   по ширине текста, и на BOCA задвоенное название («BOCA (BOCA)») сделало
   пустое на вид место кликабельным — читалось как случайное открытие. */
.ls-item.sp-two { display: flex; align-items: stretch; gap: 0; padding: 0 }
/* .sp-word занимает только вес своего текста (flex:0 1 auto — растёт некуда,
   ужимается при нехватке места), а .sp-fill забирает пустой остаток строки.
   Оба не ловят тапы — ни один не дверь, дверь только у капсул справа. */
.sp-two .sp-word { display: flex; align-items: center; gap: var(--s2); flex: 0 1 auto;
                   min-width: 0; min-height: var(--tap); padding: 0 var(--s4);
                   color: inherit; text-decoration: none }
.sp-two .sp-fill { flex: 1 1 auto; min-width: 0 }
.sp-two .sp-word b { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.sp-two .sp-word small { padding-left: var(--s2); color: var(--dim); white-space: nowrap }
/* Капсула в строке ЖИВЁТ, но перестала быть главным входом: она теперь второй,
   утилитарный вход для того, кто уже нашёл свою песню в списке. Главный вход —
   полка ниже. Цвет подняли с --dim до --accent: серым по тёмному она читалась
   как выключенная надпись, а не как дверь. Слово оставлено рядом со значком —
   значок в одиночку почти всегда двусмыслен, «a text label must be present
   alongside an icon to clarify its meaning» [NN/g «Icon Usability», 27.07.2014]. */
.sp-dance { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; min-height: var(--tap);
            padding: 0 var(--s4); border-left: 1px solid var(--line-strong);
            color: var(--accent); text-decoration: none;
            font-size: 11px; font-weight: 700; letter-spacing: .08em;
            text-transform: uppercase; white-space: nowrap }
/* Значок — треугольник «пуск», тот же смысловой знак, что на карточке полки. */
.sp-dance-g { flex: 0 0 auto; width: 0; height: 0;
              border: 5px solid transparent; border-left-width: 8px; border-right-width: 0;
              border-left-color: currentColor }
.sp-dance:hover, .sp-dance:focus-visible { background: var(--accent); color: var(--bg-0) }
/* КАПСУЛА «ПЕСНЯ» — крайняя справа и есть у КАЖДОЙ строки (правка 06.08,
   с 17.08 — единственный вход к разбору слов, название больше не ссылка).
   Цветом тише «танца»: танец новый и его надо заметить, песня — привычное
   действие, ей хватает читаемости. Фокусируется с клавиатуры как обычная
   ссылка — второй остановки на том же адресе больше нет, дублировать
   названием нечего. */
.sp-song { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; min-height: var(--tap);
           padding: 0 var(--s4); border-left: 1px solid var(--line-strong);
           color: var(--ink); text-decoration: none;
           font-size: 11px; font-weight: 700; letter-spacing: .08em;
           text-transform: uppercase; white-space: nowrap }
.sp-song:hover, .sp-song:focus-visible { background: var(--bg-4) }
/* Значок — три строки текста: то, чем разбор песни отличается от танца. */
.sp-song-g { flex: 0 0 auto; width: 11px; height: 9px;
             background: linear-gradient(currentColor 0 0) 0 0/100% 1.5px no-repeat,
                         linear-gradient(currentColor 0 0) 0 50%/100% 1.5px no-repeat,
                         linear-gradient(currentColor 0 0) 0 100%/70% 1.5px no-repeat }
/* Две капсулы рядом на 390px: название обязано ужиматься первым, а не толкать
   их за край. Отступы внутри капсул поджаты, чтобы обе целиком влезли. */
.sp-two .sp-dance, .sp-two .sp-song { padding: 0 12px }
@media (max-width: 400px) {
  .sp-two .sp-word { padding: 0 12px }
  .sp-two .sp-dance, .sp-two .sp-song { padding: 0 10px; font-size: 10px; letter-spacing: .06em }
}

/* ======================== ПОЛКА «ПОВТОРИ ЗА НИМИ» ======================== */
/* Горизонтальный ряд карточек с кадром официального клипа — единственный блок
   на экране, который продаёт картинкой, а не строчкой. Стоит выше складок с
   группами: без него одиннадцать из тринадцати входов в танец не видно вовсе.
   Ряд ВЫХОДИТ за поля списка (margin -12px = падение .ls-list) специально:
   карточка, обрезанная правым краем экрана, сама сообщает, что ряд листается —
   тот же приём, которым Material показывает прокручиваемый набор чипов
   [Material Design 3, Chips → Guidelines, «Filter chips can scroll horizontally»]. */
.sp-shelf { margin: 0 0 var(--s5) }
.sp-shelf-h { display: flex; align-items: center; gap: var(--s2); margin: 0 0 2px }
.sp-shelf-h h2 { margin: 0; font-size: 12px; font-weight: 800; letter-spacing: .14em;
                 text-transform: uppercase; color: var(--ink) }
.sp-shelf-n { flex: 0 0 auto; min-width: 20px; padding: 2px 7px; border-radius: 999px;
              background: var(--accent); color: var(--bg-0);
              font-size: 11px; font-weight: 800; line-height: 1.3; text-align: center;
              font-variant-numeric: tabular-nums }
/* Подпись под заголовком — не украшение, а ОБЕЩАНИЕ МЕХАНИКИ. «Танец» само по
   себе ничего не сулит; «по восьмёркам · 0.5× · зеркало» объясняет, что внутри
   можно делать руками и ногами, а это и есть повод нажать. */
.sp-shelf-p { margin: 0 0 var(--s3); color: var(--dim); font-size: 11.5px; line-height: 1.4 }
/* scroll-padding обязателен вместе с отрицательным полем: без него притяжение
   выравнивает первую карточку по КРАЮ КОНТЕЙНЕРА, а не по краю содержимого,
   и ряд при загрузке сам уезжает влево на 12px — первая карточка и её подпись
   оказываются подрезаны экраном. Ловилось глазами на снимке 390px. */
.sp-shelf-r { display: flex; gap: 10px; overflow-x: auto; overscroll-behavior-x: contain;
              scroll-snap-type: x proximity; scroll-padding-inline: 12px;
              -webkit-overflow-scrolling: touch;
              margin: 0 -12px; padding: 2px 12px 6px;
              scrollbar-width: none }
.sp-shelf-r::-webkit-scrollbar { display: none }
.sp-shelf-c { flex: 0 0 auto; width: 132px; scroll-snap-align: start;
              display: block; text-decoration: none; color: inherit }
.sp-shelf-pic { position: relative; display: block; width: 132px; height: 74px;
                overflow: hidden; background: var(--bg-3);
                border: 1px solid var(--line-strong) }
/* Кадр 320x180 обрезается по центру: у клипов ютюба mqdefault почти всегда
   16:9, но ловить исключение растянутой картинкой нельзя. */
.sp-shelf-pic img { width: 100%; height: 100%; object-fit: cover; display: block }
/* Треугольник «пуск» — знак того, что за карточкой видео, а не статья.
   Лежит на затемнении, иначе на светлом кадре он исчезает. */
.sp-shelf-play { position: absolute; left: 50%; top: 50%; width: 30px; height: 30px;
                 margin: -15px 0 0 -15px; border-radius: 999px;
                 background: rgba(16,11,24,.62); box-shadow: 0 1px 6px rgba(0,0,0,.35) }
.sp-shelf-play::after { content: ""; position: absolute; left: 12px; top: 9px;
                        width: 0; height: 0; border: 6px solid transparent;
                        border-left-width: 9px; border-right-width: 0; border-left-color: #FFF }
/* Название в ДВЕ строки, а не в одну с многоточием: «SUGAR HONEY ICE TEA» в
   132px обрезается до «SUGAR HONEY IC…», а песню человек узнаёт по имени
   целиком. Высота зафиксирована двумя строками, иначе карточки с коротким и
   длинным названием разъезжаются по нижнему краю. */
.sp-shelf-c b { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
                margin: 6px 0 1px; min-height: 32px; font-size: 13px; font-weight: 700;
                line-height: 1.25; color: var(--ink); overflow: hidden }
.sp-shelf-c small { display: block; font-size: 11px; color: var(--dim);
                    overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.sp-shelf-c:hover .sp-shelf-pic,
.sp-shelf-c:focus-visible .sp-shelf-pic { border-color: var(--accent) }
/* Фокус с клавиатуры обязан быть виден на самой карточке, а не только на кадре:
   при прокрутке ряда обводка по кадру уезжает под соседа. */
.sp-shelf-c:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px }
@media (prefers-reduced-motion: no-preference) {
  .sp-shelf-c { transition: transform var(--d-fast) var(--ease) }
  .sp-shelf-c:active { transform: scale(.97) }
}
/* Тёмная тема родная, а не инверсия: кромка кадра светлеет, а не темнеет, и
   счётчик берёт розовый акцент темы, у которого хватает контраста на #100B18. */
html[data-theme="dark"] .sp-shelf-pic { background: var(--bg-3); border-color: rgba(255,255,255,.14) }
html[data-theme="dark"] .sp-shelf-n { background: var(--accent); color: #1A1024 }
html[data-theme="dark"] .sp-dance:hover,
html[data-theme="dark"] .sp-dance:focus-visible { background: var(--accent); color: #1A1024 }

/* ПОЛЕ ПОИСКА — ФИРМЕННОЙ СИРЕНЬЮ (09.10.2026, две правки Сармата: «рамку обведи
   заметнее» и следом «золотым некрасиво — обведи нашим розовым, фирменным»).
   «Розовый» Сармата — сиреневая каёмка знака #C79EE8 (в светлой теме темнее,
   #8E5FD6, ради контраста к белому). Золото было в двух местах: шампань в середине
   прошлой градиентной рамки и общее кольцо фокуса сайта (:focus-visible в style.css,
   в тёмной теме золотое, с !important) — у текстового поля оно горит на ЛЮБОМ фокусе,
   не только с клавиатуры. Поэтому здесь своё кольцо фокуса той же сиренью; перебить
   !important можно только им же — исключение ровно для этого поля. Селектор с .ls-list
   сильнее и общего .ls-find в learn.html, и тёмного в theme-dark.css. */
.ls-list .ls-find {
  border: 1.5px solid #8E5FD6;
  background: #FFFFFF;
  box-shadow: inset 0 1px 3px rgba(23,32,56,.06), 0 4px 14px rgba(142,95,214,.14);
}
.ls-list .ls-find:focus,
.ls-list .ls-find:focus-visible {
  border-color: #8E5FD6;
  outline: 2px solid rgba(142,95,214,.55) !important;
  outline-offset: 2px !important;
  box-shadow: inset 0 1px 3px rgba(23,32,56,.05), 0 4px 16px rgba(142,95,214,.22) !important;
}
html[data-theme="dark"] .ls-list .ls-find {
  border: 1.5px solid #C79EE8;
  background: var(--bg-1);
  box-shadow: inset 0 2px 4px rgba(0,0,0,.40), 0 0 0 3px rgba(199,158,232,.10), 0 6px 18px rgba(199,158,232,.18);
}
html[data-theme="dark"] .ls-list .ls-find:focus,
html[data-theme="dark"] .ls-list .ls-find:focus-visible {
  border-color: #C79EE8;
  outline: 2px solid rgba(199,158,232,.6) !important;
  outline-offset: 2px !important;
  box-shadow: inset 0 2px 4px rgba(0,0,0,.40), 0 6px 22px rgba(199,158,232,.30) !important;
}

/* Номер новинки на кадре — как в гримёрке (.hm-rank в cabinet.css): полка та же, и
   номер — первое, по чему глаз узнаёт, что это тот же список (09.10.2026). */
.sp-shelf-pic .sp-rank { position: absolute; left: 6px; top: 6px; min-width: 20px; height: 20px; padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center; border-radius: 6px;
  font-family: var(--f-mono, ui-monospace, monospace); font-size: 10.5px; font-weight: 800; color: #FFF6EA;
  background: rgba(10,6,16,.66); border: 1px solid rgba(255,255,255,.30) }

/* Поле поиска закрыто readonly, пока его не коснулись (song-picker.js, «ПОЛЕ ЗАКРЫТО»):
   курсор мыши всё равно текстовый — поле выглядит и ощущается обычным полем. */
.ls-list .ls-find[readonly] { cursor: text }

/* Заказ разбора (23.10.2026, song-picker.js «ЗАКАЗ РАЗБОРА»): песни нет в каталоге →
   карточка с кнопкой; после заказа — «принято» и, если пуши выключены, кнопка их включить. */
.sp-order { margin: 12px 0; padding: 14px 16px; border-radius: 12px; border: 1px solid var(--line);
  background: var(--bg-1); color: var(--ink); font-size: 14px; line-height: 1.5 }
.sp-order b { display: block; font-size: 15px }
.sp-order p { margin: 6px 0 0; color: var(--mut) }
.sp-order .ls-gbar-go { margin-top: 10px; width: 100% }
.sp-order-more { display: block; width: 100%; margin: 10px 0; cursor: pointer; text-align: center;
  font: inherit; font-size: 13.5px; color: var(--ink); border-radius: 12px }
.sp-order-row .sp-order-go { margin-left: auto; flex: 0 0 auto; font-size: 12px; font-weight: 750;
  padding: 6px 10px; border-radius: 999px; color: #2A1710; background: linear-gradient(160deg,#FDF2E6,#EDC7A2 40%,#D9A07C) }
