Живые паттерны поведения экрана: якоря и scroll, адаптив, PWA-установка, hash-роутинг. Канон — docs/10-ux-patterns.md.
Якорные чипы выше скроллятся к секциям с scroll-margin-top: calc(var(--lv-header-h) + 12px) — заголовки не прячутся под sticky-шапкой. Прокрутите страницу ниже 480px — появится каноническая кнопка «наверх».
Капсула 48px на gradient-brand, справа над нижней навигацией, safe-area учтён. Порог появления — 480px, показ через opacity + translateY (только transform/opacity).
Ссылка вида 06-ux-lab.html#s-pwa из письма или соцсети: если контент догружается после отрисовки, позиционирование повторяется на load — сниппет в docs/10 §1.2.
Два порога — 640 и 900 — плюс токены каркаса. Медиазапросы используют литералы (в @media нельзя var()), значения сеток — из --lv-container*.
Честный флоу beforeinstallprompt: своё приглашение — только когда браузер его отдал; в standalone всё установочное скрыто; на iOS — инструкция с i-share.
Состояние определяется на каждом входе и никогда не показывает лишнего.
Роуты — #/путь, якоря страницы — #блок; роутер различает их по префиксу. Табы — настоящие ссылки <a href="#/…">: работают назад/вперёд, средний клик и «открыть в новой вкладке».
Панель по умолчанию видна без JS (прогрессивное улучшение): роутер только синхронизирует location.hash с DOM. Неизвестный роут ведёт сюда же.
Глубокая ссылка …#/nagrad открывает этот экран сразу из адресной строки — сервер не участвует. В лаборатории скролл к верху страницы при смене роута отключён (для удобства исследования), на продуктовых экранах — канон §4.1: scrollTo top.
Назад/вперёд браузера листают роуты бесплатно: hashchange и есть история. history.pushState вручную не вызывается никогда.
Текущий роут: #