# Звуковые плееры загружаются по нажатию

Дата: 14.10.2026
Статус: принята автономно (режим «Все автономно»). Задача #408.

## Зачем

На самой тяжёлой странице статьи (`en/disease/aortic-stenosis/`) запас бюджета JS был 33 байта из 100 КБ. Следующая работа над моделью часов (режим ФЖ, #403) его превысила бы. Строки пресетов в бюджет не входят: в чанках JS их нет. Растёт сам код страницы.

## Что меняется

- Код, который синтезирует звук, нужен только после нажатия «Звук» в часах сердца или «Слушать» в плеере тонов. Теперь он загружается в этот момент, через `import()`:
  - `heart-clock/heart-sounds.ts` — звук часов сердца;
  - `heart-sounds/player.ts` — плеер тонов и шумов.
- `AudioContext` по-прежнему создаётся синхронно внутри нажатия: браузеры разрешают звук только из жеста. Звук начинается, когда код загрузится.
- Если звук выключили, пока код грузился, загруженный плеер не включается: часы проверяют номер нажатия, плеер тонов — запрошенный звук.
- `playerClock` и `playerHeartRate` переезжают в `heart-sounds/player-clock.ts`: схема плеера рисуется из них до первого нажатия.
- Бюджет JS (`scripts/js-budget.ts`) не считает эти два чанка, как уже не считает 3D-сцену и живое сердце главной: страница грузит их только по действию читателя. Регулярное выражение называется `onDemandEntry`.
- Такой чанк выпадает из подсчёта, только если его грузит `import()`. Если страница или статический импорт грузит его сразу, проверка падает: иначе настоящие байты пропали бы из бюджета.
- Если загрузка кода не удалась, кнопка возвращается в «выкл», а аудиоконтекст приостанавливается.
- Плеер тонов внутри нажатия запускает беззвучный сэмпл: старые iOS играют звук после паузы, только если в жесте уже что-то прозвучало.

## Итог

Самая тяжёлая страница статьи: 101 198 байт вместо 102 367, запас 1 202 байта.

## Тесты

- Юнит: `onDemandEntry` узнаёт новые чанки и не узнаёт `player-clock` и `HeartSounds`; `counted` пропускает такой чанк при `import()` и падает при загрузке сразу.
- e2e: звук часов включается и ставит звуки в очередь, как раньше; плеер тонов играет и останавливается. В часах и в плеере выключение во время загрузки не включает звук после неё; тест проверяет, что задержанный чанк действительно запрашивался.
