# Эталон типографики ThaiForTravel Mini App

Статус: внедрено в Mini App 2 августа 2026 года.  
Базовая ширина: 390 px.  
Основа: главная страница и каталог экскурсий.  
Шрифт: `Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif`.

## 1. Зачем нужен эталон

До фиксации шкалы в `prototype/styles.css` использовались 26 числовых размеров от 8 до 39 px. Из 252 числовых объявлений `font-size` 55 имели размер 8–10 px. Особенно мелкими оказались трансферы, план отдыха, варианты программ, статусы заявок и нижняя навигация.

Главная и каталог уже задают правильный характер интерфейса: заметный заголовок, читаемая карточка, спокойный основной текст и компактные метаданные. Остальные экраны должны использовать те же роли, а не отдельную уменьшенную шкалу.

## 2. Единая шкала

| Токен / роль | Размер | Строка | Вес | Где использовать |
|---|---:|---:|---:|---|
| `display` | 30 px | 32 px | 800 | Финальный success-заголовок, редкий крупный акцент |
| `page-title` | 28 px | 31 px | 760–800 | Главный заголовок экрана или услуги |
| `context-title` | 22 px | 26 px | 760 | Дата/день в планировщике, компактный главный контекст |
| `section-title` | 21 px | 26 px | 760 | «Популярные экскурсии», «Рекомендуем», крупный раздел |
| `card-title` | 17 px | 22 px | 700–760 | Название экскурсии, трансфера, заявки |
| `card-title-compact` | 15 px | 19 px | 700–760 | Компактная рекомендация и строка варианта программы |
| `control` | 16 px | 22 px | 500–760 | Поле ввода, select, крупный сегмент и основной CTA |
| `body` | 15 px | 22 px | 400–560 | Обычный текст и основное описание |
| `body-compact` | 14 px | 20 px | 400–560 | Короткое описание карточки, аккордеон, пояснение |
| `label` | 13 px | 18 px | 680–760 | Подпись поля, кнопка «Подробнее», фильтр, статус |
| `meta` | 12 px | 16 px | 500–700 | Категория, направление, дата, длительность, вторичная цена |
| `caption` | 11 px | 14 px | 600–720 | Редкая служебная подпись и нижняя навигация |
| `price` | 17 px | 22 px | 760 | Основная цена в каталоге и карточке услуги |
| `price-compact` | 14 px | 18 px | 720–760 | Цена в компактной рекомендации или варианте |

Размеры и строки продублированы CSS-переменными `--type-*` в `prototype/styles.css`. Для иконок эта шкала не применяется.

## 3. Иерархия по экранам

### Главная

| Элемент | Роль |
|---|---|
| «Таиланд без лишних забот» | `page-title` |
| Подзаголовок | `body-compact` |
| Поиск | `control` |
| Быстрые направления | `label` |
| «Составить план отдыха» | `card-title` |
| Пояснение к плану | `meta` |
| «Популярные экскурсии» | `section-title` |
| Название услуги | `card-title` |
| Описание карточки | `body-compact` |
| Цена | `price` |
| Категория и направление | `meta` |
| Нижняя навигация | `caption` |

### Каталог и избранное

| Элемент | Роль |
|---|---|
| «Каталог экскурсий» | `page-title` |
| Подзаголовок | `body-compact` |
| Паттайя / Пхукет | `label` |
| Количество результатов | `meta` |
| Кнопка категорий и пункты списка | `label` |
| Название услуги | `card-title` |
| Описание | `body-compact` |
| Взрослая и детская цена | `price` |
| Подписи цен | `meta` |
| «Подробнее» | `label` |

### Карточка экскурсии

| Элемент | Роль |
|---|---|
| Название экскурсии | `page-title` |
| Локация и категория | `meta` |
| Краткое описание | `body` |
| Название программы | `card-title-compact` |
| Основная цена | `price` |
| Дополнительная цена/примечание | `meta` |
| Факты: длительность, направление | `meta` + выделение весом |
| Заголовок аккордеона | `card-title` |
| Содержимое аккордеона | `body-compact` |
| Закреплённый CTA | `control` |

### Трансферы и карточка трансфера

| Элемент | Роль |
|---|---|
| Заголовок страницы/маршрута | `page-title` |
| Группа «Из аэропорта…» | `card-title` |
| Направление внутри группы | `card-title-compact` |
| Тип машины | `label` |
| Вместимость и служебные данные | `meta` |
| Цена маршрута | `price-compact` |
| Памятка | `body-compact` |

### Заявка на экскурсию или трансфер

| Элемент | Роль |
|---|---|
| Заголовок заявки | `page-title` |
| Пояснение | `body-compact` |
| Выбранная услуга | `card-title` |
| Подпись поля | `label` |
| Значение input/select/textarea | `control` |
| Подсказка и ошибка поля | `meta` |
| Согласие | `caption` |
| «Отправить заявку» | `control` |

Все текстовые поля используют не меньше 16 px. Это предотвращает автоматическое масштабирование WebView на iPhone при фокусе.

### План отдыха: настройка

| Элемент | Роль |
|---|---|
| «Соберите поездку по дням» | `page-title` |
| Надпись «Настройка поездки» | `meta` |
| Описание | `body-compact` |
| Заголовок группы | `label` |
| Счётчик взрослых/детей | `control` |
| Категории | `label` |
| Доверительная подсказка | `meta` |

### План отдыха: день

| Элемент | Роль |
|---|---|
| Заголовок верхней панели | `card-title` |
| «День 1 из 5» | `meta` |
| Дата | `context-title` |
| Направление и состав группы | `meta` |
| «План на день», «Рекомендуем» | `section-title` |
| Название рекомендации | `card-title-compact` |
| Цена/длительность | `meta` или `price-compact` |
| Комментарий | `control` |
| Настройка напоминания | `label` + `meta` |

### План отдыха: поиск по каталогу

| Элемент | Роль |
|---|---|
| Заголовок | `page-title` |
| Поиск | `control` |
| Категория | `label` |
| Название экскурсии | `card-title-compact` |
| Категория и направление | `meta` |
| Цена в свёрнутой строке | `price-compact` |
| Вариант программы | `card-title-compact` |
| Примечание варианта | `meta` |

### Итог плана и «Мои заявки»

| Элемент | Роль |
|---|---|
| Заголовок экрана | `page-title` |
| Дата дня | `label` |
| Название услуги/заявки | `card-title` |
| Вариант, состав, дата, номер | `meta` |
| Статус | `label` |
| Кнопка действия | `label` |

### Успешная отправка и состояния

| Элемент | Роль |
|---|---|
| «Заявка принята» | `display` |
| Пояснение | `body` |
| Заголовок loading/empty/error | `context-title` |
| Текст состояния | `body-compact` |
| Действие | `label` или `control` для главной кнопки |

## 4. Правила применения

1. Один смысловой уровень всегда использует один токен, независимо от экрана.
2. Минимум для пользовательского текста — 11 px. Размеры 8, 9 и 10 px выводятся из интерфейса.
3. Длинный текст переносится или обрезается по строкам; шрифт не уменьшается.
4. Заголовок услуги в каталоге допускает до трёх строк. В компактной рекомендации — до двух строк с раскрытием или переходом к подробностям.
5. Основной текст ограничивается комфортной длиной строки; на ширине 390 px это обеспечивают боковые поля экрана.
6. Цены используют `font-variant-numeric: tabular-nums` и не смешиваются с поясняющим текстом в одном начертании.
7. Кегль не меняется между светлой и тёмной темами.
8. На экранах меньше 360 px сохраняется тот же кегль: уплотняются отступы и сетка, но не текст.
9. При увеличенном системном шрифте блоки растут по высоте и не получают фиксированную высоту, обрезающую текст.

## 5. Статус реализации

- 190 текстовых селекторов переведены на `--type-*` и стандартные веса `--weight-*`.
- Размеры 8, 9 и 10 px удалены из пользовательского текста.
- Цены используют табличные цифры.
- Поля ввода, списки и текстовые области используют 16 px.
- На 320 px уплотняются сетка быстрых направлений и строка цен, но размер текста не уменьшается.
- Проверены главная, каталог, карточка услуги, заявка, трансферы, «Мои заявки», настройка плана, день плана и поиск по плану на 390 px. Главная и каталог дополнительно проверены на 350 и 320 px.
- Повторяемая миграция хранится в `scripts/migrate-typography.mjs`.

Прямые числовые `font-size` в компонентах допустимы только для иконок и технического скрытия подписи. Текстовые элементы должны ссылаться на `--type-*`.
