hj

Дизайн-система Health Journal v0.1: правила, токены и компоненты, снятые с мока Pulse App. Тема одна — тёмная. Токены для клиентов — design/tokens.json в репозитории, имена совпадают.

Правила

Health Journal — приложение-проекция Hub: телефон показывает состояние Hub и передаёт действия человека. Язык интерфейса — русский. Вид взят из мока Pulse App v0.1 (палитра Tokyo Night, JetBrains Mono) и не придумывается заново: новое значение сначала появляется в tokens.json, потом в экранах.

Токены в репозитории — design/tokens.json (те же имена, формат W3C). Инвентарь состояний мока — раздел «Инвентарь мока».

Тема

Цвет

Контраст (честно). text-primary, text-secondary, accent и смысловые цвета проходят 4,5:1 на всех фонах. Не проходят, значения мока сохранены:

параконтрастпредложение
text-muted на bg-base4,10:1только подписи ≤ 3 слов; длинный текст — text-secondary
text-faint на bg-base2,76:1тихую ссылку и сделанный шаг перевести на text-muted
line-default на bg-base1,74:1рамка не должна быть единственным признаком контрола
text-on-fill на set-warmup2,91:1светлее set-warmup или текст text-primary

Типографика

Одно семейство — JetBrains Mono (mono), моноширинное: цифры не прыгают в таймерах и весах. Мелкий и плотный текст: базовый body 11px, подписи label 10px, сноски caption 9,5px, бейджи micro 9px. Значения — value-sm / value-md / value-lg, вес 800. Кнопки — button 13px 800. Заглавных букв для акцента нет: подписи строчными («сон — polar loop», «итог»), без КАПСА и разрядки.

Отступы, радиусы, размеры

Что выглядит нажимаемым

Нажимаемое несёт хотя бы один из признаков:

  1. заливка accent / good / critical (кнопки);
  2. текст accent (ссылки, «+ подход», вторичные кнопки);
  3. стрелка «›» в конце (карточки-переходы, «почему так ›», «настройки ›»);
  4. форма контрола: чип с рамкой, степпер на bg-control, переключатель.

Ненажимаемое не носит ни одного из них. Значения, подписи и бейджи без «›» — только чтение. Hover-подсветка рамки есть только в веб-моке; на телефоне на неё не опираться.

Недоступное

Текст

Раскладка телефона

Иконки

Иконок-картинок нет. Знаки — символы шрифта: ✓ › ▴ ▾ × + − ■ ▶ ♥ ⚖ ● ○ ↺ ★ ☆. Логотипа-файла нет: знак «hj» набран 13px 800, «h» — accent, «j» — accent-ai.

Токены

Цвет

Контраст — к bg-base; полупрозрачные считаются поверх него; у фонов не считается. Цвет столбца: ≥ 4,5 — норма для текста, 3–4,5 ▴ — только крупный текст, рамки и знаки, < 3 × — не для текста и не для рамок контролов.

токензначениена bg-baseгде
bg-base#1a1b26поверхностьФон экрана и карточек. Единственная тема — тёмная.
bg-sunken#16161eповерхностьУтопленные поверхности: подложка таб-бара, раскрытый календарь.
bg-raised#24283bповерхностьЗаливка выбранного и текущего: текущий шаг, текущий подход, выбранный чип.
bg-control#292e42поверхностьКнопки-степперы − / +, выключенный переключатель, дорожка прогресса.
line-default#3b42611.74:1Рамка карточек и вторичных контролов. 1,74:1 на bg-base — ниже 3:1 для рамок контролов; значение мока сохранено, см. README.
line-subtle#292e421.27:1Разделители строк внутри карточки, рамка таб-бара.
text-primary#c0caf510.59:1Основной текст и значения на bg-base, bg-raised, bg-control (≥ 8,3:1).
text-secondary#a9b1d68.10:1Пояснения и подписи на bg-base, bg-raised (≥ 6,9:1).
text-muted#737aa24.10:1Заголовки карточек, неактивные чипы. 4,1:1 на bg-base — ниже 4,5:1 для 10px; только короткие подписи.
text-faint#565f892.76:1Сноски и тихая ссылка «почему так ›». 2,76:1 на bg-base — не проходит 4,5:1; значение мока, см. README.
text-on-fill#16161eповерхностьТекст на заливках accent, good, critical, info и цветах подходов.
accent#7aa2f76.79:1Главный цвет действия: основная кнопка, рамка текущего, ссылки «… ›», включённый переключатель. 6,8:1 на bg-base.
accent-ai#bb9af77.39:1Голос ассистента и метки ассистента; RMSSD. Не для кнопок.
info#7dcfff9.96:1Весы и сон: карточка взвешивания, длительность сна.
good#9ece6a9.35:1Сделано и принято: ✓, кнопка «принять план», связь с Loop.
warn#e0af688.55:1Внимание без тревоги: «Loop был перезапущен», пометка качества данных.
attention#ff9e648.40:1Значение вне базы (ниже базы, у нижней границы), окно отдыха открыто.
critical#f7768e6.46:1Нет связи с Hub, завершить тренировку, отдых сверх максимума.
critical-tintrgba(247,118,142,.08)поверхностьФон баннера «нет связи с Hub».
critical-line#6b3a4a1.90:1Рамка разрушительной малой кнопки («забыть» весы).
pulse = {critical}#f7768e6.46:1Пульс: ♥ и кривая пульса.
quality-unverified = {warn}#e0af688.55:1Текст пометки «пульс не проверен».
quality-unverified-line#6b5a3a2.56:1Рамка пометки «пульс не проверен».
set-warmup#565f892.76:1Подход-разминка в строке подхода. text-on-fill на нём — 2,91:1, ниже нормы; значение мока.
set-ramp#7aa2f76.79:1Подход «ёлочка» (разгонный).
set-working#ff9e648.40:1Рабочий подход.
set-drop#bb9af77.39:1Дроп-подход.
chart-baseline#3d59a12.56:1Полоса личной базы на графиках; лёгкий сон.
chart-baseline-tintrgba(61,89,161,.18)поверхностьЗаливка полосы базы за столбиками.
sleep-light = {chart-baseline}#3d59a12.56:1Фаза сна: лёгкий.
sleep-rem = {info}#7dcfff9.96:1Фаза сна: REM.
sleep-deep = {accent-ai}#bb9af77.39:1Фаза сна: глубокий.
sleep-awake = {critical}#f7768e6.46:1Фаза сна: бодрствование.

Отступы

space-22pxЗазор между строками подходов, внутри стопки подписей.
space-44pxЗазор между вкладками и шаг-чипами, внутренний отступ таб-бара.
space-66pxЗазор между кнопками в ряду, внутри карточки.
space-88pxОтступ экрана и зазор между карточками.
space-1010pxВертикальный внутренний отступ карточки, зазор строки.
space-1212pxГоризонтальный внутренний отступ карточки и баннера.
space-1616pxЛевый отступ шапки.

Радиусы

radius-xs2pxСтолбики графиков, дорожки.
radius-sm4pxБейджи и чип вес × повторы.
radius-md6pxКонтролы: шаг-чипы, малые кнопки, степперы, строка подхода.
radius-tab7pxВкладка таб-бара.
radius-card8pxКарточки и баннеры.
radius-button9pxОсновная и вторичная кнопки.
radius-bar10pxПодложка таб-бара.
radius-toggle11pxДорожка переключателя (половина высоты 22).

Размеры

size-target44pxМинимальная зона нажатия.
size-row48pxСтрока настройки с переключателем, строка плана.
size-button56pxОсновная кнопка.
size-button-secondary48pxВторичная кнопка.
size-action54pxКнопка действия упражнения.
size-tab52pxВкладка таб-бара.
size-step-chip34pxШаг-чип тренировки.
size-control32pxМалая кнопка, степпер, чип «в запасе».
size-control-lg36pxСтеппер плана, чип ночи, кнопки баннера.

Прозрачность

opacity-unavailable.38Недоступно: шаг, который нельзя открыть; месяц без данных. Вместе с пунктирной рамкой и без курсора-руки.
opacity-pending.45Будущий подход в списке подходов.
opacity-inactive.55Пропущенное упражнение, прошлые столбики графика.
opacity-done.7Сделанное упражнение в плане.

Шрифт

JetBrains Mono, одно семейство: "JetBrains Mono", ui-monospace, monospace

micro9px / 1.3 / 400Пометки и бейджи: «пульс не проверен».
пульс не проверен
caption9.5px / 1.5 / 400Сноски, легенды, шаг-чипы, подписи осей.
ночь пишет сам Loop
label10px / 1.4 / 400Заголовки карточек, вторичный текст, тихая ссылка.
сон — polar loop
body11px / 1.5 / 400Базовый текст экрана.
Hub проверяет план ограничениями
body-strong11px / 1.5 / 700Заголовок баннера, название в строке.
нет связи с Hub
action12px / 1.2 / 800Главная кнопка упражнения (подход сделан / начать подход).
✓ подход сделан
button13px / 1.2 / 800Основная и вторичная кнопки 56/48.
начать разминку
nav-number16px / 1 / 800Цифра вкладки в таб-баре.
2
value-sm20px / 1 / 800Значения в малых карточках.
6:00
value-md28px / 1 / 800Главное значение карточки: вес, пульс.
80,0
value-lg34px / 1 / 800Главное значение экрана: длительность сна.
7 ч 30 мин

Компоненты

Banner · ButtonPrimary · ButtonSecondary · Card · QualityBadge · QuietLink · SetRow · StepChip · TabBar · Toggle · WeightRepsChip · WhyLine

Banner

Баннер состояния системы над содержимым вкладки: рамка 1px цвета состояния, radius-card, отступ space-8 × space-12.

  • «нет связи с Hub» — рамка critical, фон critical-tint, заголовок critical 700, под ним одна строка text-secondary (что с буфером). Появляется через 5 с без подтверждений Hub; на экране упражнения дублируется строкой «нет связи с Hub · без решений».
  • «Loop был перезапущен из-за зависания» — рамка и заголовок warn; текст: когда, почему, что данные не удалены; две кнопки size-control-lg: «настройки ›» (accent) и «понятно» (warn).
  • Баннер говорит факт и последствие, без извинений и восклицаний. Не больше одного баннера каждого вида.

ButtonPrimary

Одна главная кнопка экрана: залитая, во всю ширину, высота size-button (56), радиус radius-button, стиль button, текст text-on-fill.

  • Заливка по смыслу: accent — следующий шаг; good — принять, закончить успешно; critical — завершить тренировку.
  • На экране упражнения кнопка действия — size-action (54) и стиль action; пока идёт отдых она контурная (рамка accent, текст text-primary) и заливается accent, когда отдых дошёл до минимума.
  • Одна главная кнопка на экран, внизу, в зоне большого пальца. Текст — глагол: «начать разминку», «✓ подход сделан».
  • Недоступной главной кнопки нет: если действие сейчас невозможно, кнопку не показывают, а объясняют почему (баннер или строка text-muted).

ButtonSecondary

Контурная кнопка второго действия: высота size-button-secondary (48), рамка и текст accent, без заливки.

  • Малая кнопка в строке (size-control, radius-md, стиль label): рамка line-default, текст text-secondary; ведущая наружу — текст accent и «›»; разрушительная — рамка critical-line, текст critical; главная в строке — заливка accent.
  • Степпер − / +: квадрат size-control (32) или size-control-lg (36) на bg-control, без рамки. Значение между ними — жирное, единица — micro в text-muted.
  • Рамка line-default слабая (1,74:1). Вторичную кнопку отличает от карточки текст accent или «›», а не рамка.

Card

Карточка — рамка 1px line-default, radius-card, отступ space-10 × space-12, зазор space-6–space-8, без тени и заливки.

  • Шапка: подпись слева и мета справа, label в text-muted. Подпись — что это и откуда («сон — polar loop», «эпизоды ночи · Hub»).
  • Главное значение — value-md / value-lg, цвет по теме данных (info — сон и весы, accent-ai — RMSSD, pulse — пульс). Единица рядом — 11px text-secondary.
  • Карточка-фокус экрана (подходы, ночь) — рамка 2px accent.
  • Карточка-переход целиком нажимаемая: «›» в шапке справа. Hover-подсветка рамки accent есть только в вебе; на телефоне признак — «›».

QualityBadge

Пометка качества данных: micro, текст quality-unverified, рамка quality-unverified-line, radius-sm, отступ 1 × 5. Не нажимается.

  • «пульс не проверен» стоит у каждого пульсового значения, пока место ношения Loop не проверено (решение 18): пульс разминки, итог тренировки, причина плана. Справа в строке значения.
  • Уровень ночи — тот же бейдж 9,5px с рамкой цвета уровня: «ночь: базовая» / «ночь: расширенная».
  • Бейдж — пометка, не предупреждение: не красный, без «!».

SetRow

Строка подхода внутри карточки упражнения (рамка 2px accent). Сетка: метка 16 · тип 64 · чип вес × повторы · мета 50 · «×» 28; высота 40, radius-md.

состояниеметкафон / контурпрочее
ожидаетномер, text-faintнетвся строка opacity-pending; «×» убирает
текущий«›», accentbg-raised, контур 1px accent«×» убирает
сделан«✓», goodнетмета: «запас N» или время отдыха; «×» нет
убранстроки нетчип «убрано: … ↺» с пунктиром и текстом accent возвращает подход
  • «+ подход» — строка accent под списком, над ней пунктир line-subtle; выбор типа — четыре чипа с рамкой цвета типа.
  • Убрать можно только несделанный подход. Любая правка числа подходов — новая ревизия плана, автор — человек.
  • Чип «убрано» пунктирный, но не блёклый и с текстом accent: это действие. Пунктир сам по себе не значит «недоступно».

StepChip

Шаги тренировки: самочувствие → разминка → план → подходы → итог. Пять чипов в ряд, зазор 3px, высота size-step-chip (34), radius-md, стиль caption.

состояниерамкафонтекстпрочее
текущийaccentbg-raisedtext-primary
сделанline-defaultнетtext-faintпрефикс «✓ », открывается
доступенline-defaultнетtext-secondaryоткрывается
недоступенline-default, пунктирнетtext-mutedopacity-unavailable, тап ничего не делает
  • Недоступный шаг отличается тремя признаками сразу: пунктир, прозрачность, нет реакции. Одного цвета мало: так основатель и увидел, что шаги «выглядели одинаково».
  • Сделанный шаг остаётся нажимаемым; блёклый текст text-faint и «✓» говорят «пройдено», а не «закрыто».
  • Когда шаг станет доступен, решает Hub (подходы — только после принятого плана).

TabBar

Пять вкладок под шапкой: «сейчас», «трен», «сон», «тело», «ai». Подложка bg-sunken, рамка line-subtle, radius-bar, отступ и зазор space-4.

  • Вкладка: высота size-tab (52), radius-tab; цифра nav-number + подпись label.
  • Активная — заливка accent, цифра и подпись text-on-fill. Неактивная — цифра text-primary, подпись text-muted.
  • Таб-бар вверху, под шапкой (мок), а не внизу: внизу экрана — главная кнопка. На первом запуске (ввод адреса Hub) таб-бара нет.
  • Настройки — чип в шапке справа, не шестая вкладка.

Toggle

Переключатель в строке настройки: дорожка 38 × 22, radius-toggle; выкл — bg-control, вкл — accent; ручка 18 × 18 text-primary, сдвиг 2 → 18px.

  • Нажимается вся строка (size-row, 48), не только дорожка. Заголовок body, под ним одна строка label в text-muted: что изменится, без рекламы.
  • Строки в группе разделяет line-subtle сверху.
  • Необязательное помечается « · необязательно» в text-faint после заголовка.

WeightRepsChip

Вес × повторы в строке подхода: заливка цветом типа подхода, высота 24, radius-sm, текст text-on-fill 11px 800.

  • Цвет — тип подхода: set-warmup, set-ramp (ёлочка), set-working, set-drop. Под списком всегда легенда «■ разминка ■ ёлочка ■ рабочий ■ дроп».
  • Ширина — доля от самого тяжёлого подхода упражнения, не меньше 18%: видно лесенку весов.
  • Формат: «40 × 8», запятая в дробном весе («22,5 × 10»), без «кг» внутри чипа; без веса — «свой вес × 12».
  • Тап по чипу раскрывает правку под строкой (степперы веса и повторов). Правка сделанного меняет факт, правка будущего — план (новая ревизия).
  • text-on-fill на set-warmup — 2,91:1, ниже нормы: значение мока сохранено, кандидат на правку.

WhyLine

Свёрнутое объяснение ассистента: одна тихая строка «почему так ›» под планом. По умолчанию свёрнута.

  • Раскрытая — до трёх причин, по строке на причину: ключ text-faint шириной 72 + короткая причина text-secondary, обрезка многоточием. Пульсовая причина несёт «пульс не проверен».
  • Только то, чего не видно в самом плане. Без вступлений, без «я проанализировал», без советов.
  • Нет причин — нет строки.

Инвентарь мока

Различимые визуальные состояния в Pulse App v0.1 (design/mock/pulse-app.dc.html) на 2026-11-12 — сырьё для токенов и компонентов. Значения — как в моке.

Каркас

элементвид
экранbg-base, текст 11px text-primary, JetBrains Mono
шапка«hj» 13px 800 (accent + accent-ai); «● loop 69%» good 10px; статус Hub (нажимается, демо); чип настроек 28px, активный — заливка accent
таб-барподложка bg-sunken, рамка line-subtle, радиус 10; вкладка 52px, радиус 7; активная — заливка accent, текст text-on-fill; неактивная — цифра text-primary, подпись text-muted
область прокруткиотступ 8, зазор 8; липкая нижняя зона действий с тенью цвета фона

Кнопки и ссылки

видразмерыцветагде
главная56, радиус 9, 13px 800заливка accentначать разминку, повторить запрос, собрать план без разминки (с подстрокой)
главная, принять56заливка goodпринять план, к итогу
главная, завершить56заливка criticalзавершить тренировку
первый запуск64, радиус 9, 14pxзаливка accentсканировать QR
действие упражнения54, 12px 800заливка accent («✓ подход сделан»); контур accent до минимума отдыха и заливка после («▶ начать подход · …»); контур good («✓ закончить упражнение»); заливка good («✓ готово · к плану»)экран подходов
вторичная48, рамка accentтекст accentк плану, ещё раз, подключить
контурная главная56, рамка accentтекст accent■ закончить разминку
малая32, радиус 6, 10pxрамка line-default, текст text-secondaryизменить (адрес Hub), демо: вернуть
малая разрушительная32рамка critical-line, текст criticalзабыть (весы)
малая главная32заливка accent, 700найти (весы)
кнопки баннера36рамка line-default + текст accent; рамка и текст warnнастройки ›, понятно
пара «моё / не моё»44, радиус 8контур line-default / заливка infoвзвешивание
ссылка40текст accent, «›»каталог упражнений ›, подробнее
тихая ссылкаотступ 4, 10pxtext-faint, «›» / «▴»почему так, пересобрать с учётом разминки
тихая ссылка недоступнаяпрозрачность из логикисобрать план без разминки без связи
текстовая в шапкеcritical■ завершить
степпер32 или 36, радиус 6bg-controlвес, повторы

Чипы

видсостояния
шаг тренировкитекущий (accent, bg-raised), сделан (✓, text-faint), доступен (text-secondary), недоступен (пунктир, .38, без реакции)
выбор (самочувствие 1–5, место ношения, ночи, «в запасе»)вкл: рамка accent, bg-raised, text-primary; выкл: рамка line-default, text-muted
зона боливкл: рамка critical
тип нового подходарамка цвета типа
«убрано: …»пунктир, текст accent, возвращает
день календарябудущий — без курсора; стрелка месяца без данных — .38
звезда каталога★ warn / ☆ text-faint

Тренировка

элементсостояния
строка подходаожидает (.45, номер), текущий (bg-raised, контур accent, «›»), сделан («✓» good, «запас N» или время отдыха), в правке (как текущий + степперы)
чип вес × повторыset-warmup, set-ramp, set-working, set-drop; ширина — доля от максимального веса
карточка отдыхадо минимума — text-muted; в окне — attention; сверх максимума — critical и рамка critical; отметка минимума на дорожке
карточка упражнения в планеидёт (рамка accent, bg-raised), сделано (рамка good, .7), пропущено (.55, «✕», «↺»), ожидает
предложение ассистентаживое (принять / отклонить), принято («✓ принято · ревизия плана»), отклонено, устарело («подход уже начат»)
итогбез тоннажа: рабочие из назначенных, лучший к прошлому разу со стрелкой, запас, отмены

Состояния системы

элементвид
нет связи с Hubбаннер: рамка critical, фон critical-tint; в упражнении — строка «нет связи с Hub · без решений»; на плане — карточка с объяснением
Loop перезапущенбаннер: рамка и заголовок warn, две кнопки
весы просят подтвердитькарточка с рамкой 2px info, значение attention 28px, «моё / не моё»
«не моё» отмеченострока-карточка, нажатие закрывает
пульс не проверенбейдж micro, warn на рамке quality-unverified-line
уровень ночибейдж «ночь: базовая / расширенная» с рамкой цвета уровня
план готовитсяшаги с номером круга «1 из 3», ожидание до 30 с
ассистент не ответилтекст причины + главная «повторить запрос»

Данные

элементвид
значение карточки28px 800 в цвете темы данных; единица 11px text-secondary
значение ночи34px 800 info
полоса базыchart-baseline на bg-control, маркер — цвет статуса (good / attention)
столбики 7 ночейaccent, ниже базы — attention; прошлые .55
фазы снаsleep-light, sleep-rem, sleep-deep, sleep-awake
пульсpulse, ♥

Нашлось при инвентаризации