Files
site-portfolio/DESIGN.md
T

276 lines
15 KiB
Markdown

# DESIGN.md
Портфолио-сайт продуктового дизайнера. Лонгриды кейсов, резюме, блог. Визуал — минимализм с акцентом на типографику и контент.
---
## Продукт
Одностраничный сайт-портфолио с внутренними страницами (кейсы, резюме, блог). Основной контент — лонгриды с описанием проектов. Навигация через главную страницу с секциями: навыки, портфолио, контакты.
**Характер:** Сдержанный, профессиональный. Без визуального шума. Контент — главный элемент интерфейса.
---
## Цвета
### Токены темы
| Токен | Назначение |
|---|---|
| `--theme-h` | Оттенок акцента (0–360°) |
| `--theme-s` | Насыщенность акцента |
| `--theme-l` | Светлота акцента |
| `--accent` | Основной акцентный цвет |
| `--accent-text` | Цвет текста на акцентном фоне |
| `--accent-soft` | Мягкий акцент для фона |
| `--bg` | Фон страницы |
| `--bg-elevated` | Поверхность второго уровня |
| `--surface` | Фон карточек и секций |
| `--text` | Основной текст |
| `--text-muted` | Приглушённый текст |
| `--line` | Рамки и разделители |
### Правила
- Акцент меняется через `--theme-h/s/l` на `<html>`. Все производные пересчитываются автоматически.
- Светлая/тёмная тема — `data-theme="light|dark"` на `<html>`.
- Нейтральные фоны (`--bg`, `--surface`) слегка подмешивают оттенок акцента через `--neutral-accent-tint`.
- Не используйте хардкод hex-значений. Всегда обращайтесь к токенам.
---
## Типографика
### Семейства
| `data-font` | Стек | Назначение |
|---|---|---|
| `merriweather` | Merriweather + Alice | По умолчанию. Alice — проза, Merriweather — заголовки |
| `geologica` | Geologica + PT Sans | Гротеск + нейтральная проза |
| `mono` | Source Code Pro + PT Mono | Моноширинный |
### Шкала
| Класс | Размер | Вес | Назначение |
|---|---|---|---|
| `.hero__eyebrow` | `0.78rem` | 700 | Подзаголовок секции, ввод кейса. Uppercase, letter-spacing 0.14em |
| `.hero__title` | `clamp(3.1rem, 7.2vw, 4.85rem)` | 700 | H1 главной страницы |
| `.case-page__h1` | `clamp(2rem, 3.9vw, 2.9rem)` | 700 | H1 кейса / внутренней страницы |
| `.case-page__sub` | `clamp(1.5rem, 2vw, 1.65rem)` | 500 | Подзаголовок под H1 |
| `.section__title` | `clamp(0.95rem, 1.35vw, 1.1rem)` | 600 | Заголовки секций («Навыки», «Портфолио») |
| `.section__prose` | наследует | — | Основной текст абзацев |
| `h2` в `.case-article` | `clamp(1.5rem, 2vw, 1.65rem)` | 500 | Разделы лонгрида |
| `h3` в `.case-article` | наследует | — | Подразделы внутри H2 |
### Правила
- Заголовки используют `clamp()` — размер масштабируется от вьюпорта.
- Не задавайте `font-size` в пикселях. Используйте `rem` или `clamp()`.
- `line-height` для прозы: `1.55` (базовый), для заголовков: `1.2`.
- `max-width` текстовой колонки: `42rem` (`.section__prose`).
---
## Отступы и сетка
### Токены
| Токен | Значение | Назначение |
|---|---|---|
| `--space` | `clamp(1rem, 4vw, 2.75rem)` | Горизонтальные поля + safe-area |
| `--max` | `none` | Ширина контента = вьюпорт минус padding |
| `--radius-sm` | Зависит от `data-radius` | Малые скругления |
| `--radius-md` | Зависит от `data-radius` | Средние скругления |
| `--radius-card` | Зависит от `data-radius` | Карточки |
### Секции
| Класс | Назначение |
|---|---|
| `.section` | Вертикальные отступы через `clamp()` |
| `.section--tight` | Компактные отступы (кейсы, внутренние страницы) |
| `.section--surface` | Прозрачный фон (для mesh на главной) |
| `.section__inner` | Центрированная обёртка с `max-width: var(--max)` |
| `.case-article` | Контентная колонка лонгрида: `max-width: 48rem` |
### Брейкпоинты
| Ширина | Что меняется |
|---|---|
| `860px` | Hero → 2 колонки (`1.15fr 0.85fr`) |
| `760px` / `1180px` | Карусель портфолио: 1 → 2 → 3 карточки |
| `720px` | Сетка навыков → 2 колонки |
| `1024px` | Навыки: 6-колоночная мозаика |
| `560px` / `1024px` | Контакты → 2 → 4 колонки |
| `640px` | Wide-блоки схлопываются в ширину колонки |
### Правила
- Отдельной 12-колоночной сетки нет. Используйте CSS Grid внутри секций.
- Горизонтальные отступы — `--space` + `safe-area-inset`.
- Wide-блоки (`.case-media--wide`, `.case-callout`) шире колонки: `min(100vw - 2*padding, content + 8rem)`.
---
## Компоненты
### Кнопки
| Класс | Назначение |
|---|---|
| `.btn` | Базовый класс кнопки |
| `.btn--primary` | Основная кнопка (акцентный фон, стекло) |
| `.btn--secondary` | Вторичная кнопка (нейтральное стекло) |
| `.btn--ghost` | Текстовая кнопка без фона |
| `.btn--flat` | Плоский вариант (без «объёма») |
| `.btn--raised` | Приподнятый вариант (с тенью) |
| `.btn__icon` | Иконка внутри кнопки |
### FAB-кнопки
| Класс | Назначение |
|---|---|
| `.fab` | Базовый класс плавающей кнопки (круглая, `position: fixed`) |
| `.fab--primary` | Акцентная FAB (градиент, стекло, `--on-accent` для текста/иконки) |
| `.fab--secondary` | Вторичная FAB (нейтральная, для настроек) |
| `.fab--label` | Модификатор: снимает фиксированную ширину, добавляет текст рядом с иконкой |
| `.fab-primary__ico` | Иконка внутри primary FAB (маска через `mask-image`) |
| `.fab__label` | Текстовая подпись внутри FAB |
Правило: `--on-accent` вычисляется в синхронном `theme-init-script` (в `<head>`) по luminance акцента. Не задавайте `color` вручную — наследуется от `.fab--primary`.
### Теги
| Класс | Назначение |
|---|---|
| `.hero__tags` | Контейнер тегов в Hero |
| `.hero__tag` | Тег (пилл с рамкой). Используйте для ключевых слов |
| `.portfolio-card__tag` | Тег внутри карточки портфолио |
| `.mp-card__tags` | Контейнер тегов в mp-card |
| `.mp-card__tag` | Тег внутри mp-card |
### Фильтр-чипы
Переключаемая группа тегов над списком карточек. Нажатый чип оставляет только элементы с
совпадающим тегом, остальные скрываются.
| Класс / атрибут | Назначение |
|---|---|
| `.filter-chips` | Контейнер чипов (`<ul>`). Атрибут `data-filter-chips` включает поведение |
| `.filter-chip` | Кнопка-чип. Атрибут `data-filter-value` = тег, который она включает |
| `.filter-chip__count` | Счётчик совпадений. Проставляется скриптом автоматически |
| `data-filter-scope` | Селектор контейнера с фильтруемыми элементами. По умолчанию `document` |
| `data-filter-item` | Помечает фильтруемый элемент |
| `data-filter-tag` | Теги элемента через пробел. Несколько тегов работают как OR |
Правила:
- Состояние держится в `aria-pressed="true|false"`, а не в классе. Оформление выбранного
чипа — `[aria-pressed="true"]`, поэтому оно не зависит от `:focus` и не залипает после клика.
- Значение `all` (или пустое) показывает все элементы. Такой чип обычно первый.
- Скрытие через атрибут `hidden` + `[data-filter-item][hidden] { display: none }` — сетка
не оставляет дыр. Плавное затухание потребовало бы анимации высоты, а для фильтра
мгновенный отклик важнее.
- JS: `initFilterChips()` в `public/js/modules/ui/filter-chips.js`, подключён в `main.js`.
Счётчики и стартовое состояние берутся из разметки, модуль сам их заполняет.
- Помечайте элементы `hidden`, а не удаляйте — иначе фильтр ломает раскладку при возврате.
### Карточки
| Класс | Назначение |
|---|---|
| `.portfolio-card` | Карточка проекта в портфолио |
| `.portfolio-card__body` | Текстовая часть |
| `.portfolio-card__cover` | Обложка |
| `.skill-task-card` | Карточка навыка (задача + решения) |
| `.contact-card` | Контактная карточка (ссылка или действие) |
### Блоки лонгрида
| Класс | Назначение |
|---|---|
| `.hero__eyebrow` | Подзаголовок перед H1 |
| `.case-page__h1` | Заголовок страницы |
| `.case-page__sub` | Подзаголовок |
| `.section__prose` | Абзац текста |
| `.section__title` | Заголовок секции |
| `.case-callout` | Акцентный блок (важная мысль) |
| `.case-media` | Обёртка для изображения/видео |
| `.case-media--natural` | Изображение в натуральном масштабе |
| `.case-media--content` | По ширине текстовой колонки |
| `.case-media--wide` | Шире колонки статьи |
| `.case-media-gallery--wide` | Шире колонки статьи (галерея) |
| `.case-media-slider` | Слайдер: одна картинка, стрелки и точки-пагинация |
---
## Поведение
### Изображения
- Формат: **WebP** для всех изображений.
- Видео: **WebM** (MP4 как fallback).
- Lazy loading: `loading="lazy"`, `decoding="async"`.
- Просмотр по клику: `data-image-viewer` на `<img>`.
- Заглушка при загрузке: `.is-img-loading` / `.has-img-loading`.
### Секции
- Порядок на странице кейса: `header-case` → `fab-stack` → `main.case-article` → `projects-section` → `contact-section` → `footer`.
- Порядок на внутренних страницах: `header-minimal` → `fab-stack-home-contact` → `main.section` → `footer`.
### Навигация
- Главная: горизонтальная навигация по секциям.
- Внутренние страницы: ссылка «на главную» в шапке.
- Плавающие кнопки (FAB): тема, контакты.
---
## Do's and Don'ts
### Do's
- Используйте токены цвета (`--accent`, `--text`, `--surface`), не хардкодьте.
- Используйте `clamp()` для типографики — не фиксированные px/rem.
- Используйте `.section__prose` для основного текста — он задаёт `max-width` и `color`.
- Используйте `.hero__eyebrow` для подзаголовков перед заголовками.
- Используйте WebP для изображений, WebM для видео.
- Для лонгридов внутри `.case-article` — заголовки `h2`/`h3` стилизуются автоматически.
### Don'ts
- Не создавайте новые классы для типографики, если есть готовые в таблице шкалы.
- Не используйте `font-size` в пикселях.
- Не смешивайте стили из разных `data-font` на одной странице.
- Не используйте `.hero__tag` для навыков в резюме — используйте `.skill-card` или простой список.
- Не создавайте wide-блоки без необходимости — они выходят за колонку и ломают ритм.
- Не используйте декоративные градиенты на функциональных поверхностях.
---
## Страницы
| Страница | Шаблон | Ключевые компоненты |
|---|---|---|
| Главная | `src/pages/index.html` | Hero, Skills, Projects, Contact |
| Кейс | `src/pages/cases/*.html` | `.case-article`, `.hero__eyebrow`, `.case-page__h1`, `.case-media` |
| Резюме | `src/pages/resume*.html` | `.doc`, `.profile-header`, `.meta-grid`, `.timeline`, `.skill-grid` |
| Design System | `src/pages/cases/design-system.html` | Живой каталог компонентов и токенов |
| Demo elements | `src/pages/cases/template-elements-demo.html` | Элементы лонгрида: медиа, галереи, видео, callout |
| Mini projects | `src/pages/cases/mini-projects-showcase.html` | Карточки активности (mp-card) |
---
## Файлы
| Файл | Назначение |
|---|---|
| `public/css/main.css` | Единый CSS: токены + все компоненты |
| `src/pages/cases/design-system.html` | Живой каталог токенов, типографики, кнопок, карточек |
| `src/pages/cases/template-elements-demo.html` | Элементы лонгрида: медиа, галереи, видео, callout |
| `src/pages/cases/mini-projects-showcase.html` | Карточки активности (mp-card) |
| `docs/case-page-blocks.md` | Инструкция по блокам лонгридов |
| `DESIGN.md` | Этот файл — описание для AI-агентов |