Один источник правды для портала, отчётов и презентаций. Меняешь значение здесь, меняется на всех страницах, где подключён assets/fsr.css. Переключатель темы справа вверху, все блоки ниже живут в обеих темах.
Две строки в <head>. Скрипт, без defer: тема должна примениться до первой отрисовки, иначе при загрузке мигнёт чужой фон.
<link rel="stylesheet" href="assets/fsr.css"> <script src="assets/fsr.js"></script> <!-- кнопка темы: разметку и иконки скрипт подставит сам --> <button class="fsr-theme"></button>
Имена семантические: --bg: грунт, а не «чёрный». В светлой теме он становится бумажным, и название не врёт. Значения ниже подставлены живьём, переключи тему и увидишь, как они меняются.
Красного на экране не больше ~10% площади: это акцент и интерактив, а не заливка. Для мелкого текста на бумаге используй --accent-text: в светлой теме он темнее (#B23B40) и проходит по контрасту, тогда как --accent: нет.
Три регистра, ни одним больше. Oswald, заголовки, IBM Plex Sans, текст, IBM Plex Mono, даты, метки и данные. Моно отсылает к уличной технической эстетике: трафарет, разметка парка, протокол.
<h2>Заголовок секции</h2> /* Oswald подхватится сам */ <p class="fsr-muted">Описание</p> <span class="fsr-meta">14–24.08.2026</span> /* моно + трекинг + капс */ <td class="fsr-num">5000</td> /* табличные цифры */
Шаг спейсинга растёт заметно, соседние значения не должны быть похожими, иначе разница читается как ошибка вёрстки.
Собраны из того, что уже встречается на страницах проекта, не придуманы заново.
<span class="fsr-eyebrow">01 · Раздел отчёта</span> <span class="fsr-chip fsr-chip--ok" data-dot>готово</span> <button class="fsr-btn fsr-btn--accent">Найти площадку</button>
<a class="fsr-tile" href="…"> <div class="fsr-tile__head"><h3>Заголовок</h3><span class="fsr-tile__arrow"></span></div> <p>Описание</p> <div class="fsr-tile__meta"><span class="fsr-chip">мета</span></div> </a>
Обычная выноска, для главной мысли раздела.
Зелёный вариант, для сделанного.
Жёлтый, для рисков и ограничений.
<div class="fsr-rows"> <a href="…"><span class="rn">01</span><span class="rt">Пункт</span><span class="rd">мета</span></a> </div> <div class="fsr-callout fsr-callout--warn">…</div>
Одна линия: от первого трюка до сборной.
Интрига без деталей, сбор waitlist.
Первые споты руками сцены.
<div class="fsr-stat"><b>5000</b><span>участников</span></div> <p class="fsr-quote">Одна <em>линия</em>, от первого трюка.</p> <div class="fsr-phase"><div class="fsr-phase__item">…</div></div>
Таблицу всегда заворачиваем в .fsr-tablewrap: широкая таблица скроллится внутри себя и не ломает страницу горизонтально. Цифры, моноширинные и табличные, чтобы разряды стояли в столбик.
| Аудитория | Что ищет | Тон | Охват |
|---|---|---|---|
| Райдеры | Площадки рядом, события | Дерзкий, на равных | 12 400 |
| Родители | Безопасность, школы | Спокойный, ясный | 8 150 |
| Тренеры | Квалификации, календарь | Деловой, точный | 960 |
Красного ≤10% площади. Статус не передаём одним цветом, дублируем точкой или подписью.
Строка 60–70 знаков. Глагол в начале. Цифры вместо эпитетов. Без канцелярита.
Любая анимация гасится при prefers-reduced-motion это уже зашито в систему.
Класс fsr-img + loading="lazy" и явные width/height. Шиммер снимается сам.