  :root{
    --bg:#07070d; --ink:#eceaf4; --dim:#8f8ba6;
    --note:#ff9e2c; --chord:#b18cff; --tonic:#57d9a3;
    --rec:#e5484d; --panel:rgba(16,16,28,.86);
    /* ЕДИНЫЙ ШРИФТ всего интерфейса — системный стек, без внешних файлов (проект без зависимостей,
       веб-шрифт добавил бы загрузку и мигание нестилизованного текста). Задаётся ЗДЕСЬ, наследуется
       всем меню и стартом. Холст (draw.js, ctx.font 'system-ui') — отдельно, это игровое поле. */
    --font:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
    /* ЕДИНЫЙ АКЦЕНТ МЕНЮ И СТАРТА — тёплый оранжевый (исходный var(--note)=#ff9e2c). --accent: основной
       тон для ЗАЛИВОК/рамок/фокуса и текста на ТЁМНОМ баре (там #ff9e2c читается). На светлом #ff9e2c
       как ТЕКСТ бледен (≈2.1:1), поэтому --accent-ink — темнее (жжёный янтарь #b45309, ≈5:1 на белом) —
       для ТЕКСТА и ссылок на светлых панелях/карточке. Роли соло/аккорды/бас/ударные (INSTR_COL,
       config.js) — игровое поле, НЕ трогаем; у аккордов свой сиреневый на ТЁМНОМ холсте — другой цвет. */
    --accent:#ff9e2c; --accent-ink:#b45309;
    /* ШКАЛА РАЗМЕРОВ МЕНЮ (4 шага): заголовок панели · контролы · ярлык строки · подсказка. */
    --fs-head:16px; --fs-ctl:14px; --fs-label:13px; --fs-hint:12px;
    /* РАДИУСЫ (2 шага): контролы · панели+стартовая карточка. */
    --r-sm:10px; --r-lg:18px;
    accent-color:var(--accent);            /* нативные контролы (ползунок, фокус) — в акцент */
  }
  *{box-sizing:border-box; -webkit-tap-highlight-color:transparent;}
  html,body{margin:0;height:100%;background:var(--bg);color:var(--ink);
    font-family:var(--font);
    overflow:hidden; touch-action:none; overscroll-behavior:none;}
  /* Фокус с клавиатуры — оранжевый контур на всех интерактивных контролах меню/старта. Берём
     --accent-ink (тёмный янтарь): на СВЕТЛЫХ панелях/карточке даёт ≥3:1 (нетекстовый контраст),
     а бледный #ff9e2c контуром там был бы слаб. У холста фокусируемых элементов нет — поле не задето. */
  button:focus-visible,select:focus-visible,input:focus-visible,a:focus-visible{
    outline:2px solid var(--accent-ink); outline-offset:2px;}
  #video{display:none;}
  #canvas{position:fixed; inset:0; width:100vw; height:100vh; display:block;}

  #bar{position:fixed; top:0; left:0; right:0; z-index:10;
    display:none; gap:6px; padding:8px; align-items:center;
    overflow-x:auto; scrollbar-width:none;
    background:linear-gradient(180deg, rgba(7,7,13,.82), transparent);}
  #bar::-webkit-scrollbar{display:none;}
  #bar.on{display:flex;}
  /* АВТО-СКРЫТИЕ: в свёрнутом виде (.min, ставит ui.js) на экране остаются ТОЛЬКО индикатор роли
     (одна кнопка или две половины) и три кнопки записи (🎥 клип, 🎙 аудио, ● лупер) — всё прочее
     скрыто до раскрытия (тап/движение мыши). Это ТЕ ЖЕ элементы, не второй набор. !important
     перебивает инлайновый display, который JS ставит у ◨/〰 — их собственные правила видимости
     продолжают действовать, когда панель РАСКРЫТА (.min снят). */
  #bar.min>#scaleBtn,
  #bar.min>#splitBtn,
  #bar.min>#camBtn,
  #bar.min>#fsBtn,
  #bar.min>#jamBtn,
  #bar.min>#loopPanelBtn{ display:none !important; }
  button{background:var(--panel); color:var(--ink); flex:0 0 auto;
    border:1px solid rgba(255,255,255,.22); border-radius:var(--r-sm);
    padding:9px 12px; font-size:var(--fs-ctl); line-height:1; font-family:var(--font);}
  button:active{transform:scale(.96);}
  /* ---- КНОПКА ЗАПИСИ: компактная круглая иконка ----
     Состояние показываем ВИДОМ, а не словами: подробности («круг N т.» / «слой K»)
     пишет холстовая полоса лупера (drawLooper). Четыре состояния:
       без класса — покой (полое кольцо), .armed — петля играет, тап добавит слой,
       .on.first — пишется первый круг, .on — наложение слоя (белое кольцо внутри).
     Пульс анимирует ТОЛЬКО transform/opacity на псевдоэлементе: работа композитора,
     без перерисовки каждый кадр (на телефоне и так ~196 мс инференса + холст 60 fps). */
  #recBtn{position:relative; width:34px; height:34px; padding:0; border-radius:50%;
    font-size:15px; line-height:1; color:var(--rec); background:transparent;
    border-color:rgba(229,72,77,.55);}
  #recBtn.armed{border-color:var(--rec); box-shadow:inset 0 0 0 3px rgba(229,72,77,.32);}
  #recBtn.on{background:var(--rec); border-color:var(--rec); color:#fff;}
  #recBtn.on:not(.first){box-shadow:inset 0 0 0 2px rgba(255,255,255,.85);}  /* наложение ≠ первый круг */
  #recBtn.on::after{content:''; position:absolute; inset:-3px; border-radius:50%;
    border:2px solid var(--rec); animation:recPulse 1.1s ease-out infinite; pointer-events:none;}
  @keyframes recPulse{ 0%{transform:scale(.9); opacity:.85;} 100%{transform:scale(1.55); opacity:0;} }
  #loopBtn.on{border-color:var(--accent); color:var(--accent); font-weight:600;}
  /* Кнопка роли — индикатор И переключатель. Центрируется в панели авто-отступами
     (при нехватке места они схлопываются, кнопка просто остаётся в своём порядке).
     Цвет — акцент текущей роли: --role ставит applyInstr, fallback на сиреневый. */
  #instrBtn,#instrBtnL,#instrBtnR{border-color:var(--role,var(--chord)); color:var(--role,var(--chord)); font-weight:600;}
  #instrBtn{margin-left:auto; margin-right:auto;}
  #loopPanelBtn.on{border-color:var(--accent); color:var(--accent); font-weight:600;}
  /* Видимость instrBtn (одна роль) и instrBtnL/R (две половины) целиком в JS (applySplit),
     по splitOn — CSS-правил больше нет. PC-режим удалён: класса .phone нет. Кнопки ⇄ (swap) и
     〰 (терменвокс) убраны — их роль забрала секция «Функции рук» в панели звукоряда. */
  /* 🔄 камера: .act = тыловая (незеркальная); визуально помечаем, что вид уже не «зеркало». */
  #camBtn{padding:9px 10px; font-size:15px;}
  #camBtn.act{border-color:var(--accent); color:var(--accent); font-weight:600;}
  /* ⛶ полноэкранный режим (иконка-кнопка бара): .act = уже во весь экран. Прячется целиком в JS,
     где нет Fullscreen API. Свёрнутый бар её тоже скрывает (список .min выше) — редкая «задал и забыл». */
  #fsBtn{padding:9px 10px; font-size:15px;}
  #fsBtn.act{border-color:var(--accent); color:var(--accent); font-weight:600;}
  /* 🎥 клип и 🎙 аудио — один движок записи (clip.js), общий вид: .act = идёт запись (красный +
     мягкий пульс). Отдельно от ● лупера — другой цвет-каркас и своя иконка, чтобы не путать
     музыкальную запись с записью медиа. */
  #clipBtn,#audioBtn{padding:9px 10px; font-size:15px;}
  #clipBtn.act,#audioBtn.act{background:var(--rec); border-color:var(--rec); color:#fff; font-weight:600;
    animation:clipPulse 1.2s ease-in-out infinite;}
  /* Пока идёт одна запись, ДРУГАЯ кнопка disabled (взаимное исключение видео/аудио): приглушаем,
     чтобы было видно — сейчас нельзя. */
  #clipBtn:disabled,#audioBtn:disabled{opacity:.4;}
  /* 🎵 джем: .act = играет вариант подложки (текст кнопки показывает N/всего). Акцент — оранжевый
     var(--accent), как у прочих активных тумблеров бара (единый акцент меню). Запись остаётся
     красной (--rec) — это статус записи, а не «активный тумблер». */
  #jamBtn.act{border-color:var(--accent); color:var(--accent); font-weight:600;}
  /* Пульс на box-shadow (не на transform/opacity) — кнопка остаётся на месте и видимой, в отличие
     от recPulse (тот гасит непрозрачность у ПСЕВДОэлемента-кольца ●). */
  @keyframes clipPulse{ 0%,100%{box-shadow:0 0 0 0 rgba(229,72,77,.55);} 50%{box-shadow:0 0 0 5px rgba(229,72,77,0);} }

  /* узкий экран / портрет: компактнее верхняя панель.
     Кнопок стало много (лад, роль(и), 〰, ◨, 🔄, 🎥, ⚙, ●). На ~390px они не влезали в ОДНУ строку,
     а полоса скроллилась по горизонтали со СКРЫТЫМ скроллбаром — последние кнопки (🎥, ⚙, ●)
     уезжали за правый край и выглядели «пропавшими». Решение: РАЗРЕШАЕМ ПЕРЕНОС (flex-wrap) — всё
     видно и достижимо во вторую строку, без скрытого скролла. auto-поля у #instrBtn (центрируют
     кнопку роли в ОДНОЙ строке) при переносе мешают — обнуляем, строки центрируем justify-content. */
  @media (max-width:560px){
    button{padding:8px 9px; font-size:var(--fs-label); border-radius:var(--r-sm);}
    #bar{gap:5px; padding:6px; flex-wrap:wrap; justify-content:center;}
    #instrBtn{margin:0;}
    #recBtn{width:32px; height:32px; padding:0; border-radius:50%; font-size:14px;}
    /* Раскрытый бар в портрете переносится на ДВЕ строки (flex-wrap выше); его 2-я строка легла бы ПОД
       подсказку тура (top:56) — там оказываются ●/🎵/⚙. Пока бар РАСКРЫТ (.on без .min) и подсказка на
       ВЕРХНЕЙ позиции (не .mini/.low — те уже у нижней кромки), опускаем её ниже двух строк бара (плавно,
       transform — база уже с transition). Так кнопка второй строки не прячется под подсказкой; свёрнулся
       бар (.min, одна строка) → правило снялось → подсказка вернулась к top:56. #tutorBar идёт ПОСЛЕ #bar
       в разметке → общий сосед `~`. */
    #bar.on:not(.min) ~ #tutorBar:not(.mini):not(.low){ transform:translateY(40px); }
  }
  /* Кнопка-индикатор звукоряда «лад · тоника» — единственный вход в меню.
     Длинные названия ладов режем МНОГОТОЧИЕМ средствами CSS, а не обрезкой строки в JS. */
  #scaleBtn{border-color:var(--accent); color:var(--accent); font-weight:600;
    max-width:46vw; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}

  /* ---- ТРАНСПОРТ ЛУПЕРА: полоса под холстовой полосой лупера ----
     По ГОРИЗОНТАЛИ повторяет коробку drawLooper: она рисуется как
     roundRect(x0-10, y0, bw+20, boxH), где bw=min(560, W-40) — это ровно
     left:10/right:10 при узком экране и центрированные 580px при широком.
     По ВЕРТИКАЛИ top ставит сам drawLooper (высота коробки растёт со слоями).
     z-index 11: выше холста, но ниже панелей (14/15) — открытое меню накрывает. */
  #loopTransport{position:fixed; left:10px; right:10px; max-width:580px; margin:0 auto;
    z-index:11; display:none; justify-content:center; gap:6px;
    padding:6px 8px; border-radius:var(--r-sm);
    background:rgba(10,10,20,.74); border:1px solid rgba(255,255,255,.14);
    backdrop-filter:blur(6px);}
  #loopTransport.on{display:flex;}
  #loopTransport button{padding:7px 10px; font-size:var(--fs-label);}
  @media (max-width:560px){ #loopTransport button{padding:6px 8px; font-size:var(--fs-hint);} }

  /* Тост камеры: всплывает под верхней панелью при отказе переключения; сам гаснет (класс .on
     снимает JS по таймеру). Не мешает игре — pointer-events:none, показывается только с .on. */
  #camMsg{position:fixed; top:52px; left:0; right:0; z-index:20; text-align:center;
    opacity:0; transition:opacity .25s; pointer-events:none;}
  #camMsg.on{opacity:1;}
  #camMsg::before{content:attr(data-msg); display:inline-block;
    background:rgba(10,10,20,.9); color:var(--ink); font-size:var(--fs-label);
    padding:8px 14px; border-radius:var(--r-sm); border:1px solid rgba(255,255,255,.22);
    backdrop-filter:blur(6px);}

  /* 🎵 Подложка: в игре на кнопке стоит ИМЯ звучащего варианта («🥁 Регги (уан-дроп) · 8/12»), поэтому
     ширину ОГРАНИЧИВАЕМ и режем многоточием средствами CSS — как #scaleBtn с длинными именами ладов.
     Без этого в портрете бар (flex-wrap) переносился бы из-за одной кнопки. Полное имя есть в title и в
     тосте смены, так что многоточие ничего не прячет насовсем. */
  #jamBtn{max-width:44vw; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}

  /* Выбор подложки (🎵): два пункта под кнопкой. Позицию (left/top) ставит ui.js по кнопке — бар
     переносится по ширине, фиксированной колонки у него нет. Пункт без ритмов для текущего размера
     ГАСНЕТ с причиной в title (disabled), а не открывает пустой цикл. */
  #backingMenu{position:fixed; z-index:30; display:flex; flex-direction:column; gap:4px;
    background:rgba(10,10,20,.94); border:1px solid rgba(255,255,255,.22);
    border-radius:var(--r-sm); padding:5px; backdrop-filter:blur(6px);}
  #backingMenu[hidden]{display:none;}
  #backingMenu button{width:100%; text-align:left; white-space:nowrap;}
  #backingMenu button:disabled{opacity:.45;}

  #status{position:fixed; left:10px; right:10px; bottom:6px; z-index:10;
    font-size:var(--fs-hint); color:var(--dim); text-shadow:0 1px 2px #000;
    white-space:nowrap; overflow:hidden;}

  /* ---- ОБУЧЕНИЕ (тур): полупрозрачная полоса-подсказка сверху, поверх камеры (сетку/руки видно) ----
     z 12: выше бара (10) и холста, ниже панелей (14/15) — открытая панель её накрывает (в туре не нужны).
     Стоит ниже бара (top:56px), чтобы не закрывать кнопку роли — её жмут на шаге 5. */
  #tutorBar{position:fixed; top:56px; left:8px; right:8px; max-width:560px; margin:0 auto; z-index:12;
    display:none; background:rgba(10,10,20,.82); color:var(--ink);
    border:1px solid rgba(255,255,255,.16); border-radius:var(--r-lg);
    padding:12px 14px; backdrop-filter:blur(6px); box-shadow:0 8px 30px rgba(0,0,0,.35);
    transition:transform .28s ease, opacity .25s ease;}
  #tutorBar.on{display:block;}
  /* .hushed — палец РАБОТАЕТ ВНУТРИ открытой панели: подсказку гасим совсем (плавно, opacity) и делаем
     кликом-насквозь (pointer-events:none), чтобы касания уходили в панель под ней. Возврат — через паузу
     (ui.armStripReturn). Кладётся ПОВЕРХ .mini (положение остаётся, меняется лишь видимость). */
  #tutorBar.hushed{ opacity:0; pointer-events:none; }
  /* ДВА состояния «внизу», их ставит ui.syncTutorBarPos:
     .low — КОРОБКА ЛУПЕРА (drawLooper, y≈64), БЕЗ панели: коробка вверху, поэтому ПОЛНУЮ подсказку двигаем
       ВНИЗ (transform, плавно; top:auto не анимируется), нижний край в 8px от низа. z 16 > панелей (14/15).
     .mini — ПАНЕЛЬ ОТКРЫТА: подсказку СВОРАЧИВАЕМ в одну строку (ниже), а не двигаем целиком — полная даже
       внизу накрывала нижние ряды панели.
     100dvh (видимая высота на мобильных) с фолбэком 100vh. Геометрию панелей НЕ трогаем. */
  #tutorBar.low{ z-index:16; transform:translateY(calc(100vh - 100% - 64px)); }
  #tutorBar.low{ transform:translateY(calc(100dvh - 100% - 64px)); }
  /* ПАНЕЛЬ ОТКРЫТА → СВЁРНУТАЯ подсказка у самой нижней кромки: только КРУПНАЯ ИНСТРУКЦИЯ + Next в одной
     строке; деталь, точки, Skip и камера-нота СПРЯТАНЫ — в панели не нужны, это даёт место. ИНСТРУКЦИЮ НЕ
     прячем: шаги просят два дела разом («смени строй на Ява…, затем возьми Пелог»), а человек листает длинное
     меню — без промпта работал бы по памяти. z 16 > панелей (14/15). Сдвиг transform (плавно), край в 4px от
     низа. Ни ширины, ни замеров — работает на любом экране. .on → display:block; .on.mini → flex.
     pointer-events:none на СТРОКЕ — КЛИК-НАСКВОЗЬ: подсказка лежит НАД нижними рядами панели, но касания
     уходят СКВОЗЬ текста в панель, поэтому контрол под строкой доступен ПРЯМЫМ тапом (а тап заодно взводит
     .hushed — строка гаснет, контрол видно), не только скроллом. Next возвращаем pointer-events:auto: между
     шагами с ОТКРЫТОЙ панелью (открыл меню → Дальше → выбери лад) его надо нажать; он в углу, крохотный — под
     ним теряется лишь край строки-контрола, центр контрола сквозной.
     ⚠️ ПРАВИЛО ПИШЕТСЯ КАК `.on.mini`, А НЕ `.mini`. Раньше здесь стояло `#tutorBar.mini{display:flex}`
     БЕЗ `.on` — и оно перебивало базовое `#tutorBar{display:none}` по специфичности (1-1-0 против 1-0-0).
     А `.mini` вешает syncTutorBarPos на ЛЮБОЕ открытие панели, идёт урок или нет, поэтому ВНЕ обучения
     открытие «Звукоряда» ВЫЗЫВАЛО пустую полосу с оранжевой кнопкой у нижней кромки. Видимость обязана
     решаться РОВНО одним классом — `.on`; положение (.mini/.low/.hushed) видимостью НЕ управляет. */
  #tutorBar.on.mini{ z-index:16; display:flex; align-items:center; gap:10px; padding:10px 14px;
    pointer-events:none;
    transform:translateY(calc(100vh - 100% - 60px)); }
  #tutorBar.on.mini{ transform:translateY(calc(100dvh - 100% - 60px)); }
  #tutorBar.mini #tutorText{ flex:1; min-width:0; }                 /* инструкция забирает ширину, переносится строками сколько надо */
  #tutorBar.mini #tutorBottom{ margin-top:0; flex:0 0 auto; pointer-events:none; }   /* ряд кнопок в ту же строку, ПО УМОЛЧАНИЮ СКВОЗНОЙ: тап по селекту под строкой (в т.ч. по стрелке справа, где сидит Next) уходит в ПАНЕЛЬ, не в Next — иначе случайный «Дальше» вместо смены функции руки */
  #tutorBar.mini #tutorNext.ready{ pointer-events:auto; }            /* Next НАЖИМАЕМ только когда шаг ВЫПОЛНЕН (класс .ready — светится): ровно тогда его и жмут (открыл меню → Дальше). Мимо этого он касания НЕ перехватывает */
  #tutorBar.mini #tutorDetail,
  #tutorBar.mini #tutorAside,
  #tutorBar.mini #tutorDots,
  #tutorBar.mini #tutorDone,
  #tutorBar.mini #tutorSkip{ display:none; }                         /* перебивает инлайн-display из paint: paint ставит '' (снимает инлайн) → правило класса действует */
  #tutorText{font-size:17px; line-height:1.45;}   /* было var(--fs-ctl)=14px — подсказку читают в игре, подняли до 17 */
  /* Объяснение шага: меньше и тише инструкции, ТЕСНО под ней (margin 4px) — читается как продолжение одного блока. Пусто → скрыто. */
  #tutorDetail{font-size:14px; line-height:1.4; color:var(--dim); margin-top:4px;}
  /* Камера-нота: тот же тихий размер, но ОТДЕЛЕНА большим зазором сверху — отдельная строка, не часть блока. Пусто → скрыта. */
  #tutorAside{font-size:14px; line-height:1.4; color:var(--dim); margin-top:11px;}
  #tutorBottom{display:flex; align-items:center; gap:10px; margin-top:11px;}
  #tutorDots{flex:1; min-width:0; letter-spacing:3px; font-size:12px; color:var(--dim);}
  /* Тик подтверждения выполненного шага — зелёный, рядом с Next. Пусто/не выполнено → скрыт (JS ставит display). */
  #tutorDone{flex:0 0 auto; color:#57d9a3; font-weight:700; font-size:16px;}
  /* Next — главная (акцент-заливка, тёмный текст, как «Играть»); Skip — тихая ссылка. */
  #tutorNext{flex:0 0 auto; background:var(--accent); color:#3a2600; border:none; font-weight:700;
    border-radius:var(--r-sm); padding:8px 14px; font-size:var(--fs-ctl);}
  /* Шаг выполнен → мягкое акцент-свечение Next: «сделано, жми Дальше». АВТО-перехода нет — только подсказка глазу. */
  #tutorNext.ready{animation:tutorReady 1.15s ease-in-out infinite;}
  @keyframes tutorReady{ 0%,100%{ box-shadow:0 0 0 0 rgba(255,158,44,.6); } 50%{ box-shadow:0 0 0 7px rgba(255,158,44,0); } }
  #tutorSkip{flex:0 0 auto; background:transparent; color:var(--dim); border:none;
    font-size:var(--fs-ctl); text-decoration:underline; padding:8px 6px;}
  /* Финал тура: мягкий пульс акцентом на кнопке лада — указываем, НИЧЕГО не открывая. */
  #scaleBtn.tutorPoint{ animation:tutorPulse 1.1s ease-in-out infinite; }
  @keyframes tutorPulse{ 0%,100%{ box-shadow:0 0 0 0 rgba(255,158,44,.5); } 50%{ box-shadow:0 0 0 6px rgba(255,158,44,0); } }

  /* ---- СПИСОК УРОКОВ (меню обучения) ---- Модальный оверлей: открыт со стартовой карточки И из урока
     (возврат к списку). z 33: выше старта (30) и панелей — это модал. Светлая карточка = меню. Строки
     рисует src/tutor.js. Ряд без шагов — «Скоро» (disabled); выполненный — тихая галочка (не гейт). */
  #lessonOv{z-index:33; background:rgba(7,7,13,.86);}
  #lessonOv.on{display:flex; align-items:center; justify-content:center;}
  .lessonCard{width:100%; max-width:420px; margin:auto; background:#ffffff; color:#1e2233;
    border:1px solid rgba(20,24,50,.12); border-radius:var(--r-lg); padding:20px;
    box-shadow:0 16px 44px rgba(40,50,90,.28);}
  .lessonHead{display:flex; justify-content:space-between; align-items:center; margin-bottom:12px;}
  .lessonHead b{font-size:var(--fs-head); color:#1e2233;}
  #lessonClose{background:#eef1f8; color:#2a2f45; border:1px solid rgba(20,24,50,.16);
    border-radius:var(--r-sm); padding:7px 11px; font-size:var(--fs-label); font-weight:600;}
  .lessonRow{display:block; width:100%; text-align:left; background:#eef1f8; color:#2a2f45;
    border:1px solid rgba(20,24,50,.14); border-radius:var(--r-sm); padding:11px 13px; margin:9px 0; font-weight:600;}
  .lessonRow:disabled{opacity:.55;}
  .lr-top{display:flex; justify-content:space-between; align-items:baseline; gap:8px;}
  .lr-title{font-size:var(--fs-ctl); color:#1e2233;}
  .lr-badge{flex:0 0 auto; font-size:var(--fs-hint); font-weight:700; color:var(--accent-ink);}   /* ✓ выполнено / «Скоро» */
  .lr-desc{font-size:var(--fs-label); color:#5a6079; font-weight:400; margin-top:4px; line-height:1.4;}
  #lessonFree{width:100%; margin-top:6px; background:var(--accent); color:#3a2600; border:none;
    font-weight:700; border-radius:var(--r-sm); padding:12px; font-size:var(--fs-ctl);}

  /* ---- ПАНЕЛИ (звукоряд + лупер): СВЕТЛАЯ тема, как стартовая карточка ----
     Панели лежат ПОВЕРХ камеры (обычно ярко освещённая комната), поэтому фон ОПАКОВЫЙ белый —
     видео не просвечивает и не размывает текст; blur убран (под опаковым фоном он бесполезен).
     Радиусы (--r-lg панель, --r-sm контролы) и тёмный текст (#1e2233) — из стартовой карточки. Всё
     СТРОГО под #panelScale/#panelLoop и панельные классы (.prow/.psep/…, они есть только тут); базовые
     button/#bar/оверлеи не трогаем. Акцент .act — оранжевая заливка var(--accent) с тёмным текстом. */
  /* ---- МЕНЮ ЗВУКОРЯДА: оверлей (открыл → выбрал → закрыл) ---- */
  #panelScale{position:fixed; top:52px; left:8px; right:8px; max-width:560px; margin:0 auto; z-index:15;
    background:#ffffff; color:#1e2233; border:1px solid rgba(20,24,50,.14); border-radius:var(--r-lg);
    padding:16px; display:none; max-height:calc(100vh - 72px); overflow-y:auto;
    box-shadow:0 16px 44px rgba(40,50,90,.22);}
  #panelScale.on{display:block;}

  /* ---- ПАНЕЛЬ ЛУПЕРА ----
     РАНЬШЕ была пришвартована СНИЗУ (max-height:46vh), чтобы наглядная холстовая сетка тактов
     сверху-по-центру (draw.js drawLooper, y≈64) оставалась видна при открытой панели. Теперь этот
     компромисс СОЗНАТЕЛЬНО развёрнут ради удобства: панель занимает то же место, что и «Звукоряд»
     (сверху, во всю доступную высоту) — так короткая панель без прокрутки читается лучше, а сетку
     тактов видно после закрытия (панели взаимоисключаемы). Геометрия 1-в-1 с #panelScale. */
  #panelLoop{position:fixed; top:52px; left:8px; right:8px; max-width:560px; margin:0 auto; z-index:14;
    background:#ffffff; color:#1e2233; border:1px solid rgba(20,24,50,.14); border-radius:var(--r-lg);
    padding:16px; display:none; max-height:calc(100vh - 72px); overflow-y:auto;
    box-shadow:0 16px 44px rgba(40,50,90,.22);}
  #panelLoop.on{display:block;}
  .prow{display:flex; align-items:center; gap:10px; margin:10px 0;}
  .prow label{flex:0 0 128px; font-size:var(--fs-label); color:#5a6079;}
  .prow select,.prow input[type=range],.prow .seg{flex:1; min-width:0;}
  select{background:#14142a; color:var(--ink); border:1px solid rgba(255,255,255,.22);
    border-radius:var(--r-sm); padding:8px; font-size:var(--fs-ctl); width:100%; font-family:var(--font);}
  /* Списки светлые (лад — длинный список, должен читаться); опаковый белый фон и тёмный текст. */
  #panelScale select,#panelLoop select{background:#f4f6fc; color:#1e2233;
    border:1px solid rgba(20,24,50,.20); border-radius:var(--r-sm);}
  input[type=range]{accent-color:var(--accent);}
  .val{flex:0 0 44px; font-size:var(--fs-label); color:#1e2233; text-align:right;}
  .seg{display:flex; gap:6px;}
  .seg button{flex:1;}
  /* Кнопки внутри панелей — светлая второстепенная тема (как #learnBtn), КРОМЕ активных (.act):
     у активных оранжевый акцент var(--accent) — читается как «выбрано» и на светлом. */
  #panelScale button:not(.act),#panelLoop button:not(.act){background:#eef1f8; color:#2a2f45;
    border:1px solid rgba(20,24,50,.16); border-radius:var(--r-sm); font-weight:600;}
  /* Выбранный сегмент — оранжевая заливка var(--accent)=#ff9e2c, ТЁМНЫЙ текст #1a1206 (исходная пара;
     белый на #ff9e2c был бы ≈2.1:1 — нечитаемо, поэтому текст тёмный). */
  .seg button.act{background:var(--accent); color:#1a1206; border-color:var(--accent); font-weight:600;}
  .phead{display:flex; justify-content:space-between; align-items:center; margin-bottom:4px;}
  .phead b{font-size:var(--fs-head); color:#1e2233;}
  .psep{border-top:1px solid rgba(20,24,50,.12); margin:14px 0 4px; padding-top:6px;
    font-size:var(--fs-hint); color:#6a7089; text-transform:uppercase; letter-spacing:.06em;}
  .phint{font-size:var(--fs-hint); color:#6a7089; line-height:1.4; margin:6px 2px 2px;}
  /* Недоступный ряд панели: гасим подпись, но НЕ прячем — пропавший контрол человек объяснить не
     может. Сейчас ни один ряд «Звукоряда» так не гаснет («Раскладка нот» доступна всем ладам —
     переменное число нот в прямоугольнике раскладывает любой), правило оставлено как общее. */
  .prow.off label{opacity:.55;}
  #panelScale select:disabled,#panelLoop select:disabled{opacity:.5;}
  /* Функции рук: маленький ярлык роли (🎸 Соло / 🎚 Бас) над парой строк Левая/Правая — группирует
     назначения по роли, но строки помечены РУКОЙ (видно, что выбор на руку, не на половину). */
  .handFnRole{font-size:var(--fs-label); color:#6a7089; font-weight:600; margin:10px 2px 2px; letter-spacing:.02em;}
  /* Эталон A4: пресет-список тянется, поле числа узкое справа, «Гц» — подпись. Светлая тема панели. */
  #aRefRow .seg{align-items:center;}
  #aRefRow #aRefSel{flex:1; min-width:0;}
  #aRefRow #aRefInput{flex:0 0 62px; background:#f4f6fc; color:#1e2233; text-align:right;
    border:1px solid rgba(20,24,50,.20); border-radius:var(--r-sm); padding:8px; font-size:var(--fs-ctl);}
  #aRefRow .unit{flex:0 0 auto; font-size:var(--fs-label); color:#5a6079;}
  #loopBarsV{flex:1; text-align:center; align-self:center;}

  /* ---- оверлеи: старт и учебник ---- */
  .ov{position:fixed; inset:0; z-index:25; background:rgba(7,7,13,.94);
    display:none; overflow-y:auto; padding:22px 18px 40px;}
  .ov.on{display:block;}
  .ov .inner{max-width:640px; margin:0 auto; font-size:14px; line-height:1.55;}
  .ov h1{font-size:26px; margin:6px 0 12px;} .ov h1 span{color:var(--note);}
  .ov h2{color:var(--note); font-size:17px; margin:20px 0 6px;}
  .ov b{color:var(--tonic);}
  .ov code{background:#14142a; border-radius:6px; padding:1px 6px; font-size:13px;}
  .ov .closeRow{position:sticky; top:0; text-align:right; z-index:2;}

  /* #helpOv держим выше стартового слоя (z30) и демо (z35) — учебник всплывает над всем. */
  #helpOv{z-index:40;}

  /* СТАРТ — СВЕТЛЫЙ приветственный слой (после «▶ Играть» экран занимает камера освещённой комнаты;
     светлый старт с ней созвучен). Светлый фон-градиент + белая карточка с ТЁМНЫМ текстом. ВСЕ стили
     строго под #start/.startCard — тёмная тема приложения (бар/панели/оверлеи) не затрагивается. */
  #start{z-index:30; display:none;
    background:linear-gradient(160deg,#eef2fb 0%,#e3e9f5 55%,#dbe6f1 100%);
    overflow-y:auto; padding:20px;}
  #start.on{display:flex; align-items:center; justify-content:center;}   /* id+.on перебивает .ov.on (display:block) */
  .startCard{width:100%; max-width:340px; margin:auto; text-align:center; color:#1e2233;   /* тёмный текст наследуется всей карточкой; margin:auto центрирует и даёт прокрутку */
    background:#ffffff; border:1px solid rgba(20,24,50,.12);
    border-radius:var(--r-lg); padding:26px 24px 20px; box-shadow:0 16px 44px rgba(40,50,90,.18);}
  /* «Handsong» — двухтоновый заголовок: «Hand» тёмный (#1e2233), «song» в тёплом акценте (--accent-ink,
     жжёный янтарь ≈5:1 на белом — читаемо; бледный #ff9e2c как крупный текст был бы ≈2.1:1). Оживляет
     имя, как раньше акцентная «Synth» в «Air Synth 3». Одно слово окрашено наполовину — не радуга. */
  .startCard h1{font-size:28px; margin:2px 0 6px; color:#1e2233;}
  .startCard h1 span{color:var(--accent-ink);}
  .startTag{font-size:var(--fs-label); color:#5a6079; margin:0 0 20px;}
  .startBtns{display:flex; flex-direction:column; gap:11px; align-items:stretch;}
  /* Кнопки старта — СВОЯ светлая тема (базовый button тёмный). «Играть» — ГЛАВНАЯ кнопка, оранжевая
     заливка var(--accent)=#ff9e2c (единый акцент приложения) с ТЁМНЫМ текстом #3a2600 (исходная пара,
     высокий контраст на оранжевом), доминирует над второстепенной; «Обучение» — светлая второстепенная. */
  #start button{border-radius:var(--r-sm); line-height:1.1;}
  #startBtn{font-size:18px; padding:15px 32px; background:var(--accent);
    color:#3a2600; border:none; font-weight:700;}
  #learnBtn{font-size:15px; padding:12px 20px; background:#eef1f8;
    color:#2a2f45; border:1px solid rgba(20,24,50,.16); font-weight:600;}
  #loadmsg{font-size:var(--fs-hint); color:#5a6079; min-height:1.2em; margin:12px 0 0;}
  #learnMsg{font-size:var(--fs-hint); color:#b26a00; min-height:1em; margin:6px 0 0;}   /* «скоро»-заметка — тёмно-янтарная, читается на белом */
  /* ⬇ Установка (PWA) — ТИХАЯ кнопка ПОД двумя главными: своя тонкая рамка (не заливка var(--note)/светлая
     как у главных), поэтому не спорит с «Играть»/«Обучение». Отдельный ребёнок карточки (не в .startBtns —
     там stretch-колонка), центрируется text-align. #installHint — короткая подпись/iOS-инструкция под ней.
     id-селектор перебивает #start button. Видимостью управляет ui.js (installProbe). */
  #installBtn{display:flex; width:fit-content; align-items:center; gap:6px; margin:14px auto 0;
    font-size:var(--fs-label); padding:9px 18px; background:transparent; color:var(--accent-ink);
    border:1px solid rgba(180,83,9,.5); border-radius:var(--r-sm); font-weight:600;}
  #installHint{font-size:var(--fs-hint); color:#6a7089; margin:7px 0 0; line-height:1.45;}
  /* ⛶ полноэкранный — ЗАМЕТНАЯ вторичная кнопка (полезна почти всем каждый сеанс): по весу близка к двум
     главным (15px, крупный padding), но остаётся вторичной — контурная, не залита как «Играть»/«Обучение».
     Не в .startBtns (там stretch-колонка) — отдельный ребёнок карточки, центрируется text-align. .act =
     уже во весь экран (синий акцент ссылок карточки). id-селектор — перебить #start button. */
  #fsBtnStart{display:flex; width:fit-content; align-items:center; gap:7px; margin:16px auto 0;
    font-size:15px; padding:11px 24px; background:transparent; color:#3a4059;
    border:1px solid rgba(20,24,50,.24); border-radius:var(--r-sm); font-weight:600;}
  #fsBtnStart.act{color:var(--accent-ink); border-color:rgba(180,83,9,.5);}
  /* Подвал — читаемо на телефоне (13px), но тише и мельче двух главных кнопок (18/15px), чтобы не спорить
     с ними. Ссылки узнаются цветом+весом (не только подчёркиванием). */
  .startFoot{margin-top:18px; padding-top:13px; border-top:1px solid rgba(20,24,50,.10);
    font-size:var(--fs-label); color:#5a6079; line-height:1.55;}
  /* Переключатель языка — тихая строка подвала (i18n). Светлый select (базовый select тёмный —
     перебиваем id-селектором) шириной под текст, не во всю строку; глобус — нейтральная метка без слов. */
  .startLang{display:flex; align-items:center; justify-content:center; gap:7px; margin:0 0 12px;}
  #langSel{width:auto; flex:0 0 auto; background:#f4f6fc; color:#2a2f45;
    border:1px solid rgba(20,24,50,.16); border-radius:var(--r-sm);
    padding:6px 10px; font-size:var(--fs-label); font-weight:600;}
  .startFoot p{margin:0 0 8px;}
  .startFoot a{color:var(--accent-ink); font-weight:600; text-decoration:none;
    border-bottom:1px solid rgba(180,83,9,.4); white-space:nowrap;}
  /* Строка поддержки — чуть тише подвала. «Donate» заметнее «Feedback» (жирнее, ярче подчёркивание). */
  .startSupport{margin:10px 0 0; color:#6a7089;}
  #donateLink{font-weight:700; border-bottom-color:rgba(180,83,9,.6);}

  /* ДЕМО «путешествие по строям»: оверлей поверх стартового (z 35 > start 30). Фон-тинт
     ставит demo.js поцветно на каждую сцену; здесь — только раскладка подписи. */
  #demoOv{z-index:35; text-align:center;}
  #demoOv .demoInner{max-width:560px; margin:0 auto; padding-top:22vh;
    display:flex; flex-direction:column; align-items:center; gap:12px;}
  #demoScene{font-size:13px; color:var(--dim); letter-spacing:.18em;}
  #demoName{font-size:30px; font-weight:800; color:var(--ink); line-height:1.2;}
  #demoCulture{font-size:18px; color:var(--note);}
  #demoHint{font-size:13px; color:var(--dim); max-width:420px; margin:6px auto 0;}
  #demoSkip{margin-top:22px; font-size:16px; padding:12px 26px;}

  