Хэллоуин-слой: как украсить сайт на неделю и ничего не сломать
На неделю сайт одевается в хэллоуинское: по экрану летают мыши, в углах горят тыквы, из-за форм выглядывает Баба-Яга. Вёрстка при этом не меняется — ни одной правки в шаблон, ни одной новой картинки в загрузках.

Главная: залп по клику и тыква у края экрана.
Задача
Праздник — повод вернуться на сайт тем, кто уже был, и повод показать его тем, кто только присматривается. Но у нас не витрина, а работающий сайт: заявки, курсы, оплата. Значит, условия жёсткие:
- украшение живёт неделю и выключается одной строкой, без релиза;
- вёрстка и стили не трогаются вообще;
- формы и оплата работают как раньше — ни одного перехваченного клика;
- всё это должно быть лёгким: без библиотек, шрифтов и внешних картинок.
Решение
Сделал отдельный слой поверх страницы. Это обычный div с position: fixed и pointer-events: none: он рисуется выше контента, но прозрачен для мыши. Формы, ссылки и кнопки получают клики как обычно — слой их просто не видит.
Весь арт — SVG прямо в скрипте. Восемнадцать персонажей: мышь, тыква, тыква-фонарь, мара, ворон, череп, мухоморы, сова, кот Баюн, паук, кучка угольков, метла, блуждающий огонёк, Баба-Яга, избушка на курьих ножках и Кощей. Плюс три прелоадера — смеющаяся тыква, мышь по кругу и Баба-Яга в ступе.

Модалка «Обратиться с вопросом»: слой выше окна, но клики по полям доходят до формы.
Формы и оплату проверил отдельно. Страница оплаты /pay/ — самостоятельная, без шаблона сайта, и слой туда не подключён вообще. Модалка формы — это iframe поверх страницы: украшение рисуется выше, но клик доходит до полей, я проверял через elementFromPoint — в точке поля возвращается само поле, а не слой.

Оплата остаётся чистой: на /pay/ слой не подключается.
Механика
Залп по клику. Клик в любом месте — 4–9 сущностей, которые разлетаются веером. Мышей примерно пятая часть, остальные не повторяются в одном залпе: за один клик может вылететь избушка, череп, кот и угольки.
Три способа исчезнуть. Кто-то тает по пути, кто-то уносится за край экрана, кто-то вспыхивает и растворяется рядом. Одинаковых кликов не получается.
Фон. Птицы и мыши пролетают волной, по диагонали и по дуге — не только слева направо. Пауки перебегают экран и срываются вверх. Кучка угольков садится в точку и через секунду разваливается на трёх-пятерых мохнатиков: у каждого свой размер, своё покачивание и своё моргание.
Выглядывания. Кто-то показывается из-за края экрана, кто-то — из-за реального блока страницы: за блоком элемент подрезается маской clip-path, поэтому он действительно прячется, а не лежит сверху.

Страница курса: пролёты и выглядывания из-за блоков.
Тыквы по краям. Каждые несколько секунд у левого или правого края появляется тыква с тёплым пульсирующим ореолом. Клик — всполох на весь экран, случайная фраза из двадцати четырёх («Чур меня, чур!», «Домовой проснулся!», «Т-с-с! Слышишь скрип?») и небольшой залп. Одновременно живёт до четырёх тыкв.

Приглашение к клику: «Жми!», рост и «ба-бах», если не нажать.
Приглашение к клику. Новичку на первой тыкве показывается пузырь «Жми!». Если не нажать, тыква подрастает, призыв нарастает — «Ну жми…», «ЖМИ!», «Да жми же!», — а потом она лопается сама: большой всполох и залп, тем сильнее, чем дольше её игнорировали. После первого клика подсказка больше не появляется.

Клик по тыкве: всполох и фраза.
Деликатность. На десктопе одновременно живёт не больше 52 элементов, на мобильных — 26, и сами персонажи там мельче. Если у человека включено prefers-reduced-motion, фоновые пролёты и покачивания отключаются. Включается и выключается всё флагом в коде, параметром ?halloween=off и календарным окном с 20 октября по 3 ноября.
Вес. 44 КБ скрипта и 12 КБ стилей, без зависимостей и без единого сетевого запроса: ни картинок, ни шрифтов, ни аналитики.

Блог: то же украшение на другой странице.
Результат
Украшение отработало неделю на боевом сайте и не потребовало ни одной правки вёрстки. Оплата и формы не изменились: страница оплаты вообще не знает про слой, модалка формы принимает клики как раньше.
Выключение — одна строка в шаблоне или параметр в адресе для себя. Никаких остатков: слой создаётся скриптом и им же убирается.
Отдельно собрал из этого набор: восемнадцать SVG-персонажей и три анимированных прелоадера. Их можно ставить на другие сайты, отдавать в видео и презентации — вектор, ноль зависимостей.
Метрик и конверсии я не считаю: это украшение, а не лендинг. Задача была — сделать неделю живой и ничего не сломать. Обе задачи закрыты.

Мобильный вид: те же персонажи, меньше и реже.