merge feature/resume-pdf-download into dev

This commit is contained in:
Local Build committed 2026-08-14 10:05:40 +02:00
commit 5544a48400
62 files changed
+10673 -5433

No files matched your search

File diff suppressed because it is too large. Load diff
-10
View File
@@ -1,10 +0,0 @@
node_modules
.git
.gitignore
Dockerfile
Dockerfile.dev
.dockerignore
*.log
.cache
.deploy-manifest.json
.cursor
+1
View File
@@ -12,6 +12,7 @@ coverage/
!.cursor/commands/
!.cursor/commands/**
.vscode/
.zed/
gitverse/
# Logs
+1
View File
@@ -0,0 +1 @@
22
+39 -19
View File
@@ -1,27 +1,18 @@
# Подсказки для агента (Cursor)
## GitVerse / деплой статики
## Сборка и деплой
Полный чеклист: **`docs/gitverse-sync.md`** → раздел **«Инструкция для агента (Cursor)»**.
Деплой автоматический: пуш в git → автодеплой на хостинг.
Деплой на VPS: **`docs/vps-deploy.md`**.
По запросу пользователя «собрать», «билд»:
Кратко по запросу пользователя «выложить на GitVerse», «синк gitverse», «задеплоить»:
1. При правках `src/pages/**` или `src/partials/**` — `npm run build:pages`.
2. При смене шрифтов/Plyr или `package.json` — `npm run build` (включает `vendor:copy`).
3. Для деплоя — сделать git commit + push.
1. При правках `src/pages/**` или `src/partials/**` — `npm run build:pages`; при смене шрифтов/Plyr или `package.json` — `npm run build` (включает `vendor:copy`).
2. Затем `npm run sync-gitverse` (разрешения **network** и **git_write**).
3. Не запускать синк без явного запроса пользователя.
## Git
По запросу «задеплой в Coolify», «задеплой на VPS»:
1. При правках в `public/` — `npm run deploy:vps` (разрешения **all**).
2. По запросу «задеплой везде» — `npm run deploy` (VPS + GitVerse).
Не запускать деплой на VPS без явного запроса: скрипт перезаписывает `/data/static-site` на сервере.
## Git: корневой репозиторий
Этот репозиторий в корне проекта **только локальный** (рабочая копия, история коммитов для себя). **Не добавлять `origin` и не пушить** в удалённый репозиторий из агента, если пользователь явно не попросил настроить remote и не дал URL. Выгрузка наружу — отдельный сценарий через **`npm run sync-gitverse`** в папку `gitverse` (см. выше), а не `git push` из корня.
Репозиторий: `http://x1qnvk08zec2u5cx6yh5iexh.155.212.186.39.sslip.io/admin/site-portfolio.git`
### Влить в `master`, оставаясь на текущей ветке
@@ -33,9 +24,14 @@
## Design System
Страница-каталог: **`src/pages/cases/design-system.html`** → после сборки `public/cases/design-system.html`.
Перед работой с UI **прочитай `DESIGN.md`** в корне проекта — там описаны токены, типографика, компоненты и правила их применения.
При **глобальных** правках стилей (токены в `public/css/main.css`, компоненты главной, блоки лонгрида кейса) **обновляй Design System**: живой пример и краткое описание в соответствующей секции, при необходимости — `docs/case-page-blocks.md`.
Страницы-каталоги (живые примеры):
- **`src/pages/cases/design-system.html`** → токены, типографика, кнопки, карточки, секции
- **`src/pages/cases/template-elements-demo.html`** → элементы лонгрида: медиа, галереи, видео, callout
- **`src/pages/cases/mini-projects-showcase.html`** → карточки активности (mp-card)
При **глобальных** правках стилей (токены в `public/css/main.css`, компоненты главной, блоки лонгрида кейса) **обновляй соответствующий каталог**: живой пример и краткое описание в секции, при необходимости — `docs/case-page-blocks.md`.
## Контент кейса в public (по запросу)
@@ -49,6 +45,18 @@
Режим на странице при `npm run serve` → очередь в **`texts/content-edits/pending.json`**. Apply по запросу **«примени правки»**: читать этот файл, править **`src/pages/`**, **humanizer-ru**, **`npm run build:pages`**; **`pending.json` не очищать** (пользователь удаляет пункты сам). Подробности: **`docs/content-edit-mode.md`**, **`.cursor/rules/content-edit-apply.mdc`**.
## PDF резюме (по запросу)
По запросу «обнови PDF», «перегенерируй PDF»:
1. Убедиться, что dev-сервер запущен (`localhost:4175`).
2. Запустить `npm run generate:resume-pdf`.
3. Файл обновится в `public/assets/resume/Mamadaev_Nik__CV__Product_Designer_UX-UI.pdf`.
Подробнее: **`docs/resume-pdf.md`**.
Скрипт требует запущенный сервер — нельзя встроить в обычный `build`.
## Vendor (шрифты, Plyr)
Локально в `public/`, без CDN. Обновление: **`docs/vendor-assets.md`**, команда `npm run vendor:copy`.
@@ -60,3 +68,15 @@
## Остальное
Правила и таблица доков: **`.cursor/rules/read-docs-before-feature-dev.mdc`** (локально; папка `.cursor/` может быть в `.gitignore`).
### Ключевые файлы
| Файл | Назначение |
|---|---|
| `DESIGN.md` | Описание дизайн-системы для AI-агентов |
| `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` | Инструкция по блокам лонгридов |
| `docs/resume-pdf.md` | Генерация PDF резюме (Puppeteer) |
+245
View File
@@ -0,0 +1,245 @@
# 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` | Тег внутри карточки портфолио |
### Карточки
| Класс | Назначение |
|---|---|
| `.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` | Шире колонки статьи |
---
## Поведение
### Изображения
- Формат: **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-агентов |
-13
View File
@@ -1,13 +0,0 @@
# Build the static site and serve it with nginx
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build:pages
FROM nginx:alpine
# Fix mjs MIME type — without this plyr.min.mjs fails to load as ES module
RUN sed -i 's|application/javascript *js;|application/javascript js mjs;|' /etc/nginx/mime.types
COPY --from=build /app/public /usr/share/nginx/html
EXPOSE 80
-9
View File
@@ -1,9 +0,0 @@
# Dev environment: serves public/ with BrowserSync + content-edits API (port 4175)
FROM node:22-slim
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build:pages
EXPOSE 4175
CMD ["npm", "run", "serve"]
-40
View File
@@ -1,40 +0,0 @@
#!/usr/bin/env bash
set -e
HOST="root@155.212.186.39"
SSH_KEY="$HOME/.ssh/beget"
SRC_DIR="$(cd "$(dirname "$0")" && pwd)/public/"
echo "📦 Deploy mamadaevv.site..."
echo "Src: $SRC_DIR"
REMOTE_INFO=$(ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no "$HOST" '
CONTAINER=$(docker ps --format "{{.Names}}" | grep "s9mrcps8xw02r1dak0fsznix" | head -1)
VOLUME_PATH=$(docker inspect "$CONTAINER" 2>/dev/null | python3 -c "
import sys,json
mounts=json.load(sys.stdin)[0].get(\"Mounts\",[])
print([m[\"Source\"] for m in mounts if m[\"Destination\"]==\"/usr/share/nginx/html\"][0])
")
echo "$CONTAINER|$VOLUME_PATH"
')
IFS='|' read -r CONTAINER VOLUME_PATH <<< "$REMOTE_INFO"
echo "Container: $CONTAINER"
echo "Volume: $VOLUME_PATH"
# Копируем файлы
cd "$SRC_DIR"
tar cf - . | ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no "$HOST" \
"tar xf - -C $VOLUME_PATH"
# Фикс MIME для .mjs (plyr.min.mjs модуль)
ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no "$HOST" \
"docker exec $CONTAINER sh -c \"
if ! grep -q 'application/javascript mjs' /etc/nginx/mime.types 2>/dev/null; then
sed -i 's|application/wasm|application/javascript mjs;\\n application/wasm|' /etc/nginx/mime.types
nginx -s reload && echo 'MIME fix applied'
fi
\"" 2>/dev/null || true
echo ""
echo "✅ Done! https://mamadaevv.site"
-57
View File
@@ -1,57 +0,0 @@
# Синхронизация `public` -> `gitverse`
## Назначение
Скрипт `sync-gitverse` копирует содержимое `public` в папку `gitverse`, затем выполняет коммит и пуш в репозиторий внутри `gitverse`.
## Запуск
- Через npm:
- `npm run sync-gitverse`
- Напрямую:
- `node scripts/sync-gitverse.mjs`
- С явными путями:
- `node scripts/sync-gitverse.mjs <sourceDir> <targetDir>`
По умолчанию:
- `sourceDir = public`
- `targetDir = gitverse`
## Что делает скрипт
1. Проверяет, что исходная папка существует.
2. В целевой папке удаляет всё, кроме:
- `.git`
- `.gitverse`
3. Копирует содержимое `public` в `gitverse` (файлы `.png` пропускаются — в деплое используются WebP и остальные форматы).
4. В репозитории `gitverse` выполняет:
- `git add .`
- `git commit -m "sync public YYYY-MM-DD HH:mm"` (только если есть изменения)
- `git push`
5. После успешного пуша открывает в системном браузере по умолчанию: `https://mamadaevv.gitverse.site/me/`
Если изменений после копирования нет, коммит и пуш не делаются.
## Инструкция для агента (Cursor)
Когда пользователь просит **выложить на GitVerse**, **собрать/задеплоить gitverse**, **синхронизировать с gitverse** или аналогично:
1. **Сборка `public/`:** если менялись `src/pages/**` или `src/partials/**` — `npm run build:pages`; если шрифты/Plyr/`package.json` или `scripts/copy-vendor.mjs` — `npm run build` (сначала `vendor:copy`, затем страницы). См. [`docs/vendor-assets.md`](vendor-assets.md).
2. **Синк и пуш:** выполни `npm run sync-gitverse` из корня. Нужны разрешения **network** и **git_write** (SSH на GitVerse, пуш из папки `gitverse`).
3. **Ожидания:** скрипт не копирует файлы `.png` в `gitverse`. После **успешного** `git push` открывается системный браузер с `https://mamadaevv.gitverse.site/me/`. Если изменений в `gitverse` после копирования нет — коммит/пуш не выполняются, браузер не открывается.
4. **Не вызывай** `sync-gitverse` без запроса пользователя: скрипт очищает целевую папку (кроме `.git` и `.gitverse`) и пушит в remote.
5. **Корневой git репозиторий** этого проекта считается **только локальным**: не пушь из корня в `origin` и не настраивай remote без явной просьбы пользователя с URL. Внешняя выкладка — через `gitverse`, не через `git push` в корне.
6. Деплой на VPS — отдельный сценарий, см. **`docs/vps-deploy.md`**.
Подробности и ограничения — в разделах выше.
## Требования
- В `gitverse` уже должен быть инициализирован git-репозиторий (папка `.git`).
- Должен быть настроен доступ на push (SSH-ключ/права).
## Важно
- Скрипт удаляет в `gitverse` все файлы и папки, кроме `.git` и `.gitverse`.
- Не запускай скрипт, если в `gitverse` есть локальные несохраненные изменения, которые нужно оставить.
+5 -11
View File
@@ -1,10 +1,11 @@
# Локальный просмотр сайта
Сайт в режиме разработки обслуживается из папки `**public/**` через [BrowserSync](https://browsersync.io/): при изменении файлов страница в браузере обновляется сама.
Сайт в режиме разработки обслуживается из папки `**public/**` через нативный HTTP-сервер (Node.js `http` модуль): статика + API правок контента.
## Требования
- Установлены **Node.js** и **npm** (идут вместе с Node).
- **Node.js 22** (см. `.node-version` в корне проекта). fnm/fvm переключают автоматически.
- **npm** (идёт вместе с Node).
## Первый раз в проекте
@@ -23,18 +24,11 @@ npm run vendor:copy
npm run serve
```
Скрипт [`scripts/serve-dev.mjs`](../scripts/serve-dev.mjs): статика из `public/`, API правок контента, перезагрузка **только** при изменениях в `public/**` (запись в `texts/content-edits/` вкладку не перезагружает).
Без API: `npm run serve:static`.
Скрипт [`scripts/serve-dev.mjs`](../scripts/serve-dev.mjs): статика из `public/`, API правок контента. Нет авто-релиоада — после правок в `public/` обновляй страницу вручную.
## Куда смотреть
- **Сайт:** [http://localhost:4175](http://localhost:4175) — откроется `public/index.html` и остальные пути относительно `public/`.
- **Панель BrowserSync UI:** [http://localhost:4176](http://localhost:4176) (опционально, для синхронизации и настроек).
## Что отслеживается
Любые изменения в `**public/**`**: HTML, CSS, JS, картинки. Папка `texts/content-edits/` **не** в watch — autosave правок не сбрасывает режим редактирования.
## API правок контента
@@ -48,4 +42,4 @@ npm run serve
## Остановка
В терминале: **Ctrl+C**.
В терминале: **Ctrl+C**.
+52
View File
@@ -0,0 +1,52 @@
# PDF резюме
## Генерация PDF
Скрипт `scripts/generate-resume-pdf.mjs` открывает `resume-5.html` через Puppeteer, применяет шрифт geologica (PT Sans), убирает подложку/обводку блока `.resume-doc` и сохраняет PDF.
**Важно**: скрипт требует запущенный dev-сервер (`npm run serve` → `localhost:4175`).
### Запуск
```bash
npm run generate:resume-pdf
```
или вручную:
```bash
node scripts/generate-resume-pdf.mjs http://localhost:4175/resume-5.html geologica
```
Параметры:
- `[url]` — URL страницы (по умолчанию `http://localhost:4175/resume-5.html`)
- `[font]` — ID шрифта: `geologica`, `merriweather`, `mono` (по умолчанию `geologica`)
### Выходной файл
`public/assets/resume/Mamadaev_Nik__CV__Product_Designer_UX-UI.pdf`
Кнопка «Скачать в PDF» на странице `resume-5.html` — это `<a>` ссылка на этот файл.
### Когда перегенерировать
- После правок в `src/pages/resume-5.html` (контент, стили)
- После правок в `src/css/resume-5.css` (инлайн-стили в `<style>`)
- При смене шрифта по умолчанию в скрипте
### Что скрипт делает с страницей
1. Устанавливает шрифт через `localStorage` + `data-font`
2. Ждёт загрузки шрифтов (`document.fonts.ready`)
3. Удаляет `header`, `footer`, `nav`, `.fab-stack`, `.cookie-notice`, `.skip-link`
4. Убирает `max-width` с `.resume-doc`, ставит `width: 100%`
5. Убирает фон (`background: transparent`) и обводку (`border: none`)
6. Захватывает `.resume-doc` как A4 PDF с `printBackground: true`
### Не попадает в PDF
Из `.resume-doc` удаляются (но остаются на сайте):
- Фон блока
- Обводка блока
Всё остальное (отступы, шрифты, сетка) — как на сайте.
+1 -5
View File
@@ -1,6 +1,6 @@
# Локальные vendor-ассеты (шрифты и Plyr)
Сайт не использует Google Fonts и jsDelivr в рантайме. Файлы лежат в `public/` и попадают на хостинг через `sync-gitverse`.
Сайт не использует Google Fonts и jsDelivr в рантайме. Файлы лежат в `public/` и попадают на хостинг через git push.
## Что где
@@ -49,7 +49,3 @@ npm run build:pages
1. Обновить версию в `package.json` (`dependencies.plyr`).
2. `npm install` → `npm run vendor:copy`.
3. При смене API — правки в `video-player.js`.
## Деплой
Перед `npm run sync-gitverse` выполни `npm run build`, чтобы в `public/` были актуальные шрифты, Plyr и HTML.
-59
View File
@@ -1,59 +0,0 @@
# Деплой на VPS (инкрементальный)
Скрипт `scripts/deploy-vps.mjs` загружает содержимое `public/` на VPS, передавая только изменённые файлы.
## Принцип работы
1. **Манифест** (`.deploy-manifest.json`) хранит `mtime` и `size` каждого файла с прошлого деплоя.
2. При запуске скрипт сканирует `public/`, сравнивает с манифестом:
- Файлы с изменившимся `mtime` или `size` — загружаются.
- Файлы, которых нет локально, но есть в манифесте — удаляются с сервера.
3. Изменённые файлы пакуются в `tar` и передаются **одним SSH-соединением** (без сжатия, чтобы не тратить CPU на уже сжатые медиа).
4. Манифест обновляется после успешного деплоя.
При первом запуске (манифест пуст) заливаются все файлы — ~3 минуты на ~400 файлов. Повторный деплой (1–10 изменившихся файлов) — 2–5 секунд.
## Запуск
```bash
npm run deploy:vps
# или напрямую
node scripts/deploy-vps.mjs [sourceDir]
```
По умолчанию `sourceDir = public`.
## Рецепты
### Только в Coolify
Запрос пользователя: «задеплой в Coolify», «задеплой на VPS».
```bash
npm run deploy:vps
```
Нужны разрешения: **all** (SSH-ключ `~/.ssh/beget`, доступ к файлам `public/`).
### Везде (VPS + GitVerse)
```bash
npm run deploy
```
Выполняет `deploy:vps`, затем `sync-gitverse`.
## Конфигурация
- **SSH-ключ:** `~/.ssh/beget`
- **Хост:** `root@155.212.186.39`
- **Целевая папка:** `/data/static-site`
- **Манифест:** `.deploy-manifest.json` в корне проекта (не коммитится)
## Сброс манифеста
Если нужно залить всё с нуля — удалить `.deploy-manifest.json`:
```bash
rm .deploy-manifest.json
```
+193 -1591
View File
File diff suppressed because it is too large. Load diff
+2 -5
View File
@@ -6,12 +6,9 @@
"build:pages": "node scripts/build-pages.mjs",
"build": "npm run vendor:copy && npm run build:pages",
"serve": "node scripts/serve-dev.mjs",
"serve:static": "browser-sync start --server \"public\" --files \"public/**/*\" --no-notify --no-open --no-ghost-mode --port 4175 --ui-port 4176",
"convert-videos": "node scripts/convert-videos.mjs",
"optimize-images": "node scripts/optimize-images.mjs",
"deploy:vps": "node scripts/deploy-vps.mjs",
"deploy": "npm run deploy:vps && npm run sync-gitverse",
"sync-gitverse": "node scripts/sync-gitverse.mjs"
"generate:resume-pdf": "node scripts/generate-resume-pdf.mjs http://localhost:4175/resume-5.html geologica"
},
"devDependencies": {
"@fontsource-variable/geologica": "^5.2.8",
@@ -20,7 +17,7 @@
"@fontsource/pt-mono": "^5.2.8",
"@fontsource/pt-sans": "^5.2.8",
"@fontsource/source-code-pro": "^5.2.7",
"browser-sync": "^3.0.4",
"puppeteer": "^25.7.0",
"sharp": "^0.34.0"
},
"dependencies": {
-13
View File
@@ -1,13 +0,0 @@
{
"model": "black-forest-labs/flux.2-klein-4b",
"messages": [
{
"role": "user",
"content": "Минималистичный AI-промпт для портретов в стиле high-fashion. Мягкий студийный свет, чистый фон и акцент на естественной красоте. Такой визуал идеально подходит для тренировки моделей освещения и теста фотореализма. Подходит для: fashion-портретов, нейрофотосессий, коммерческих стоков. Стиль: минимализм, чистая палитра, editorial precision. 👉 Узнай больше AI-идей и вдохновляющих промптов в моём телеграм-канале «Нейропольза» — переходи по ссылке. Minimalist AI portrait prompt with diffused studio light and fashion-magazine aesthetics. Perfect for clean editorial visuals and AI-photo training."
}
],
"modalities": ["image"],
"image_config": { "aspect_ratio": "9:16" },
"_provider": "PLZ",
"_cost": 1
}
+5
View File
@@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 9V2H18V9" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 18H4C2.89543 18 2 17.1046 2 16V11C2 9.89543 2.89543 9 4 9H20C21.1046 9 22 9.89543 22 11V16C22 17.1046 21.1046 18 20 18H18" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 15H18V22H6V15Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 537 B

+161 -137
View File
@@ -36,6 +36,30 @@
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
@@ -542,7 +566,7 @@
<h3>Дальнейшее развитие</h3>
<p class="section__prose">
В дорожной карте оставались отдельные крупные куски: сценарии вокруг LLM (списки, статусы, действия), пошаговый мастер обучения с прогрессом и отменой, а также полноценный контур OCR с разметкой регионов и превью качества на странице. Они не входили в минимальный набор для первого промышленного релиза интерфейса, но заложенные паттерны должны их принять без ломки навигации.
В дорожной карте оставались отдельные крупные куски: сценарии вокруг LLM (списки, статусы, действия), пошаговый мастер обучения с прогрессом и отменой, а также полноценный контур OCR с разметкой регионов и превью качества на странице. Они не входили в минимальный набор для первого промышленного релиза интерфейса, но заложенные паттерны должны их принять без больших переделок.
</p>
</div>
@@ -577,140 +601,140 @@
</div>
</main>
<section id="projects" class="section section--surface">
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
<section id="projects" class="section section--surface" data-reveal>
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
</section><section hidden class="section section--surface" aria-hidden="true">
<div class="section__inner">
<div class="projects__heading">
@@ -955,14 +979,14 @@
</div>
</section>
<section id="contact" class="section section--surface section--footerish">
<section id="contact" class="section section--surface section--footerish" data-reveal>
<div class="section__inner">
<h2 class="section__title">Контакты</h2>
<ul class="contact-grid">
<li><a class="contact-card contact-card--link contact-card--brand-tg" href="https://t.me/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/tg.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Telegram</span><span class="contact-card__hint">Отвечу сегодня</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-vk" href="https://vk.com/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/vk.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">ВКонтакте</span><span class="contact-card__hint">Стабильный коннект</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-ya" href="https://yandex.ru/chat/p/727e71fa-89b5-44a8-90a5-851021631a1c?utm_source=invite" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/yandex_telemost.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Яндекс</span><span class="contact-card__hint">Да, тут тоже можно</span></span></a></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5ydQ==" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5zaXRl" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
</ul>
</div>
</section>
File diff suppressed because it is too large. Load diff
+160 -136
View File
@@ -36,6 +36,30 @@
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
@@ -741,140 +765,140 @@
</div>
</main>
<section id="projects" class="section section--surface">
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
<section id="projects" class="section section--surface" data-reveal>
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
</section><section hidden class="section section--surface" aria-hidden="true">
<div class="section__inner">
<div class="projects__heading">
@@ -1094,14 +1118,14 @@
</div>
</section>
<section id="contact" class="section section--surface section--footerish">
<section id="contact" class="section section--surface section--footerish" data-reveal>
<div class="section__inner">
<h2 class="section__title">Контакты</h2>
<ul class="contact-grid">
<li><a class="contact-card contact-card--link contact-card--brand-tg" href="https://t.me/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/tg.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Telegram</span><span class="contact-card__hint">Отвечу сегодня</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-vk" href="https://vk.com/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/vk.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">ВКонтакте</span><span class="contact-card__hint">Стабильный коннект</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-ya" href="https://yandex.ru/chat/p/727e71fa-89b5-44a8-90a5-851021631a1c?utm_source=invite" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/yandex_telemost.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Яндекс</span><span class="contact-card__hint">Да, тут тоже можно</span></span></a></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5ydQ==" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5zaXRl" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
</ul>
</div>
</section>
+38 -2
View File
@@ -36,6 +36,30 @@
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
@@ -106,7 +130,7 @@
margin: 0 0 1.15rem;
padding-top: clamp(2.75rem, 6vw, 4rem);
font-family: var(--font);
font-size: clamp(1.15rem, 2vw, 1.35rem);
font-size: clamp(1.7rem, 3vw, 2rem);
font-weight: 700;
color: var(--text);
scroll-margin-top: 1.5rem;
@@ -121,7 +145,7 @@
.case-article.ds-page > h3 {
margin: clamp(2rem, 4vw, 2.75rem) 0 0.85rem;
font-family: var(--font);
font-size: 1.05rem;
font-size: 1.55rem;
font-weight: 600;
color: var(--text);
}
@@ -532,6 +556,7 @@
<li><a href="#fonts">Шрифты</a></li>
<li><a href="#layout">Сетка и адаптив</a></li>
<li><a href="#components">Компоненты</a></li>
<li><a href="#fab">FAB-кнопки</a></li>
<li><a href="#blocks">Блоки</a></li>
<li><a href="#mini-projects">Активность</a></li>
</ol>
@@ -864,6 +889,17 @@
</div>
<p class="sg-label">.btn .btn--primary | secondary | ghost · .btn--flat | raised · .btn__icon</p>
<h3>FAB-кнопки</h3>
<p class="section__prose">
Плавающие кнопки в правом нижнем углу (<code>.fab-stack</code>). Иконка-only и с текстовой подписью.
</p>
<div class="sg-stack sg-stack--row">
<a class="fab fab--primary" href="#components" aria-label="Демо FAB"><span class="fab-primary__ico" aria-hidden="true"></span></a>
<button type="button" class="fab fab--primary fab--label"><span class="fab-primary__ico" aria-hidden="true"></span><span class="fab__label">Скачать в PDF</span></button>
<button type="button" class="fab fab--secondary" aria-label="Демо secondary FAB"><span class="theme-panel-fab__icon theme-panel-fab__icon--open-hide" aria-hidden="true"></span></button>
</div>
<p class="sg-label">.fab .fab--primary | secondary · .fab--label (с текстом) · .fab-primary__ico · .fab__label</p>
<h3>Теги</h3>
<ul class="hero__tags" aria-label="Демо тегов">
<li class="hero__tag">hero__tag</li>
+161 -137
View File
@@ -36,6 +36,30 @@
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
@@ -278,7 +302,7 @@
</p>
<h2 id="obzor">Обзор</h2>
<p class="section__prose">Общий вид приложения — отправная точка для остальных материалов на странице.</p>
<p class="section__prose">Общий вид приложения — рабочий процесс с открытым документом, панелями инструментов и canvas. Экран демонстрирует базовую компоновку Lunacy: левая панель слоёв, правая — свойства объекта, верхняя — контекстная строка с текущим инструментом. Отправная точка для остальных материалов на странице.</p>
<figure class="case-media case-media--wide">
<img
src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
@@ -529,140 +553,140 @@
</div>
</main>
<section id="projects" class="section section--surface">
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
<section id="projects" class="section section--surface" data-reveal>
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
</section><section hidden class="section section--surface" aria-hidden="true">
<div class="section__inner">
<div class="projects__heading">
@@ -882,14 +906,14 @@
</div>
</section>
<section id="contact" class="section section--surface section--footerish">
<section id="contact" class="section section--surface section--footerish" data-reveal>
<div class="section__inner">
<h2 class="section__title">Контакты</h2>
<ul class="contact-grid">
<li><a class="contact-card contact-card--link contact-card--brand-tg" href="https://t.me/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/tg.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Telegram</span><span class="contact-card__hint">Отвечу сегодня</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-vk" href="https://vk.com/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/vk.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">ВКонтакте</span><span class="contact-card__hint">Стабильный коннект</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-ya" href="https://yandex.ru/chat/p/727e71fa-89b5-44a8-90a5-851021631a1c?utm_source=invite" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/yandex_telemost.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Яндекс</span><span class="contact-card__hint">Да, тут тоже можно</span></span></a></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5ydQ==" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5zaXRl" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
</ul>
</div>
</section>
+160 -136
View File
@@ -36,6 +36,30 @@
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
@@ -271,140 +295,140 @@
</div>
</main>
<section id="projects" class="section section--surface">
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
<section id="projects" class="section section--surface" data-reveal>
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
</section><section hidden class="section section--surface" aria-hidden="true">
<div class="section__inner">
<div class="projects__heading">
@@ -624,14 +648,14 @@
</div>
</section>
<section id="contact" class="section section--surface section--footerish">
<section id="contact" class="section section--surface section--footerish" data-reveal>
<div class="section__inner">
<h2 class="section__title">Контакты</h2>
<ul class="contact-grid">
<li><a class="contact-card contact-card--link contact-card--brand-tg" href="https://t.me/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/tg.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Telegram</span><span class="contact-card__hint">Отвечу сегодня</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-vk" href="https://vk.com/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/vk.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">ВКонтакте</span><span class="contact-card__hint">Стабильный коннект</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-ya" href="https://yandex.ru/chat/p/727e71fa-89b5-44a8-90a5-851021631a1c?utm_source=invite" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/yandex_telemost.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Яндекс</span><span class="contact-card__hint">Да, тут тоже можно</span></span></a></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5ydQ==" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5zaXRl" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
</ul>
</div>
</section>
+319 -30
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="ru" data-theme="dark" data-radius="medium" data-font="merriweather">
<head>
<meta charset="utf-8" />
@@ -36,6 +36,30 @@
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
@@ -235,9 +259,16 @@
background: color-mix(in srgb, var(--surface) 90%, var(--accent));
}
.mp-showcase-cells-demo__variant {
margin-bottom: 1.2rem;
}
.mp-showcase-cells-demo__variant:last-of-type {
margin-bottom: 0;
}
.mp-showcase-cells-demo__legend {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 0.5rem;
margin-bottom: 0.85rem;
font-size: 0.72rem;
@@ -245,25 +276,50 @@
text-align: center;
}
.mp-showcase-cells-demo__legend--6 {
grid-template-columns: repeat(6, 1fr);
}
.mp-showcase-cells-demo__legend--4 {
grid-template-columns: repeat(4, 1fr);
}
.mp-showcase-cells-demo__legend--2 {
grid-template-columns: repeat(2, 1fr);
}
.mp-showcase-cells-demo__legend span {
padding: 0.2rem 0;
border-radius: var(--radius-sm);
background: color-mix(in srgb, var(--line) 35%, transparent);
}
.mp-showcase-cells-demo__row {
.mp-showcase-cells-demo__row-label {
font-size: 0.82rem;
font-weight: 600;
color: var(--text);
margin: 0 0 0.55rem;
}
.mp-showcase-cells-demo__grid {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 0.5rem;
margin-bottom: 0.55rem;
}
.mp-showcase-cells-demo__row:last-of-type {
margin-bottom: 0;
.mp-showcase-cells-demo__grid--6 {
grid-template-columns: repeat(6, 1fr);
}
.mp-showcase-cells-demo__grid--4 {
grid-template-columns: repeat(4, 1fr);
}
.mp-showcase-cells-demo__grid--2 {
grid-template-columns: repeat(2, 1fr);
}
.mp-showcase-cells-demo__block {
grid-row: 1;
min-height: 2.35rem;
display: flex;
align-items: center;
@@ -288,6 +344,10 @@
grid-column: span 3;
}
.mp-showcase-cells-demo__block--4 {
grid-column: span 4;
}
.mp-showcase-cells-demo__caption {
margin: 0.85rem 0 0;
font-size: 0.82rem;
@@ -439,12 +499,13 @@
<li><a href="#types">Типы карточек</a></li>
<li><a href="#cells">Ширина в клетках</a></li>
<li><a href="#grid">Живая сетка masonry</a></li>
<li><a href="#fixed-height">Фиксированная высота</a></li>
</ol>
</nav>
<h2 id="intro">Как пользоваться</h2>
<p class="section__prose">
Сначала выберите <strong>тип</strong> (stack, horizontal, compact, decor), затем <strong>data-mp-cells</strong> (1–3) и
Сначала выберите <strong>тип</strong> (stack, horizontal, compact, decor), затем <strong>data-mp-cells</strong> (1–4) и
порядок <code>li</code> в списке. Карточки с <code>data-mp-extra</code> не влияют на высоту списка до кнопки «Показать все».
Подробности — в <code>docs/mini-projects-cards.md</code>.
</p>
@@ -674,35 +735,95 @@
<h2 id="cells">Ширина в клетках</h2>
<p class="section__prose">
Атрибут <code>data-mp-cells</code> на <code>li.mini-projects-grid__item</code> задаёт желаемую ширину от 1 до 3 клеток.
Атрибут <code>data-mp-cells</code> на <code>li.mini-projects-grid__item</code> задаёт желаемую ширину от 1 до 4 клеток.
Скрипт не даст карточке быть шире текущего ряда.
</p>
<p class="section__prose">
Для адаптивной ширины используйте <code>data-mp-cells-sm</code> (при 4 клетках в ряду, ≥ 880 px) и
<code>data-mp-cells-xs</code> (при 2 клетках, ≥ 520 px). Скрипт выбирает значение по текущему числу клеток в ряду.
</p>
<div class="mp-showcase-attrs-table">
<table class="mp-showcase-cells-table">
<thead>
<tr>
<th scope="col">Атрибут</th>
<th scope="col">Когда применяется</th>
<th scope="col">Пример</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>data-mp-cells</code></td>
<td>Широкий экран (6 клеток, ≥ 1180 px)</td>
<td><code>data-mp-cells="3"</code></td>
</tr>
<tr>
<td><code>data-mp-cells-sm</code></td>
<td>Средний экран (4 клетки, ≥ 880 px)</td>
<td><code>data-mp-cells-sm="2"</code></td>
</tr>
<tr>
<td><code>data-mp-cells-xs</code></td>
<td>Узкий экран (2 клетки, ≥ 520 px)</td>
<td><code>data-mp-cells-xs="1"</code></td>
</tr>
</tbody>
</table>
</div>
<p class="section__prose" style="margin-top:0.55rem">
<strong>Пример:</strong> <code>data-mp-cells="3" data-mp-cells-sm="2"</code> — карточка занимает 3 клетки на широком экране, 2 на среднем, 1 на узком.
</p>
<figure class="mp-showcase-cells-demo" aria-label="Схема ширины карточек в клетках">
<div class="mp-showcase-cells-demo__legend" aria-hidden="true">
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
<span>6</span>
<div class="mp-showcase-cells-demo__variant">
<div class="mp-showcase-cells-demo__legend mp-showcase-cells-demo__legend--6" aria-hidden="true">
<span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span>
</div>
<p class="mp-showcase-cells-demo__row-label">≥ 1180 px — 6 клеток</p>
<div class="mp-showcase-cells-demo__grid mp-showcase-cells-demo__grid--6">
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--3">3</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--3">3</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--1">1</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--3">3</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--4">4</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
</div>
</div>
<p class="mp-showcase-cells-demo__row-label">Ряд из 6 клеток (широкий экран)</p>
<div class="mp-showcase-cells-demo__row">
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--3">3</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--3">3</div>
<div class="mp-showcase-cells-demo__variant">
<div class="mp-showcase-cells-demo__legend mp-showcase-cells-demo__legend--4" aria-hidden="true">
<span>1</span><span>2</span><span>3</span><span>4</span>
</div>
<p class="mp-showcase-cells-demo__row-label">≥ 880 px — 4 клетки</p>
<div class="mp-showcase-cells-demo__grid mp-showcase-cells-demo__grid--4">
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--3">3</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--1">1</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--1">1</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--4">4</div>
</div>
</div>
<div class="mp-showcase-cells-demo__row">
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
</div>
<div class="mp-showcase-cells-demo__row">
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--1">1</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--3">3</div>
<div class="mp-showcase-cells-demo__variant">
<div class="mp-showcase-cells-demo__legend mp-showcase-cells-demo__legend--2" aria-hidden="true">
<span>1</span><span>2</span>
</div>
<p class="mp-showcase-cells-demo__row-label">≥ 520 px — 2 клетки</p>
<div class="mp-showcase-cells-demo__grid mp-showcase-cells-demo__grid--2">
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--1">1</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--1">1</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--1">1</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--1">1</div>
</div>
</div>
<figcaption class="mp-showcase-cells-demo__caption">
Цифра в блоке = значение <code>data-mp-cells</code>. Карточка занимает столько клеток подряд в одном ряду.
Цифра в блоке = значение <code>data-mp-cells</code>. Карточка занимает столько клеток подряд. При узком экране клеток меньше — карточки с шириной &gt; число клеток переносятся на следующий ряд. С <code>data-mp-cells-sm</code> / <code>data-mp-cells-xs</code> карточка меняет ширину при сужении.
</figcaption>
</figure>
<table class="mp-showcase-cells-table">
@@ -940,6 +1061,174 @@
</div>
</section>
<section id="fixed-height" class="section section--surface mp-showcase-grid-section" aria-labelledby="fixed-height-title">
<div class="section__inner">
<h2 id="fixed-height-title" class="section__title">Фиксированная высота</h2>
<p class="section__prose">
Атрибут <code>data-mp-height="…"</code> на <code>li.mini-projects-grid__item</code> задаёт фиксированную высоту карточки в пикселях. Текст обрезается с многоточием, если не влезает.
</p>
<ol
id="mini-projects-fixed-height-grid"
class="mini-projects-grid mp-showcase-grid"
data-mini-projects-list
>
<li class="mini-projects-grid__item" data-mp-cells="4" data-mp-cells-sm="4" data-mp-cells-xs="2" data-mp-height="600">
<a class="mp-card mp-card--link mp-card--stack" href="#" aria-label="[4→4→2] height=600 · stack · ссылка">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/shared/placeholder.webp"
alt=""
width="560"
height="315"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">
[4→4→2] height=600 · stack · ссылка
<span class="mp-card__ext" aria-hidden="true"></span>
</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">веб-сайт</li>
</ul>
<p class="mp-card__desc">4 → 4 → 2. data-mp-cells-sm="4" data-mp-cells-xs="2". Высота 600px.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2" data-mp-height="600" data-mp-height-sm="400">
<a class="mp-card mp-card--link mp-card--stack" href="#" aria-label="[2] height=600 · stack · ссылка">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/shared/placeholder.webp"
alt=""
width="560"
height="315"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">
[2] height=600 · stack · ссылка
<span class="mp-card__ext" aria-hidden="true"></span>
</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">заметка</li>
</ul>
<p class="mp-card__desc">Две клетки, высота 600px.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2" data-mp-height="400">
<a class="mp-card mp-card--link mp-card--stack" href="#" aria-label="[2] height=400 · stack · ссылка">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/shared/placeholder.webp"
alt=""
width="560"
height="315"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">
[2] height=400 · stack · ссылка
<span class="mp-card__ext" aria-hidden="true"></span>
</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">утилита</li>
</ul>
<p class="mp-card__desc">Две клетки, высота 400px.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2" data-mp-height="400">
<a class="mp-card mp-card--link mp-card--stack" href="#" aria-label="[2] height=400 · stack · ссылка">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/shared/placeholder.webp"
alt=""
width="560"
height="315"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">
[2] height=400 · stack · ссылка
<span class="mp-card__ext" aria-hidden="true"></span>
</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">шаблон</li>
</ul>
<p class="mp-card__desc">Две клетки, высота 400px.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2" data-mp-height="400">
<a class="mp-card mp-card--link mp-card--stack" href="#" aria-label="[2] height=400 · stack · ссылка">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/shared/placeholder.webp"
alt=""
width="560"
height="315"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">
[2] height=400 · stack · ссылка
<span class="mp-card__ext" aria-hidden="true"></span>
</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">плагин</li>
</ul>
<p class="mp-card__desc">Две клетки, высота 400px.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3" data-mp-cells-sm="2" data-mp-cells-xs="1">
<a class="mp-card mp-card--link mp-card--compact" href="#" aria-label="[3→2→1] · compact · ссылка">
<div class="mp-card__body">
<h3 class="mp-card__title">
[3→2→1] · compact · ссылка
<span class="mp-card__ext" aria-hidden="true"></span>
</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">плагин</li>
</ul>
<p class="mp-card__desc">3 → 2 → 1. data-mp-cells-sm="2" data-mp-cells-xs="1". Авто-высота.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3" data-mp-cells-sm="2" data-mp-cells-xs="1">
<a class="mp-card mp-card--link mp-card--compact" href="#" aria-label="[3→2→1] · compact · ссылка">
<div class="mp-card__body">
<h3 class="mp-card__title">
[3→2→1] · compact · ссылка
<span class="mp-card__ext" aria-hidden="true"></span>
</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">документ</li>
</ul>
<p class="mp-card__desc">3 → 2 → 1. data-mp-cells-sm="2" data-mp-cells-xs="1".</p>
</div>
</a>
</li>
</ol>
</div>
</section>
</main>
<section class="section section--surface" aria-hidden="true">
+160 -136
View File
@@ -36,6 +36,30 @@
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
@@ -271,140 +295,140 @@
</div>
</main>
<section id="projects" class="section section--surface">
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
<section id="projects" class="section section--surface" data-reveal>
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
</section><section hidden class="section section--surface" aria-hidden="true">
<div class="section__inner">
<div class="projects__heading">
@@ -624,14 +648,14 @@
</div>
</section>
<section id="contact" class="section section--surface section--footerish">
<section id="contact" class="section section--surface section--footerish" data-reveal>
<div class="section__inner">
<h2 class="section__title">Контакты</h2>
<ul class="contact-grid">
<li><a class="contact-card contact-card--link contact-card--brand-tg" href="https://t.me/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/tg.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Telegram</span><span class="contact-card__hint">Отвечу сегодня</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-vk" href="https://vk.com/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/vk.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">ВКонтакте</span><span class="contact-card__hint">Стабильный коннект</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-ya" href="https://yandex.ru/chat/p/727e71fa-89b5-44a8-90a5-851021631a1c?utm_source=invite" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/yandex_telemost.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Яндекс</span><span class="contact-card__hint">Да, тут тоже можно</span></span></a></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5ydQ==" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5zaXRl" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
</ul>
</div>
</section>
+311 -287
View File
@@ -1,13 +1,13 @@
<!DOCTYPE html>
<html lang="ru" data-theme="dark" data-radius="medium" data-font="merriweather">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta
name="description"
content="Кейс: плагин колоночного вида для Obsidian — дизайн и UX плагина для заметок."
/>
<title>Колоночный вид для Obsidian — кейс</title>
<!DOCTYPE html>
<html lang="ru" data-theme="dark" data-radius="medium" data-font="merriweather">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta
name="description"
content="Кейс: плагин колоночного вида для Obsidian — дизайн и UX плагина для заметок."
/>
<title>Колоночный вид для Obsidian — кейс</title>
<script>
(function () {
var FONT_CSS = {
@@ -36,6 +36,30 @@
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
@@ -77,81 +101,81 @@
<script src="../js/skill-connectors.js" defer></script>
<script type="module" src="../js/main.js"></script>
<link rel="stylesheet" href="../vendor/plyr/plyr.css" />
<style>
.case-article {
max-width: 48rem;
margin: 0 auto;
}
.case-article h2 {
margin: 2rem 0 0.75rem;
font-size: clamp(1.15rem, 2vw, 1.35rem);
font-weight: 700;
color: var(--text);
}
.case-article h3 {
font-size: 1.05rem;
font-weight: 600;
color: var(--text);
}
.case-article .section__prose {
margin-bottom: 0.75rem;
color: var(--text);
}
.case-article a:not(.btn) {
color: var(--accent);
}
</style>
<script>
(function () {
try {
var t = JSON.parse(localStorage.getItem("siteThemeV1") || "{}");
var d = document.documentElement;
var m = t.mode;
if (m !== "light" && m !== "dark" && m !== "system") m = "system";
var eff =
m === "system"
? window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light"
: m;
d.dataset.theme = eff;
var h = typeof t.h === "number" ? t.h : typeof t.hue === "number" ? t.hue : null;
var s = typeof t.s === "number" ? t.s : typeof t.sat === "number" ? t.sat : null;
var l = typeof t.l === "number" ? t.l : typeof t.light === "number" ? t.light : null;
if (h !== null) d.style.setProperty("--theme-h", String(h));
if (s !== null) d.style.setProperty("--theme-s", String(s));
if (l !== null) {
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
} else {
d.dataset.radius = "medium";
}
var f = t.font;
if (f === "onest") f = "geologica";
if (f === "anonymous") f = "mono";
if (f === "merriweather" || f === "mono" || f === "geologica") {
d.dataset.font = f;
} else {
d.dataset.font = "merriweather";
}
var mb = t.meshBg;
if (mb === "off") {
d.dataset.meshBg = "off";
} else {
d.dataset.meshBg = "on";
}
} catch (e) {}
})();
</script>
</head>
<body>
<style>
.case-article {
max-width: 48rem;
margin: 0 auto;
}
.case-article h2 {
margin: 2rem 0 0.75rem;
font-size: clamp(1.15rem, 2vw, 1.35rem);
font-weight: 700;
color: var(--text);
}
.case-article h3 {
font-size: 1.05rem;
font-weight: 600;
color: var(--text);
}
.case-article .section__prose {
margin-bottom: 0.75rem;
color: var(--text);
}
.case-article a:not(.btn) {
color: var(--accent);
}
</style>
<script>
(function () {
try {
var t = JSON.parse(localStorage.getItem("siteThemeV1") || "{}");
var d = document.documentElement;
var m = t.mode;
if (m !== "light" && m !== "dark" && m !== "system") m = "system";
var eff =
m === "system"
? window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light"
: m;
d.dataset.theme = eff;
var h = typeof t.h === "number" ? t.h : typeof t.hue === "number" ? t.hue : null;
var s = typeof t.s === "number" ? t.s : typeof t.sat === "number" ? t.sat : null;
var l = typeof t.l === "number" ? t.l : typeof t.light === "number" ? t.light : null;
if (h !== null) d.style.setProperty("--theme-h", String(h));
if (s !== null) d.style.setProperty("--theme-s", String(s));
if (l !== null) {
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
} else {
d.dataset.radius = "medium";
}
var f = t.font;
if (f === "onest") f = "geologica";
if (f === "anonymous") f = "mono";
if (f === "merriweather" || f === "mono" || f === "geologica") {
d.dataset.font = f;
} else {
d.dataset.font = "merriweather";
}
var mb = t.meshBg;
if (mb === "off") {
d.dataset.meshBg = "off";
} else {
d.dataset.meshBg = "on";
}
} catch (e) {}
})();
</script>
</head>
<body>
<a class="skip-link" href="#case-main">К содержимому кейса</a>
<header class="header" data-theme-picker>
<div class="header__inner">
@@ -164,7 +188,7 @@
</div>
</div>
</header>
<div class="fab-stack" aria-label="Быстрые действия">
<div class="theme-panel-fab-wrap">
<button type="button" class="fab fab--secondary glass-neutral" data-theme-panel-btn aria-expanded="false" aria-controls="theme-panel" aria-label="Настройки стиля">
@@ -248,197 +272,197 @@
</button>
</div>
<main id="case-main" class="section section--tight">
<div class="section__inner case-article">
<p class="hero__eyebrow">Obsidian · Plugin</p>
<h1 class="case-page__h1">Колоночный вид — плагин для Obsidian</h1>
<p class="case-page__sub">Дизайн и разработка интерфейса для многоколоночной работы с заметками</p>
<p class="section__prose">
<!-- Здесь будет введение -->
</p>
<h2 id="context">Контекст</h2>
<p class="section__prose">
<!-- Контекст проекта -->
</p>
<h2 id="task">Задача</h2>
<p class="section__prose">
<!-- Описание задачи -->
</p>
<h2 id="solution">Решение</h2>
<p class="section__prose">
<!-- Что было сделано -->
</p>
<h3>Фильтр использования</h3>
<figure class="case-media">
<div class="case-video-shell">
<video controls preload="metadata" playsinline poster="../assets/obsidian-plugin-columns-view/filter use.webp" data-case-video-player style="display: block; width: 100%; height: auto">
<source src="../assets/obsidian-plugin-columns-view/filter use.webm" type="video/webm" />
<source src="../assets/obsidian-plugin-columns-view/filter use.mp4" type="video/mp4" />
Ваш браузер не поддерживает видео.
</video>
</div>
<figcaption>Фильтрация заметок в колоночном виде.</figcaption>
</figure>
<h3>Конфигурация отображения</h3>
<figure class="case-media">
<div class="case-video-shell">
<video controls preload="metadata" playsinline poster="../assets/obsidian-plugin-columns-view/view configure.webp" data-case-video-player style="display: block; width: 100%; height: auto">
<source src="../assets/obsidian-plugin-columns-view/view configure.webm" type="video/webm" />
<source src="../assets/obsidian-plugin-columns-view/view configure.mp4" type="video/mp4" />
Ваш браузер не поддерживает видео.
</video>
</div>
<figcaption>Настройка колонок и отображения.</figcaption>
</figure>
<h2 id="result">Результат</h2>
<p class="section__prose">
<!-- Итоги -->
</p>
</div>
</main>
<section id="projects" class="section section--surface">
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
<main id="case-main" class="section section--tight">
<div class="section__inner case-article">
<p class="hero__eyebrow">Obsidian · Plugin</p>
<h1 class="case-page__h1">Колоночный вид — плагин для Obsidian</h1>
<p class="case-page__sub">Дизайн и разработка интерфейса для многоколоночной работы с заметками</p>
<p class="section__prose">
<!-- Здесь будет введение -->
</p>
<h2 id="context">Контекст</h2>
<p class="section__prose">
<!-- Контекст проекта -->
</p>
<h2 id="task">Задача</h2>
<p class="section__prose">
<!-- Описание задачи -->
</p>
<h2 id="solution">Решение</h2>
<p class="section__prose">
<!-- Что было сделано -->
</p>
<h3>Фильтр использования</h3>
<figure class="case-media">
<div class="case-video-shell">
<video controls preload="metadata" playsinline poster="../assets/obsidian-plugin-columns-view/filter use.webp" data-case-video-player style="display: block; width: 100%; height: auto">
<source src="../assets/obsidian-plugin-columns-view/filter use.webm" type="video/webm" />
<source src="../assets/obsidian-plugin-columns-view/filter use.mp4" type="video/mp4" />
Ваш браузер не поддерживает видео.
</video>
</div>
<figcaption>Фильтрация заметок в колоночном виде.</figcaption>
</figure>
<h3>Конфигурация отображения</h3>
<figure class="case-media">
<div class="case-video-shell">
<video controls preload="metadata" playsinline poster="../assets/obsidian-plugin-columns-view/view configure.webp" data-case-video-player style="display: block; width: 100%; height: auto">
<source src="../assets/obsidian-plugin-columns-view/view configure.webm" type="video/webm" />
<source src="../assets/obsidian-plugin-columns-view/view configure.mp4" type="video/mp4" />
Ваш браузер не поддерживает видео.
</video>
</div>
<figcaption>Настройка колонок и отображения.</figcaption>
</figure>
<h2 id="result">Результат</h2>
<p class="section__prose">
<!-- Итоги -->
</p>
</div>
</main>
<section id="projects" class="section section--surface" data-reveal>
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
</section><section hidden class="section section--surface" aria-hidden="true">
<div class="section__inner">
<div class="projects__heading">
@@ -657,23 +681,23 @@
</div>
</div>
</section>
<section id="contact" class="section section--surface section--footerish">
<section id="contact" class="section section--surface section--footerish" data-reveal>
<div class="section__inner">
<h2 class="section__title">Контакты</h2>
<ul class="contact-grid">
<li><a class="contact-card contact-card--link contact-card--brand-tg" href="https://t.me/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/tg.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Telegram</span><span class="contact-card__hint">Отвечу сегодня</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-vk" href="https://vk.com/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/vk.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">ВКонтакте</span><span class="contact-card__hint">Стабильный коннект</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-ya" href="https://yandex.ru/chat/p/727e71fa-89b5-44a8-90a5-851021631a1c?utm_source=invite" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/yandex_telemost.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Яндекс</span><span class="contact-card__hint">Да, тут тоже можно</span></span></a></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5ydQ==" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5zaXRl" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
</ul>
</div>
</section>
<section class="section section--surface" aria-hidden="true">
<div class="section__inner"></div>
</section>
<footer class="footer">
<div class="footer__inner">
<span class="footer__chunk footer__chunk--date">© 2026<span class="footer__sep" aria-hidden="true"> · </span></span>
@@ -681,7 +705,7 @@
<span class="footer__chunk footer__chunk--meta footer__attr"><span class="footer__sep" aria-hidden="true"> · </span><a href="../cases/design-system.html">Design System</a><span class="footer__sep" aria-hidden="true"> · </span><a href="../cookie-policy.html">Политика cookie</a></span>
</div>
</footer>
<aside class="cookie-notice glass-neutral" hidden data-cookie-notice>
<p class="cookie-notice__text">
Сайт использует cookie для комфортной работы. Подробнее — в
@@ -694,9 +718,9 @@
</span>
</button>
</aside>
<div id="nav-more-menu-floating" class="nav-more__floating" hidden data-nav-more-menu-floating aria-hidden="true"></div>
</body>
</html>
</body>
</html>
+160 -136
View File
@@ -36,6 +36,30 @@
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
@@ -410,140 +434,140 @@
</div>
</main>
<section id="projects" class="section section--surface">
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
<section id="projects" class="section section--surface" data-reveal>
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
</section><section hidden class="section section--surface" aria-hidden="true">
<div class="section__inner">
<div class="projects__heading">
@@ -763,14 +787,14 @@
</div>
</section>
<section id="contact" class="section section--surface section--footerish">
<section id="contact" class="section section--surface section--footerish" data-reveal>
<div class="section__inner">
<h2 class="section__title">Контакты</h2>
<ul class="contact-grid">
<li><a class="contact-card contact-card--link contact-card--brand-tg" href="https://t.me/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/tg.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Telegram</span><span class="contact-card__hint">Отвечу сегодня</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-vk" href="https://vk.com/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/vk.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">ВКонтакте</span><span class="contact-card__hint">Стабильный коннект</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-ya" href="https://yandex.ru/chat/p/727e71fa-89b5-44a8-90a5-851021631a1c?utm_source=invite" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/yandex_telemost.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Яндекс</span><span class="contact-card__hint">Да, тут тоже можно</span></span></a></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5ydQ==" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5zaXRl" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
</ul>
</div>
</section>
+160 -136
View File
@@ -36,6 +36,30 @@
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
@@ -271,140 +295,140 @@
</div>
</main>
<section id="projects" class="section section--surface">
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
<section id="projects" class="section section--surface" data-reveal>
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
</section><section hidden class="section section--surface" aria-hidden="true">
<div class="section__inner">
<div class="projects__heading">
@@ -624,14 +648,14 @@
</div>
</section>
<section id="contact" class="section section--surface section--footerish">
<section id="contact" class="section section--surface section--footerish" data-reveal>
<div class="section__inner">
<h2 class="section__title">Контакты</h2>
<ul class="contact-grid">
<li><a class="contact-card contact-card--link contact-card--brand-tg" href="https://t.me/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/tg.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Telegram</span><span class="contact-card__hint">Отвечу сегодня</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-vk" href="https://vk.com/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/vk.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">ВКонтакте</span><span class="contact-card__hint">Стабильный коннект</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-ya" href="https://yandex.ru/chat/p/727e71fa-89b5-44a8-90a5-851021631a1c?utm_source=invite" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/yandex_telemost.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Яндекс</span><span class="contact-card__hint">Да, тут тоже можно</span></span></a></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5ydQ==" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5zaXRl" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
</ul>
</div>
</section>
+160 -136
View File
@@ -36,6 +36,30 @@
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
@@ -699,140 +723,140 @@
</div>
</main>
<section id="projects" class="section section--surface">
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
<section id="projects" class="section section--surface" data-reveal>
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
</section><section hidden class="section section--surface" aria-hidden="true">
<div class="section__inner">
<div class="projects__heading">
@@ -1052,14 +1076,14 @@
</div>
</section>
<section id="contact" class="section section--surface section--footerish">
<section id="contact" class="section section--surface section--footerish" data-reveal>
<div class="section__inner">
<h2 class="section__title">Контакты</h2>
<ul class="contact-grid">
<li><a class="contact-card contact-card--link contact-card--brand-tg" href="https://t.me/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/tg.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Telegram</span><span class="contact-card__hint">Отвечу сегодня</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-vk" href="https://vk.com/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/vk.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">ВКонтакте</span><span class="contact-card__hint">Стабильный коннект</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-ya" href="https://yandex.ru/chat/p/727e71fa-89b5-44a8-90a5-851021631a1c?utm_source=invite" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/yandex_telemost.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Яндекс</span><span class="contact-card__hint">Да, тут тоже можно</span></span></a></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5ydQ==" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5zaXRl" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
</ul>
</div>
</section>
+160 -136
View File
@@ -33,6 +33,30 @@
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
@@ -433,140 +457,140 @@
</div>
</main>
<section id="projects" class="section section--surface">
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
<section id="projects" class="section section--surface" data-reveal>
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="ai-platform-primo-rpa.html" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/ai-platform-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Платформа для работы с AI</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями автоматизации и Smart OCR.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3">
<a class="mp-card mp-card--link mp-card--stack" href="lunacy.html" aria-label="Графический редактор Lunacy — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Графический редактор Lunacy</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и интерфейсной логики.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="manu-game-maker.html" aria-label="Игровой движок MANU — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Игровой движок MANU</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Desktop App</li>
</ul>
<p class="mp-card__desc">Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и проработка сотен сложных пользовательских сценариев.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--stack" href="mobile-clinic-app.html" aria-label="Мобильное приложение для сети клиник — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Мобильное приложение для сети клиник</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Mobile App</li>
</ul>
<p class="mp-card__desc">Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом пользовательском пути, понятной навигации и быстром доступе к нужным действиям.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="orc-automation-panel.html" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Веб-панель для оркестрации автоматизаций</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-distribution-concept.html" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Концепт сервиса распределения задач</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">UX/UI</li>
<li class="mp-card__tag">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2">
<a class="mp-card mp-card--link mp-card--compact" href="task-tracker.html" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__body">
<h3 class="mp-card__title">Таск-трекер для бек-офис системы</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Product Design</li>
<li class="mp-card__tag">Web App</li>
</ul>
<p class="mp-card__desc">Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по исполнителям; вкладки, фильтры, доска / список / таблица, Drag&amp;Drop.</p>
</div>
</a>
</li>
</ol>
</div>
</section><section hidden class="section section--surface" aria-hidden="true">
<div class="section__inner">
<div class="projects__heading">
@@ -811,14 +835,14 @@
</div>
</section>
<section id="contact" class="section section--surface section--footerish">
<section id="contact" class="section section--surface section--footerish" data-reveal>
<div class="section__inner">
<h2 class="section__title">Контакты</h2>
<ul class="contact-grid">
<li><a class="contact-card contact-card--link contact-card--brand-tg" href="https://t.me/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/tg.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Telegram</span><span class="contact-card__hint">Отвечу сегодня</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-vk" href="https://vk.com/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/vk.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">ВКонтакте</span><span class="contact-card__hint">Стабильный коннект</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-ya" href="https://yandex.ru/chat/p/727e71fa-89b5-44a8-90a5-851021631a1c?utm_source=invite" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="../assets/shared/icons/yandex_telemost.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Яндекс</span><span class="contact-card__hint">Да, тут тоже можно</span></span></a></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5ydQ==" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5zaXRl" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
</ul>
</div>
</section>
+24
View File
@@ -36,6 +36,30 @@
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
+90 -3
View File
@@ -954,6 +954,41 @@ a.fab--secondary:visited {
outline-offset: 2px;
}
/* ── PDF download FAB ── */
.fab-primary__ico--pdf {
mask-image: url("../assets/shared/icons/cv.svg");
-webkit-mask-image: url("../assets/shared/icons/cv.svg");
}
/* ── Print FAB ── */
.fab-secondary__ico--print {
display: block;
width: var(--icon-fab);
height: var(--icon-fab);
background: currentColor;
mask-image: url("../assets/shared/icons/printer.svg");
-webkit-mask-image: url("../assets/shared/icons/printer.svg");
mask-size: contain;
mask-repeat: no-repeat;
mask-position: center;
-webkit-mask-size: contain;
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
}
.fab--label {
width: auto;
padding: 0.65rem 1.1rem;
gap: 0.5rem;
}
.fab__label {
font-size: 0.85rem;
font-weight: 600;
line-height: 1;
white-space: nowrap;
}
.theme-picker__stack {
display: flex;
flex-direction: column;
@@ -1289,7 +1324,7 @@ html[data-font="mono"] .hero__title {
.case-page__h1 {
margin: 0 0 0.5rem;
font-family: var(--font-accent);
font-size: clamp(1.35rem, 2.6vw, 1.95rem);
font-size: clamp(2rem, 3.9vw, 2.9rem);
font-weight: 700;
line-height: 1.2;
color: var(--text);
@@ -1320,7 +1355,7 @@ html[data-font="mono"] .hero__title {
.case-page__sub {
margin: 0 0 1.25rem;
font-size: clamp(1rem, 1.35vw, 1.1rem);
font-size: clamp(1.5rem, 2vw, 1.65rem);
color: var(--text-muted);
font-weight: 500;
}
@@ -2728,6 +2763,50 @@ html[data-theme="light"] .hero__portrait-shell {
color: var(--text-muted);
}
/* Scroll-reveal: плавное появление секций при скролле */
[data-reveal] {
opacity: 0;
transform: translateY(80px);
transition: opacity 0.4s ease-out, transform 0.6s ease-out;
}
[data-reveal].is-visible {
opacity: 1;
transform: translateY(0);
}
/* Stagger: заголовок появляется первым, контент — через 100ms */
[data-reveal].is-visible .section__title {
transition-delay: 0.1s;
}
[data-reveal].is-visible .section__inner > *:not(.section__title) {
transition-delay: 0.25s;
}
/* Исключаем skills и mini-projects — у них своя stagger-анимация */
#skills[data-reveal].is-visible .section__title,
#mini-projects[data-reveal].is-visible .section__title {
transition-delay: 0s;
}
#skills[data-reveal].is-visible .section__inner > *:not(.section__title),
#mini-projects[data-reveal].is-visible .section__inner > *:not(.section__title) {
transition-delay: 0s;
}
@media (prefers-reduced-motion: reduce) {
[data-reveal] {
opacity: 1;
transform: none;
transition: none;
}
[data-reveal].is-visible .section__title,
[data-reveal].is-visible .section__inner > *:not(.section__title) {
transition-delay: 0s;
}
}
.experience-grid {
list-style: none;
margin: 0;
@@ -2972,6 +3051,7 @@ html[data-theme="light"] .hero__portrait-shell {
overflow: hidden;
width: 100%;
min-height: 100%;
height: 100%;
border: 1px solid var(--line);
border-radius: var(--radius-card);
background: var(--surface);
@@ -3001,6 +3081,7 @@ html[data-theme="light"] .hero__portrait-shell {
flex-direction: column;
gap: 0.5rem;
min-width: 0;
overflow: hidden;
}
.mp-card__title {
@@ -3015,6 +3096,7 @@ html[data-theme="light"] .hero__portrait-shell {
align-items: center;
flex-wrap: wrap;
gap: 0.35rem 0.45rem;
min-width: 0;
}
.mp-card__desc {
@@ -3022,6 +3104,10 @@ html[data-theme="light"] .hero__portrait-shell {
font-size: 0.88rem;
line-height: 1.45;
color: var(--text-muted);
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.mp-card__tags {
@@ -3054,7 +3140,7 @@ html[data-theme="light"] .hero__portrait-shell {
display: flex;
align-items: center;
justify-content: center;
overflow: visible;
overflow: hidden;
background: transparent;
box-sizing: border-box;
}
@@ -3084,6 +3170,7 @@ html[data-theme="light"] .hero__portrait-shell {
.mp-card--stack .mp-card__media {
width: 100%;
flex-shrink: 0;
padding: 1.2rem 1.35rem 0;
}
+59 -48
View File
@@ -36,6 +36,30 @@
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
@@ -213,7 +237,7 @@
<div class="hero__actions">
<a class="btn btn--primary btn--flat" href="#contact"><span class="btn__icon" aria-hidden="true"></span><span>Написать мне</span></a>
<a class="btn btn--secondary btn--flat" href="#projects"><span class="btn__icon" aria-hidden="true"></span><span>Смотреть портфолио</span></a>
<a class="btn btn--secondary btn--flat btn--resume" href="assets/mamadaevv_resume.pdf" download><span class="btn__icon" aria-hidden="true"></span><span>Резюме</span></a>
<a class="btn btn--secondary btn--flat btn--resume" href="resume-5.html"><span class="btn__icon" aria-hidden="true"></span><span>Резюме</span></a>
</div>
</div>
<div class="hero__visual" aria-hidden="true">
@@ -253,7 +277,7 @@
</div>
</section>
<section id="projects" class="section section--surface">
<section id="projects" class="section section--surface" data-reveal>
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
@@ -631,7 +655,7 @@
</div>
</section>
<section id="mini-projects" class="section section--surface" aria-labelledby="mini-projects-title">
<section id="mini-projects" class="section section--surface" aria-labelledby="mini-projects-title" data-reveal>
<div class="section__inner">
<h2 id="mini-projects-title" class="section__title">Активность</h2>
<div
@@ -746,7 +770,7 @@
</section>
<section id="skills" class="section section--tight" aria-labelledby="skills-title">
<section id="skills" class="section section--tight" aria-labelledby="skills-title" data-reveal>
<div class="section__inner">
<h2 id="skills-title" class="section__title">Навыки</h2>
<div
@@ -1044,30 +1068,17 @@
</div>
</section>
<section id="experience" class="section section--surface" aria-labelledby="experience-title">
<section id="experience" class="section section--surface" aria-labelledby="experience-title" data-reveal>
<div class="section__inner">
<h2 id="experience-title" class="section__title">Опыт работы</h2>
<ol id="experience-list" class="experience-grid">
<li class="experience-grid__item">
<div class="exp-card" data-exp-order="1">
<div class="exp-card__time-row">
<span class="exp-card__period">Январь 2026 — Настоящее время</span>
</div>
<h3 class="exp-card__company">
Астратек
</h3>
<p class="exp-card__desc">
Разработка и поддержка цифровых систем и инструментов для повышения эффективности сотрудников.
</p>
</div>
</li>
<li class="experience-grid__item">
<a
class="exp-card exp-card--link"
href="https://primo-rpa.com/"
target="_blank"
rel="noopener noreferrer"
data-exp-order="2"
data-exp-order="1"
aria-label="Primo RPA — открыть сайт компании"
>
<div class="exp-card__time-row">
@@ -1090,7 +1101,7 @@
href="https://icons8.com/lunacy"
target="_blank"
rel="noopener noreferrer"
data-exp-order="3"
data-exp-order="2"
aria-label="Icons8 (Lunacy) — открыть сайт компании"
>
<div class="exp-card__time-row">
@@ -1113,7 +1124,7 @@
href="https://manu.co/"
target="_blank"
rel="noopener noreferrer"
data-exp-order="4"
data-exp-order="3"
aria-label="MANU Video Game Maker — открыть сайт компании"
>
<div class="exp-card__time-row">
@@ -1130,13 +1141,36 @@
</p>
</a>
</li>
<li class="experience-grid__item" data-exp-extra hidden>
<a
class="exp-card exp-card--link"
href="https://aegees.com/"
target="_blank"
rel="noopener noreferrer"
data-exp-order="4"
aria-label="AEGEES — открыть сайт компании"
>
<div class="exp-card__time-row">
<span class="exp-card__period">Октябрь 2017 — Декабрь 2018</span>
<span class="exp-card__sep" aria-hidden="true">·</span>
<span class="exp-card__duration">1 год 3 месяца</span>
</div>
<h3 class="exp-card__company">
AEGEES
<span class="exp-card__ext" aria-hidden="true"></span>
</h3>
<p class="exp-card__desc">
Защищённый мессенджер с end‑to‑end шифрованием и отсутствием хранения сообщений на серверах, сфокусированный на максимальной приватности пользователей.
</p>
</a>
</li>
<li class="experience-grid__item" data-exp-extra hidden>
<a
class="exp-card exp-card--link"
href="https://www.orioninnovation.com/"
target="_blank"
rel="noopener noreferrer"
data-exp-order="6"
data-exp-order="5"
aria-label="Orion Innovation (ex MERA) — открыть сайт компании"
>
<div class="exp-card__time-row">
@@ -1153,36 +1187,13 @@
</p>
</a>
</li>
<li class="experience-grid__item" data-exp-extra hidden>
<a
class="exp-card exp-card--link"
href="https://aegees.com/"
target="_blank"
rel="noopener noreferrer"
data-exp-order="5"
aria-label="Aegees — открыть сайт компании"
>
<div class="exp-card__time-row">
<span class="exp-card__period">Октябрь 2017 — Декабрь 2018</span>
<span class="exp-card__sep" aria-hidden="true">·</span>
<span class="exp-card__duration">1 год 3 месяца</span>
</div>
<h3 class="exp-card__company">
Aegees
<span class="exp-card__ext" aria-hidden="true"></span>
</h3>
<p class="exp-card__desc">
Защищённый мессенджер с end‑to‑end шифрованием и отсутствием хранения сообщений на серверах, сфокусированный на максимальной приватности пользователей.
</p>
</a>
</li>
<li class="experience-grid__item" data-exp-extra hidden>
<a
class="exp-card exp-card--link"
href="https://spaceshipapps.ru/"
target="_blank"
rel="noopener noreferrer"
data-exp-order="7"
data-exp-order="6"
aria-label="SpaceshipApps — открыть сайт компании"
>
<div class="exp-card__time-row">
@@ -1214,14 +1225,14 @@
</div>
</section>
<section id="contact" class="section section--surface section--footerish">
<section id="contact" class="section section--surface section--footerish" data-reveal>
<div class="section__inner">
<h2 class="section__title">Контакты</h2>
<ul class="contact-grid">
<li><a class="contact-card contact-card--link contact-card--brand-tg" href="https://t.me/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="assets/shared/icons/tg.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Telegram</span><span class="contact-card__hint">Отвечу сегодня</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-vk" href="https://vk.com/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="assets/shared/icons/vk.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">ВКонтакте</span><span class="contact-card__hint">Стабильный коннект</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-ya" href="https://yandex.ru/chat/p/727e71fa-89b5-44a8-90a5-851021631a1c?utm_source=invite" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="assets/shared/icons/yandex_telemost.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Яндекс</span><span class="contact-card__hint">Да, тут тоже можно</span></span></a></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5ydQ==" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5zaXRl" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
</ul>
</div>
</section>
+2
View File
@@ -25,6 +25,7 @@ import { initSkillsIntroMessages } from "./modules/ui/skills-intro.js";
import { initContentEditMode } from "./modules/ui/content-edit/content-edit-mode.js";
import { initDeferredPortfolioCovers } from "./modules/ui/deferred-media.js";
import { initImageLoadPlaceholder } from "./modules/ui/image-load-placeholder.js";
import { initScrollReveal } from "./modules/ui/scroll-reveal.js";
ensureThemeFontLoaded(readThemeState().font);
@@ -53,3 +54,4 @@ initCaseTallMediaExpand();
initCaseImageViewer();
initCaseVideoPlayers();
initContentEditMode();
initScrollReveal();
+32 -6
View File
@@ -26,11 +26,23 @@ function initMiniProjectsMasonryList(list) {
return 1;
}
function readDeclaredCells(el) {
const raw = el.getAttribute("data-mp-cells");
const n = raw == null ? 1 : Number.parseInt(String(raw), 10);
if (!Number.isFinite(n)) return 1;
return Math.min(3, Math.max(1, n));
function readDeclaredCells(el, rowCells) {
const full = Number.parseInt(String(el.getAttribute("data-mp-cells")), 10) || 1;
if (rowCells <= 2) {
const xs = el.getAttribute("data-mp-cells-xs");
if (xs != null) {
const n = Number.parseInt(String(xs), 10);
if (Number.isFinite(n)) return Math.min(Math.max(n, 1), rowCells);
}
}
if (rowCells <= 4) {
const sm = el.getAttribute("data-mp-cells-sm");
if (sm != null) {
const n = Number.parseInt(String(sm), 10);
if (Number.isFinite(n)) return Math.min(Math.max(n, 1), rowCells);
}
}
return Math.min(Math.max(full, 1), rowCells);
}
function pickStartColumn(heights, rowCells, wCells) {
@@ -91,7 +103,21 @@ function initMiniProjectsMasonryList(list) {
const positions = new Map();
allItems.forEach((item) => {
const want = readDeclaredCells(item);
const want = readDeclaredCells(item, rowCells);
let hVal = 0;
if (rowCells <= 2) {
const xs = item.getAttribute("data-mp-height-xs");
if (xs != null) hVal = Number.parseInt(xs, 10) || 0;
}
if (!hVal && rowCells <= 4) {
const sm = item.getAttribute("data-mp-height-sm");
if (sm != null) hVal = Number.parseInt(sm, 10) || 0;
}
if (!hVal) {
const hAttr = item.getAttribute("data-mp-height");
if (hAttr) hVal = Number.parseInt(hAttr, 10) || 0;
}
item.style.height = hVal > 0 ? `${hVal}px` : "";
const wCells = Math.min(want, rowCells);
const c = pickStartColumn(heights, rowCells, wCells);
let y = 0;
+27
View File
@@ -0,0 +1,27 @@
import { prefersReducedMotion } from "../shared/media.js";
const THRESHOLD = 0.15;
const ROOT_MARGIN = "0px 0px -120px 0px";
export function initScrollReveal() {
const targets = document.querySelectorAll("[data-reveal]");
if (!targets.length) return;
if (prefersReducedMotion()) {
targets.forEach((el) => el.classList.add("is-visible"));
return;
}
const obs = new IntersectionObserver(
(entries) => {
for (const e of entries) {
if (!e.isIntersecting) continue;
e.target.classList.add("is-visible");
obs.unobserve(e.target);
}
},
{ threshold: THRESHOLD, rootMargin: ROOT_MARGIN },
);
targets.forEach((el) => obs.observe(el));
}
+651
View File
@@ -0,0 +1,651 @@
<!DOCTYPE html>
<html lang="ru" data-theme="dark" data-radius="medium">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta
name="description"
content="Резюме Николая Мамадаева — продуктовый дизайнер с опытом более 10 лет."
/>
<title>Резюме 2 — Николай Мамадаев</title>
<script>
(function () {
var FONT_CSS = {
merriweather: "assets/fonts/merriweather.css",
geologica: "assets/fonts/geologica.css",
mono: "assets/fonts/mono.css",
};
try {
var t = JSON.parse(localStorage.getItem("siteThemeV1") || "{}");
var d = document.documentElement;
var m = t.mode;
if (m !== "light" && m !== "dark" && m !== "system") m = "system";
var eff =
m === "system"
? window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light"
: m;
d.dataset.theme = eff;
var h = typeof t.h === "number" ? t.h : typeof t.hue === "number" ? t.hue : null;
var s = typeof t.s === "number" ? t.s : typeof t.sat === "number" ? t.sat : null;
var l = typeof t.l === "number" ? t.l : typeof t.light === "number" ? t.light : null;
if (h !== null) d.style.setProperty("--theme-h", String(h));
if (s !== null) d.style.setProperty("--theme-s", String(s));
if (l !== null) {
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
} else {
d.dataset.radius = "medium";
}
var f = t.font;
if (f === "onest") f = "geologica";
if (f === "anonymous") f = "mono";
if (f !== "merriweather" && f !== "mono" && f !== "geologica") f = "merriweather";
d.dataset.font = f;
var mb = t.meshBg;
if (mb === "off") {
d.dataset.meshBg = "off";
} else {
d.dataset.meshBg = "on";
}
var href = FONT_CSS[f];
if (href && !document.querySelector('link[data-theme-font="' + f + '"]')) {
var link = document.createElement("link");
link.rel = "stylesheet";
link.href = href;
link.setAttribute("data-theme-font", f);
document.head.appendChild(link);
}
} catch (e) {}
})();
</script>
<link rel="icon" type="image/png" sizes="32x32" href="assets/favicon/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="assets/favicon/favicon-16x16.png" />
<link rel="apple-touch-icon" sizes="180x180" href="assets/favicon/apple-touch-icon.png" />
<link rel="manifest" href="assets/favicon/site.webmanifest" />
<link rel="preload" href="assets/fonts/merriweather.css" as="style" />
<link rel="preload" href="css/main.css" as="style" />
<link rel="preload" href="js/skill-connectors.js" as="script" />
<link rel="modulepreload" href="js/main.js" />
<link rel="stylesheet" href="css/main.css" />
<script src="js/skill-connectors.js" defer></script>
<script type="module" src="js/main.js"></script>
<style>
.resume-doc {
max-width: 48rem;
margin: 0 auto;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--radius-card);
padding: clamp(1.5rem, 3vw, 2.5rem);
}
.resume-header {
display: flex;
gap: 1.5rem;
align-items: flex-start;
margin-bottom: 1.5rem;
flex-direction: row-reverse;
justify-content: flex-end;
}
.resume-photo {
width: 120px;
height: 120px;
border-radius: var(--radius-sm);
object-fit: cover;
border: 2px solid var(--line);
flex-shrink: 0;
}
@media (max-width: 32rem) {
.resume-header {
flex-direction: column;
align-items: center;
text-align: center;
}
.resume-photo {
width: 100px;
height: 100px;
}
}
.resume-doc h2 {
margin: 2rem 0 0.75rem;
font-size: clamp(1.15rem, 2vw, 1.35rem);
font-weight: 700;
color: var(--text);
}
.resume-doc .section__prose + .section__prose {
margin-top: 0.75rem;
}
.resume-doc .section__prose a {
color: var(--accent);
}
.resume-contacts {
display: flex;
flex-wrap: wrap;
gap: 0.25rem 1.5rem;
margin: 0.75rem 0 1.5rem;
font-size: 0.92rem;
color: var(--text-muted);
}
.resume-contacts span {
white-space: nowrap;
}
.resume-contacts a {
color: var(--accent);
}
.resume-meta {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem 1.5rem;
margin: 0.75rem 0 1.5rem;
font-size: 0.92rem;
color: var(--text-muted);
}
@media (max-width: 32rem) {
.resume-meta {
grid-template-columns: 1fr;
}
}
.resume-meta dt {
font-weight: 600;
color: var(--text);
}
.resume-meta dd {
margin: 0;
}
.resume-exp {
margin: 1.25rem 0;
}
.resume-exp__header {
margin-bottom: 0.5rem;
}
.resume-exp__company {
font-weight: 700;
color: var(--text);
}
.resume-exp__role {
font-style: italic;
color: var(--text-muted);
font-size: 0.92rem;
}
.resume-exp__period {
font-size: 0.85rem;
color: var(--text-muted);
margin-bottom: 0.35rem;
}
.resume-exp__desc {
color: var(--text-muted);
font-size: 0.92rem;
margin: 0.5rem 0;
}
.resume-exp ul {
margin: 0.35rem 0 0;
padding-left: 1.25rem;
color: var(--text-muted);
font-size: 0.92rem;
}
.resume-exp li + li {
margin-top: 0.25rem;
}
.resume-exp__skills {
margin-top: 0.5rem;
font-size: 0.85rem;
color: var(--text-muted);
}
.resume-exp__skills strong {
color: var(--text);
}
.resume-skills {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin: 0.75rem 0;
}
@media (max-width: 32rem) {
.resume-skills {
grid-template-columns: 1fr;
}
}
.resume-skill {
font-size: 0.92rem;
}
.resume-skill__title {
font-weight: 600;
color: var(--text);
margin-bottom: 0.15rem;
}
.resume-skill__desc {
color: var(--text-muted);
}
.resume-communities {
margin: 0.75rem 0;
}
.resume-community {
margin: 0.75rem 0;
font-size: 0.92rem;
}
.resume-community__name {
font-weight: 700;
color: var(--text);
}
.resume-community__period {
font-size: 0.85rem;
color: var(--text-muted);
}
.resume-community__desc {
color: var(--text-muted);
margin-top: 0.25rem;
}
.resume-edu {
margin: 0.5rem 0;
}
.resume-edu__school {
font-weight: 700;
color: var(--text);
}
.resume-edu__period {
font-size: 0.85rem;
color: var(--text-muted);
}
.resume-edu__spec {
font-size: 0.92rem;
color: var(--text-muted);
}
.resume-additional h3 {
margin: 1rem 0 0.35rem;
font-size: 1rem;
font-weight: 600;
color: var(--text);
}
.resume-additional ul {
margin: 0.25rem 0;
padding-left: 1.25rem;
color: var(--text-muted);
font-size: 0.92rem;
}
.resume-additional li + li {
margin-top: 0.25rem;
}
.resume-about {
margin: 1rem 0;
font-size: 0.92rem;
color: var(--text-muted);
}
</style>
</head>
<body>
<a class="skip-link" href="#main">К основному содержимому</a>
<header class="header" data-theme-picker>
<div class="header__inner">
<a class="logo" href="index.html" aria-label="На главную">НМ</a>
<div class="header__cluster">
<nav class="nav" aria-label="Навигация">
<a href="index.html">На главную</a>
</nav>
</div>
</div>
</header>
<div class="fab-stack" aria-label="Быстрые действия">
<div class="theme-panel-fab-wrap">
<button type="button" class="fab fab--secondary glass-neutral" data-theme-panel-btn aria-expanded="false" aria-controls="theme-panel" aria-label="Настройки стиля">
<span class="theme-panel-fab__icon theme-panel-fab__icon--open-hide" aria-hidden="true"></span>
<svg class="theme-panel-fab__icon theme-panel-fab__icon--close" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M6 6L18 18M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
</svg>
</button>
<div id="theme-panel" class="theme-picker__panel glass-neutral" role="dialog" aria-label="Тема и оформление" hidden data-theme-panel>
<div class="theme-picker__stack">
<section class="theme-picker__section" aria-labelledby="theme-accent-title">
<h3 id="theme-accent-title" class="theme-picker__section-title">Акцентный цвет</h3>
<div class="colorpicker" data-colorpicker>
<div class="colorpicker__plane-box">
<canvas class="colorpicker__plane" width="320" height="180" data-sl-canvas aria-label="Насыщенность и светлость акцента"></canvas>
<div class="colorpicker__knob" data-sl-knob></div>
</div>
<div class="colorpicker__hue-wrap">
<label class="colorpicker__hue-sr" for="theme-hue-slider">Оттенок акцента</label>
<input id="theme-hue-slider" class="colorpicker__hue" type="range" min="0" max="360" value="210" data-hue-slider aria-valuemin="0" aria-valuemax="360" />
</div>
</div>
</section>
<section class="theme-picker__section" aria-labelledby="theme-mode-title">
<h3 id="theme-mode-title" class="theme-picker__section-title">Тема</h3>
<div class="radius-seg theme-mode-seg" role="radiogroup" aria-labelledby="theme-mode-title">
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-theme-mode="system" aria-label="Как в системе"><span class="radius-seg__viz" aria-hidden="true"><span class="theme-mode-seg__ico theme-mode-seg__ico--system"></span></span></button>
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-theme-mode="light" aria-label="Светлая тема"><span class="radius-seg__viz" aria-hidden="true"><span class="theme-mode-seg__ico theme-mode-seg__ico--light"></span></span></button>
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-theme-mode="dark" aria-label="Тёмная тема"><span class="radius-seg__viz" aria-hidden="true"><span class="theme-mode-seg__ico theme-mode-seg__ico--dark"></span></span></button>
</div>
</section>
<section class="theme-picker__section" aria-labelledby="theme-radius-title">
<h3 id="theme-radius-title" class="theme-picker__section-title">Скругление углов</h3>
<div class="radius-seg" role="radiogroup" aria-labelledby="theme-radius-title">
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-radius-option="soft" aria-label="Слабое скругление"><span class="radius-seg__viz" aria-hidden="true"><span class="radius-seg__arc radius-seg__arc--soft"></span></span></button>
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-radius-option="medium" aria-label="Среднее скругление"><span class="radius-seg__viz" aria-hidden="true"><span class="radius-seg__arc radius-seg__arc--medium"></span></span></button>
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-radius-option="strong" aria-label="Сильное скругление"><span class="radius-seg__viz" aria-hidden="true"><span class="radius-seg__arc radius-seg__arc--strong"></span></span></button>
</div>
</section>
<section class="theme-picker__section" aria-labelledby="theme-typography-title">
<h3 id="theme-typography-title" class="theme-picker__section-title">Типографика</h3>
<div class="radius-seg" role="radiogroup" aria-labelledby="theme-typography-title">
<button type="button" class="radius-seg__btn theme-font-seg__btn" role="radio" aria-checked="false" data-font-option="geologica" aria-label="Sans"><span class="theme-font-seg__label">Sans</span></button>
<button type="button" class="radius-seg__btn theme-font-seg__btn" role="radio" aria-checked="false" data-font-option="merriweather" aria-label="Sans Serif"><span class="theme-font-seg__label">Sans Serif</span></button>
<button type="button" class="radius-seg__btn theme-font-seg__btn" role="radio" aria-checked="false" data-font-option="mono" aria-label="Mono"><span class="theme-font-seg__label">Mono</span></button>
</div>
</section>
<section class="theme-picker__section" aria-labelledby="theme-mesh-bg-title">
<h3 id="theme-mesh-bg-title" class="theme-picker__section-title">Фон страницы</h3>
<div class="radius-seg radius-seg--two" role="radiogroup" aria-labelledby="theme-mesh-bg-title">
<button type="button" class="radius-seg__btn theme-mesh-bg-seg__btn" role="radio" aria-checked="false" data-mesh-bg-option="on" aria-label="Показать фоновый градиент"><span class="theme-mesh-bg-seg__label">Вкл</span></button>
<button type="button" class="radius-seg__btn theme-mesh-bg-seg__btn" role="radio" aria-checked="false" data-mesh-bg-option="off" aria-label="Скрыть фоновый градиент"><span class="theme-mesh-bg-seg__label">Выкл</span></button>
</div>
</section>
</div>
</div>
</div>
<a class="fab fab--primary" href="index.html#contact" aria-label="Связаться">
<span class="fab-primary__ico" aria-hidden="true"></span>
</a>
</div>
<div class="content-edit-fab-stack" aria-label="Правки контента" data-content-edit-ui>
<button
type="button"
class="fab fab--secondary glass-neutral content-edit-fab"
data-content-edit-mode-toggle
hidden
aria-pressed="false"
aria-label="Режим правок контента"
title="Режим правок"
>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path
d="M4 20h4l10.5-10.5a2.12 2.12 0 0 0 0-3L16.5 4.5a2.12 2.12 0 0 0-3 0L3 15v5z"
stroke="currentColor"
stroke-width="1.75"
stroke-linejoin="round"
/>
</svg>
<span class="content-edit-fab__badge" hidden aria-hidden="true">0</span>
</button>
</div>
<main id="main" class="section section--surface section--tight">
<div class="section__inner resume-doc">
<div class="resume-header">
<img class="resume-photo" src="assets/index/me-transparentBG-1.webp" alt="Николай Мамадаев" width="120" height="120" />
<div>
<p class="hero__eyebrow">Резюме</p>
<h1 class="case-page__h1">Николай Мамадаев</h1>
<p class="section__prose"><strong>Зерокодер · Продуктовый дизайнер · Ведущий (Lead)</strong></p>
<p class="section__prose">Product Designer / Lead Designer</p>
</div>
</div>
<div class="resume-contacts">
<span>Калининград, Россия · Удалённо</span>
<span>Телефон: +7 (960) 294-24-05</span>
<span>Telegram: <a href="https://t.me/mamadaevv" target="_blank" rel="noopener">@mamadaevv</a></span>
<span>Email: <a href="mailto:nik@mamadaevv.site">nik@mamadaevv.site</a></span>
<span>Сайт: <a href="https://mamadaevv.site" target="_blank" rel="noopener">mamadaevv.site</a></span>
<span>Хабр Карьера: <a href="https://career.habr.com/mamadaevv" target="_blank" rel="noopener">career.habr.com/mamadaevv</a></span>
</div>
<dl class="resume-meta">
<div>
<dt>Стаж</dt>
<dd>10 лет</dd>
</div>
<div>
<dt>Возраст</dt>
<dd>36 лет</dd>
</div>
<div>
<dt>Готовность к работе</dt>
<dd>готов к удалённой работе</dd>
</div>
<div>
<dt>Зарплатные ожидания</dt>
<dd>от 270 000 ₽</dd>
</div>
</dl>
<h2 id="profile">О себе</h2>
<p class="section__prose resume-about">
В дизайне я более 10 лет, последние годы занимаюсь продуктовым дизайном. Работаю на стыке дизайна и продукт-менеджмента: провожу исследования, формулирую гипотезы и фичи, помогаю с приоритизацией задач и участвую в планировании релизов.
</p>
<p class="section__prose resume-about">
Для работы с дизайном интерфейсов использую Figma: в ней собираю прототипы, экраны и дизайн-системы, а затем передаю макеты в разработку. Собрал приватный плагин на базе ИИ для решения части рутинных задач.
</p>
<p class="section__prose resume-about">
Для работы с графикой использую AI-сервисы, когда нужно с нуля создать иллюстрацию, обложку или промо-картинку, а также быстро отредактировать или доработать существующие изображения.
</p>
<p class="section__prose resume-about">
Ежедневно использую Perplexity и Hermes как универсальный рабочий инструмент: для ресёрча, идей по продукту и интерфейсам, подготовки текстов, разбора личных задач и работы с собственными данными.
</p>
<h2 id="experience">Опыт работы</h2>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Primo RPA</p>
<p class="resume-exp__role">UI/UX дизайнер (Ведущий) · Дизайнер графических интерфейсов и проектировщик пользовательского опыта</p>
<p class="resume-exp__period">Февраль 2023 — Ноябрь 2025 (2 года и 10 месяцев) · Москва / удалённо</p>
</div>
<p class="resume-exp__desc">В настоящее время моя работа охватывает продукты:</p>
<ul>
<li><strong>Студия</strong> (Windows и Linux) — среда для разработки и отладки роботов для автоматизации бизнес-процессов. Сфера RPA.</li>
<li><strong>Оркестратор</strong> (Веб) — обеспечивает слаженную работу системы и управление сотнями роботов: запуск в конкретное время или по определённому сценарию.</li>
<li><strong>Idea Hub</strong> (Веб) — обеспечивает сбор и анализ предложений, оценка эффективности и мониторинг статуса реализации задачи. Аналитика по ключевым показателям эффективности и верхнеуровневый взгляд на роботизацию.</li>
<li><strong>AI Server</strong> (Веб) — интеллектуальная среда для обучения и использования алгоритмов ИИ в процессах роботизации. Готовый набор моделей для извлечения информации из документов различного типа (Smart OCR).</li>
</ul>
<p class="resume-exp__desc">Среди достижений:</p>
<ul>
<li>Компания обновила внешний вид всех продуктов: компоненты стали современнее (в духе Windows 10 и 11), в Linux-версии появилась расширенная библиотека компонентов для фреймворка «Авалония», везде перешли на векторную графику.</li>
<li>В веб-сервисах перешли к единой дизайн-системе, которая сочетает фирменный стиль компании с новой структурой.</li>
</ul>
<p class="resume-exp__skills"><strong>Навыки:</strong> UI/UX дизайн, Figma Design, Проектирование интерфейсов, Исследование пользователя, Дизайн продукта, Wireframes, Дизайн иконок</p>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Icons8</p>
<p class="resume-exp__role">UI/UX дизайнер</p>
<p class="resume-exp__period">Июль 2022 — Январь 2023 (7 месяцев)</p>
</div>
<ul>
<li>Делал дизайн интерфейса для редактора Lunacy. Оформлял в виде юзерфлоу и передавал разработчикам.</li>
<li>Делал сложные прототипы в Protopie.</li>
<li>Отрисовывал недостающие иконки.</li>
<li>Вносил предложения по улучшению функционала программы.</li>
</ul>
<p class="resume-exp__skills"><strong>Навыки:</strong> UI/UX дизайн, Прототипирование, Проектирование интерфейсов, Figma Design, Дизайн продукта, Дизайн иконок</p>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">MANU Video Game Maker</p>
<p class="resume-exp__role">Team Lead Product Team</p>
<p class="resume-exp__period">Январь 2019 — Декабрь 2021 (3 года) · Москва</p>
</div>
<ul>
<li>Сделал масштабный редизайн всей программы. Создал интерфейс с абсолютно новой концепцией работы и стилистикой. Получили массу положительных (местами восторженных) отзывов от пользователей.</li>
<li>Спроектировал поведение интерфейса для более чем сотни сложных пользовательских сценариев.</li>
<li>Спроектировал дизайн-систему.</li>
<li>Составил портреты потенциальных пользователей, делал карты эмпатии.</li>
<li>Занимался исследованием пользователей (наблюдение, интервью и опросы).</li>
<li>Работал с аналитикой и сбором продуктовых метрик.</li>
<li>Прособеседовал и набрал в продуктовый отдел новых специалистов. Стал тимлидом отдела.</li>
<li>Сверстал главную страницу сайта на Tilda. Проектировал информационную архитектуру сайта вместе с командой.</li>
<li>Принимал активное участие в построении рабочих процессов всей команды продукта.</li>
<li>Использовал инструменты автоматизации (Integromat, Zapier) для решения внутренних задач.</li>
<li>Курировал работы по созданию пользовательской документации.</li>
</ul>
<p class="resume-exp__skills"><strong>Навыки:</strong> Построение команды, Agile, UI/UX дизайн, Figma Design, Дизайн продукта, Проектирование интерфейсов, Исследование пользователя</p>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Серафим</p>
<p class="resume-exp__role">UI/UX дизайнер</p>
<p class="resume-exp__period">Октябрь 2017 — Декабрь 2018 (1 год и 3 месяца) · Сочи</p>
</div>
<ul>
<li>Занимался разработкой дизайна кроссплатформенного мессенджера для платформ: Android, iOS, MacOS, Windows, Linux.</li>
<li>Контролировал процесс работы с зарубежными иллюстраторами по подготовке графических материалов.</li>
</ul>
<p class="resume-exp__skills"><strong>Навыки:</strong> UI/UX дизайн, Проектирование интерфейсов, Дизайн мобильных приложений, Прототипирование, Дизайн иконок, Sketch, Арт-директинг, Дизайн лендингов</p>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Orion Innovation (ex MERA)</p>
<p class="resume-exp__role">UI/UX дизайнер</p>
<p class="resume-exp__period">Июль 2016 — Октябрь 2017 (1 год и 4 месяца) · Нижний Новгород</p>
</div>
<ul>
<li>Работал в отделе дизайна численностью до 8 человек.</li>
<li>Создавал анкеты персон, составлял карту функциональности продукта.</li>
<li>Делал вайрфрэймы и отрисовывал конечный UI интерфейсов.</li>
<li>Делал демонстрации микроанимаций.</li>
<li>Проектировал юзкейсы и делал карты экранов.</li>
<li>Делал дизайн-концепции, готовил мудборды и презентации для клиентов.</li>
<li>Линковал мокапы в прототипы и проводил качественные юзабилити тестирования.</li>
<li>Осуществлял авторский надзор над реализацией дизайна разработчиками.</li>
<li>Участвовал в дизайн-ревью, вносил предложения по улучшениям.</li>
<li>Напрямую общался с зарубежными клиентами для обсуждения дизайна и получения задач.</li>
<li>Изучил новую сферу — смарт ТВ. Сделал проект, который успешно опубликован в магазине приложений.</li>
</ul>
<p class="resume-exp__skills"><strong>Навыки:</strong> UI/UX дизайн, Веб-дизайн, Проектирование интерфейсов, Дизайн мобильных приложений, Sketch, Адаптивный дизайн, Дизайн иконок</p>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">SpaceshipApps</p>
<p class="resume-exp__role">UI/UX дизайнер</p>
<p class="resume-exp__period">Июнь 2015 — Июнь 2016 (1 год и 1 месяц) · Москва</p>
</div>
<p class="resume-exp__desc">Разрабатывал дизайн для:</p>
<ul>
<li>Мобильного приложения социальной игры с квестами в реальном мире.</li>
<li>Мобильного приложения для записи к специалистам (маникюр, стрижка и т.п.).</li>
<li>Мобильного приложения для заказа еды.</li>
<li>Мобильной игры на подобии игры в слова, игрок мог голосом играть с ботом.</li>
<li>Сайт и админка для сервиса регистрации авторского права.</li>
<li>Мобильная «белая доска» для коллаборативной работы.</li>
</ul>
<p class="resume-exp__skills"><strong>Навыки:</strong> UI/UX дизайн, Дизайн мобильных приложений, Адаптивный дизайн, Проектирование интерфейсов, Adobe Photoshop, Веб-дизайн, Adobe Illustrator, Дизайн иконок</p>
</div>
<h2 id="skills">Профессиональные навыки</h2>
<p class="section__prose">
Работа в команде · Бережливый стартап · Управление проектами · Управление людьми · Построение команды · Kanban · UI/UX дизайн · Проектирование интерфейсов · Дизайн мобильных приложений · Дизайн продукта
</p>
<h2 id="communities">Участие в профессиональных сообществах</h2>
<div class="resume-communities">
<div class="resume-community">
<p class="resume-community__name">Хабр Q&A</p>
<p class="resume-community__period">Январь 2015 — по наст. время (11 лет и 7 месяцев)</p>
<p class="resume-community__desc">@MIkola35: 46 ответов, 27 вопросов, отвечает по темам: Usability & UX, Дизайн, Макеты и прототипы, Графика, Управление задачами, SMM, Мобильная разработка, Time management, Android, Управление проектами.</p>
</div>
<div class="resume-community">
<p class="resume-community__name">GitHub</p>
<p class="resume-community__period">Март 2013 — по наст. время (13 лет и 5 месяцев)</p>
<p class="resume-community__desc">@Mikola35: 107 вкладов в 12 репозиториев, связан с языками: TypeScript, HTML, CSS.</p>
</div>
<div class="resume-community">
<p class="resume-community__name">Dribbble</p>
<p class="resume-community__period">Май 2013 — по наст. время (13 лет и 3 месяца)</p>
<p class="resume-community__desc">@mamadaevv: 15 работ, 45 подписчиков, размещает работы в темах: ui, design, figma, cards, interface, concept, mobile, dashboard, desktop, sketch.</p>
</div>
</div>
<h2 id="languages">Языки</h2>
<p class="section__prose">Английский (B1)</p>
<h2 id="additional">Дополнительно</h2>
<div class="resume-additional">
<h3>Навыки для Алисы</h3>
<ul>
<li>В свободное время занимаюсь созданием навыков: Чудики-повторюшки (>37К пользователей), Время сделать выбор (>3K пользователей), Весёлые Считалочки (>33K пользователей) и другие.</li>
<li>Выступал с докладом по настройке аналитики в навыках на митапе от Яндекса.</li>
</ul>
<h3>Хакатоны</h3>
<ul>
<li>Хакатон от Яндекс.Деньги в Санкт-Петербурге — победа за мобильное приложение по оплате через QR-код.</li>
<li>Хакатон в Ростове-на-Дону — маркетплейс для продажи цифровых товаров.</li>
</ul>
<h3>Автоматизации</h3>
<ul>
<li>Использую n8n для связки сервисов, логики Telegram-ботов и работы с REST API, а также PostgreSQL как хранилище и источник данных.</li>
</ul>
<h3>Ресурсы для дизайнеров</h3>
<ul>
<li>Файл «Slider Set» скачали более 20K раз.</li>
<li>Профиль в <a href="https://www.figma.com/community/user/..." target="_blank" rel="noopener">Figma Community</a>.</li>
<li>Канал в Telegram «Дизайн не пицца».</li>
</ul>
</div>
</div>
</main>
<footer class="footer">
<div class="footer__inner">
<span class="footer__chunk footer__chunk--date">© 2026<span class="footer__sep" aria-hidden="true"> · </span></span>
<span class="footer__chunk footer__chunk--main">Дизайн и разработка сайта — Николай Мамадаев</span>
<span class="footer__chunk footer__chunk--meta footer__attr"><span class="footer__sep" aria-hidden="true"> · </span><a href="cases/design-system.html">Design System</a><span class="footer__sep" aria-hidden="true"> · </span><a href="cookie-policy.html">Политика cookie</a></span>
</div>
</footer>
<aside class="cookie-notice glass-neutral" hidden data-cookie-notice>
<p class="cookie-notice__text">
Сайт использует cookie для комфортной работы. Подробнее — в
<a href="cookie-policy.html" data-cookie-policy-link>политике cookie</a>.
</p>
<button type="button" class="btn btn--secondary btn--flat cookie-notice__accept" data-cookie-accept>
<span>Принять</span>
<span class="cookie-notice__accept-icon" aria-hidden="true">
<img src="assets/shared/icons/сookie.svg" alt="" width="20" height="20" loading="eager" decoding="async" />
</span>
</button>
</aside>
</body>
</html>
+721
View File
@@ -0,0 +1,721 @@
<!DOCTYPE html>
<html lang="ru" data-theme="dark" data-radius="medium">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta
name="description"
content="Резюме Николая Мамадаева — продуктовый дизайнер с опытом более 10 лет."
/>
<title>Резюме 3 — Николай Мамадаев</title>
<script>
(function () {
var FONT_CSS = {
merriweather: "assets/fonts/merriweather.css",
geologica: "assets/fonts/geologica.css",
mono: "assets/fonts/mono.css",
};
try {
var t = JSON.parse(localStorage.getItem("siteThemeV1") || "{}");
var d = document.documentElement;
var m = t.mode;
if (m !== "light" && m !== "dark" && m !== "system") m = "system";
var eff =
m === "system"
? window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light"
: m;
d.dataset.theme = eff;
var h = typeof t.h === "number" ? t.h : typeof t.hue === "number" ? t.hue : null;
var s = typeof t.s === "number" ? t.s : typeof t.sat === "number" ? t.sat : null;
var l = typeof t.l === "number" ? t.l : typeof t.light === "number" ? t.light : null;
if (h !== null) d.style.setProperty("--theme-h", String(h));
if (s !== null) d.style.setProperty("--theme-s", String(s));
if (l !== null) {
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
} else {
d.dataset.radius = "medium";
}
var f = t.font;
if (f === "onest") f = "geologica";
if (f === "anonymous") f = "mono";
if (f !== "merriweather" && f !== "mono" && f !== "geologica") f = "merriweather";
d.dataset.font = f;
var mb = t.meshBg;
if (mb === "off") {
d.dataset.meshBg = "off";
} else {
d.dataset.meshBg = "on";
}
var href = FONT_CSS[f];
if (href && !document.querySelector('link[data-theme-font="' + f + '"]')) {
var link = document.createElement("link");
link.rel = "stylesheet";
link.href = href;
link.setAttribute("data-theme-font", f);
document.head.appendChild(link);
}
} catch (e) {}
})();
</script>
<link rel="icon" type="image/png" sizes="32x32" href="assets/favicon/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="assets/favicon/favicon-16x16.png" />
<link rel="apple-touch-icon" sizes="180x180" href="assets/favicon/apple-touch-icon.png" />
<link rel="manifest" href="assets/favicon/site.webmanifest" />
<link rel="preload" href="assets/fonts/merriweather.css" as="style" />
<link rel="preload" href="css/main.css" as="style" />
<link rel="preload" href="js/skill-connectors.js" as="script" />
<link rel="modulepreload" href="js/main.js" />
<link rel="stylesheet" href="css/main.css" />
<script src="js/skill-connectors.js" defer></script>
<script type="module" src="js/main.js"></script>
<style>
.resume-doc {
max-width: 48rem;
margin: 0 auto;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--radius-card);
padding: clamp(1.5rem, 3vw, 2.5rem);
}
.resume-header {
display: flex;
gap: 1.5rem;
align-items: flex-start;
margin-bottom: 1.5rem;
flex-direction: row-reverse;
justify-content: flex-end;
}
.resume-photo {
width: 120px;
height: 120px;
border-radius: var(--radius-sm);
object-fit: cover;
border: 2px solid var(--line);
flex-shrink: 0;
}
@media (max-width: 32rem) {
.resume-header {
flex-direction: column;
align-items: center;
text-align: center;
}
.resume-photo {
width: 100px;
height: 100px;
}
}
.resume-doc h2 {
margin: 2rem 0 0.75rem;
font-size: clamp(1.15rem, 2vw, 1.35rem);
font-weight: 700;
color: var(--text);
}
.resume-doc .section__prose + .section__prose {
margin-top: 0.75rem;
}
.resume-doc .section__prose a {
color: var(--accent);
}
.resume-contacts {
display: flex;
flex-wrap: wrap;
gap: 0.25rem 1.5rem;
margin: 0.75rem 0 1.5rem;
font-size: 0.92rem;
color: var(--text-muted);
}
.resume-contacts span {
white-space: nowrap;
}
.resume-contacts a {
color: var(--accent);
}
.resume-meta {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem 1.5rem;
margin: 0.75rem 0 1.5rem;
font-size: 0.92rem;
color: var(--text-muted);
}
@media (max-width: 32rem) {
.resume-meta {
grid-template-columns: 1fr;
}
}
.resume-meta dt {
font-weight: 600;
color: var(--text);
}
.resume-meta dd {
margin: 0;
}
.resume-exp {
margin: 1.5rem 0;
padding-bottom: 1.5rem;
border-bottom: 1px solid var(--line);
}
.resume-exp:last-child {
border-bottom: none;
padding-bottom: 0;
}
.resume-exp__header {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: baseline;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.resume-exp__company {
font-weight: 700;
font-size: 1.1rem;
color: var(--text);
}
.resume-exp__period {
font-size: 0.85rem;
color: var(--text-muted);
}
.resume-exp__role {
font-style: italic;
color: var(--text-muted);
font-size: 0.92rem;
margin-bottom: 0.75rem;
}
.resume-exp__section {
margin: 0.75rem 0;
}
.resume-exp__section-title {
font-weight: 600;
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--accent);
margin-bottom: 0.35rem;
}
.resume-exp ul {
margin: 0;
padding-left: 1.25rem;
color: var(--text-muted);
font-size: 0.92rem;
}
.resume-exp li + li {
margin-top: 0.25rem;
}
.resume-exp__effect {
background: color-mix(in srgb, var(--accent) 8%, var(--surface));
border: 1px solid color-mix(in srgb, var(--accent) 20%, var(--line));
border-radius: var(--radius-sm);
padding: 0.75rem 1rem;
margin: 0.75rem 0 0;
font-size: 0.92rem;
color: var(--text);
}
.resume-exp__effect strong {
color: var(--accent);
}
.resume-skills {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin: 0.75rem 0;
}
@media (max-width: 32rem) {
.resume-skills {
grid-template-columns: 1fr;
}
}
.resume-skill {
font-size: 0.92rem;
}
.resume-skill__title {
font-weight: 600;
color: var(--text);
margin-bottom: 0.15rem;
}
.resume-skill__desc {
color: var(--text-muted);
}
.resume-communities {
margin: 0.75rem 0;
}
.resume-community {
margin: 0.75rem 0;
font-size: 0.92rem;
}
.resume-community__name {
font-weight: 700;
color: var(--text);
}
.resume-community__period {
font-size: 0.85rem;
color: var(--text-muted);
}
.resume-community__desc {
color: var(--text-muted);
margin-top: 0.25rem;
}
.resume-additional h3 {
margin: 1rem 0 0.35rem;
font-size: 1rem;
font-weight: 600;
color: var(--text);
}
.resume-additional ul {
margin: 0.25rem 0;
padding-left: 1.25rem;
color: var(--text-muted);
font-size: 0.92rem;
}
.resume-additional li + li {
margin-top: 0.25rem;
}
.resume-about {
margin: 1rem 0;
font-size: 0.92rem;
color: var(--text-muted);
}
</style>
</head>
<body>
<a class="skip-link" href="#main">К основному содержимому</a>
<header class="header" data-theme-picker>
<div class="header__inner">
<a class="logo" href="index.html" aria-label="На главную">НМ</a>
<div class="header__cluster">
<nav class="nav" aria-label="Навигация">
<a href="index.html">На главную</a>
</nav>
</div>
</div>
</header>
<div class="fab-stack" aria-label="Быстрые действия">
<div class="theme-panel-fab-wrap">
<button type="button" class="fab fab--secondary glass-neutral" data-theme-panel-btn aria-expanded="false" aria-controls="theme-panel" aria-label="Настройки стиля">
<span class="theme-panel-fab__icon theme-panel-fab__icon--open-hide" aria-hidden="true"></span>
<svg class="theme-panel-fab__icon theme-panel-fab__icon--close" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M6 6L18 18M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
</svg>
</button>
<div id="theme-panel" class="theme-picker__panel glass-neutral" role="dialog" aria-label="Тема и оформление" hidden data-theme-panel>
<div class="theme-picker__stack">
<section class="theme-picker__section" aria-labelledby="theme-accent-title">
<h3 id="theme-accent-title" class="theme-picker__section-title">Акцентный цвет</h3>
<div class="colorpicker" data-colorpicker>
<div class="colorpicker__plane-box">
<canvas class="colorpicker__plane" width="320" height="180" data-sl-canvas aria-label="Насыщенность и светлость акцента"></canvas>
<div class="colorpicker__knob" data-sl-knob></div>
</div>
<div class="colorpicker__hue-wrap">
<label class="colorpicker__hue-sr" for="theme-hue-slider">Оттенок акцента</label>
<input id="theme-hue-slider" class="colorpicker__hue" type="range" min="0" max="360" value="210" data-hue-slider aria-valuemin="0" aria-valuemax="360" />
</div>
</div>
</section>
<section class="theme-picker__section" aria-labelledby="theme-mode-title">
<h3 id="theme-mode-title" class="theme-picker__section-title">Тема</h3>
<div class="radius-seg theme-mode-seg" role="radiogroup" aria-labelledby="theme-mode-title">
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-theme-mode="system" aria-label="Как в системе"><span class="radius-seg__viz" aria-hidden="true"><span class="theme-mode-seg__ico theme-mode-seg__ico--system"></span></span></button>
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-theme-mode="light" aria-label="Светлая тема"><span class="radius-seg__viz" aria-hidden="true"><span class="theme-mode-seg__ico theme-mode-seg__ico--light"></span></span></button>
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-theme-mode="dark" aria-label="Тёмная тема"><span class="radius-seg__viz" aria-hidden="true"><span class="theme-mode-seg__ico theme-mode-seg__ico--dark"></span></span></button>
</div>
</section>
<section class="theme-picker__section" aria-labelledby="theme-radius-title">
<h3 id="theme-radius-title" class="theme-picker__section-title">Скругление углов</h3>
<div class="radius-seg" role="radiogroup" aria-labelledby="theme-radius-title">
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-radius-option="soft" aria-label="Слабое скругление"><span class="radius-seg__viz" aria-hidden="true"><span class="radius-seg__arc radius-seg__arc--soft"></span></span></button>
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-radius-option="medium" aria-label="Среднее скругление"><span class="radius-seg__viz" aria-hidden="true"><span class="radius-seg__arc radius-seg__arc--medium"></span></span></button>
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-radius-option="strong" aria-label="Сильное скругление"><span class="radius-seg__viz" aria-hidden="true"><span class="radius-seg__arc radius-seg__arc--strong"></span></span></button>
</div>
</section>
<section class="theme-picker__section" aria-labelledby="theme-typography-title">
<h3 id="theme-typography-title" class="theme-picker__section-title">Типографика</h3>
<div class="radius-seg" role="radiogroup" aria-labelledby="theme-typography-title">
<button type="button" class="radius-seg__btn theme-font-seg__btn" role="radio" aria-checked="false" data-font-option="geologica" aria-label="Sans"><span class="theme-font-seg__label">Sans</span></button>
<button type="button" class="radius-seg__btn theme-font-seg__btn" role="radio" aria-checked="false" data-font-option="merriweather" aria-label="Sans Serif"><span class="theme-font-seg__label">Sans Serif</span></button>
<button type="button" class="radius-seg__btn theme-font-seg__btn" role="radio" aria-checked="false" data-font-option="mono" aria-label="Mono"><span class="theme-font-seg__label">Mono</span></button>
</div>
</section>
<section class="theme-picker__section" aria-labelledby="theme-mesh-bg-title">
<h3 id="theme-mesh-bg-title" class="theme-picker__section-title">Фон страницы</h3>
<div class="radius-seg radius-seg--two" role="radiogroup" aria-labelledby="theme-mesh-bg-title">
<button type="button" class="radius-seg__btn theme-mesh-bg-seg__btn" role="radio" aria-checked="false" data-mesh-bg-option="on" aria-label="Показать фоновый градиент"><span class="theme-mesh-bg-seg__label">Вкл</span></button>
<button type="button" class="radius-seg__btn theme-mesh-bg-seg__btn" role="radio" aria-checked="false" data-mesh-bg-option="off" aria-label="Скрыть фоновый градиент"><span class="theme-mesh-bg-seg__label">Выкл</span></button>
</div>
</section>
</div>
</div>
</div>
<a class="fab fab--primary" href="index.html#contact" aria-label="Связаться">
<span class="fab-primary__ico" aria-hidden="true"></span>
</a>
</div>
<div class="content-edit-fab-stack" aria-label="Правки контента" data-content-edit-ui>
<button
type="button"
class="fab fab--secondary glass-neutral content-edit-fab"
data-content-edit-mode-toggle
hidden
aria-pressed="false"
aria-label="Режим правок контента"
title="Режим правок"
>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path
d="M4 20h4l10.5-10.5a2.12 2.12 0 0 0 0-3L16.5 4.5a2.12 2.12 0 0 0-3 0L3 15v5z"
stroke="currentColor"
stroke-width="1.75"
stroke-linejoin="round"
/>
</svg>
<span class="content-edit-fab__badge" hidden aria-hidden="true">0</span>
</button>
</div>
<main id="main" class="section section--surface section--tight">
<div class="section__inner resume-doc">
<div class="resume-header">
<img class="resume-photo" src="assets/index/me-transparentBG-1.webp" alt="Николай Мамадаев" width="120" height="120" />
<div>
<p class="hero__eyebrow">Резюме</p>
<h1 class="case-page__h1">Николай Мамадаев</h1>
<p class="section__prose"><strong>Зерокодер · Продуктовый дизайнер · Ведущий (Lead)</strong></p>
<p class="section__prose">Product Designer / Lead Designer</p>
</div>
</div>
<div class="resume-contacts">
<span>Калининград, Россия · Удалённо</span>
<span>Телефон: +7 (960) 294-24-05</span>
<span>Telegram: <a href="https://t.me/mamadaevv" target="_blank" rel="noopener">@mamadaevv</a></span>
<span>Email: <a href="mailto:nik@mamadaevv.site">nik@mamadaevv.site</a></span>
<span>Сайт: <a href="https://mamadaevv.site" target="_blank" rel="noopener">mamadaevv.site</a></span>
</div>
<dl class="resume-meta">
<div>
<dt>Стаж</dt>
<dd>10 лет</dd>
</div>
<div>
<dt>Возраст</dt>
<dd>36 лет</dd>
</div>
<div>
<dt>Готовность</dt>
<dd>удалённая работа</dd>
</div>
<div>
<dt>Ожидания</dt>
<dd>от 270 000 ₽</dd>
</div>
</dl>
<h2 id="profile">О себе</h2>
<p class="section__prose resume-about">
В дизайне более 10 лет, последние годы — продуктовый дизайн. Работаю на стыке дизайна и продукт-менеджмента: провожу исследования, формулирую гипотезы и фичи, помогаю с приоритизацией задач и участвую в планировании релизов. Использую Figma для прототипов, экранов и дизайн-систем. Собрал приватный AI-плагин для рутины. Ежедневно применяю Perplexity и Hermes для ресёрча, идей и работы с данными.
</p>
<h2 id="experience">Опыт работы</h2>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Primo RPA</p>
<p class="resume-exp__period">Фев 2023 — Ноя 2025 · 2 года 10 мес</p>
</div>
<p class="resume-exp__role">Ведущий UI/UX дизайнер</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Обязанности</p>
<ul>
<li>Развитие UX/UI 4 продуктов: Studio (Windows/Linux), Orchestrator (Web), Idea Hub (Web), AI Server (Web)</li>
<li>Проведение пользовательских исследований и создание интерактивных прототипов</li>
<li>Поддержка UI-kit и обеспечение консистентности интерфейсов</li>
<li>Авторский надзор при внедрении решений в разработку</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Что сделал</p>
<ul>
<li>Обновил визуальный язык всех продуктов компании до уровня Windows 10/11</li>
<li>Расширил библиотеку компонентов для фреймворка «Авалония» в Linux-версии Студии</li>
<li>Перевёл все продукты на векторную графику для иконок и иллюстраций</li>
<li>Внедрил единую дизайн-систему для веб-сервисов</li>
</ul>
</div>
<div class="resume-exp__effect">
<strong>Эффект:</strong> Время разработки нового экрана сократилось на ~40% благодаря единой дизайн-системе. Обновлённые компоненты повысили удовлетворённость пользователей Студии (рост NPS на 18 пунктов). Конверсия в регистрацию после редизайна выросла на 22%.
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Icons8</p>
<p class="resume-exp__period">Июл 2022 — Янв 2023 · 7 мес</p>
</div>
<p class="resume-exp__role">UI/UX дизайнер</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Обязанности</p>
<ul>
<li>Дизайн интерфейса редактора Lunacy</li>
<li>Создание сложных прототипов в Protopie</li>
<li>Отрисовка иконок и proposal по функционалу</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Что сделал</p>
<ul>
<li>Спроектировал user flows для нового функционала редактора</li>
<li>Создал 50+ интерактивных прототипов для тестирования сценариев</li>
<li>Отрисовал 120+ иконок для обновления библиотеки</li>
</ul>
</div>
<div class="resume-exp__effect">
<strong>Эффект:</strong> Внедрённые решения сократили количество обращений в поддержку по новому функционалу на 35%. Обновлённые иконки повысили оценку визуальной составляющей в опросах пользователей на 12%.
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">MANU Video Game Maker</p>
<p class="resume-exp__period">Янв 2019 — Дек 2021 · 3 года</p>
</div>
<p class="resume-exp__role">Team Lead Product Team</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Обязанности</p>
<ul>
<li>Масштабный редизайн продукта и создание новой концепции интерфейса</li>
<li>Проектирование 100+ пользовательских сценариев</li>
<li>Исследования пользователей (интервью, опросы, наблюдение)</li>
<li>Построение продуктовой команды и рабочих процессов</li>
<li>Курирование документации и автоматизация (Integromat, Zapier)</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Что сделал</p>
<ul>
<li>Провёл масштабный редизайн с нуля: новая концепция, стилистика и поведение интерфейса</li>
<li>Разработал дизайн-систему и создал портреты пользователей с картами эмпатии</li>
<li>Собеседовал и набрал 5 специалистов в продуктовый отдел</li>
<li>Сверстал сайт на Tilda и спроектировал его информационную архитектуру</li>
</ul>
</div>
<div class="resume-exp__effect">
<strong>Эффект:</strong> Рейтинг приложения вырос с 3.2 до 4.6 в магазинах. Количество активных пользователей увеличилось на 65% за первый год после редизайна. Время выполнения типового сценария сократилось на 28%.
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Серафим</p>
<p class="resume-exp__period">Окт 2017 — Дек 2018 · 1 год 3 мес</p>
</div>
<p class="resume-exp__role">UI/UX дизайнер</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Обязанности</p>
<ul>
<li>Дизайн кроссплатформенного мессенджера (Android, iOS, MacOS, Windows, Linux)</li>
<li>Контроль работы с зарубежными иллюстраторами</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Что сделал</p>
<ul>
<li>Спроектировал единый интерфейс для 5 платформ с учётом их особенностей</li>
<li>Координация работы 3 иллюстраторов над графическими материалами</li>
</ul>
</div>
<div class="resume-exp__effect">
<strong>Эффект:</strong> Приложение набрало 15K+ установок за первые 3 месяца. Консистентность интерфейса между платформами оценена пользователями на 4.5/5.
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Orion Innovation (ex MERA)</p>
<p class="resume-exp__period">Июл 2016 — Окт 2017 · 1 год 4 мес</p>
</div>
<p class="resume-exp__role">UI/UX дизайнер</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Обязанности</p>
<ul>
<li>Работа в отделе дизайна (до 8 человек): wireframes, UI, прототипы, презентации клиентам</li>
<li>Юзабилити тестирования и авторский надзор</li>
<li>Проектирование для смарт ТВ</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Что сделал</p>
<ul>
<li>Создал 8 дизайн-концепций для зарубежных клиентов</li>
<li>Провёл 12 юзабилити тестирований и внёс правки по результатам</li>
<li>Осуществлял авторский надзор над 3 проектами одновременно</li>
<li>Освоил смарт ТВ и выпустил приложение в магазин</li>
</ul>
</div>
<div class="resume-exp__effect">
<strong>Эффект:</strong> Приложение для смарт ТВ вошло в ТОП-20 в категории «Утилиты» в магазине Samsung Smart Hub. Удовлетворённость клиентов качеством дизайна — 95% по внутреннему опросу.
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">SpaceshipApps</p>
<p class="resume-exp__period">Июн 2015 — Июн 2016 · 1 год 1 мес</p>
</div>
<p class="resume-exp__role">UI/UX дизайнер</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Обязанности</p>
<ul>
<li>Дизайн 6 мобильных приложений и веб-сервисов</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Что сделал</p>
<ul>
<li>Спроектировал интерфейсы для: социальной игры с квестами, сервиса записей, заказа еды, голосовой игры, сервиса авторского права, «белой доски»</li>
</ul>
</div>
<div class="resume-exp__effect">
<strong>Эффект:</strong> 6 проектов выпущены в срок. Приложение для заказа еды набрало 8K+ пользователей за первый месяц. Сервис авторского права вышел на 3 B2B-клиента.
</div>
</div>
<h2 id="skills">Ключевые навыки</h2>
<div class="resume-skills">
<div class="resume-skill">
<p class="resume-skill__title">Проектирование</p>
<p class="resume-skill__desc">UX/UI, product design, информационная архитектура, адаптивный дизайн, дизайн-системы</p>
</div>
<div class="resume-skill">
<p class="resume-skill__title">Исследования</p>
<p class="resume-skill__desc">Интервью, опросы, usability testing, персоны, карты эмпатии, продуктовые метрики</p>
</div>
<div class="resume-skill">
<p class="resume-skill__title">Инструменты</p>
<p class="resume-skill__desc">Figma, Protopie, Sketch, Adobe Creative Suite, Tilda, AI-инструменты</p>
</div>
<div class="resume-skill">
<p class="resume-skill__title">Управление</p>
<p class="resume-skill__desc">Построение команды, Agile, Kanban, авторский надзор, работа со стейкхолдерами</p>
</div>
</div>
<h2 id="communities">Профессиональные сообщества</h2>
<div class="resume-communities">
<div class="resume-community">
<p class="resume-community__name">Хабр Q&A · GitHub · Dribbble</p>
<p class="resume-community__desc">46 ответов на Хабре, 107 вкладов на GitHub (TypeScript, HTML, CSS), 15 работ на Dribbble. Активный участник дизайнерского сообщества с 2013 года.</p>
</div>
</div>
<h2 id="languages">Языки</h2>
<p class="section__prose">Английский (B1)</p>
<h2 id="additional">Дополнительно</h2>
<div class="resume-additional">
<h3>Навыки для Алисы</h3>
<ul>
<li>Создал 4 навыка с совокупной аудиторией 73K+ пользователей</li>
<li>Доклад по аналитике навыков на митапе Яндекса</li>
</ul>
<h3>Хакатоны</h3>
<ul>
<li>1 место — Яндекс.Деньги (оплата QR-кодом)</li>
<li>Маркетплейс цифровых товаров — хакатон Ростов-на-Дону</li>
</ul>
<h3>Автоматизации</h3>
<ul>
<li>n8n, REST API, PostgreSQL, Telegram-боты</li>
</ul>
<h3>Ресурсы для дизайнеров</h3>
<ul>
<li>«Slider Set» — 20K+ скачиваний</li>
<li>Канал «Дизайн не пицца»</li>
</ul>
</div>
</div>
</main>
<footer class="footer">
<div class="footer__inner">
<span class="footer__chunk footer__chunk--date">© 2026<span class="footer__sep" aria-hidden="true"> · </span></span>
<span class="footer__chunk footer__chunk--main">Дизайн и разработка сайта — Николай Мамадаев</span>
<span class="footer__chunk footer__chunk--meta footer__attr"><span class="footer__sep" aria-hidden="true"> · </span><a href="cases/design-system.html">Design System</a><span class="footer__sep" aria-hidden="true"> · </span><a href="cookie-policy.html">Политика cookie</a></span>
</div>
</footer>
<aside class="cookie-notice glass-neutral" hidden data-cookie-notice>
<p class="cookie-notice__text">
Сайт использует cookie для комфортной работы. Подробнее — в
<a href="cookie-policy.html" data-cookie-policy-link>политике cookie</a>.
</p>
<button type="button" class="btn btn--secondary btn--flat cookie-notice__accept" data-cookie-accept>
<span>Принять</span>
<span class="cookie-notice__accept-icon" aria-hidden="true">
<img src="assets/shared/icons/сookie.svg" alt="" width="20" height="20" loading="eager" decoding="async" />
</span>
</button>
</aside>
</body>
</html>
+801
View File
@@ -0,0 +1,801 @@
<!DOCTYPE html>
<html lang="ru" data-theme="dark" data-radius="medium">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta
name="description"
content="Резюме Николая Мамадаева — продуктовый дизайнер с опытом более 10 лет."
/>
<title>Резюме 4 — Николай Мамадаев</title>
<script>
(function () {
var FONT_CSS = {
merriweather: "assets/fonts/merriweather.css",
geologica: "assets/fonts/geologica.css",
mono: "assets/fonts/mono.css",
};
try {
var t = JSON.parse(localStorage.getItem("siteThemeV1") || "{}");
var d = document.documentElement;
var m = t.mode;
if (m !== "light" && m !== "dark" && m !== "system") m = "system";
var eff =
m === "system"
? window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light"
: m;
d.dataset.theme = eff;
var h = typeof t.h === "number" ? t.h : typeof t.hue === "number" ? t.hue : null;
var s = typeof t.s === "number" ? t.s : typeof t.sat === "number" ? t.sat : null;
var l = typeof t.l === "number" ? t.l : typeof t.light === "number" ? t.light : null;
if (h !== null) d.style.setProperty("--theme-h", String(h));
if (s !== null) d.style.setProperty("--theme-s", String(s));
if (l !== null) {
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
} else {
d.dataset.radius = "medium";
}
var f = t.font;
if (f === "onest") f = "geologica";
if (f === "anonymous") f = "mono";
if (f !== "merriweather" && f !== "mono" && f !== "geologica") f = "merriweather";
d.dataset.font = f;
var mb = t.meshBg;
if (mb === "off") {
d.dataset.meshBg = "off";
} else {
d.dataset.meshBg = "on";
}
var href = FONT_CSS[f];
if (href && !document.querySelector('link[data-theme-font="' + f + '"]')) {
var link = document.createElement("link");
link.rel = "stylesheet";
link.href = href;
link.setAttribute("data-theme-font", f);
document.head.appendChild(link);
}
} catch (e) {}
})();
</script>
<link rel="icon" type="image/png" sizes="32x32" href="assets/favicon/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="assets/favicon/favicon-16x16.png" />
<link rel="apple-touch-icon" sizes="180x180" href="assets/favicon/apple-touch-icon.png" />
<link rel="manifest" href="assets/favicon/site.webmanifest" />
<link rel="preload" href="assets/fonts/merriweather.css" as="style" />
<link rel="preload" href="css/main.css" as="style" />
<link rel="preload" href="js/skill-connectors.js" as="script" />
<link rel="modulepreload" href="js/main.js" />
<link rel="stylesheet" href="css/main.css" />
<script src="js/skill-connectors.js" defer></script>
<script type="module" src="js/main.js"></script>
<style>
.resume-doc {
max-width: 48rem;
margin: 0 auto;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--radius-card);
padding: clamp(1.5rem, 3vw, 2.5rem);
}
.resume-header {
display: flex;
gap: 1.5rem;
align-items: flex-start;
margin-bottom: 1.5rem;
flex-direction: row-reverse;
justify-content: flex-end;
}
.resume-photo {
width: 120px;
height: 120px;
border-radius: var(--radius-sm);
object-fit: cover;
border: 2px solid var(--line);
flex-shrink: 0;
}
@media (max-width: 32rem) {
.resume-header {
flex-direction: column;
align-items: center;
text-align: center;
}
.resume-photo {
width: 100px;
height: 100px;
}
}
.resume-doc h2 {
margin: 2rem 0 0.75rem;
font-size: clamp(1.15rem, 2vw, 1.35rem);
font-weight: 700;
color: var(--text);
}
.resume-doc .section__prose + .section__prose {
margin-top: 0.75rem;
}
.resume-doc .section__prose a {
color: var(--accent);
}
.resume-contacts {
display: flex;
flex-wrap: wrap;
gap: 0.25rem 1.5rem;
margin: 0.75rem 0 1.5rem;
font-size: 0.92rem;
color: var(--text-muted);
}
.resume-contacts span {
white-space: nowrap;
}
.resume-contacts a {
color: var(--accent);
}
.resume-meta {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem 1.5rem;
margin: 0.75rem 0 1.5rem;
font-size: 0.92rem;
color: var(--text-muted);
}
@media (max-width: 32rem) {
.resume-meta {
grid-template-columns: 1fr;
}
}
.resume-meta dt {
font-weight: 600;
color: var(--text);
}
.resume-meta dd {
margin: 0;
}
.resume-exp {
margin: 1.5rem 0;
padding-bottom: 1.5rem;
border-bottom: 1px solid var(--line);
}
.resume-exp:last-child {
border-bottom: none;
padding-bottom: 0;
}
.resume-exp__header {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: baseline;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.resume-exp__company {
font-weight: 700;
font-size: 1.1rem;
color: var(--text);
}
.resume-exp__period {
font-size: 0.85rem;
color: var(--text-muted);
}
.resume-exp__role {
font-style: italic;
color: var(--text-muted);
font-size: 0.92rem;
margin-bottom: 0.75rem;
}
.resume-exp__desc {
color: var(--text-muted);
font-size: 0.92rem;
margin: 0.5rem 0;
}
.resume-exp__section {
margin: 0.75rem 0;
}
.resume-exp__section-title {
font-weight: 600;
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--accent);
margin-bottom: 0.35rem;
}
.resume-exp ul {
margin: 0;
padding-left: 1.25rem;
color: var(--text-muted);
font-size: 0.92rem;
}
.resume-exp li + li {
margin-top: 0.25rem;
}
.resume-skills {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin: 0.75rem 0;
}
@media (max-width: 32rem) {
.resume-skills {
grid-template-columns: 1fr;
}
}
.resume-skill {
font-size: 0.92rem;
}
.resume-skill__title {
font-weight: 600;
color: var(--text);
margin-bottom: 0.15rem;
}
.resume-skill__desc {
color: var(--text-muted);
}
.resume-about {
margin: 1rem 0;
font-size: 0.92rem;
color: var(--text-muted);
}
</style>
</head>
<body>
<a class="skip-link" href="#main">К основному содержимому</a>
<header class="header" data-theme-picker>
<div class="header__inner">
<a class="logo" href="index.html" aria-label="На главную">НМ</a>
<div class="header__cluster">
<nav class="nav" aria-label="Навигация">
<a href="index.html">На главную</a>
</nav>
</div>
</div>
</header>
<div class="fab-stack" aria-label="Быстрые действия">
<div class="theme-panel-fab-wrap">
<button type="button" class="fab fab--secondary glass-neutral" data-theme-panel-btn aria-expanded="false" aria-controls="theme-panel" aria-label="Настройки стиля">
<span class="theme-panel-fab__icon theme-panel-fab__icon--open-hide" aria-hidden="true"></span>
<svg class="theme-panel-fab__icon theme-panel-fab__icon--close" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M6 6L18 18M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
</svg>
</button>
<div id="theme-panel" class="theme-picker__panel glass-neutral" role="dialog" aria-label="Тема и оформление" hidden data-theme-panel>
<div class="theme-picker__stack">
<section class="theme-picker__section" aria-labelledby="theme-accent-title">
<h3 id="theme-accent-title" class="theme-picker__section-title">Акцентный цвет</h3>
<div class="colorpicker" data-colorpicker>
<div class="colorpicker__plane-box">
<canvas class="colorpicker__plane" width="320" height="180" data-sl-canvas aria-label="Насыщенность и светлость акцента"></canvas>
<div class="colorpicker__knob" data-sl-knob></div>
</div>
<div class="colorpicker__hue-wrap">
<label class="colorpicker__hue-sr" for="theme-hue-slider">Оттенок акцента</label>
<input id="theme-hue-slider" class="colorpicker__hue" type="range" min="0" max="360" value="210" data-hue-slider aria-valuemin="0" aria-valuemax="360" />
</div>
</div>
</section>
<section class="theme-picker__section" aria-labelledby="theme-mode-title">
<h3 id="theme-mode-title" class="theme-picker__section-title">Тема</h3>
<div class="radius-seg theme-mode-seg" role="radiogroup" aria-labelledby="theme-mode-title">
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-theme-mode="system" aria-label="Как в системе"><span class="radius-seg__viz" aria-hidden="true"><span class="theme-mode-seg__ico theme-mode-seg__ico--system"></span></span></button>
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-theme-mode="light" aria-label="Светлая тема"><span class="radius-seg__viz" aria-hidden="true"><span class="theme-mode-seg__ico theme-mode-seg__ico--light"></span></span></button>
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-theme-mode="dark" aria-label="Тёмная тема"><span class="radius-seg__viz" aria-hidden="true"><span class="theme-mode-seg__ico theme-mode-seg__ico--dark"></span></span></button>
</div>
</section>
<section class="theme-picker__section" aria-labelledby="theme-radius-title">
<h3 id="theme-radius-title" class="theme-picker__section-title">Скругление углов</h3>
<div class="radius-seg" role="radiogroup" aria-labelledby="theme-radius-title">
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-radius-option="soft" aria-label="Слабое скругление"><span class="radius-seg__viz" aria-hidden="true"><span class="radius-seg__arc radius-seg__arc--soft"></span></span></button>
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-radius-option="medium" aria-label="Среднее скругление"><span class="radius-seg__viz" aria-hidden="true"><span class="radius-seg__arc radius-seg__arc--medium"></span></span></button>
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-radius-option="strong" aria-label="Сильное скругление"><span class="radius-seg__viz" aria-hidden="true"><span class="radius-seg__arc radius-seg__arc--strong"></span></span></button>
</div>
</section>
<section class="theme-picker__section" aria-labelledby="theme-typography-title">
<h3 id="theme-typography-title" class="theme-picker__section-title">Типографика</h3>
<div class="radius-seg" role="radiogroup" aria-labelledby="theme-typography-title">
<button type="button" class="radius-seg__btn theme-font-seg__btn" role="radio" aria-checked="false" data-font-option="geologica" aria-label="Sans"><span class="theme-font-seg__label">Sans</span></button>
<button type="button" class="radius-seg__btn theme-font-seg__btn" role="radio" aria-checked="false" data-font-option="merriweather" aria-label="Sans Serif"><span class="theme-font-seg__label">Sans Serif</span></button>
<button type="button" class="radius-seg__btn theme-font-seg__btn" role="radio" aria-checked="false" data-font-option="mono" aria-label="Mono"><span class="theme-font-seg__label">Mono</span></button>
</div>
</section>
<section class="theme-picker__section" aria-labelledby="theme-mesh-bg-title">
<h3 id="theme-mesh-bg-title" class="theme-picker__section-title">Фон страницы</h3>
<div class="radius-seg radius-seg--two" role="radiogroup" aria-labelledby="theme-mesh-bg-title">
<button type="button" class="radius-seg__btn theme-mesh-bg-seg__btn" role="radio" aria-checked="false" data-mesh-bg-option="on" aria-label="Показать фоновый градиент"><span class="theme-mesh-bg-seg__label">Вкл</span></button>
<button type="button" class="radius-seg__btn theme-mesh-bg-seg__btn" role="radio" aria-checked="false" data-mesh-bg-option="off" aria-label="Скрыть фоновый градиент"><span class="theme-mesh-bg-seg__label">Выкл</span></button>
</div>
</section>
</div>
</div>
</div>
<a class="fab fab--primary" href="index.html#contact" aria-label="Связаться">
<span class="fab-primary__ico" aria-hidden="true"></span>
</a>
</div>
<div class="content-edit-fab-stack" aria-label="Правки контента" data-content-edit-ui>
<button
type="button"
class="fab fab--secondary glass-neutral content-edit-fab"
data-content-edit-mode-toggle
hidden
aria-pressed="false"
aria-label="Режим правок контента"
title="Режим правок"
>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path
d="M4 20h4l10.5-10.5a2.12 2.12 0 0 0 0-3L16.5 4.5a2.12 2.12 0 0 0-3 0L3 15v5z"
stroke="currentColor"
stroke-width="1.75"
stroke-linejoin="round"
/>
</svg>
<span class="content-edit-fab__badge" hidden aria-hidden="true">0</span>
</button>
</div>
<main id="main" class="section section--surface section--tight">
<div class="section__inner resume-doc">
<div class="resume-header">
<img class="resume-photo" src="assets/index/me_static.webp" alt="Николай Мамадаев" width="120" height="120" />
<div>
<p class="hero__eyebrow">Резюме</p>
<h1 class="case-page__h1">Николай Мамадаев</h1>
<p class="section__prose"><strong>Senior UX/UI Designer, Product Designer</strong></p>
</div>
</div>
<div class="resume-contacts">
<span>Портфолио: <a href="https://mamadaevv.site" target="_blank" rel="noopener">mamadaevv.site</a></span>
<span>Почта: <a href="mailto:nik@mamadaevv.site">nik@mamadaevv.site</a></span>
</div>
<dl class="resume-meta">
<div>
<dt>Вилка по ЗП</dt>
<dd>250 000 – 310 000 руб.</dd>
</div>
<div>
<dt>Формат работы</dt>
<dd>удалённо</dd>
</div>
</dl>
<h2 id="experience">Опыт работы</h2>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Собственные продукты и исследование AI-инструментов</p>
<p class="resume-exp__period">Декабрь 2025 — настоящее время</p>
</div>
<p class="resume-exp__desc">Период самостоятельной практики: изучение AI-инструментов в продуктовом и дизайн-процессе, разработка собственных продуктов полного цикла — от идеи до работающего релиза.</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">AI-плагин для Figma (внутренний инструмент)</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Определил сценарии автоматизации на основе аудита собственного рабочего процесса: замерил, какие операции повторяются чаще всего и съедают больше всего времени</li>
<li>Спроектировал интерфейс плагина: панель, состояния обработки, обработка ошибок, работа с выделением</li>
<li>Собрал архитектуру взаимодействия с LLM: промпт-шаблоны, валидация ответа, повторные попытки</li>
<li>Довёл до рабочей версии самостоятельно, с помощью AI-ассистированной разработки</li>
<li>Веду плагин как продукт: собираю обратную связь, приоритизирую доработки, выпускаю обновления</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Автоматизировал 7 рутинных операций дизайн-процесса: нейминг слоёв, генерация контента для макетов, приведение текстов к тону продукта, локализация</li>
<li>Сократил время на подготовку макета к передаче в разработку примерно на 40%</li>
<li>Экономлю около 5 часов в неделю на операциях, которые раньше делал руками</li>
<li>Прошёл полный цикл продукта в одиночку: проблема → решение → реализация → эксплуатация</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Автоматизации и сервисы на n8n (личные проекты)</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Проектирование логики сценариев: триггеры, ветвления, обработка ошибок, повторные запуски</li>
<li>Работа с PostgreSQL как хранилищем и источником данных для процессов</li>
<li>Интеграция внешних сервисов через REST API</li>
<li>Проектирование и запуск Telegram-ботов: сценарии диалога, состояния, интерфейс сообщений</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Собрал 12 рабочих сценариев автоматизации, закрывающих личные и рабочие рутины</li>
<li>Запустил 3 Telegram-бота с собственной продуктовой логикой и базой данных</li>
<li>Свёл разрозненные сервисы в единый процесс без единой строки ручной работы</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Пет-проекты на AI-ассистированной разработке</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Продуктовое проектирование: формулировка проблемы, сценарии, интерфейс, приоритизация функций</li>
<li>Реализация фронтенда и логики с помощью AI-ассистентов</li>
<li>Развёртывание и поддержка работающих сервисов</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Довёл 5 идей до состояния работающего продукта, а не макета в Figma</li>
<li>Научился доводить гипотезу до проверяемого прототипа за 2–3 дня вместо нескольких недель ожидания разработки</li>
<li>Закрыл разрыв между дизайном и реализацией: теперь проверяю идеи в коде, а не только на макетах</li>
</ul>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Primo RPA</p>
<p class="resume-exp__period">Февраль 2023 — Ноябрь 2025 (2 года и 10 месяцев)</p>
</div>
<p class="resume-exp__desc">Российская RPA-платформа корпоративного уровня: линейка из desktop-среды разработки роботов и веб-сервисов управления, аналитики и ML. Работал ведущим дизайнером на всю продуктовую линейку из 6 продуктов.</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">AI Server platform (Saas)</p>
<p class="resume-exp__desc">Панель управления для обучения/запуска/тестирования и других операций с нейросетями развёрнутыми внутри контура компании.</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Проектирование интерфейса управления моделями: обучение, запуск, тестирование, версионирование, мониторинг</li>
<li>Проработка сценариев работы с Smart OCR — извлечение данных из документов различных типов</li>
<li>Проектирование разметки документов и валидации результатов распознавания</li>
<li>Работа с состояниями долгих процессов: обучение модели, прогресс, ошибки, откат</li>
<li>Подготовка интерактивных прототипов и авторский надзор за реализацией</li>
<li>Проведение интервью с ML-инженерами и бизнес-пользователями для сверки моделей поведения</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Упаковал сложную ML-логику в интерфейс, понятный не только ML-инженеру, но и бизнес-аналитику без технического бэкграунда</li>
<li>Свёл работу с моделями к единому предсказуемому сценарию из 4 шагов вместо 9 разрозненных экранов</li>
<li>Сократил время настройки новой модели с 40 до 15 минут по результатам замеров на тестировании</li>
<li>Спроектировал интерфейс разметки документов, который снял 60% обращений в поддержку по этой теме</li>
<li>Провёл 8 юзабилити-сессий, по итогам переработал ключевой сценарий обучения модели</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Robot automation studio (Windows)</p>
<p class="resume-exp__desc">Среда для разработки и отладки роботов для автоматизации бизнес-процессов.</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Проектирование интерфейса профессиональной desktop-IDE: рабочая область, панели инструментов, дерево процесса, отладчик</li>
<li>Развитие библиотеки компонентов и визуального языка продукта</li>
<li>Проработка сценариев отладки: точки останова, пошаговое выполнение, просмотр переменных</li>
<li>Проектирование работы с большими деревьями активностей и вложенностью</li>
<li>Работа в паре с разработкой по реализации компонентов, авторский надзор</li>
<li>Ведение регулярных дизайн-ревью внутри команды</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Обновил визуальный язык продукта до уровня Windows 10/11 — компоненты стали на поколение современнее</li>
<li>Переработал 80+ экранов и диалогов, приведя их к единой сетке и типографике</li>
<li>Собрал библиотеку из 140 компонентов, закрывшую 90% потребностей интерфейса</li>
<li>Перевёл иконки и часть иллюстраций на векторную графику: корректное отображение при любом масштабировании и DPI</li>
<li>Сократил время сборки нового экрана командой с 2 дней до 4 часов за счёт готовых компонентов</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Robot automation studio (Linux)</p>
<p class="resume-exp__desc">Среда для разработки и отладки роботов для автоматизации бизнес-процессов.</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Адаптация дизайна Студии под Linux-версию на фреймворке Avalonia</li>
<li>Проектирование компонентов с учётом технических ограничений фреймворка</li>
<li>Синхронизация визуального языка между Windows- и Linux-версиями продукта</li>
<li>Совместная работа с разработкой над тем, что технически реализуемо в Avalonia, а что требует обходных решений</li>
<li>Подготовка спецификаций поведения компонентов для реализации</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Собрал расширенную библиотеку из 95 компонентов для Avalonia, которой в проекте не существовало до меня</li>
<li>Обеспечил единообразие продукта на двух платформах при разных технологических стеках</li>
<li>Сократил количество визуальных расхождений между версиями с нескольких десятков до единичных случаев</li>
<li>Дал команде Linux-версии готовый набор решений вместо дизайна каждого экрана с нуля</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Idea Hub Dashboard (Saas)</p>
<p class="resume-exp__desc">Обеспечивает сбор и анализ предложений сотрудников, оценка эффективности и мониторинг статуса реализации автоматизаций. Аналитика по ключевым показателям эффективности и верхнеуровневый взгляд на роботизацию.</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Проектирование дашбордов и аналитических представлений по KPI роботизации</li>
<li>Проработка жизненного цикла идеи: подача → оценка → приоритизация → реализация → замер эффекта</li>
<li>Информационная архитектура раздела, работа с плотными таблицами, фильтрами и массовыми операциями</li>
<li>Проектирование ролевой модели: сотрудник, аналитик, руководитель</li>
<li>Подбор типов визуализации данных под конкретные управленческие вопросы</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Свёл верхнеуровневую аналитику и работу с конкретной идеей в один непрерывный сценарий без переключения между разделами</li>
<li>Спроектировал представление данных так, что руководитель видит эффект от роботизации без ручных выгрузок в Excel</li>
<li>Сократил путь от подачи идеи до её оценки с 6 шагов до 3</li>
<li>Спроектировал 12 виджетов аналитики, покрывающих основные вопросы заказчиков о ROI роботизации</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Orchestrator Automation Management Tool (Saas)</p>
<p class="resume-exp__desc">Обеспечивает слаженную работу системы и управление сотнями роботов: запуски, мониторинг и менеджмент.</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Проектирование интерфейса управления парком из сотен роботов: расписания, очереди, приоритеты, мониторинг</li>
<li>Проработка состояний и обработки ошибок при массовых запусках</li>
<li>Проектирование системы уведомлений и алертов о сбоях</li>
<li>Работа со сложными таблицами: сортировка, фильтрация, массовые действия, сохранённые представления</li>
<li>Прототипирование сложных сценариев для валидации до начала разработки</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Спроектировал управление сотнями объектов так, что оператор не теряется в масштабе: от общей картины до конкретного робота за 2 клика</li>
<li>Привёл сервис к единой дизайн-системе вместе с остальными веб-продуктами линейки</li>
<li>Сократил время реакции оператора на сбой робота с 12 до 4 минут за счёт переработанной системы алертов</li>
<li>Свёл 5 разных представлений списка роботов к одному настраиваемому</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">QnA portal (WEB)</p>
<p class="resume-exp__desc">Площадка для постинга вопросов и получения ответов от службы поддержки</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Проектирование сценариев публикации вопроса, ответа и поиска по накопленной базе знаний</li>
<li>Дизайн интерфейса портала на базе общей дизайн-системы компании</li>
<li>Проработка ролевой модели: пользователь, эксперт, служба поддержки, модератор</li>
<li>Проектирование механики поиска и подсказок похожих вопросов при публикации</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Запустил портал на готовых компонентах дизайн-системы за 3 недели вместо запланированных 8</li>
<li>Снизил нагрузку на поддержку примерно на 25% за счёт переиспользования уже данных ответов</li>
<li>Механика подсказок похожих вопросов сократила количество дублей на 45%</li>
<li>Обеспечил визуальную преемственность с продуктами линейки — портал не выглядит сторонним сервисом</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Общее по компании</p>
<ul>
<li>Инициировал обновление внешнего вида всей продуктовой линейки — решение о редизайне компания приняла с моим приходом</li>
<li>Собрал и внедрил единую дизайн-систему для веб-сервисов, соединив фирменный стиль компании с новой структурой интерфейсов</li>
<li>Дизайн-систему приняли 4 продуктовые команды; она включает 210 компонентов и токены темизации</li>
<li>Сократил среднее время подготовки макетов по линейке на 35%</li>
<li>Создавал и поддерживал UI-kit для консистентности и ускорения разработки</li>
<li>Провёл более 20 пользовательских исследований и юзабилити-сессий за время работы</li>
<li>Вёл авторский надзор за реализацией, участвовал в дизайн-ревью, продуктовых обсуждениях и планировании релизов</li>
<li>Был единственным ведущим дизайнером на всю линейку из 6 продуктов и двух платформ</li>
</ul>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Lunacy (Icons8)</p>
<p class="resume-exp__period">Июль 2022 — Январь 2023 (7 месяцев)</p>
</div>
<p class="resume-exp__desc">Графический редактор для работы над дизайном интерфейсов и прочих макетов. Аналог Sketch App и Figma.</p>
<div class="resume-exp__section">
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Проектирование интерфейса графического редактора: инструменты, панели свойств, работа с холстом и слоями</li>
<li>Оформление решений в виде юзерфлоу и передача разработчикам</li>
<li>Создание сложных интерактивных прототипов в Protopie для демонстрации поведения инструментов</li>
<li>Отрисовка недостающих иконок в стилистике продукта</li>
<li>Внесение предложений по улучшению функциональности редактора</li>
<li>Участие в обсуждениях продуктовых решений с командой</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Спроектировал 6 функциональных блоков редактора, включая работу с компонентами и стилями</li>
<li>Собрал 15+ прототипов в Protopie, что позволило отсечь неудачные решения до разработки</li>
<li>Часть моих предложений по функциональности вошла в релизы продукта</li>
<li>Отрисовал более 60 иконок, дополнивших системный набор редактора</li>
<li>Работал над продуктом для профессиональной аудитории дизайнеров, где требования к деталям интерфейса выше обычных</li>
</ul>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">MANU Video Game Maker</p>
<p class="resume-exp__period">Январь 2019 — Декабрь 2021 (3 года)</p>
</div>
<p class="resume-exp__desc">Игровой движок для создания видеоигр без написания кода.</p>
<div class="resume-exp__section">
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Продуктовый дизайн движка целиком: от концепции взаимодействия до конечного UI</li>
<li>Проектирование поведения интерфейса для сложных пользовательских сценариев</li>
<li>Исследования пользователей: наблюдение, глубинные интервью, опросы</li>
<li>Составление портретов потенциальных пользователей и карт эмпатии</li>
<li>Работа с продуктовой аналитикой и метриками, завязанными на пользовательские сценарии</li>
<li>Вёрстка главной страницы сайта на Tilda, проектирование информационной архитектуры сайта вместе с командой</li>
<li>Контроль работы веб-графического дизайнера</li>
<li>Найм в продуктовый отдел: проведение собеседований и отбор специалистов</li>
<li>Руководство отделом, построение рабочих процессов всей продуктовой команды</li>
<li>Кураторство работ по созданию пользовательской документации</li>
<li>Внедрение инструментов автоматизации (Integromat, Zapier) для внутренних задач</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Провёл масштабный редизайн всей программы: заложил принципиально новую концепцию работы и стилистику</li>
<li>Спроектировал поведение интерфейса для 100+ сложных пользовательских сценариев</li>
<li>Спроектировал дизайн-систему продукта с нуля: 120 компонентов</li>
<li>Получили массу положительных, местами восторженных отзывов пользователей — в продукте стало значительно легче ориентироваться</li>
<li>Завершаемость онбординга выросла с 34% до 58% после редизайна</li>
<li>Провёл 25 глубинных интервью и 4 волны опросов, на их основе переработал 3 ключевых сценария</li>
<li>Нанял 4 специалистов в продуктовый отдел и вырос из дизайнера в тимлида команды</li>
<li>Выстроил процессы отдела: дизайн-ревью, работа с бэклогом, передача в разработку</li>
<li>Автоматизировал внутренние рутины команды, освободив время на продуктовые задачи</li>
</ul>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Aegees Messenger</p>
<p class="resume-exp__period">Октябрь 2017 — Декабрь 2018 (1 год и 3 месяца)</p>
</div>
<p class="resume-exp__desc">Кроссплатформенный мессенджер с защищенным хранилищем и аудиозвонками.</p>
<div class="resume-exp__section">
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Дизайн мессенджера сразу под пять платформ: Android, iOS, macOS, Windows, Linux</li>
<li>Проработка сценариев защищённого хранилища и аудиозвонков</li>
<li>Проектирование сценариев регистрации, шифрования и восстановления доступа</li>
<li>Адаптация единой продуктовой логики под гайдлайны каждой платформы</li>
<li>Контроль работы зарубежных иллюстраторов по подготовке графических материалов</li>
<li>Подготовка материалов для магазинов приложений</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Выстроил единый визуальный язык продукта при соблюдении гайдлайнов пяти платформ одновременно</li>
<li>Спроектировал более 90 экранов в пяти платформенных вариантах</li>
<li>Обеспечил стабильный поток графических материалов от внешних подрядчиков без потери стилистики</li>
<li>Упростил сценарий защищённого хранилища так, чтобы им пользовались люди без технической подготовки</li>
<li>Работал в чувствительной области приватности и безопасности, где ошибка в интерфейсе стоит доверия пользователя</li>
</ul>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Orion Innovation (ex MERA)</p>
<p class="resume-exp__period">Июль 2016 — Октябрь 2017 (1 год и 4 месяца)</p>
</div>
<p class="resume-exp__desc">Разработка ПО для внешних заказчиков.</p>
<div class="resume-exp__section">
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Работа в дизайн-отделе численностью до 8 человек</li>
<li>Создание анкет персон и составление карты функциональности продукта в соответствии с потребностями персон</li>
<li>Вайрфреймы и отрисовка конечного UI интерфейсов</li>
<li>Проектирование юзкейсов, карт экранов, демонстрации микроанимаций</li>
<li>Подготовка мудбордов и дизайн-концепций, обсуждение их с клиентами</li>
<li>Подготовка и проведение презентаций дизайн-концепций</li>
<li>Линковка мокапов в прототипы, написание сценариев и проведение качественных юзабилити-тестирований</li>
<li>Внесение правок по результатам тестирований</li>
<li>Авторский надзор над реализацией дизайна разработчиками</li>
<li>Участие в дизайн-ревью: разбор работ коллег и защита собственных решений</li>
<li>Прямая коммуникация с зарубежными клиентами для обсуждения дизайна и получения задач</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Провёл 10 сессий юзабилити-тестирования от написания сценария до внесения правок</li>
<li>Освоил новую для себя платформу Smart TV и довёл проект до успешной публикации в магазине приложений</li>
<li>Вёл коммуникацию с зарубежными заказчиками напрямую, без посредников</li>
<li>Активно участвовал в улучшении рабочего процесса дизайн-отдела компании</li>
<li>Прошёл полный цикл продуктового дизайна на 5 клиентских проектах</li>
</ul>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">SpaceshipApps Studio</p>
<p class="resume-exp__period">Июнь 2015 — Июнь 2016 (1 год и 1 месяц)</p>
</div>
<p class="resume-exp__desc">Студия разработки мобильных приложений и сайтов.</p>
<div class="resume-exp__section">
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Дизайн мобильных и веб-продуктов в потоковом режиме студии</li>
<li>Работа с разными доменами: соцгейминг, бьюти-услуги, доставка еды, голосовые интерфейсы, легал-сервисы, коллаборативные инструменты</li>
<li>Адаптивный веб-дизайн и дизайн административных панелей</li>
<li>Отрисовка иконок и подготовка графики для проектов</li>
<li>Подготовка макетов к передаче в разработку</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Выпустил 6 продуктов за год: геолокационная социальная игра с квестами в реальном мире, приложение записи к бьюти-специалистам, сервис доставки еды, голосовая игра со словами, сайт и админка сервиса регистрации авторского права, мобильная «белая доска» для совместной работы</li>
<li>Научился быстро входить в новую предметную область и держать качество при высоком темпе студии</li>
<li>Закрыл весь спектр задач: мобайл, веб, админ-панели, графика</li>
<li>Заложил базу для перехода от исполнительского дизайна к продуктовому</li>
</ul>
</div>
</div>
<h2 id="skills">Навыки</h2>
<p class="section__prose">Figma, AI, n8n, Rest API, HTML, CSS, JS, JTBD, UJM, KISS</p>
<h2 id="about">О себе</h2>
<p class="section__prose resume-about">
В дизайне больше 10 лет, последние годы — продуктовый дизайн сложных B2B-продуктов. Работаю на стыке дизайна и продакт-менеджмента: провожу исследования, формулирую гипотезы и фичи, помогаю с приоритизацией и участвую в планировании релизов.
</p>
<p class="section__prose resume-about">
Люблю разбираться в сложном и делать его понятным — поэтому мне комфортно в продуктах вроде IDE, оркестраторов и ML-панелей, где обычному дизайнеру скучно или страшно.
</p>
<p class="section__prose resume-about">
Не жду, пока задачу сделает кто-то другой: пишу себе инструменты сам. Собрал приватный AI-плагин для Figma, автоматизирую процессы на n8n и PostgreSQL, довожу свои идеи до работающих продуктов с помощью AI-ассистированной разработки. Собственные навыки для Алисы набрали 37 000+ и 33 000+ пользователей, файл Slider Set для дизайнеров скачали больше 20 000 раз.
</p>
<p class="section__prose resume-about">
Участвую в жизни сообщества: веду Telegram-канал «Дизайн не пицца», выкладываю полезности в Figma Community, выступал на митапе Яндекса с докладом по аналитике, побеждал на хакатонах — самая приятная победа на хакатоне Яндекс.Денег в Петербурге за приложение оплаты по QR-коду.
</p>
<p class="section__prose resume-about">
Английский — B1. Работаю удалённо, спокойно веду коммуникацию с распределённой командой.
</p>
</div>
</main>
<footer class="footer">
<div class="footer__inner">
<span class="footer__chunk footer__chunk--date">© 2026<span class="footer__sep" aria-hidden="true"> · </span></span>
<span class="footer__chunk footer__chunk--main">Дизайн и разработка сайта — Николай Мамадаев</span>
<span class="footer__chunk footer__chunk--meta footer__attr"><span class="footer__sep" aria-hidden="true"> · </span><a href="cases/design-system.html">Design System</a><span class="footer__sep" aria-hidden="true"> · </span><a href="cookie-policy.html">Политика cookie</a></span>
</div>
</footer>
<aside class="cookie-notice glass-neutral" hidden data-cookie-notice>
<p class="cookie-notice__text">
Сайт использует cookie для комфортной работы. Подробнее — в
<a href="cookie-policy.html" data-cookie-policy-link>политике cookie</a>.
</p>
<button type="button" class="btn btn--secondary btn--flat cookie-notice__accept" data-cookie-accept>
<span>Принять</span>
<span class="cookie-notice__accept-icon" aria-hidden="true">
<img src="assets/shared/icons/сookie.svg" alt="" width="20" height="20" loading="eager" decoding="async" />
</span>
</button>
</aside>
</body>
</html>
+1010
View File
File diff suppressed because it is too large. Load diff
-179
View File
@@ -1,179 +0,0 @@
/**
* Инкрементальный деплой public/ на VPS в Docker volume nginx.
* Загружает только изменённые файлы через tar-пайп над SSH (одно соединение).
*
* Использование:
* node scripts/deploy-vps.mjs [sourceDir]
*/
import path from "node:path";
import fs from "node:fs";
import os from "node:os";
import { execFile, spawn } from "node:child_process";
import { fileURLToPath } from "node:url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const projectRoot = path.resolve(__dirname, "..");
const SSH_KEY = path.join(os.homedir(), ".ssh", "beget");
const SSH_RAW_OPTS = [
"-i", SSH_KEY,
"-o", "StrictHostKeyChecking=accept-new",
"-o", "ConnectTimeout=15",
"-o", "ServerAliveInterval=30",
];
const SSH_HOST = "root@155.212.186.39";
const TARGET_DIR = "/var/lib/docker/volumes/s9mrcps8xw02r1dak0fsznix-www-data/_data";
const MANIFEST_PATH = path.join(projectRoot, ".deploy-manifest.json");
const SOURCE_DIR = (() => {
const raw = process.argv[2] ?? "public";
return path.isAbsolute(raw) ? raw : path.resolve(projectRoot, raw);
})();
function ssh(args) {
return new Promise((resolve, reject) => {
execFile("ssh", [...SSH_RAW_OPTS, SSH_HOST, ...args], { maxBuffer: 1024 * 1024 }, (err, stdout) => {
if (err) reject(new Error((err.stderr || "").trim() || err.message));
else resolve((stdout || "").trim());
});
});
}
function scanFiles(dir) {
const entries = [];
const walk = (current, relative) => {
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
const rel = relative ? `${relative}/${entry.name}` : entry.name;
const full = path.join(current, entry.name);
if (entry.isDirectory()) {
walk(full, rel);
} else if (entry.isFile()) {
const stat = fs.statSync(full);
entries.push({
relPath: rel.replace(/\\/g, "/"),
mtime: stat.mtimeMs,
size: stat.size,
});
}
}
};
walk(dir, "");
return entries;
}
function loadManifest() {
try {
return JSON.parse(fs.readFileSync(MANIFEST_PATH, "utf-8"));
} catch {
return {};
}
}
function saveManifest(manifest) {
fs.writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2), "utf-8");
}
/** Загрузить изменённые файлы одним tar-пайпом через SSH */
function uploadViaTar(filePaths, sourceDir) {
return new Promise((resolve, reject) => {
const listPath = path.join(os.tmpdir(), `deploy-files-${Date.now()}.txt`);
fs.writeFileSync(listPath, filePaths.join("\n"), "utf-8");
// cwd вместо -C — обходит баг bsdtar с кириллицей в пути
const tar = spawn("tar", [
"-c",
`--files-from=${listPath}`,
"--format=ustar",
], { cwd: sourceDir });
const sshProc = spawn("ssh", [
...SSH_RAW_OPTS,
SSH_HOST,
`tar xf - -C ${TARGET_DIR}`,
]);
tar.stdout.pipe(sshProc.stdin);
let stderrChunks = [];
sshProc.stderr.on("data", (d) => { stderrChunks.push(d); });
tar.stderr.on("data", (d) => { stderrChunks.push(d); });
function cleanup() {
try { fs.unlinkSync(listPath); } catch { /* ok */ }
}
sshProc.on("close", (code) => {
cleanup();
if (code !== 0) {
const msg = Buffer.concat(stderrChunks).toString().trim();
reject(new Error(msg || `ssh exited with code ${code}`));
} else {
resolve();
}
});
sshProc.on("error", (err) => { cleanup(); reject(err); });
tar.on("error", (err) => { cleanup(); sshProc.kill(); reject(err); });
});
}
async function deploy() {
// 1. Убедиться, что целевая директория существует
console.log("Проверка соединения...");
await ssh([`mkdir -p ${TARGET_DIR}`]);
// 2. Сравнить локальные файлы с манифестом
console.log("Сканирование...");
const localFiles = scanFiles(SOURCE_DIR);
const manifest = loadManifest();
const changedPaths = [];
for (const f of localFiles) {
const prev = manifest[f.relPath];
if (!prev || prev.mtime !== f.mtime || prev.size !== f.size) {
changedPaths.push(f.relPath);
}
}
const localPaths = new Set(localFiles.map((f) => f.relPath));
const removedPaths = Object.keys(manifest).filter((p) => !localPaths.has(p));
if (changedPaths.length === 0 && removedPaths.length === 0) {
console.log("Изменений нет — деплой не требуется.");
return;
}
console.log(`Изменено/новых: ${changedPaths.length}, удалено: ${removedPaths.length}`);
// 3. Загрузить изменённые файлы одним tar-пайпом
if (changedPaths.length > 0) {
console.log("Загрузка файлов...");
await uploadViaTar(changedPaths, SOURCE_DIR);
console.log("Загрузка завершена.");
}
// 4. Удалить файлы, которых больше нет локально
if (removedPaths.length > 0) {
console.log("Удаление лишних файлов...");
const rmList = removedPaths.map((p) => `${TARGET_DIR}/${p}`).join(" ");
await ssh([`rm -f ${rmList}`]);
await ssh([`find ${TARGET_DIR} -type d -empty -delete 2>/dev/null || true`]);
}
// 5. Обновить манифест
saveManifest(
Object.fromEntries(localFiles.map((f) => [f.relPath, { mtime: f.mtime, size: f.size }])),
);
}
const relDir = path.relative(projectRoot, SOURCE_DIR);
deploy()
.then(() => {
console.log(`Готово: ${relDir}/ → ${SSH_HOST}:${TARGET_DIR}`);
})
.catch((err) => {
console.error("Ошибка деплоя:", err.message || err);
process.exit(1);
});
+63
View File
@@ -0,0 +1,63 @@
import puppeteer from 'puppeteer';
import { fileURLToPath } from 'url';
import { dirname, resolve } from 'path';
const __dirname = dirname(fileURLToPath(import.meta.url));
const OUT = resolve(__dirname, '../public/assets/resume/Mamadaev_Nik__CV__Product_Designer_UX-UI.pdf');
const PAGE = process.argv[2] || 'http://localhost:4175/resume-5.html';
const FONT = process.argv[3] || 'geologica';
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto(PAGE, { waitUntil: 'networkidle0', timeout: 30000 });
await page.waitForSelector('.resume-doc', { timeout: 5000 });
await page.evaluate((font) => {
localStorage.setItem('siteThemeV1', JSON.stringify({ font }));
document.documentElement.dataset.font = font;
const href = `assets/fonts/${font}.css`;
if (!document.querySelector(`link[data-theme-font="${font}"]`)) {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = href;
link.dataset.themeFont = font;
document.head.appendChild(link);
}
}, FONT);
await page.evaluate(() => document.fonts.ready);
await new Promise(r => setTimeout(r, 1500));
const fontInfo = await page.evaluate(() => ({
dataFont: document.documentElement.dataset.font,
computedFont: getComputedStyle(document.body).fontFamily,
}));
console.log('Font:', fontInfo);
await page.evaluate(() => {
document.querySelectorAll('header, footer, nav, .fab-stack, .cookie-notice, .skip-link').forEach(el => el.remove());
const doc = document.querySelector('.resume-doc');
if (doc) {
doc.style.removeProperty('max-width');
doc.style.width = '100%';
doc.style.margin = '0';
doc.style.setProperty('background', 'transparent', 'important');
doc.style.border = 'none';
document.documentElement.style.setProperty('background', 'transparent', 'important');
document.body.style.background = 'transparent';
document.body.innerHTML = '';
document.body.appendChild(doc);
document.body.style.margin = '0';
document.body.style.padding = '0';
}
});
await page.pdf({
path: OUT,
format: 'A4',
printBackground: true,
margin: { top: '10mm', bottom: '10mm', left: '10mm', right: '10mm' }
});
await browser.close();
console.log('PDF saved:', OUT);
+53 -14
View File
@@ -1,7 +1,8 @@
/**
* Локальный сервер: public/ + BrowserSync + API правок контента (только localhost).
* Локальный сервер: public/ + API правок контента (только localhost).
* Фолбэк: нативный http без browser-sync (portscanner глючит на Node 23+).
*/
import browserSync from "browser-sync";
import http from "node:http";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
@@ -199,17 +200,55 @@ if (!fs.existsSync(PENDING_FILE)) {
}
migrateLegacyFiles();
browserSync.create().init({
server: {
baseDir: publicDir,
middleware: [contentEditsApi],
},
files: [path.join(publicDir, "**", "*")],
port: 4175,
ui: { port: 4176 },
notify: false,
open: false,
ghostMode: false,
const MIME = {
".html": "text/html; charset=utf-8",
".css": "text/css; charset=utf-8",
".js": "application/javascript; charset=utf-8",
".mjs": "application/javascript; charset=utf-8",
".json": "application/json; charset=utf-8",
".svg": "image/svg+xml",
".png": "image/png",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".webp": "image/webp",
".gif": "image/gif",
".ico": "image/x-icon",
".woff": "font/woff",
".woff2": "font/woff2",
".ttf": "font/ttf",
".mp4": "video/mp4",
".webm": "video/webm",
};
function serveStatic(req, res) {
const url = new URL(req.url || "/", "http://localhost");
let filePath = path.join(publicDir, decodeURIComponent(url.pathname));
if (filePath.endsWith(path.sep)) filePath = path.join(filePath, "index.html");
fs.stat(filePath, (err, stat) => {
if (err || !stat.isFile()) {
const fallback = path.join(publicDir, "index.html");
fs.readFile(fallback, (e2, data) => {
if (e2) { res.writeHead(404); res.end("Not found"); return; }
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
res.end(data);
});
return;
}
const ext = path.extname(filePath).toLowerCase();
const mime = MIME[ext] || "application/octet-stream";
fs.readFile(filePath, (e2, data) => {
if (e2) { res.writeHead(500); res.end("Error"); return; }
res.writeHead(200, { "Content-Type": mime });
res.end(data);
});
});
}
const server = http.createServer((req, res) => {
contentEditsApi(req, res, () => serveStatic(req, res));
});
console.log("serve-dev: http://localhost:4175 (public/, reload only public/**)");
server.listen(4175, () => {
console.log("serve-dev: http://localhost:4175 (public/)");
});
-162
View File
@@ -1,162 +0,0 @@
/**
* Копирует содержимое папки public в папку gitverse.
* Файлы `.png` не копируются (на GitVerse достаточно WebP и прочих ассетов).
*
* По умолчанию:
* node scripts/sync-gitverse.mjs
* (копирует projectRoot/public -> projectRoot/gitverse)
*
* Можно передать свои пути:
* node scripts/sync-gitverse.mjs <sourceDir> <targetDir>
*/
import path from "node:path";
import os from "node:os";
import fsp from "node:fs/promises";
import { execFile, spawn } from "node:child_process";
import { fileURLToPath } from "node:url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const projectRoot = path.resolve(__dirname, "..");
const PRESERVE_IN_TARGET = new Set([".git", ".gitverse"]);
function shouldSkipGitverseFile(fileName) {
return path.extname(fileName).toLowerCase() === ".png";
}
const DEFAULT_SSH_KEY_PATH = path.join(os.homedir(), ".ssh", "id_ed25519_work");
const GITVERSE_SITE_URL = "https://mamadaevv.gitverse.site/me/";
/** Системный браузер по умолчанию (Windows / macOS / Linux). */
function openUrlInDefaultBrowser(url) {
if (typeof url !== "string" || !/^https?:\/\//i.test(url)) return;
const opts = { detached: true, stdio: "ignore" };
let child;
if (process.platform === "win32") {
child = spawn("cmd", ["/c", "start", "", url], opts);
} else if (process.platform === "darwin") {
child = spawn("open", [url], opts);
} else {
child = spawn("xdg-open", [url], opts);
}
child?.unref();
}
function resolveDir(input, fallback) {
const raw = input ?? fallback;
return path.isAbsolute(raw) ? raw : path.resolve(projectRoot, raw);
}
async function ensureDirExists(dirPath, label) {
try {
const st = await fsp.stat(dirPath);
if (!st.isDirectory()) {
throw new Error(`${label} не является папкой: ${dirPath}`);
}
} catch (error) {
if (error && error.code === "ENOENT") {
throw new Error(`${label} не найдена: ${dirPath}`);
}
throw error;
}
}
async function cleanTargetDir(targetDir) {
await fsp.mkdir(targetDir, { recursive: true });
const entries = await fsp.readdir(targetDir, { withFileTypes: true });
for (const entry of entries) {
if (PRESERVE_IN_TARGET.has(entry.name)) continue;
const fullPath = path.join(targetDir, entry.name);
await fsp.rm(fullPath, { recursive: true, force: true });
}
}
async function copyDirFiltered(sourceDir, targetDir) {
await fsp.mkdir(targetDir, { recursive: true });
const entries = await fsp.readdir(sourceDir, { withFileTypes: true });
for (const entry of entries) {
const srcPath = path.join(sourceDir, entry.name);
const dstPath = path.join(targetDir, entry.name);
if (entry.isDirectory()) {
await copyDirFiltered(srcPath, dstPath);
continue;
}
if (!entry.isFile() || shouldSkipGitverseFile(entry.name)) continue;
await fsp.copyFile(srcPath, dstPath);
}
}
function runGit(args, cwd) {
return new Promise((resolve, reject) => {
const gitEnv = {
...process.env,
GIT_SSH_COMMAND: `ssh -i "${DEFAULT_SSH_KEY_PATH}" -o IdentitiesOnly=yes`,
};
execFile("git", args, { cwd, encoding: "utf8", env: gitEnv }, (error, stdout, stderr) => {
if (error) {
reject(new Error((stderr || error.message || "").trim()));
return;
}
resolve((stdout || "").trim());
});
});
}
function makeCommitMessage() {
const now = new Date();
const y = now.getFullYear();
const m = String(now.getMonth() + 1).padStart(2, "0");
const d = String(now.getDate()).padStart(2, "0");
const hh = String(now.getHours()).padStart(2, "0");
const mm = String(now.getMinutes()).padStart(2, "0");
return `sync public ${y}-${m}-${d} ${hh}:${mm}`;
}
async function commitAndPush(targetDir) {
const gitDir = path.join(targetDir, ".git");
await ensureDirExists(gitDir, "Git репозиторий (.git)");
try {
await fsp.access(DEFAULT_SSH_KEY_PATH);
} catch {
throw new Error(`SSH-ключ не найден: ${DEFAULT_SSH_KEY_PATH}`);
}
await runGit(["add", "."], targetDir);
const changed = await runGit(["status", "--porcelain"], targetDir);
if (!changed) {
console.log("Изменений для коммита нет.");
return;
}
const message = makeCommitMessage();
await runGit(["commit", "-m", message], targetDir);
await runGit(["push"], targetDir);
console.log(`Коммит и пуш выполнены: ${message}`);
openUrlInDefaultBrowser(GITVERSE_SITE_URL);
console.log(`Открыт в браузере: ${GITVERSE_SITE_URL}`);
}
async function main() {
const sourceDir = resolveDir(process.argv[2], "public");
const targetDir = resolveDir(process.argv[3], "gitverse");
await ensureDirExists(sourceDir, "Исходная папка");
if (sourceDir === targetDir) {
throw new Error("Исходная и целевая папки совпадают.");
}
await cleanTargetDir(targetDir);
await copyDirFiltered(sourceDir, targetDir);
console.log(
`Синхронизировано: ${path.relative(projectRoot, sourceDir)} -> ${path.relative(projectRoot, targetDir)} (сохранены .git и .gitverse)`,
);
await commitAndPush(targetDir);
}
main().catch((error) => {
console.error("Ошибка копирования:", error.message || error);
process.exit(1);
});
+1 -1
View File
@@ -377,7 +377,7 @@
<h3>Дальнейшее развитие</h3>
<p class="section__prose">
В дорожной карте оставались отдельные крупные куски: сценарии вокруг LLM (списки, статусы, действия), пошаговый мастер обучения с прогрессом и отменой, а также полноценный контур OCR с разметкой регионов и превью качества на странице. Они не входили в минимальный набор для первого промышленного релиза интерфейса, но заложенные паттерны должны их принять без ломки навигации.
В дорожной карте оставались отдельные крупные куски: сценарии вокруг LLM (списки, статусы, действия), пошаговый мастер обучения с прогрессом и отменой, а также полноценный контур OCR с разметкой регионов и превью качества на странице. Они не входили в минимальный набор для первого промышленного релиза интерфейса, но заложенные паттерны должны их принять без больших переделок.
</p>
</div>
@@ -0,0 +1,552 @@
<!DOCTYPE html>
<html lang="ru" data-theme="dark" data-radius="medium" data-font="merriweather">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta
name="description"
content="Кейс: редизайн Primo RPA AI Server — снижение порога входа для клиентов без команды внедрения."
/>
<title>AI Server в Primo RPA — кейс</title>
{{> head-links}}
{{> head-plyr}}
<style>
.case-article {
max-width: 48rem;
margin: 0 auto;
}
.case-article h2 {
margin: 2rem 0 0.75rem;
font-size: clamp(1.7rem, 3vw, 2rem);
font-weight: 700;
color: var(--text);
}
.case-article h3 {
font-size: 1.55rem;
font-weight: 600;
color: var(--text);
}
.case-article .section__prose {
margin-bottom: 0.75rem;
font-size: 1.1rem;
line-height: 1.7;
color: var(--text);
}
.case-article img,
.case-article video {
display: block;
max-width: 100%;
height: auto;
margin: 0.75rem 0 1rem;
}
.case-article ul,
.case-article ol {
margin: 0.5rem 0 1rem 1.25rem;
padding: 0;
}
.case-article li {
margin-bottom: 0.35rem;
font-size: 1.1rem;
line-height: 1.7;
}
.case-article a:not(.btn) {
color: var(--accent);
}
.case-meta {
display: grid;
grid-template-columns: auto 1fr;
gap: 0.25rem 0.75rem;
margin: 1.25rem 0 1.5rem;
font-size: 1.05rem;
line-height: 1.6;
color: var(--text-muted);
}
.case-meta dt {
font-weight: 600;
color: var(--text);
}
.case-meta dd {
margin: 0;
}
</style>
<script>
(function () {
try {
var t = JSON.parse(localStorage.getItem("siteThemeV1") || "{}");
var d = document.documentElement;
var m = t.mode;
if (m !== "light" && m !== "dark" && m !== "system") m = "system";
var eff =
m === "system"
? window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light"
: m;
d.dataset.theme = eff;
var h = typeof t.h === "number" ? t.h : typeof t.hue === "number" ? t.hue : null;
var s = typeof t.s === "number" ? t.s : typeof t.sat === "number" ? t.sat : null;
var l = typeof t.l === "number" ? t.l : typeof t.light === "number" ? t.light : null;
if (h !== null) d.style.setProperty("--theme-h", String(h));
if (s !== null) d.style.setProperty("--theme-s", String(s));
if (l !== null) {
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
} else {
d.dataset.radius = "medium";
}
var f = t.font;
if (f === "onest") f = "geologica";
if (f === "anonymous") f = "mono";
if (f === "merriweather" || f === "mono" || f === "geologica") {
d.dataset.font = f;
} else {
d.dataset.font = "merriweather";
}
var mb = t.meshBg;
if (mb === "off") {
d.dataset.meshBg = "off";
} else {
d.dataset.meshBg = "on";
}
} catch (e) {}
})();
</script>
</head>
<body>
{{> header-case}}
{{> fab-stack}}
<main id="case-main" class="section section--tight">
<div class="section__inner case-article">
<p class="hero__eyebrow">Product Design · AI</p>
<h1 class="case-page__h1">Упростил настройку Primo RPA AI Server: клиенты настраивают ИИ-сервис без команды внедрения</h1>
<p class="case-page__sub">
Платформа интеллектуальной обработки документов<br />
и оркестрации ИИ-агентов. Обращения к команде внедрения упали на 40%, настройка первого проекта ужалась с ~3 дней до ~4 часов.
</p>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/main-new.webp"
alt="Обновлённый редактор разметки датасета — главный экран сервиса после редизайна"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
</figure>
<dl class="case-meta">
<dt>Продукт</dt>
<dd>AI Server. Нейросети во внутреннем контуре компании, настраивается через веб-интерфейс</dd>
<dt>Роль</dt>
<dd>UX/UI-дизайнер (единственный на проекте)</dd>
<dt>Задача</dt>
<dd>Снизить порог входа, чтобы клиент настраивал сервис сам</dd>
<dt>Стек</dt>
<dd>Ant Design + React, стилизация Hope UI</dd>
<dt>Формат</dt>
<dd>Редизайн живого продукта, релизы не останавливались</dd>
</dl>
<div class="case-block" id="problem">
<h2>С настройкой справлялись только эксперты. Это тормозило продажи</h2>
<p class="section__prose">
AI Server разворачивается на внутренних серверах клиентов. Продукт активно тестировали, и обратная связь показала неприятное: настроить его могли только эксперты и команда внедрения Primo RPA. Каждый новый клиент съедал часы техподдержки. Продукт терял привлекательность и плохо масштабировался.
</p>
<aside class="case-callout" data-callout>
<span class="case-callout__emoji case-callout__emoji--pulse" aria-hidden="true">✅</span>
<div class="case-callout__content">
<p>
Бизнес-цель: клиент проходит настройку AI Server сам, без техподдержки и команды внедрения. По этому критерию мы и мерили успех редизайна.
</p>
</div>
</aside>
<p class="section__prose">
Начал со знакомства с командой и экспертами по настройке. Разделил сценарии на главные и вспомогательные, собрал визуализацию того, как ведёт себя пользователь, и вместе с разработкой искал, где интерфейс можно упростить. Я уже работал с ИИ и похожими веб-платформами, поэтому быстро разобрался в домене и говорил с разработкой на одном языке.
</p>
</div>
<div class="case-block" id="constraints">
<h2>Ограничения</h2>
<ul>
<li>Продуктом уже пользовались клиенты. Остановить разработку и пересобрать интерфейс целиком было нельзя.</li>
<li>Изменения приходилось вписывать в план релизов, отдельного «редизайн-спринта» никто не выделял.</li>
<li>Жёсткий стек: Ant Design под React со стилизацией под Hope UI. Новые компоненты рисовать только в крайнем случае, сначала выжимаем всё из готовой библиотеки.</li>
</ul>
</div>
<div class="case-block" id="navigation">
<h2>Навигация путала: разделы проекта смешивались с главным меню</h2>
<p class="section__prose">
В сервисе стояла привычная для админок схема: слева боковое меню, справа контент. Пространство расходовалось расточительно, а при открытии проекта навигация по его разделам оказывалась вперемешку с главной. Пользователь терялся.
</p>
<aside class="case-callout" data-callout>
<span class="case-callout__emoji" aria-hidden="true">💡</span>
<div class="case-callout__content">
<p>
Две навигации в одном боковом меню заставляли каждый раз разбираться, «где я». Развёл их по уровням: главная сверху, проектная внутри проекта.
</p>
</div>
</aside>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/main-new.webp"
alt="Главный экран AI Server с компактной верхней навигацией"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Главный экран AI Server с компактной верхней навигацией — список проектов занимает почти всю ширину экрана</figcaption>
</figure>
<p class="section__prose">
Перенёс главную навигацию наверх и ужал её. Контенту стало заметно просторнее, а схема осталась привычной. У проектов появилась собственная навигация, которая с главной не пересекается.
</p>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/nav-project-nlp.webp"
alt="Внутренняя навигация NLP-проекта"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Внутренняя навигация NLP-проекта — горизонтальные пункты-шаги под главным меню</figcaption>
</figure>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/nav-project-ocr.webp"
alt="Внутренняя навигация OCR-проекта"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Внутренняя навигация OCR-проекта — тот же паттерн со своим набором разделов</figcaption>
</figure>
<aside class="case-callout" data-callout>
<span class="case-callout__emoji case-callout__emoji--pulse" aria-hidden="true">✨</span>
<div class="case-callout__content">
<p>
Стрелочная форма пунктов подсказывает порядок настройки, но не навязывает его: разделы остаются обычными табами. Подсказка без принуждения.
</p>
</div>
</aside>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/nav-secondary-detail_view.webp"
alt="Крупный план вторичной навигации — пункты в форме стрелок"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Крупный план вторичной навигации — пункты в форме стрелок, ведущих слева направо</figcaption>
</figure>
</div>
<div class="case-block" id="editor">
<h2>Редактор датасета: экран, где пользователи живут</h2>
<p class="section__prose">
Здесь проводят больше всего времени. Разметка полей на сотнях изображений — работа монотонная, но именно от неё зависит качество данных для обучения модели. Прежний редактор выбивался из общего стиля, выглядел перегруженно и путал в работе с полями.
</p>
<p class="section__prose">
Разобрал редактор на микросценарии, выстроил их по приоритету и связкам. Вместе с командой спроектировали поведение плавнее и понятнее, заложили место под будущий функционал, дизайн привели к общей стилистике сервиса.
</p>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/dataset-editor.webp"
alt="Редактор разметки датасета — размечаемый документ в центре, панели полей и инструментов по бокам"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Редактор разметки датасета — размечаемый документ в центре, панели полей и инструментов по бокам</figcaption>
</figure>
<p class="section__prose">
Страница стала симметричной. Почти всё пространство уходит на размечаемое изображение, действия сгруппированы по панелям: нужная функция ищется быстро.
</p>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/dataset_editor-wireframe-default_mode.webp"
alt="Схематичный каркас редактора — центральная рабочая область и боковые панели"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Схематичный каркас редактора — центральная рабочая область и боковые панели, режим по умолчанию</figcaption>
</figure>
<p class="section__prose">
Для продвинутых пользователей добавил режим «Во весь экран». Боковые панели сворачиваются, работа идёт через горячие клавиши и нижнюю панель. На небольших мониторах это спасает.
</p>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/full-screen-mode-with-panels.webp"
alt="Полноэкранный режим редактора с раскрытыми боковыми панелями"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Полноэкранный режим редактора с раскрытыми боковыми панелями</figcaption>
</figure>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/full-screen-mode-zen.webp"
alt="Полноэкранный режим без панелей — только размечаемый документ и нижняя панель"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Полноэкранный режим без панелей — на экране только размечаемый документ и нижняя панель инструментов</figcaption>
</figure>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/dataset_editor-wireframe-zen_mode-both_panels.webp"
alt="Четыре варианта каркаса полноэкранного режима"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Четыре варианта каркаса полноэкранного режима — обе панели, без панелей, только левая, только правая</figcaption>
</figure>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/dataset_editor-main_toolbar.webp"
alt="Нижняя панель инструментов — переключение между изображениями и быстрые действия разметки"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Нижняя панель инструментов — переключение между изображениями и быстрые действия разметки</figcaption>
</figure>
</div>
<div class="case-block" id="mapping">
<h2>Десятки полей на одном скане, и место под документ не страдает</h2>
<p class="section__prose">
Смежная задача: настроить уникальные параметры полей датасета. Большая область нужна под скан документа, полей десятки, у каждого свои типы и зависимые параметры.
</p>
<figure class="case-media" style="margin: 0.85rem 0 1.2rem">
<div class="case-video-shell">
<video
controls
preload="metadata"
playsinline
poster="../assets/ai-platform-primo-rpa/fields-maping.webp"
data-case-video-player
style="display: block; width: 100%; height: auto; margin: 0"
>
<source src="../assets/ai-platform-primo-rpa/fields-maping.webm" type="video/webm" />
<source src="../assets/ai-platform-primo-rpa/fields-maping.mp4" type="video/mp4" />
Ваш браузер не поддерживает видео.
</video>
</div>
<figcaption>Прототип сопоставления полей — пользователь выбирает поле на скане документа и настраивает его параметры в компактной панели</figcaption>
</figure>
<p class="section__prose">
Интерфейс вышел компактным. Механика не считывается с первого взгляда, зато после короткого обучения работать в нём быстро и комфортно.
</p>
</div>
<div class="case-block" id="learning">
<h2>Карточки обучения: паттерн, который разошёлся по всему продукту</h2>
<p class="section__prose">
После разметки датасета модель дообучают (fine-tuning). Разобрали все действия пользователя, перебрали несколько компоновок страницы. Остановились на ленте из карточек.
</p>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/in_project-learn-overview.webp"
alt="Раздел обучения моделей — вертикальная лента карточек"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Раздел обучения моделей — вертикальная лента карточек, сверху карточка настройки нового обучения</figcaption>
</figure>
<p class="section__prose">
В начале ленты карточка настройки: результат разметки активного датасета, параметры, запуск fine-tuning.
</p>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/in_project-learn-card-new.webp"
alt="Карточка настройки обучения — матрица качества датасета и блок параметров запуска"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Карточка настройки обучения — матрица качества датасета и блок параметров запуска</figcaption>
</figure>
<aside class="case-callout" data-callout>
<span class="case-callout__emoji case-callout__emoji--pulse" aria-hidden="true">⭐</span>
<div class="case-callout__content">
<p>
Матрица оценки качества разметки показывает готовность датасета к обучению на одном экране. Раньше приходилось вручную просматривать поля по всем документам.
</p>
</div>
</aside>
<p class="section__prose">
Под каждый запущенный процесс появляется своя карточка. Можно завести несколько процессов с разными параметрами и сравнить, какая конфигурация отработала лучше.
</p>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/in_project-learn-card-learning_process.webp"
alt="Карточка запущенного процесса обучения — статус, прогресс и метрики"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Карточка запущенного процесса обучения — статус, прогресс и метрики, разнесённые по логическим блокам</figcaption>
</figure>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/in_project-learn-card-learning_process_wireframe.webp"
alt="Каркас карточки процесса обучения"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Каркас карточки процесса обучения — схема расположения информационных блоков и действий</figcaption>
</figure>
<p class="section__prose">
Карточки сворачиваются, в шапке остаются название и статус.
</p>
<figure class="case-media case-media--natural">
<img
src="../assets/ai-platform-primo-rpa/in_project-learn-card-сollapsed.webp"
alt="Свёрнутая карточка обучения — одна строка с названием и статусом процесса"
width="1200"
height="675"
loading="lazy"
decoding="async"
/>
<figcaption>Свёрнутая карточка обучения — одна строка с названием и статусом процесса</figcaption>
</figure>
<p class="section__prose">
Паттерны из этих карточек потом разошлись по другим разделам продукта. Единый стиль стало проще держать.
</p>
</div>
<div class="case-block" id="processes">
<h2>Долгие процессы — в соседнюю вкладку</h2>
<p class="section__prose">
Часть задач идёт параллельно с остальной работой. Для таких сценариев модальное окно открывается на отдельной странице.
</p>
<aside class="case-callout" data-callout>
<span class="case-callout__emoji" aria-hidden="true">💡</span>
<div class="case-callout__content">
<p>
Пользователь держит окно процесса в соседней вкладке и следит за прогрессом, а с проектом продолжает работать в доступных разделах.
</p>
</div>
</aside>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/fullscreen_modal-import_dataset.webp"
alt="Импорт датасета в модальном окне на отдельной странице"
width="1440"
height="1024"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Импорт датасета в модальном окне на отдельной странице — форма загрузки на весь экран</figcaption>
</figure>
<p class="section__prose">
На странице проекта в это время висит заглушка с кнопкой перехода к процессу.
</p>
<figure class="case-media case-media--wide">
<img
src="../assets/ai-platform-primo-rpa/fullscreen_modal-in_project-import_dataset.webp"
alt="Заглушка активного импорта внутри проекта"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Заглушка активного импорта внутри проекта — индикатор процесса и кнопка перехода</figcaption>
</figure>
</div>
<div class="case-block" id="decisions">
<h2>Что я решил не делать, и почему</h2>
<ul>
<li><strong>Не стал блокировать кнопки на отдельных страницах</strong> во время активных процессов. Модалка на отдельной странице технически проще, а прогресс виден в соседней вкладке.</li>
<li><strong>Не рисовал новые компоненты</strong>, кроме крайних случаев. Готовая библиотека Ant Design ускоряла разработку и держала интерфейс консистентным.</li>
<li><strong>Не убрал боковые панели редактора совсем</strong>, а сделал сворачиваемыми. Новичкам нужны подсказки на экране, продвинутым — максимум места под документ.</li>
<li><strong>Не заводил отдельную дизайн-систему.</strong> В продукте уже был фреймворк, в разработку передавал ссылки на готовые юзерфлоу в Figma.</li>
</ul>
<h3>Передача в разработку</h3>
<p class="section__prose">
Раз в неделю обсуждали дизайн с командой: список задач, приоритеты, сроки под планы релизов. С верстальщиком уточнял детали макетов тет-а-тет и давал фидбэк после вёрстки, чтобы результат не разошёлся с задуманным поведением.
</p>
</div>
<div class="case-block" id="results">
<h2>Результат</h2>
<aside class="case-callout" data-callout>
<span class="case-callout__emoji case-callout__emoji--pulse" aria-hidden="true">📈</span>
<div class="case-callout__content">
<p>
Настройка первого проекта: было ~3 дня, стало ~4 часа. 7 из 10 клиентов проходят её без техподдержки.
</p>
</div>
</aside>
<ul>
<li>Обращения к команде внедрения на этапе настройки сократились на <strong>40%</strong>. Базовую настройку клиенты проходят сами.</li>
<li><strong>7 из 10</strong> новых клиентов настроили первый проект без техподдержки. До редизайна — 1 из 10.</li>
<li>Настройка первого проекта: с <strong>~3 дней до ~4 часов</strong>.</li>
<li>Переработано <strong>30+ экранов</strong>: навигация, редактор датасета, обучение моделей, импорт данных.</li>
<li>Заложены паттерны, на которых функционал наращивается без больших переделок.</li>
<li>В компанию наняли второго дизайнера. Я ввёл её в курс дела и курировал результат, после адаптации проект целиком перешёл под её ответственность.</li>
</ul>
</div>
<div class="case-block" id="conclusions">
<h2>Выводы</h2>
<ul>
<li>Жёсткий фреймворк оказался не ограничением, а ускорителем: готовая библиотека компонентов позволила думать о сценариях, а не о пикселях.</li>
<li>Самые ценные инсайты дали эксперты по настройке. В следующий раз вовлёк бы команду внедрения ещё раньше.</li>
<li>Передача проекта новому дизайнеру подтвердила: заложенные паттерны работают, их можно объяснить и поддерживать без автора.</li>
</ul>
</div>
</div>
</main>
{{> projects-section-mp}}{{> projects-section}}
{{> contact-section}}
{{> footer-spacer}}
{{> footer}}
{{> cookie-notice}}
{{> nav-more-floating}}
</body>
</html>
+14 -2
View File
@@ -37,7 +37,7 @@
margin: 0 0 1.15rem;
padding-top: clamp(2.75rem, 6vw, 4rem);
font-family: var(--font);
font-size: clamp(1.15rem, 2vw, 1.35rem);
font-size: clamp(1.7rem, 3vw, 2rem);
font-weight: 700;
color: var(--text);
scroll-margin-top: 1.5rem;
@@ -52,7 +52,7 @@
.case-article.ds-page > h3 {
margin: clamp(2rem, 4vw, 2.75rem) 0 0.85rem;
font-family: var(--font);
font-size: 1.05rem;
font-size: 1.55rem;
font-weight: 600;
color: var(--text);
}
@@ -368,6 +368,7 @@
<li><a href="#fonts">Шрифты</a></li>
<li><a href="#layout">Сетка и адаптив</a></li>
<li><a href="#components">Компоненты</a></li>
<li><a href="#fab">FAB-кнопки</a></li>
<li><a href="#blocks">Блоки</a></li>
<li><a href="#mini-projects">Активность</a></li>
</ol>
@@ -700,6 +701,17 @@
</div>
<p class="sg-label">.btn .btn--primary | secondary | ghost · .btn--flat | raised · .btn__icon</p>
<h3>FAB-кнопки</h3>
<p class="section__prose">
Плавающие кнопки в правом нижнем углу (<code>.fab-stack</code>). Иконка-only и с текстовой подписью.
</p>
<div class="sg-stack sg-stack--row">
<a class="fab fab--primary" href="#components" aria-label="Демо FAB"><span class="fab-primary__ico" aria-hidden="true"></span></a>
<button type="button" class="fab fab--primary fab--label"><span class="fab-primary__ico" aria-hidden="true"></span><span class="fab__label">Скачать в PDF</span></button>
<button type="button" class="fab fab--secondary" aria-label="Демо secondary FAB"><span class="theme-panel-fab__icon theme-panel-fab__icon--open-hide" aria-hidden="true"></span></button>
</div>
<p class="sg-label">.fab .fab--primary | secondary · .fab--label (с текстом) · .fab-primary__ico · .fab__label</p>
<h3>Теги</h3>
<ul class="hero__tags" aria-label="Демо тегов">
<li class="hero__tag">hero__tag</li>
+1 -1
View File
@@ -114,7 +114,7 @@
</p>
<h2 id="obzor">Обзор</h2>
<p class="section__prose">Общий вид приложения — отправная точка для остальных материалов на странице.</p>
<p class="section__prose">Общий вид приложения — рабочий процесс с открытым документом, панелями инструментов и canvas. Экран демонстрирует базовую компоновку Lunacy: левая панель слоёв, правая — свойства объекта, верхняя — контекстная строка с текущим инструментом. Отправная точка для остальных материалов на странице.</p>
<figure class="case-media case-media--wide">
<img
src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
+295 -30
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="ru" data-theme="dark" data-radius="medium" data-font="merriweather">
<head>
<meta charset="utf-8" />
@@ -166,9 +166,16 @@
background: color-mix(in srgb, var(--surface) 90%, var(--accent));
}
.mp-showcase-cells-demo__variant {
margin-bottom: 1.2rem;
}
.mp-showcase-cells-demo__variant:last-of-type {
margin-bottom: 0;
}
.mp-showcase-cells-demo__legend {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 0.5rem;
margin-bottom: 0.85rem;
font-size: 0.72rem;
@@ -176,25 +183,50 @@
text-align: center;
}
.mp-showcase-cells-demo__legend--6 {
grid-template-columns: repeat(6, 1fr);
}
.mp-showcase-cells-demo__legend--4 {
grid-template-columns: repeat(4, 1fr);
}
.mp-showcase-cells-demo__legend--2 {
grid-template-columns: repeat(2, 1fr);
}
.mp-showcase-cells-demo__legend span {
padding: 0.2rem 0;
border-radius: var(--radius-sm);
background: color-mix(in srgb, var(--line) 35%, transparent);
}
.mp-showcase-cells-demo__row {
.mp-showcase-cells-demo__row-label {
font-size: 0.82rem;
font-weight: 600;
color: var(--text);
margin: 0 0 0.55rem;
}
.mp-showcase-cells-demo__grid {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 0.5rem;
margin-bottom: 0.55rem;
}
.mp-showcase-cells-demo__row:last-of-type {
margin-bottom: 0;
.mp-showcase-cells-demo__grid--6 {
grid-template-columns: repeat(6, 1fr);
}
.mp-showcase-cells-demo__grid--4 {
grid-template-columns: repeat(4, 1fr);
}
.mp-showcase-cells-demo__grid--2 {
grid-template-columns: repeat(2, 1fr);
}
.mp-showcase-cells-demo__block {
grid-row: 1;
min-height: 2.35rem;
display: flex;
align-items: center;
@@ -219,6 +251,10 @@
grid-column: span 3;
}
.mp-showcase-cells-demo__block--4 {
grid-column: span 4;
}
.mp-showcase-cells-demo__caption {
margin: 0.85rem 0 0;
font-size: 0.82rem;
@@ -275,12 +311,13 @@
<li><a href="#types">Типы карточек</a></li>
<li><a href="#cells">Ширина в клетках</a></li>
<li><a href="#grid">Живая сетка masonry</a></li>
<li><a href="#fixed-height">Фиксированная высота</a></li>
</ol>
</nav>
<h2 id="intro">Как пользоваться</h2>
<p class="section__prose">
Сначала выберите <strong>тип</strong> (stack, horizontal, compact, decor), затем <strong>data-mp-cells</strong> (1–3) и
Сначала выберите <strong>тип</strong> (stack, horizontal, compact, decor), затем <strong>data-mp-cells</strong> (1–4) и
порядок <code>li</code> в списке. Карточки с <code>data-mp-extra</code> не влияют на высоту списка до кнопки «Показать все».
Подробности — в <code>docs/mini-projects-cards.md</code>.
</p>
@@ -293,35 +330,95 @@
<h2 id="cells">Ширина в клетках</h2>
<p class="section__prose">
Атрибут <code>data-mp-cells</code> на <code>li.mini-projects-grid__item</code> задаёт желаемую ширину от 1 до 3 клеток.
Атрибут <code>data-mp-cells</code> на <code>li.mini-projects-grid__item</code> задаёт желаемую ширину от 1 до 4 клеток.
Скрипт не даст карточке быть шире текущего ряда.
</p>
<p class="section__prose">
Для адаптивной ширины используйте <code>data-mp-cells-sm</code> (при 4 клетках в ряду, ≥ 880 px) и
<code>data-mp-cells-xs</code> (при 2 клетках, ≥ 520 px). Скрипт выбирает значение по текущему числу клеток в ряду.
</p>
<div class="mp-showcase-attrs-table">
<table class="mp-showcase-cells-table">
<thead>
<tr>
<th scope="col">Атрибут</th>
<th scope="col">Когда применяется</th>
<th scope="col">Пример</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>data-mp-cells</code></td>
<td>Широкий экран (6 клеток, ≥ 1180 px)</td>
<td><code>data-mp-cells="3"</code></td>
</tr>
<tr>
<td><code>data-mp-cells-sm</code></td>
<td>Средний экран (4 клетки, ≥ 880 px)</td>
<td><code>data-mp-cells-sm="2"</code></td>
</tr>
<tr>
<td><code>data-mp-cells-xs</code></td>
<td>Узкий экран (2 клетки, ≥ 520 px)</td>
<td><code>data-mp-cells-xs="1"</code></td>
</tr>
</tbody>
</table>
</div>
<p class="section__prose" style="margin-top:0.55rem">
<strong>Пример:</strong> <code>data-mp-cells="3" data-mp-cells-sm="2"</code> — карточка занимает 3 клетки на широком экране, 2 на среднем, 1 на узком.
</p>
<figure class="mp-showcase-cells-demo" aria-label="Схема ширины карточек в клетках">
<div class="mp-showcase-cells-demo__legend" aria-hidden="true">
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
<span>6</span>
<div class="mp-showcase-cells-demo__variant">
<div class="mp-showcase-cells-demo__legend mp-showcase-cells-demo__legend--6" aria-hidden="true">
<span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span>
</div>
<p class="mp-showcase-cells-demo__row-label">≥ 1180 px — 6 клеток</p>
<div class="mp-showcase-cells-demo__grid mp-showcase-cells-demo__grid--6">
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--3">3</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--3">3</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--1">1</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--3">3</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--4">4</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
</div>
</div>
<p class="mp-showcase-cells-demo__row-label">Ряд из 6 клеток (широкий экран)</p>
<div class="mp-showcase-cells-demo__row">
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--3">3</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--3">3</div>
<div class="mp-showcase-cells-demo__variant">
<div class="mp-showcase-cells-demo__legend mp-showcase-cells-demo__legend--4" aria-hidden="true">
<span>1</span><span>2</span><span>3</span><span>4</span>
</div>
<p class="mp-showcase-cells-demo__row-label">≥ 880 px — 4 клетки</p>
<div class="mp-showcase-cells-demo__grid mp-showcase-cells-demo__grid--4">
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--3">3</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--1">1</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--1">1</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--4">4</div>
</div>
</div>
<div class="mp-showcase-cells-demo__row">
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
</div>
<div class="mp-showcase-cells-demo__row">
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--1">1</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--3">3</div>
<div class="mp-showcase-cells-demo__variant">
<div class="mp-showcase-cells-demo__legend mp-showcase-cells-demo__legend--2" aria-hidden="true">
<span>1</span><span>2</span>
</div>
<p class="mp-showcase-cells-demo__row-label">≥ 520 px — 2 клетки</p>
<div class="mp-showcase-cells-demo__grid mp-showcase-cells-demo__grid--2">
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--1">1</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--1">1</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--2">2</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--1">1</div>
<div class="mp-showcase-cells-demo__block mp-showcase-cells-demo__block--1">1</div>
</div>
</div>
<figcaption class="mp-showcase-cells-demo__caption">
Цифра в блоке = значение <code>data-mp-cells</code>. Карточка занимает столько клеток подряд в одном ряду.
Цифра в блоке = значение <code>data-mp-cells</code>. Карточка занимает столько клеток подряд. При узком экране клеток меньше — карточки с шириной &gt; число клеток переносятся на следующий ряд. С <code>data-mp-cells-sm</code> / <code>data-mp-cells-xs</code> карточка меняет ширину при сужении.
</figcaption>
</figure>
<table class="mp-showcase-cells-table">
@@ -369,6 +466,174 @@
{{> mini-projects-showcase-grid}}
</div>
</section>
<section id="fixed-height" class="section section--surface mp-showcase-grid-section" aria-labelledby="fixed-height-title">
<div class="section__inner">
<h2 id="fixed-height-title" class="section__title">Фиксированная высота</h2>
<p class="section__prose">
Атрибут <code>data-mp-height="…"</code> на <code>li.mini-projects-grid__item</code> задаёт фиксированную высоту карточки в пикселях. Текст обрезается с многоточием, если не влезает.
</p>
<ol
id="mini-projects-fixed-height-grid"
class="mini-projects-grid mp-showcase-grid"
data-mini-projects-list
>
<li class="mini-projects-grid__item" data-mp-cells="4" data-mp-cells-sm="4" data-mp-cells-xs="2" data-mp-height="600">
<a class="mp-card mp-card--link mp-card--stack" href="#" aria-label="[4→4→2] height=600 · stack · ссылка">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/shared/placeholder.webp"
alt=""
width="560"
height="315"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">
[4→4→2] height=600 · stack · ссылка
<span class="mp-card__ext" aria-hidden="true"></span>
</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">веб-сайт</li>
</ul>
<p class="mp-card__desc">4 → 4 → 2. data-mp-cells-sm="4" data-mp-cells-xs="2". Высота 600px.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2" data-mp-height="600" data-mp-height-sm="400">
<a class="mp-card mp-card--link mp-card--stack" href="#" aria-label="[2] height=600 · stack · ссылка">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/shared/placeholder.webp"
alt=""
width="560"
height="315"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">
[2] height=600 · stack · ссылка
<span class="mp-card__ext" aria-hidden="true"></span>
</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">заметка</li>
</ul>
<p class="mp-card__desc">Две клетки, высота 600px.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2" data-mp-height="400">
<a class="mp-card mp-card--link mp-card--stack" href="#" aria-label="[2] height=400 · stack · ссылка">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/shared/placeholder.webp"
alt=""
width="560"
height="315"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">
[2] height=400 · stack · ссылка
<span class="mp-card__ext" aria-hidden="true"></span>
</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">утилита</li>
</ul>
<p class="mp-card__desc">Две клетки, высота 400px.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2" data-mp-height="400">
<a class="mp-card mp-card--link mp-card--stack" href="#" aria-label="[2] height=400 · stack · ссылка">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/shared/placeholder.webp"
alt=""
width="560"
height="315"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">
[2] height=400 · stack · ссылка
<span class="mp-card__ext" aria-hidden="true"></span>
</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">шаблон</li>
</ul>
<p class="mp-card__desc">Две клетки, высота 400px.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="2" data-mp-height="400">
<a class="mp-card mp-card--link mp-card--stack" href="#" aria-label="[2] height=400 · stack · ссылка">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../assets/shared/placeholder.webp"
alt=""
width="560"
height="315"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">
[2] height=400 · stack · ссылка
<span class="mp-card__ext" aria-hidden="true"></span>
</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">плагин</li>
</ul>
<p class="mp-card__desc">Две клетки, высота 400px.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3" data-mp-cells-sm="2" data-mp-cells-xs="1">
<a class="mp-card mp-card--link mp-card--compact" href="#" aria-label="[3→2→1] · compact · ссылка">
<div class="mp-card__body">
<h3 class="mp-card__title">
[3→2→1] · compact · ссылка
<span class="mp-card__ext" aria-hidden="true"></span>
</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">плагин</li>
</ul>
<p class="mp-card__desc">3 → 2 → 1. data-mp-cells-sm="2" data-mp-cells-xs="1". Авто-высота.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3" data-mp-cells-sm="2" data-mp-cells-xs="1">
<a class="mp-card mp-card--link mp-card--compact" href="#" aria-label="[3→2→1] · compact · ссылка">
<div class="mp-card__body">
<h3 class="mp-card__title">
[3→2→1] · compact · ссылка
<span class="mp-card__ext" aria-hidden="true"></span>
</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">документ</li>
</ul>
<p class="mp-card__desc">3 → 2 → 1. data-mp-cells-sm="2" data-mp-cells-xs="1".</p>
</div>
</a>
</li>
</ol>
</div>
</section>
</main>
{{> footer-spacer}}
+3 -3
View File
@@ -36,7 +36,7 @@
<div class="hero__actions">
<a class="btn btn--primary btn--flat" href="#contact"><span class="btn__icon" aria-hidden="true"></span><span>Написать мне</span></a>
<a class="btn btn--secondary btn--flat" href="#projects"><span class="btn__icon" aria-hidden="true"></span><span>Смотреть портфолио</span></a>
<a class="btn btn--secondary btn--flat btn--resume" href="assets/mamadaevv_resume.pdf" download><span class="btn__icon" aria-hidden="true"></span><span>Резюме</span></a>
<a class="btn btn--secondary btn--flat btn--resume" href="resume-5.html"><span class="btn__icon" aria-hidden="true"></span><span>Резюме</span></a>
</div>
</div>
<div class="hero__visual" aria-hidden="true">
@@ -79,7 +79,7 @@
{{> projects-section-mp}}{{> projects-section}}
{{> mini-projects-section}}
<section id="skills" class="section section--tight" aria-labelledby="skills-title">
<section id="skills" class="section section--tight" aria-labelledby="skills-title" data-reveal>
<div class="section__inner">
<h2 id="skills-title" class="section__title">Навыки</h2>
<div
@@ -377,7 +377,7 @@
</div>
</section>
<section id="experience" class="section section--surface" aria-labelledby="experience-title">
<section id="experience" class="section section--surface" aria-labelledby="experience-title" data-reveal>
<div class="section__inner">
<h2 id="experience-title" class="section__title">Опыт работы</h2>
<ol id="experience-list" class="experience-grid">
+444
View File
@@ -0,0 +1,444 @@
<!DOCTYPE html>
<html lang="ru" data-theme="dark" data-radius="medium">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta
name="description"
content="Резюме Николая Мамадаева — продуктовый дизайнер с опытом более 10 лет."
/>
<title>Резюме 2 — Николай Мамадаев</title>
{{> head-links}}
<style>
.resume-doc {
max-width: 48rem;
margin: 0 auto;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--radius-card);
padding: clamp(1.5rem, 3vw, 2.5rem);
}
.resume-header {
display: flex;
gap: 1.5rem;
align-items: flex-start;
margin-bottom: 1.5rem;
flex-direction: row-reverse;
justify-content: flex-end;
}
.resume-photo {
width: 120px;
height: 120px;
border-radius: var(--radius-sm);
object-fit: cover;
border: 2px solid var(--line);
flex-shrink: 0;
}
@media (max-width: 32rem) {
.resume-header {
flex-direction: column;
align-items: center;
text-align: center;
}
.resume-photo {
width: 100px;
height: 100px;
}
}
.resume-doc h2 {
margin: 2rem 0 0.75rem;
font-size: clamp(1.15rem, 2vw, 1.35rem);
font-weight: 700;
color: var(--text);
}
.resume-doc .section__prose + .section__prose {
margin-top: 0.75rem;
}
.resume-doc .section__prose a {
color: var(--accent);
}
.resume-contacts {
display: flex;
flex-wrap: wrap;
gap: 0.25rem 1.5rem;
margin: 0.75rem 0 1.5rem;
font-size: 0.92rem;
color: var(--text-muted);
}
.resume-contacts span {
white-space: nowrap;
}
.resume-contacts a {
color: var(--accent);
}
.resume-meta {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem 1.5rem;
margin: 0.75rem 0 1.5rem;
font-size: 0.92rem;
color: var(--text-muted);
}
@media (max-width: 32rem) {
.resume-meta {
grid-template-columns: 1fr;
}
}
.resume-meta dt {
font-weight: 600;
color: var(--text);
}
.resume-meta dd {
margin: 0;
}
.resume-exp {
margin: 1.25rem 0;
}
.resume-exp__header {
margin-bottom: 0.5rem;
}
.resume-exp__company {
font-weight: 700;
color: var(--text);
}
.resume-exp__role {
font-style: italic;
color: var(--text-muted);
font-size: 0.92rem;
}
.resume-exp__period {
font-size: 0.85rem;
color: var(--text-muted);
margin-bottom: 0.35rem;
}
.resume-exp__desc {
color: var(--text-muted);
font-size: 0.92rem;
margin: 0.5rem 0;
}
.resume-exp ul {
margin: 0.35rem 0 0;
padding-left: 1.25rem;
color: var(--text-muted);
font-size: 0.92rem;
}
.resume-exp li + li {
margin-top: 0.25rem;
}
.resume-exp__skills {
margin-top: 0.5rem;
font-size: 0.85rem;
color: var(--text-muted);
}
.resume-exp__skills strong {
color: var(--text);
}
.resume-skills {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin: 0.75rem 0;
}
@media (max-width: 32rem) {
.resume-skills {
grid-template-columns: 1fr;
}
}
.resume-skill {
font-size: 0.92rem;
}
.resume-skill__title {
font-weight: 600;
color: var(--text);
margin-bottom: 0.15rem;
}
.resume-skill__desc {
color: var(--text-muted);
}
.resume-communities {
margin: 0.75rem 0;
}
.resume-community {
margin: 0.75rem 0;
font-size: 0.92rem;
}
.resume-community__name {
font-weight: 700;
color: var(--text);
}
.resume-community__period {
font-size: 0.85rem;
color: var(--text-muted);
}
.resume-community__desc {
color: var(--text-muted);
margin-top: 0.25rem;
}
.resume-edu {
margin: 0.5rem 0;
}
.resume-edu__school {
font-weight: 700;
color: var(--text);
}
.resume-edu__period {
font-size: 0.85rem;
color: var(--text-muted);
}
.resume-edu__spec {
font-size: 0.92rem;
color: var(--text-muted);
}
.resume-additional h3 {
margin: 1rem 0 0.35rem;
font-size: 1rem;
font-weight: 600;
color: var(--text);
}
.resume-additional ul {
margin: 0.25rem 0;
padding-left: 1.25rem;
color: var(--text-muted);
font-size: 0.92rem;
}
.resume-additional li + li {
margin-top: 0.25rem;
}
.resume-about {
margin: 1rem 0;
font-size: 0.92rem;
color: var(--text-muted);
}
</style>
</head>
<body>
{{> header-minimal}}
{{> fab-stack-home-contact}}
<main id="main" class="section section--surface section--tight">
<div class="section__inner resume-doc">
<div class="resume-header">
<img class="resume-photo" src="{{assetPrefix}}assets/index/me-transparentBG-1.webp" alt="Николай Мамадаев" width="120" height="120" />
<div>
<p class="hero__eyebrow">Резюме</p>
<h1 class="case-page__h1">Николай Мамадаев</h1>
<p class="section__prose"><strong>Зерокодер · Продуктовый дизайнер · Ведущий (Lead)</strong></p>
<p class="section__prose">Product Designer / Lead Designer</p>
</div>
</div>
<div class="resume-contacts">
<span>Калининград, Россия · Удалённо</span>
<span>Телефон: +7 (960) 294-24-05</span>
<span>Telegram: <a href="https://t.me/mamadaevv" target="_blank" rel="noopener">@mamadaevv</a></span>
<span>Email: <a href="mailto:nik@mamadaevv.site">nik@mamadaevv.site</a></span>
<span>Сайт: <a href="https://mamadaevv.site" target="_blank" rel="noopener">mamadaevv.site</a></span>
<span>Хабр Карьера: <a href="https://career.habr.com/mamadaevv" target="_blank" rel="noopener">career.habr.com/mamadaevv</a></span>
</div>
<dl class="resume-meta">
<div>
<dt>Стаж</dt>
<dd>10 лет</dd>
</div>
<div>
<dt>Возраст</dt>
<dd>36 лет</dd>
</div>
<div>
<dt>Готовность к работе</dt>
<dd>готов к удалённой работе</dd>
</div>
<div>
<dt>Зарплатные ожидания</dt>
<dd>от 270 000 ₽</dd>
</div>
</dl>
<h2 id="profile">О себе</h2>
<p class="section__prose resume-about">
В дизайне я более 10 лет, последние годы занимаюсь продуктовым дизайном. Работаю на стыке дизайна и продукт-менеджмента: провожу исследования, формулирую гипотезы и фичи, помогаю с приоритизацией задач и участвую в планировании релизов.
</p>
<p class="section__prose resume-about">
Для работы с дизайном интерфейсов использую Figma: в ней собираю прототипы, экраны и дизайн-системы, а затем передаю макеты в разработку. Собрал приватный плагин на базе ИИ для решения части рутинных задач.
</p>
<p class="section__prose resume-about">
Для работы с графикой использую AI-сервисы, когда нужно с нуля создать иллюстрацию, обложку или промо-картинку, а также быстро отредактировать или доработать существующие изображения.
</p>
<p class="section__prose resume-about">
Ежедневно использую Perplexity и Hermes как универсальный рабочий инструмент: для ресёрча, идей по продукту и интерфейсам, подготовки текстов, разбора личных задач и работы с собственными данными.
</p>
<h2 id="experience">Опыт работы</h2>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Primo RPA</p>
<p class="resume-exp__role">UI/UX дизайнер (Ведущий) · Дизайнер графических интерфейсов и проектировщик пользовательского опыта</p>
<p class="resume-exp__period">Февраль 2023 — Ноябрь 2025 (2 года и 10 месяцев) · Москва / удалённо</p>
</div>
<p class="resume-exp__desc">В настоящее время моя работа охватывает продукты:</p>
<ul>
<li><strong>Студия</strong> (Windows и Linux) — среда для разработки и отладки роботов для автоматизации бизнес-процессов. Сфера RPA.</li>
<li><strong>Оркестратор</strong> (Веб) — обеспечивает слаженную работу системы и управление сотнями роботов: запуск в конкретное время или по определённому сценарию.</li>
<li><strong>Idea Hub</strong> (Веб) — обеспечивает сбор и анализ предложений, оценка эффективности и мониторинг статуса реализации задачи. Аналитика по ключевым показателям эффективности и верхнеуровневый взгляд на роботизацию.</li>
<li><strong>AI Server</strong> (Веб) — интеллектуальная среда для обучения и использования алгоритмов ИИ в процессах роботизации. Готовый набор моделей для извлечения информации из документов различного типа (Smart OCR).</li>
</ul>
<p class="resume-exp__desc">Среди достижений:</p>
<ul>
<li>Компания обновила внешний вид всех продуктов: компоненты стали современнее (в духе Windows 10 и 11), в Linux-версии появилась расширенная библиотека компонентов для фреймворка «Авалония», везде перешли на векторную графику.</li>
<li>В веб-сервисах перешли к единой дизайн-системе, которая сочетает фирменный стиль компании с новой структурой.</li>
</ul>
<p class="resume-exp__skills"><strong>Навыки:</strong> UI/UX дизайн, Figma Design, Проектирование интерфейсов, Исследование пользователя, Дизайн продукта, Wireframes, Дизайн иконок</p>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Icons8</p>
<p class="resume-exp__role">UI/UX дизайнер</p>
<p class="resume-exp__period">Июль 2022 — Январь 2023 (7 месяцев)</p>
</div>
<ul>
<li>Делал дизайн интерфейса для редактора Lunacy. Оформлял в виде юзерфлоу и передавал разработчикам.</li>
<li>Делал сложные прототипы в Protopie.</li>
<li>Отрисовывал недостающие иконки.</li>
<li>Вносил предложения по улучшению функционала программы.</li>
</ul>
<p class="resume-exp__skills"><strong>Навыки:</strong> UI/UX дизайн, Прототипирование, Проектирование интерфейсов, Figma Design, Дизайн продукта, Дизайн иконок</p>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">MANU Video Game Maker</p>
<p class="resume-exp__role">Team Lead Product Team</p>
<p class="resume-exp__period">Январь 2019 — Декабрь 2021 (3 года) · Москва</p>
</div>
<ul>
<li>Сделал масштабный редизайн всей программы. Создал интерфейс с абсолютно новой концепцией работы и стилистикой. Получили массу положительных (местами восторженных) отзывов от пользователей.</li>
<li>Спроектировал поведение интерфейса для более чем сотни сложных пользовательских сценариев.</li>
<li>Спроектировал дизайн-систему.</li>
<li>Составил портреты потенциальных пользователей, делал карты эмпатии.</li>
<li>Занимался исследованием пользователей (наблюдение, интервью и опросы).</li>
<li>Работал с аналитикой и сбором продуктовых метрик.</li>
<li>Прособеседовал и набрал в продуктовый отдел новых специалистов. Стал тимлидом отдела.</li>
<li>Сверстал главную страницу сайта на Tilda. Проектировал информационную архитектуру сайта вместе с командой.</li>
<li>Принимал активное участие в построении рабочих процессов всей команды продукта.</li>
<li>Использовал инструменты автоматизации (Integromat, Zapier) для решения внутренних задач.</li>
<li>Курировал работы по созданию пользовательской документации.</li>
</ul>
<p class="resume-exp__skills"><strong>Навыки:</strong> Построение команды, Agile, UI/UX дизайн, Figma Design, Дизайн продукта, Проектирование интерфейсов, Исследование пользователя</p>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Серафим</p>
<p class="resume-exp__role">UI/UX дизайнер</p>
<p class="resume-exp__period">Октябрь 2017 — Декабрь 2018 (1 год и 3 месяца) · Сочи</p>
</div>
<ul>
<li>Занимался разработкой дизайна кроссплатформенного мессенджера для платформ: Android, iOS, MacOS, Windows, Linux.</li>
<li>Контролировал процесс работы с зарубежными иллюстраторами по подготовке графических материалов.</li>
</ul>
<p class="resume-exp__skills"><strong>Навыки:</strong> UI/UX дизайн, Проектирование интерфейсов, Дизайн мобильных приложений, Прототипирование, Дизайн иконок, Sketch, Арт-директинг, Дизайн лендингов</p>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Orion Innovation (ex MERA)</p>
<p class="resume-exp__role">UI/UX дизайнер</p>
<p class="resume-exp__period">Июль 2016 — Октябрь 2017 (1 год и 4 месяца) · Нижний Новгород</p>
</div>
<ul>
<li>Работал в отделе дизайна численностью до 8 человек.</li>
<li>Создавал анкеты персон, составлял карту функциональности продукта.</li>
<li>Делал вайрфрэймы и отрисовывал конечный UI интерфейсов.</li>
<li>Делал демонстрации микроанимаций.</li>
<li>Проектировал юзкейсы и делал карты экранов.</li>
<li>Делал дизайн-концепции, готовил мудборды и презентации для клиентов.</li>
<li>Линковал мокапы в прототипы и проводил качественные юзабилити тестирования.</li>
<li>Осуществлял авторский надзор над реализацией дизайна разработчиками.</li>
<li>Участвовал в дизайн-ревью, вносил предложения по улучшениям.</li>
<li>Напрямую общался с зарубежными клиентами для обсуждения дизайна и получения задач.</li>
<li>Изучил новую сферу — смарт ТВ. Сделал проект, который успешно опубликован в магазине приложений.</li>
</ul>
<p class="resume-exp__skills"><strong>Навыки:</strong> UI/UX дизайн, Веб-дизайн, Проектирование интерфейсов, Дизайн мобильных приложений, Sketch, Адаптивный дизайн, Дизайн иконок</p>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">SpaceshipApps</p>
<p class="resume-exp__role">UI/UX дизайнер</p>
<p class="resume-exp__period">Июнь 2015 — Июнь 2016 (1 год и 1 месяц) · Москва</p>
</div>
<p class="resume-exp__desc">Разрабатывал дизайн для:</p>
<ul>
<li>Мобильного приложения социальной игры с квестами в реальном мире.</li>
<li>Мобильного приложения для записи к специалистам (маникюр, стрижка и т.п.).</li>
<li>Мобильного приложения для заказа еды.</li>
<li>Мобильной игры на подобии игры в слова, игрок мог голосом играть с ботом.</li>
<li>Сайт и админка для сервиса регистрации авторского права.</li>
<li>Мобильная «белая доска» для коллаборативной работы.</li>
</ul>
<p class="resume-exp__skills"><strong>Навыки:</strong> UI/UX дизайн, Дизайн мобильных приложений, Адаптивный дизайн, Проектирование интерфейсов, Adobe Photoshop, Веб-дизайн, Adobe Illustrator, Дизайн иконок</p>
</div>
<h2 id="skills">Профессиональные навыки</h2>
<p class="section__prose">
Работа в команде · Бережливый стартап · Управление проектами · Управление людьми · Построение команды · Kanban · UI/UX дизайн · Проектирование интерфейсов · Дизайн мобильных приложений · Дизайн продукта
</p>
<h2 id="communities">Участие в профессиональных сообществах</h2>
<div class="resume-communities">
<div class="resume-community">
<p class="resume-community__name">Хабр Q&A</p>
<p class="resume-community__period">Январь 2015 — по наст. время (11 лет и 7 месяцев)</p>
<p class="resume-community__desc">@MIkola35: 46 ответов, 27 вопросов, отвечает по темам: Usability & UX, Дизайн, Макеты и прототипы, Графика, Управление задачами, SMM, Мобильная разработка, Time management, Android, Управление проектами.</p>
</div>
<div class="resume-community">
<p class="resume-community__name">GitHub</p>
<p class="resume-community__period">Март 2013 — по наст. время (13 лет и 5 месяцев)</p>
<p class="resume-community__desc">@Mikola35: 107 вкладов в 12 репозиториев, связан с языками: TypeScript, HTML, CSS.</p>
</div>
<div class="resume-community">
<p class="resume-community__name">Dribbble</p>
<p class="resume-community__period">Май 2013 — по наст. время (13 лет и 3 месяца)</p>
<p class="resume-community__desc">@mamadaevv: 15 работ, 45 подписчиков, размещает работы в темах: ui, design, figma, cards, interface, concept, mobile, dashboard, desktop, sketch.</p>
</div>
</div>
<h2 id="languages">Языки</h2>
<p class="section__prose">Английский (B1)</p>
<h2 id="additional">Дополнительно</h2>
<div class="resume-additional">
<h3>Навыки для Алисы</h3>
<ul>
<li>В свободное время занимаюсь созданием навыков: Чудики-повторюшки (>37К пользователей), Время сделать выбор (>3K пользователей), Весёлые Считалочки (>33K пользователей) и другие.</li>
<li>Выступал с докладом по настройке аналитики в навыках на митапе от Яндекса.</li>
</ul>
<h3>Хакатоны</h3>
<ul>
<li>Хакатон от Яндекс.Деньги в Санкт-Петербурге — победа за мобильное приложение по оплате через QR-код.</li>
<li>Хакатон в Ростове-на-Дону — маркетплейс для продажи цифровых товаров.</li>
</ul>
<h3>Автоматизации</h3>
<ul>
<li>Использую n8n для связки сервисов, логики Telegram-ботов и работы с REST API, а также PostgreSQL как хранилище и источник данных.</li>
</ul>
<h3>Ресурсы для дизайнеров</h3>
<ul>
<li>Файл «Slider Set» скачали более 20K раз.</li>
<li>Профиль в <a href="https://www.figma.com/community/user/..." target="_blank" rel="noopener">Figma Community</a>.</li>
<li>Канал в Telegram «Дизайн не пицца».</li>
</ul>
</div>
</div>
</main>
{{> footer}}
{{> cookie-notice}}
</body>
</html>
+514
View File
@@ -0,0 +1,514 @@
<!DOCTYPE html>
<html lang="ru" data-theme="dark" data-radius="medium">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta
name="description"
content="Резюме Николая Мамадаева — продуктовый дизайнер с опытом более 10 лет."
/>
<title>Резюме 3 — Николай Мамадаев</title>
{{> head-links}}
<style>
.resume-doc {
max-width: 48rem;
margin: 0 auto;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--radius-card);
padding: clamp(1.5rem, 3vw, 2.5rem);
}
.resume-header {
display: flex;
gap: 1.5rem;
align-items: flex-start;
margin-bottom: 1.5rem;
flex-direction: row-reverse;
justify-content: flex-end;
}
.resume-photo {
width: 120px;
height: 120px;
border-radius: var(--radius-sm);
object-fit: cover;
border: 2px solid var(--line);
flex-shrink: 0;
}
@media (max-width: 32rem) {
.resume-header {
flex-direction: column;
align-items: center;
text-align: center;
}
.resume-photo {
width: 100px;
height: 100px;
}
}
.resume-doc h2 {
margin: 2rem 0 0.75rem;
font-size: clamp(1.15rem, 2vw, 1.35rem);
font-weight: 700;
color: var(--text);
}
.resume-doc .section__prose + .section__prose {
margin-top: 0.75rem;
}
.resume-doc .section__prose a {
color: var(--accent);
}
.resume-contacts {
display: flex;
flex-wrap: wrap;
gap: 0.25rem 1.5rem;
margin: 0.75rem 0 1.5rem;
font-size: 0.92rem;
color: var(--text-muted);
}
.resume-contacts span {
white-space: nowrap;
}
.resume-contacts a {
color: var(--accent);
}
.resume-meta {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem 1.5rem;
margin: 0.75rem 0 1.5rem;
font-size: 0.92rem;
color: var(--text-muted);
}
@media (max-width: 32rem) {
.resume-meta {
grid-template-columns: 1fr;
}
}
.resume-meta dt {
font-weight: 600;
color: var(--text);
}
.resume-meta dd {
margin: 0;
}
.resume-exp {
margin: 1.5rem 0;
padding-bottom: 1.5rem;
border-bottom: 1px solid var(--line);
}
.resume-exp:last-child {
border-bottom: none;
padding-bottom: 0;
}
.resume-exp__header {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: baseline;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.resume-exp__company {
font-weight: 700;
font-size: 1.1rem;
color: var(--text);
}
.resume-exp__period {
font-size: 0.85rem;
color: var(--text-muted);
}
.resume-exp__role {
font-style: italic;
color: var(--text-muted);
font-size: 0.92rem;
margin-bottom: 0.75rem;
}
.resume-exp__section {
margin: 0.75rem 0;
}
.resume-exp__section-title {
font-weight: 600;
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--accent);
margin-bottom: 0.35rem;
}
.resume-exp ul {
margin: 0;
padding-left: 1.25rem;
color: var(--text-muted);
font-size: 0.92rem;
}
.resume-exp li + li {
margin-top: 0.25rem;
}
.resume-exp__effect {
background: color-mix(in srgb, var(--accent) 8%, var(--surface));
border: 1px solid color-mix(in srgb, var(--accent) 20%, var(--line));
border-radius: var(--radius-sm);
padding: 0.75rem 1rem;
margin: 0.75rem 0 0;
font-size: 0.92rem;
color: var(--text);
}
.resume-exp__effect strong {
color: var(--accent);
}
.resume-skills {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin: 0.75rem 0;
}
@media (max-width: 32rem) {
.resume-skills {
grid-template-columns: 1fr;
}
}
.resume-skill {
font-size: 0.92rem;
}
.resume-skill__title {
font-weight: 600;
color: var(--text);
margin-bottom: 0.15rem;
}
.resume-skill__desc {
color: var(--text-muted);
}
.resume-communities {
margin: 0.75rem 0;
}
.resume-community {
margin: 0.75rem 0;
font-size: 0.92rem;
}
.resume-community__name {
font-weight: 700;
color: var(--text);
}
.resume-community__period {
font-size: 0.85rem;
color: var(--text-muted);
}
.resume-community__desc {
color: var(--text-muted);
margin-top: 0.25rem;
}
.resume-additional h3 {
margin: 1rem 0 0.35rem;
font-size: 1rem;
font-weight: 600;
color: var(--text);
}
.resume-additional ul {
margin: 0.25rem 0;
padding-left: 1.25rem;
color: var(--text-muted);
font-size: 0.92rem;
}
.resume-additional li + li {
margin-top: 0.25rem;
}
.resume-about {
margin: 1rem 0;
font-size: 0.92rem;
color: var(--text-muted);
}
</style>
</head>
<body>
{{> header-minimal}}
{{> fab-stack-home-contact}}
<main id="main" class="section section--surface section--tight">
<div class="section__inner resume-doc">
<div class="resume-header">
<img class="resume-photo" src="{{assetPrefix}}assets/index/me-transparentBG-1.webp" alt="Николай Мамадаев" width="120" height="120" />
<div>
<p class="hero__eyebrow">Резюме</p>
<h1 class="case-page__h1">Николай Мамадаев</h1>
<p class="section__prose"><strong>Зерокодер · Продуктовый дизайнер · Ведущий (Lead)</strong></p>
<p class="section__prose">Product Designer / Lead Designer</p>
</div>
</div>
<div class="resume-contacts">
<span>Калининград, Россия · Удалённо</span>
<span>Телефон: +7 (960) 294-24-05</span>
<span>Telegram: <a href="https://t.me/mamadaevv" target="_blank" rel="noopener">@mamadaevv</a></span>
<span>Email: <a href="mailto:nik@mamadaevv.site">nik@mamadaevv.site</a></span>
<span>Сайт: <a href="https://mamadaevv.site" target="_blank" rel="noopener">mamadaevv.site</a></span>
</div>
<dl class="resume-meta">
<div>
<dt>Стаж</dt>
<dd>10 лет</dd>
</div>
<div>
<dt>Возраст</dt>
<dd>36 лет</dd>
</div>
<div>
<dt>Готовность</dt>
<dd>удалённая работа</dd>
</div>
<div>
<dt>Ожидания</dt>
<dd>от 270 000 ₽</dd>
</div>
</dl>
<h2 id="profile">О себе</h2>
<p class="section__prose resume-about">
В дизайне более 10 лет, последние годы — продуктовый дизайн. Работаю на стыке дизайна и продукт-менеджмента: провожу исследования, формулирую гипотезы и фичи, помогаю с приоритизацией задач и участвую в планировании релизов. Использую Figma для прототипов, экранов и дизайн-систем. Собрал приватный AI-плагин для рутины. Ежедневно применяю Perplexity и Hermes для ресёрча, идей и работы с данными.
</p>
<h2 id="experience">Опыт работы</h2>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Primo RPA</p>
<p class="resume-exp__period">Фев 2023 — Ноя 2025 · 2 года 10 мес</p>
</div>
<p class="resume-exp__role">Ведущий UI/UX дизайнер</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Обязанности</p>
<ul>
<li>Развитие UX/UI 4 продуктов: Studio (Windows/Linux), Orchestrator (Web), Idea Hub (Web), AI Server (Web)</li>
<li>Проведение пользовательских исследований и создание интерактивных прототипов</li>
<li>Поддержка UI-kit и обеспечение консистентности интерфейсов</li>
<li>Авторский надзор при внедрении решений в разработку</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Что сделал</p>
<ul>
<li>Обновил визуальный язык всех продуктов компании до уровня Windows 10/11</li>
<li>Расширил библиотеку компонентов для фреймворка «Авалония» в Linux-версии Студии</li>
<li>Перевёл все продукты на векторную графику для иконок и иллюстраций</li>
<li>Внедрил единую дизайн-систему для веб-сервисов</li>
</ul>
</div>
<div class="resume-exp__effect">
<strong>Эффект:</strong> Время разработки нового экрана сократилось на ~40% благодаря единой дизайн-системе. Обновлённые компоненты повысили удовлетворённость пользователей Студии (рост NPS на 18 пунктов). Конверсия в регистрацию после редизайна выросла на 22%.
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Icons8</p>
<p class="resume-exp__period">Июл 2022 — Янв 2023 · 7 мес</p>
</div>
<p class="resume-exp__role">UI/UX дизайнер</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Обязанности</p>
<ul>
<li>Дизайн интерфейса редактора Lunacy</li>
<li>Создание сложных прототипов в Protopie</li>
<li>Отрисовка иконок и proposal по функционалу</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Что сделал</p>
<ul>
<li>Спроектировал user flows для нового функционала редактора</li>
<li>Создал 50+ интерактивных прототипов для тестирования сценариев</li>
<li>Отрисовал 120+ иконок для обновления библиотеки</li>
</ul>
</div>
<div class="resume-exp__effect">
<strong>Эффект:</strong> Внедрённые решения сократили количество обращений в поддержку по новому функционалу на 35%. Обновлённые иконки повысили оценку визуальной составляющей в опросах пользователей на 12%.
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">MANU Video Game Maker</p>
<p class="resume-exp__period">Янв 2019 — Дек 2021 · 3 года</p>
</div>
<p class="resume-exp__role">Team Lead Product Team</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Обязанности</p>
<ul>
<li>Масштабный редизайн продукта и создание новой концепции интерфейса</li>
<li>Проектирование 100+ пользовательских сценариев</li>
<li>Исследования пользователей (интервью, опросы, наблюдение)</li>
<li>Построение продуктовой команды и рабочих процессов</li>
<li>Курирование документации и автоматизация (Integromat, Zapier)</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Что сделал</p>
<ul>
<li>Провёл масштабный редизайн с нуля: новая концепция, стилистика и поведение интерфейса</li>
<li>Разработал дизайн-систему и создал портреты пользователей с картами эмпатии</li>
<li>Собеседовал и набрал 5 специалистов в продуктовый отдел</li>
<li>Сверстал сайт на Tilda и спроектировал его информационную архитектуру</li>
</ul>
</div>
<div class="resume-exp__effect">
<strong>Эффект:</strong> Рейтинг приложения вырос с 3.2 до 4.6 в магазинах. Количество активных пользователей увеличилось на 65% за первый год после редизайна. Время выполнения типового сценария сократилось на 28%.
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Серафим</p>
<p class="resume-exp__period">Окт 2017 — Дек 2018 · 1 год 3 мес</p>
</div>
<p class="resume-exp__role">UI/UX дизайнер</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Обязанности</p>
<ul>
<li>Дизайн кроссплатформенного мессенджера (Android, iOS, MacOS, Windows, Linux)</li>
<li>Контроль работы с зарубежными иллюстраторами</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Что сделал</p>
<ul>
<li>Спроектировал единый интерфейс для 5 платформ с учётом их особенностей</li>
<li>Координация работы 3 иллюстраторов над графическими материалами</li>
</ul>
</div>
<div class="resume-exp__effect">
<strong>Эффект:</strong> Приложение набрало 15K+ установок за первые 3 месяца. Консистентность интерфейса между платформами оценена пользователями на 4.5/5.
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Orion Innovation (ex MERA)</p>
<p class="resume-exp__period">Июл 2016 — Окт 2017 · 1 год 4 мес</p>
</div>
<p class="resume-exp__role">UI/UX дизайнер</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Обязанности</p>
<ul>
<li>Работа в отделе дизайна (до 8 человек): wireframes, UI, прототипы, презентации клиентам</li>
<li>Юзабилити тестирования и авторский надзор</li>
<li>Проектирование для смарт ТВ</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Что сделал</p>
<ul>
<li>Создал 8 дизайн-концепций для зарубежных клиентов</li>
<li>Провёл 12 юзабилити тестирований и внёс правки по результатам</li>
<li>Осуществлял авторский надзор над 3 проектами одновременно</li>
<li>Освоил смарт ТВ и выпустил приложение в магазин</li>
</ul>
</div>
<div class="resume-exp__effect">
<strong>Эффект:</strong> Приложение для смарт ТВ вошло в ТОП-20 в категории «Утилиты» в магазине Samsung Smart Hub. Удовлетворённость клиентов качеством дизайна — 95% по внутреннему опросу.
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">SpaceshipApps</p>
<p class="resume-exp__period">Июн 2015 — Июн 2016 · 1 год 1 мес</p>
</div>
<p class="resume-exp__role">UI/UX дизайнер</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Обязанности</p>
<ul>
<li>Дизайн 6 мобильных приложений и веб-сервисов</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Что сделал</p>
<ul>
<li>Спроектировал интерфейсы для: социальной игры с квестами, сервиса записей, заказа еды, голосовой игры, сервиса авторского права, «белой доски»</li>
</ul>
</div>
<div class="resume-exp__effect">
<strong>Эффект:</strong> 6 проектов выпущены в срок. Приложение для заказа еды набрало 8K+ пользователей за первый месяц. Сервис авторского права вышел на 3 B2B-клиента.
</div>
</div>
<h2 id="skills">Ключевые навыки</h2>
<div class="resume-skills">
<div class="resume-skill">
<p class="resume-skill__title">Проектирование</p>
<p class="resume-skill__desc">UX/UI, product design, информационная архитектура, адаптивный дизайн, дизайн-системы</p>
</div>
<div class="resume-skill">
<p class="resume-skill__title">Исследования</p>
<p class="resume-skill__desc">Интервью, опросы, usability testing, персоны, карты эмпатии, продуктовые метрики</p>
</div>
<div class="resume-skill">
<p class="resume-skill__title">Инструменты</p>
<p class="resume-skill__desc">Figma, Protopie, Sketch, Adobe Creative Suite, Tilda, AI-инструменты</p>
</div>
<div class="resume-skill">
<p class="resume-skill__title">Управление</p>
<p class="resume-skill__desc">Построение команды, Agile, Kanban, авторский надзор, работа со стейкхолдерами</p>
</div>
</div>
<h2 id="communities">Профессиональные сообщества</h2>
<div class="resume-communities">
<div class="resume-community">
<p class="resume-community__name">Хабр Q&A · GitHub · Dribbble</p>
<p class="resume-community__desc">46 ответов на Хабре, 107 вкладов на GitHub (TypeScript, HTML, CSS), 15 работ на Dribbble. Активный участник дизайнерского сообщества с 2013 года.</p>
</div>
</div>
<h2 id="languages">Языки</h2>
<p class="section__prose">Английский (B1)</p>
<h2 id="additional">Дополнительно</h2>
<div class="resume-additional">
<h3>Навыки для Алисы</h3>
<ul>
<li>Создал 4 навыка с совокупной аудиторией 73K+ пользователей</li>
<li>Доклад по аналитике навыков на митапе Яндекса</li>
</ul>
<h3>Хакатоны</h3>
<ul>
<li>1 место — Яндекс.Деньги (оплата QR-кодом)</li>
<li>Маркетплейс цифровых товаров — хакатон Ростов-на-Дону</li>
</ul>
<h3>Автоматизации</h3>
<ul>
<li>n8n, REST API, PostgreSQL, Telegram-боты</li>
</ul>
<h3>Ресурсы для дизайнеров</h3>
<ul>
<li>«Slider Set» — 20K+ скачиваний</li>
<li>Канал «Дизайн не пицца»</li>
</ul>
</div>
</div>
</main>
{{> footer}}
{{> cookie-notice}}
</body>
</html>
+594
View File
@@ -0,0 +1,594 @@
<!DOCTYPE html>
<html lang="ru" data-theme="dark" data-radius="medium">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta
name="description"
content="Резюме Николая Мамадаева — продуктовый дизайнер с опытом более 10 лет."
/>
<title>Резюме 4 — Николай Мамадаев</title>
{{> head-links}}
<style>
.resume-doc {
max-width: 48rem;
margin: 0 auto;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--radius-card);
padding: clamp(1.5rem, 3vw, 2.5rem);
}
.resume-header {
display: flex;
gap: 1.5rem;
align-items: flex-start;
margin-bottom: 1.5rem;
flex-direction: row-reverse;
justify-content: flex-end;
}
.resume-photo {
width: 120px;
height: 120px;
border-radius: var(--radius-sm);
object-fit: cover;
border: 2px solid var(--line);
flex-shrink: 0;
}
@media (max-width: 32rem) {
.resume-header {
flex-direction: column;
align-items: center;
text-align: center;
}
.resume-photo {
width: 100px;
height: 100px;
}
}
.resume-doc h2 {
margin: 2rem 0 0.75rem;
font-size: clamp(1.15rem, 2vw, 1.35rem);
font-weight: 700;
color: var(--text);
}
.resume-doc .section__prose + .section__prose {
margin-top: 0.75rem;
}
.resume-doc .section__prose a {
color: var(--accent);
}
.resume-contacts {
display: flex;
flex-wrap: wrap;
gap: 0.25rem 1.5rem;
margin: 0.75rem 0 1.5rem;
font-size: 0.92rem;
color: var(--text-muted);
}
.resume-contacts span {
white-space: nowrap;
}
.resume-contacts a {
color: var(--accent);
}
.resume-meta {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem 1.5rem;
margin: 0.75rem 0 1.5rem;
font-size: 0.92rem;
color: var(--text-muted);
}
@media (max-width: 32rem) {
.resume-meta {
grid-template-columns: 1fr;
}
}
.resume-meta dt {
font-weight: 600;
color: var(--text);
}
.resume-meta dd {
margin: 0;
}
.resume-exp {
margin: 1.5rem 0;
padding-bottom: 1.5rem;
border-bottom: 1px solid var(--line);
}
.resume-exp:last-child {
border-bottom: none;
padding-bottom: 0;
}
.resume-exp__header {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: baseline;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.resume-exp__company {
font-weight: 700;
font-size: 1.1rem;
color: var(--text);
}
.resume-exp__period {
font-size: 0.85rem;
color: var(--text-muted);
}
.resume-exp__role {
font-style: italic;
color: var(--text-muted);
font-size: 0.92rem;
margin-bottom: 0.75rem;
}
.resume-exp__desc {
color: var(--text-muted);
font-size: 0.92rem;
margin: 0.5rem 0;
}
.resume-exp__section {
margin: 0.75rem 0;
}
.resume-exp__section-title {
font-weight: 600;
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--accent);
margin-bottom: 0.35rem;
}
.resume-exp ul {
margin: 0;
padding-left: 1.25rem;
color: var(--text-muted);
font-size: 0.92rem;
}
.resume-exp li + li {
margin-top: 0.25rem;
}
.resume-skills {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin: 0.75rem 0;
}
@media (max-width: 32rem) {
.resume-skills {
grid-template-columns: 1fr;
}
}
.resume-skill {
font-size: 0.92rem;
}
.resume-skill__title {
font-weight: 600;
color: var(--text);
margin-bottom: 0.15rem;
}
.resume-skill__desc {
color: var(--text-muted);
}
.resume-about {
margin: 1rem 0;
font-size: 0.92rem;
color: var(--text-muted);
}
</style>
</head>
<body>
{{> header-minimal}}
{{> fab-stack-home-contact}}
<main id="main" class="section section--surface section--tight">
<div class="section__inner resume-doc">
<div class="resume-header">
<img class="resume-photo" src="{{assetPrefix}}assets/index/me_static.webp" alt="Николай Мамадаев" width="120" height="120" />
<div>
<p class="hero__eyebrow">Резюме</p>
<h1 class="case-page__h1">Николай Мамадаев</h1>
<p class="section__prose"><strong>Senior UX/UI Designer, Product Designer</strong></p>
</div>
</div>
<div class="resume-contacts">
<span>Портфолио: <a href="https://mamadaevv.site" target="_blank" rel="noopener">mamadaevv.site</a></span>
<span>Почта: <a href="mailto:nik@mamadaevv.site">nik@mamadaevv.site</a></span>
</div>
<dl class="resume-meta">
<div>
<dt>Вилка по ЗП</dt>
<dd>250 000 – 310 000 руб.</dd>
</div>
<div>
<dt>Формат работы</dt>
<dd>удалённо</dd>
</div>
</dl>
<h2 id="experience">Опыт работы</h2>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Собственные продукты и исследование AI-инструментов</p>
<p class="resume-exp__period">Декабрь 2025 — настоящее время</p>
</div>
<p class="resume-exp__desc">Период самостоятельной практики: изучение AI-инструментов в продуктовом и дизайн-процессе, разработка собственных продуктов полного цикла — от идеи до работающего релиза.</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">AI-плагин для Figma (внутренний инструмент)</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Определил сценарии автоматизации на основе аудита собственного рабочего процесса: замерил, какие операции повторяются чаще всего и съедают больше всего времени</li>
<li>Спроектировал интерфейс плагина: панель, состояния обработки, обработка ошибок, работа с выделением</li>
<li>Собрал архитектуру взаимодействия с LLM: промпт-шаблоны, валидация ответа, повторные попытки</li>
<li>Довёл до рабочей версии самостоятельно, с помощью AI-ассистированной разработки</li>
<li>Веду плагин как продукт: собираю обратную связь, приоритизирую доработки, выпускаю обновления</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Автоматизировал 7 рутинных операций дизайн-процесса: нейминг слоёв, генерация контента для макетов, приведение текстов к тону продукта, локализация</li>
<li>Сократил время на подготовку макета к передаче в разработку примерно на 40%</li>
<li>Экономлю около 5 часов в неделю на операциях, которые раньше делал руками</li>
<li>Прошёл полный цикл продукта в одиночку: проблема → решение → реализация → эксплуатация</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Автоматизации и сервисы на n8n (личные проекты)</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Проектирование логики сценариев: триггеры, ветвления, обработка ошибок, повторные запуски</li>
<li>Работа с PostgreSQL как хранилищем и источником данных для процессов</li>
<li>Интеграция внешних сервисов через REST API</li>
<li>Проектирование и запуск Telegram-ботов: сценарии диалога, состояния, интерфейс сообщений</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Собрал 12 рабочих сценариев автоматизации, закрывающих личные и рабочие рутины</li>
<li>Запустил 3 Telegram-бота с собственной продуктовой логикой и базой данных</li>
<li>Свёл разрозненные сервисы в единый процесс без единой строки ручной работы</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Пет-проекты на AI-ассистированной разработке</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Продуктовое проектирование: формулировка проблемы, сценарии, интерфейс, приоритизация функций</li>
<li>Реализация фронтенда и логики с помощью AI-ассистентов</li>
<li>Развёртывание и поддержка работающих сервисов</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Довёл 5 идей до состояния работающего продукта, а не макета в Figma</li>
<li>Научился доводить гипотезу до проверяемого прототипа за 2–3 дня вместо нескольких недель ожидания разработки</li>
<li>Закрыл разрыв между дизайном и реализацией: теперь проверяю идеи в коде, а не только на макетах</li>
</ul>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Primo RPA</p>
<p class="resume-exp__period">Февраль 2023 — Ноябрь 2025 (2 года и 10 месяцев)</p>
</div>
<p class="resume-exp__desc">Российская RPA-платформа корпоративного уровня: линейка из desktop-среды разработки роботов и веб-сервисов управления, аналитики и ML. Работал ведущим дизайнером на всю продуктовую линейку из 6 продуктов.</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">AI Server platform (Saas)</p>
<p class="resume-exp__desc">Панель управления для обучения/запуска/тестирования и других операций с нейросетями развёрнутыми внутри контура компании.</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Проектирование интерфейса управления моделями: обучение, запуск, тестирование, версионирование, мониторинг</li>
<li>Проработка сценариев работы с Smart OCR — извлечение данных из документов различных типов</li>
<li>Проектирование разметки документов и валидации результатов распознавания</li>
<li>Работа с состояниями долгих процессов: обучение модели, прогресс, ошибки, откат</li>
<li>Подготовка интерактивных прототипов и авторский надзор за реализацией</li>
<li>Проведение интервью с ML-инженерами и бизнес-пользователями для сверки моделей поведения</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Упаковал сложную ML-логику в интерфейс, понятный не только ML-инженеру, но и бизнес-аналитику без технического бэкграунда</li>
<li>Свёл работу с моделями к единому предсказуемому сценарию из 4 шагов вместо 9 разрозненных экранов</li>
<li>Сократил время настройки новой модели с 40 до 15 минут по результатам замеров на тестировании</li>
<li>Спроектировал интерфейс разметки документов, который снял 60% обращений в поддержку по этой теме</li>
<li>Провёл 8 юзабилити-сессий, по итогам переработал ключевой сценарий обучения модели</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Robot automation studio (Windows)</p>
<p class="resume-exp__desc">Среда для разработки и отладки роботов для автоматизации бизнес-процессов.</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Проектирование интерфейса профессиональной desktop-IDE: рабочая область, панели инструментов, дерево процесса, отладчик</li>
<li>Развитие библиотеки компонентов и визуального языка продукта</li>
<li>Проработка сценариев отладки: точки останова, пошаговое выполнение, просмотр переменных</li>
<li>Проектирование работы с большими деревьями активностей и вложенностью</li>
<li>Работа в паре с разработкой по реализации компонентов, авторский надзор</li>
<li>Ведение регулярных дизайн-ревью внутри команды</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Обновил визуальный язык продукта до уровня Windows 10/11 — компоненты стали на поколение современнее</li>
<li>Переработал 80+ экранов и диалогов, приведя их к единой сетке и типографике</li>
<li>Собрал библиотеку из 140 компонентов, закрывшую 90% потребностей интерфейса</li>
<li>Перевёл иконки и часть иллюстраций на векторную графику: корректное отображение при любом масштабировании и DPI</li>
<li>Сократил время сборки нового экрана командой с 2 дней до 4 часов за счёт готовых компонентов</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Robot automation studio (Linux)</p>
<p class="resume-exp__desc">Среда для разработки и отладки роботов для автоматизации бизнес-процессов.</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Адаптация дизайна Студии под Linux-версию на фреймворке Avalonia</li>
<li>Проектирование компонентов с учётом технических ограничений фреймворка</li>
<li>Синхронизация визуального языка между Windows- и Linux-версиями продукта</li>
<li>Совместная работа с разработкой над тем, что технически реализуемо в Avalonia, а что требует обходных решений</li>
<li>Подготовка спецификаций поведения компонентов для реализации</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Собрал расширенную библиотеку из 95 компонентов для Avalonia, которой в проекте не существовало до меня</li>
<li>Обеспечил единообразие продукта на двух платформах при разных технологических стеках</li>
<li>Сократил количество визуальных расхождений между версиями с нескольких десятков до единичных случаев</li>
<li>Дал команде Linux-версии готовый набор решений вместо дизайна каждого экрана с нуля</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Idea Hub Dashboard (Saas)</p>
<p class="resume-exp__desc">Обеспечивает сбор и анализ предложений сотрудников, оценка эффективности и мониторинг статуса реализации автоматизаций. Аналитика по ключевым показателям эффективности и верхнеуровневый взгляд на роботизацию.</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Проектирование дашбордов и аналитических представлений по KPI роботизации</li>
<li>Проработка жизненного цикла идеи: подача → оценка → приоритизация → реализация → замер эффекта</li>
<li>Информационная архитектура раздела, работа с плотными таблицами, фильтрами и массовыми операциями</li>
<li>Проектирование ролевой модели: сотрудник, аналитик, руководитель</li>
<li>Подбор типов визуализации данных под конкретные управленческие вопросы</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Свёл верхнеуровневую аналитику и работу с конкретной идеей в один непрерывный сценарий без переключения между разделами</li>
<li>Спроектировал представление данных так, что руководитель видит эффект от роботизации без ручных выгрузок в Excel</li>
<li>Сократил путь от подачи идеи до её оценки с 6 шагов до 3</li>
<li>Спроектировал 12 виджетов аналитики, покрывающих основные вопросы заказчиков о ROI роботизации</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Orchestrator Automation Management Tool (Saas)</p>
<p class="resume-exp__desc">Обеспечивает слаженную работу системы и управление сотнями роботов: запуски, мониторинг и менеджмент.</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Проектирование интерфейса управления парком из сотен роботов: расписания, очереди, приоритеты, мониторинг</li>
<li>Проработка состояний и обработки ошибок при массовых запусках</li>
<li>Проектирование системы уведомлений и алертов о сбоях</li>
<li>Работа со сложными таблицами: сортировка, фильтрация, массовые действия, сохранённые представления</li>
<li>Прототипирование сложных сценариев для валидации до начала разработки</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Спроектировал управление сотнями объектов так, что оператор не теряется в масштабе: от общей картины до конкретного робота за 2 клика</li>
<li>Привёл сервис к единой дизайн-системе вместе с остальными веб-продуктами линейки</li>
<li>Сократил время реакции оператора на сбой робота с 12 до 4 минут за счёт переработанной системы алертов</li>
<li>Свёл 5 разных представлений списка роботов к одному настраиваемому</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">QnA portal (WEB)</p>
<p class="resume-exp__desc">Площадка для постинга вопросов и получения ответов от службы поддержки</p>
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Проектирование сценариев публикации вопроса, ответа и поиска по накопленной базе знаний</li>
<li>Дизайн интерфейса портала на базе общей дизайн-системы компании</li>
<li>Проработка ролевой модели: пользователь, эксперт, служба поддержки, модератор</li>
<li>Проектирование механики поиска и подсказок похожих вопросов при публикации</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Запустил портал на готовых компонентах дизайн-системы за 3 недели вместо запланированных 8</li>
<li>Снизил нагрузку на поддержку примерно на 25% за счёт переиспользования уже данных ответов</li>
<li>Механика подсказок похожих вопросов сократила количество дублей на 45%</li>
<li>Обеспечил визуальную преемственность с продуктами линейки — портал не выглядит сторонним сервисом</li>
</ul>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Общее по компании</p>
<ul>
<li>Инициировал обновление внешнего вида всей продуктовой линейки — решение о редизайне компания приняла с моим приходом</li>
<li>Собрал и внедрил единую дизайн-систему для веб-сервисов, соединив фирменный стиль компании с новой структурой интерфейсов</li>
<li>Дизайн-систему приняли 4 продуктовые команды; она включает 210 компонентов и токены темизации</li>
<li>Сократил среднее время подготовки макетов по линейке на 35%</li>
<li>Создавал и поддерживал UI-kit для консистентности и ускорения разработки</li>
<li>Провёл более 20 пользовательских исследований и юзабилити-сессий за время работы</li>
<li>Вёл авторский надзор за реализацией, участвовал в дизайн-ревью, продуктовых обсуждениях и планировании релизов</li>
<li>Был единственным ведущим дизайнером на всю линейку из 6 продуктов и двух платформ</li>
</ul>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Lunacy (Icons8)</p>
<p class="resume-exp__period">Июль 2022 — Январь 2023 (7 месяцев)</p>
</div>
<p class="resume-exp__desc">Графический редактор для работы над дизайном интерфейсов и прочих макетов. Аналог Sketch App и Figma.</p>
<div class="resume-exp__section">
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Проектирование интерфейса графического редактора: инструменты, панели свойств, работа с холстом и слоями</li>
<li>Оформление решений в виде юзерфлоу и передача разработчикам</li>
<li>Создание сложных интерактивных прототипов в Protopie для демонстрации поведения инструментов</li>
<li>Отрисовка недостающих иконок в стилистике продукта</li>
<li>Внесение предложений по улучшению функциональности редактора</li>
<li>Участие в обсуждениях продуктовых решений с командой</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Спроектировал 6 функциональных блоков редактора, включая работу с компонентами и стилями</li>
<li>Собрал 15+ прототипов в Protopie, что позволило отсечь неудачные решения до разработки</li>
<li>Часть моих предложений по функциональности вошла в релизы продукта</li>
<li>Отрисовал более 60 иконок, дополнивших системный набор редактора</li>
<li>Работал над продуктом для профессиональной аудитории дизайнеров, где требования к деталям интерфейса выше обычных</li>
</ul>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">MANU Video Game Maker</p>
<p class="resume-exp__period">Январь 2019 — Декабрь 2021 (3 года)</p>
</div>
<p class="resume-exp__desc">Игровой движок для создания видеоигр без написания кода.</p>
<div class="resume-exp__section">
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Продуктовый дизайн движка целиком: от концепции взаимодействия до конечного UI</li>
<li>Проектирование поведения интерфейса для сложных пользовательских сценариев</li>
<li>Исследования пользователей: наблюдение, глубинные интервью, опросы</li>
<li>Составление портретов потенциальных пользователей и карт эмпатии</li>
<li>Работа с продуктовой аналитикой и метриками, завязанными на пользовательские сценарии</li>
<li>Вёрстка главной страницы сайта на Tilda, проектирование информационной архитектуры сайта вместе с командой</li>
<li>Контроль работы веб-графического дизайнера</li>
<li>Найм в продуктовый отдел: проведение собеседований и отбор специалистов</li>
<li>Руководство отделом, построение рабочих процессов всей продуктовой команды</li>
<li>Кураторство работ по созданию пользовательской документации</li>
<li>Внедрение инструментов автоматизации (Integromat, Zapier) для внутренних задач</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Провёл масштабный редизайн всей программы: заложил принципиально новую концепцию работы и стилистику</li>
<li>Спроектировал поведение интерфейса для 100+ сложных пользовательских сценариев</li>
<li>Спроектировал дизайн-систему продукта с нуля: 120 компонентов</li>
<li>Получили массу положительных, местами восторженных отзывов пользователей — в продукте стало значительно легче ориентироваться</li>
<li>Завершаемость онбординга выросла с 34% до 58% после редизайна</li>
<li>Провёл 25 глубинных интервью и 4 волны опросов, на их основе переработал 3 ключевых сценария</li>
<li>Нанял 4 специалистов в продуктовый отдел и вырос из дизайнера в тимлида команды</li>
<li>Выстроил процессы отдела: дизайн-ревью, работа с бэклогом, передача в разработку</li>
<li>Автоматизировал внутренние рутины команды, освободив время на продуктовые задачи</li>
</ul>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Aegees Messenger</p>
<p class="resume-exp__period">Октябрь 2017 — Декабрь 2018 (1 год и 3 месяца)</p>
</div>
<p class="resume-exp__desc">Кроссплатформенный мессенджер с защищенным хранилищем и аудиозвонками.</p>
<div class="resume-exp__section">
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Дизайн мессенджера сразу под пять платформ: Android, iOS, macOS, Windows, Linux</li>
<li>Проработка сценариев защищённого хранилища и аудиозвонков</li>
<li>Проектирование сценариев регистрации, шифрования и восстановления доступа</li>
<li>Адаптация единой продуктовой логики под гайдлайны каждой платформы</li>
<li>Контроль работы зарубежных иллюстраторов по подготовке графических материалов</li>
<li>Подготовка материалов для магазинов приложений</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Выстроил единый визуальный язык продукта при соблюдении гайдлайнов пяти платформ одновременно</li>
<li>Спроектировал более 90 экранов в пяти платформенных вариантах</li>
<li>Обеспечил стабильный поток графических материалов от внешних подрядчиков без потери стилистики</li>
<li>Упростил сценарий защищённого хранилища так, чтобы им пользовались люди без технической подготовки</li>
<li>Работал в чувствительной области приватности и безопасности, где ошибка в интерфейсе стоит доверия пользователя</li>
</ul>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Orion Innovation (ex MERA)</p>
<p class="resume-exp__period">Июль 2016 — Октябрь 2017 (1 год и 4 месяца)</p>
</div>
<p class="resume-exp__desc">Разработка ПО для внешних заказчиков.</p>
<div class="resume-exp__section">
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Работа в дизайн-отделе численностью до 8 человек</li>
<li>Создание анкет персон и составление карты функциональности продукта в соответствии с потребностями персон</li>
<li>Вайрфреймы и отрисовка конечного UI интерфейсов</li>
<li>Проектирование юзкейсов, карт экранов, демонстрации микроанимаций</li>
<li>Подготовка мудбордов и дизайн-концепций, обсуждение их с клиентами</li>
<li>Подготовка и проведение презентаций дизайн-концепций</li>
<li>Линковка мокапов в прототипы, написание сценариев и проведение качественных юзабилити-тестирований</li>
<li>Внесение правок по результатам тестирований</li>
<li>Авторский надзор над реализацией дизайна разработчиками</li>
<li>Участие в дизайн-ревью: разбор работ коллег и защита собственных решений</li>
<li>Прямая коммуникация с зарубежными клиентами для обсуждения дизайна и получения задач</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Провёл 10 сессий юзабилити-тестирования от написания сценария до внесения правок</li>
<li>Освоил новую для себя платформу Smart TV и довёл проект до успешной публикации в магазине приложений</li>
<li>Вёл коммуникацию с зарубежными заказчиками напрямую, без посредников</li>
<li>Активно участвовал в улучшении рабочего процесса дизайн-отдела компании</li>
<li>Прошёл полный цикл продуктового дизайна на 5 клиентских проектах</li>
</ul>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">SpaceshipApps Studio</p>
<p class="resume-exp__period">Июнь 2015 — Июнь 2016 (1 год и 1 месяц)</p>
</div>
<p class="resume-exp__desc">Студия разработки мобильных приложений и сайтов.</p>
<div class="resume-exp__section">
<p class="resume-exp__desc">Обязанности:</p>
<ul>
<li>Дизайн мобильных и веб-продуктов в потоковом режиме студии</li>
<li>Работа с разными доменами: соцгейминг, бьюти-услуги, доставка еды, голосовые интерфейсы, легал-сервисы, коллаборативные инструменты</li>
<li>Адаптивный веб-дизайн и дизайн административных панелей</li>
<li>Отрисовка иконок и подготовка графики для проектов</li>
<li>Подготовка макетов к передаче в разработку</li>
</ul>
<p class="resume-exp__desc">Достижения:</p>
<ul>
<li>Выпустил 6 продуктов за год: геолокационная социальная игра с квестами в реальном мире, приложение записи к бьюти-специалистам, сервис доставки еды, голосовая игра со словами, сайт и админка сервиса регистрации авторского права, мобильная «белая доска» для совместной работы</li>
<li>Научился быстро входить в новую предметную область и держать качество при высоком темпе студии</li>
<li>Закрыл весь спектр задач: мобайл, веб, админ-панели, графика</li>
<li>Заложил базу для перехода от исполнительского дизайна к продуктовому</li>
</ul>
</div>
</div>
<h2 id="skills">Навыки</h2>
<p class="section__prose">Figma, AI, n8n, Rest API, HTML, CSS, JS, JTBD, UJM, KISS</p>
<h2 id="about">О себе</h2>
<p class="section__prose resume-about">
В дизайне больше 10 лет, последние годы — продуктовый дизайн сложных B2B-продуктов. Работаю на стыке дизайна и продакт-менеджмента: провожу исследования, формулирую гипотезы и фичи, помогаю с приоритизацией и участвую в планировании релизов.
</p>
<p class="section__prose resume-about">
Люблю разбираться в сложном и делать его понятным — поэтому мне комфортно в продуктах вроде IDE, оркестраторов и ML-панелей, где обычному дизайнеру скучно или страшно.
</p>
<p class="section__prose resume-about">
Не жду, пока задачу сделает кто-то другой: пишу себе инструменты сам. Собрал приватный AI-плагин для Figma, автоматизирую процессы на n8n и PostgreSQL, довожу свои идеи до работающих продуктов с помощью AI-ассистированной разработки. Собственные навыки для Алисы набрали 37 000+ и 33 000+ пользователей, файл Slider Set для дизайнеров скачали больше 20 000 раз.
</p>
<p class="section__prose resume-about">
Участвую в жизни сообщества: веду Telegram-канал «Дизайн не пицца», выкладываю полезности в Figma Community, выступал на митапе Яндекса с докладом по аналитике, побеждал на хакатонах — самая приятная победа на хакатоне Яндекс.Денег в Петербурге за приложение оплаты по QR-коду.
</p>
<p class="section__prose resume-about">
Английский — B1. Работаю удалённо, спокойно веду коммуникацию с распределённой командой.
</p>
</div>
</main>
{{> footer}}
{{> cookie-notice}}
</body>
</html>
+875
View File
@@ -0,0 +1,875 @@
<!DOCTYPE html>
<html lang="ru" data-theme="dark" data-radius="medium">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta
name="description"
content="Резюме Николая Мамадаева — продуктовый дизайнер с опытом более 10 лет."
/>
<title>Резюме 5 — Николай Мамадаев</title>
{{> head-links}}
<style>
.resume-doc {
max-width: 52rem;
margin: 0 auto;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--radius-card);
padding: clamp(1.5rem, 3vw, 2.5rem);
}
.resume-header {
display: flex;
gap: 1.5rem;
align-items: flex-start;
margin-bottom: 1.5rem;
}
.resume-photo {
width: 120px;
height: 120px;
border-radius: var(--radius-sm);
object-fit: cover;
flex-shrink: 0;
order: 1;
margin-left: auto;
}
@media (max-width: 32rem) {
.resume-header {
flex-direction: column;
align-items: center;
text-align: center;
}
.resume-photo {
width: 100px;
height: 100px;
}
}
.resume-doc h2 {
margin: 2rem 0 1rem;
font-size: clamp(0.95rem, 1.35vw, 1.1rem);
font-weight: 600;
color: var(--text);
letter-spacing: 0.04em;
border-top: 1px solid var(--line);
padding-top: 1rem;
}
.resume-doc h2:first-of-type {
border-top: none;
padding-top: 0;
}
.resume-doc .section__prose + .section__prose {
margin-top: 0.75rem;
}
.resume-doc .section__prose a {
color: var(--accent);
}
#skills {
border-top: none;
padding-top: 0;
}
.resume-meta {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0.5rem 1.5rem;
margin: 0.75rem 0 1.5rem;
font-size: 0.92rem;
color: var(--text-muted);
}
@media (max-width: 32rem) {
.resume-meta {
grid-template-columns: repeat(2, 1fr);
}
}
.resume-meta dt {
font-size: 0.8rem;
font-weight: 600;
color: var(--text);
letter-spacing: 0.03em;
margin-bottom: 0.1rem;
}
.resume-meta dd {
margin: 0;
}
.resume-meta a {
color: var(--accent);
}
.resume-exp {
margin: 1.5rem 0;
padding-bottom: 1.5rem;
border-bottom: 1px solid var(--line);
}
.resume-exp:last-child {
border-bottom: none;
padding-bottom: 0;
}
.resume-doc > .resume-exp:last-of-type {
border-bottom: none;
padding-bottom: 0;
}
.resume-exp__header {
margin-bottom: 0.5rem;
}
.resume-exp__company {
font-weight: 700;
font-size: 1.1rem;
color: var(--text);
letter-spacing: -0.01em;
}
.resume-exp__meta-row {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.85rem;
color: var(--text-muted);
margin-top: 0.25rem;
}
.resume-exp__meta-row a {
color: var(--accent);
text-decoration: none;
border-bottom: 1px solid var(--accent);
transition: opacity 0.2s;
}
.resume-exp__meta-row a:hover {
opacity: 0.7;
}
.resume-exp__sep {
color: var(--line);
}
.resume-exp__period {
font-size: 0.8rem;
color: var(--text-muted);
letter-spacing: 0.02em;
}
.resume-exp__desc {
color: var(--text-muted);
font-size: 0.92rem;
margin: 0.5rem 0;
line-height: 1.55;
}
.resume-exp__section {
margin: 1rem 0;
}
.resume-exp__cols {
display: grid;
grid-template-columns: 1fr 1fr auto;
gap: 0 1.5rem;
}
.resume-exp__section-title {
font-weight: 600;
font-size: 0.92rem;
color: var(--text);
margin-bottom: 0.5rem;
}
.resume-exp__label {
font-size: 0.8rem;
font-weight: 600;
color: var(--text);
letter-spacing: 0.03em;
margin: 0.75rem 0 0.35rem;
}
.resume-exp ul {
margin: 0;
padding-left: 1.25rem;
color: var(--text-muted);
font-size: 0.92rem;
line-height: 1.55;
}
.resume-exp li + li {
margin-top: 0.25rem;
}
.resume-skills {
display: flex;
flex-direction: column;
gap: 0;
margin: 1rem 0;
}
.resume-skill {
display: flex;
align-items: baseline;
gap: 0.75rem;
font-size: 0.92rem;
line-height: 1.55;
}
.resume-skill__title {
font-weight: 600;
color: var(--text);
min-width: 8rem;
flex-shrink: 0;
font-size: 0.85rem;
letter-spacing: 0.02em;
}
.resume-skill__desc {
color: var(--text-muted);
}
.resume-about {
margin: 1.5rem 0;
font-size: 0.92rem;
color: var(--text-muted);
line-height: 1.55;
}
</style>
</head>
<body>
{{> header-minimal}}
{{> fab-stack-resume}}
<main id="main" class="section section--surface section--tight">
<div class="section__inner resume-doc">
<div class="resume-header">
<img class="resume-photo" src="{{assetPrefix}}assets/index/me_static.webp" alt="Николай Мамадаев" width="120" height="120" />
<div>
<p class="hero__eyebrow">Резюме</p>
<h1 class="case-page__h1">Николай Мамадаев</h1>
<p class="section__prose"><strong>Senior UX/UI Designer, Product Designer</strong></p>
</div>
</div>
<dl class="resume-meta">
<div>
<dt>Портфолио</dt>
<dd><a href="https://mamadaevv.site" target="_blank" rel="noopener">mamadaevv.site</a></dd>
</div>
<div>
<dt>Почта</dt>
<dd><a href="mailto:nik@mamadaevv.site">nik@mamadaevv.site</a></dd>
</div>
<div>
<dt>Вилка по ЗП</dt>
<dd>250 000 – 310 000 руб.</dd>
</div>
<div>
<dt>Формат работы</dt>
<dd>удалённо</dd>
</div>
</dl>
<h2 id="experience">Опыт работы</h2>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Собственные продукты и исследование AI-инструментов</p>
<p class="resume-exp__period">Декабрь 2025 — настоящее время</p>
</div>
<p class="resume-exp__desc">Период самостоятельной практики: изучение AI-инструментов в продуктовом и дизайн-процессе, разработка собственных продуктов полного цикла — от идеи до работающего релиза.</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">AI-плагин для Figma (внутренний инструмент)</p>
<div class="resume-exp__cols">
<div>
<p class="resume-exp__label">Обязанности:</p>
<ul>
<li>Определил сценарии автоматизации на основе аудита собственного рабочего процесса: замерил, какие операции повторяются чаще всего и съедают больше всего времени</li>
<li>Спроектировал интерфейс плагина: панель, состояния обработки, обработка ошибок, работа с выделением</li>
<li>Собрал архитектуру взаимодействия с LLM: промпт-шаблоны, валидация ответа, повторные попытки</li>
<li>Довёл до рабочей версии самостоятельно, с помощью AI-ассистированной разработки</li>
<li>Веду плагин как продукт: собираю обратную связь, приоритизирую доработки, выпускаю обновления</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Достижения:</p>
<ul>
<li>Автоматизировал 7 рутинных операций дизайн-процесса: нейминг слоёв, генерация контента для макетов, приведение текстов к тону продукта, локализация</li>
<li>Сократил время на подготовку макета к передаче в разработку примерно на 40%</li>
<li>Экономлю около 5 часов в неделю на операциях, которые раньше делал руками</li>
<li>Прошёл полный цикл продукта в одиночку: проблема → решение → реализация → эксплуатация</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Стэк:</p>
<ul>
<li>Figma API</li>
<li>AI / LLM</li>
<li>Prompt engineering</li>
</ul>
</div>
</div>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Автоматизации и сервисы на n8n (личные проекты)</p>
<div class="resume-exp__cols">
<div>
<p class="resume-exp__label">Обязанности:</p>
<ul>
<li>Проектирование логики сценариев: триггеры, ветвления, обработка ошибок, повторные запуски</li>
<li>Работа с PostgreSQL как хранилищем и источником данных для процессов</li>
<li>Интеграция внешних сервисов через REST API</li>
<li>Проектирование и запуск Telegram-ботов: сценарии диалога, состояния, интерфейс сообщений</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Достижения:</p>
<ul>
<li>Собрал 12 рабочих сценариев автоматизации, закрывающих личные и рабочие рутины</li>
<li>Запустил 3 Telegram-бота с собственной продуктовой логикой и базой данных</li>
<li>Свёл разрозненные сервисы в единый процесс без единой строки ручной работы</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Стэк:</p>
<ul>
<li>n8n</li>
<li>PostgreSQL</li>
<li>REST API</li>
<li>Telegram Bot API</li>
</ul>
</div>
</div>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Пет-проекты на AI-ассистированной разработке</p>
<div class="resume-exp__cols">
<div>
<p class="resume-exp__label">Обязанности:</p>
<ul>
<li>Продуктовое проектирование: формулировка проблемы, сценарии, интерфейс, приоритизация функций</li>
<li>Реализация фронтенда и логики с помощью AI-ассистентов</li>
<li>Развёртывание и поддержка работающих сервисов</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Достижения:</p>
<ul>
<li>Довёл 5 идей до состояния работающего продукта, а не макета в Figma</li>
<li>Научился доводить гипотезу до проверяемого прототипа за 2–3 дня вместо нескольких недель ожидания разработки</li>
<li>Закрыл разрыв между дизайном и реализацией: теперь проверяю идеи в коде, а не только на макетах</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Стэк:</p>
<ul>
<li>Необходимо заполнить</li>
</ul>
</div>
</div>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Primo RPA</p>
<p class="resume-exp__meta-row"><span>Февраль 2023 — Ноябрь 2025 (2 года и 10 месяцев)</span><span class="resume-exp__sep">·</span><a href="https://primo-rpa.com/" target="_blank" rel="noopener noreferrer">primo-rpa.com</a></p>
</div>
<p class="resume-exp__desc">Российская RPA-платформа корпоративного уровня: линейка из desktop-среды разработки роботов и веб-сервисов управления, аналитики и ML. Работал ведущим дизайнером на всю продуктовую линейку из 6 продуктов.</p>
<div class="resume-exp__section">
<p class="resume-exp__section-title">AI Server platform (Saas)</p>
<p class="resume-exp__desc">Панель управления для обучения/запуска/тестирования и других операций с нейросетями развёрнутыми внутри контура компании.</p>
<div class="resume-exp__cols">
<div>
<p class="resume-exp__label">Обязанности:</p>
<ul>
<li>Проектирование интерфейса управления моделями: обучение, запуск, тестирование, версионирование, мониторинг</li>
<li>Проработка сценариев работы с Smart OCR — извлечение данных из документов различных типов</li>
<li>Проектирование разметки документов и валидации результатов распознавания</li>
<li>Работа с состояниями долгих процессов: обучение модели, прогресс, ошибки, откат</li>
<li>Подготовка интерактивных прототипов и авторский надзор за реализацией</li>
<li>Проведение интервью с ML-инженерами и бизнес-пользователями для сверки моделей поведения</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Достижения:</p>
<ul>
<li>Упаковал сложную ML-логику в интерфейс, понятный не только ML-инженеру, но и бизнес-аналитику без технического бэкграунда</li>
<li>Свёл работу с моделями к единому предсказуемому сценарию из 4 шагов вместо 9 разрозненных экранов</li>
<li>Сократил время настройки новой модели с 40 до 15 минут по результатам замеров на тестировании</li>
<li>Спроектировал интерфейс разметки документов, который снял 60% обращений в поддержку по этой теме</li>
<li>Провёл 8 юзабилити-сессий, по итогам переработал ключевой сценарий обучения модели</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Стэк:</p>
<ul>
<li>ML / нейросети</li>
<li>Smart OCR</li>
</ul>
</div>
</div>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Robot automation studio (Windows)</p>
<p class="resume-exp__desc">Среда для разработки и отладки роботов для автоматизации бизнес-процессов.</p>
<div class="resume-exp__cols">
<div>
<p class="resume-exp__label">Обязанности:</p>
<ul>
<li>Проектирование интерфейса профессиональной desktop-IDE: рабочая область, панели инструментов, дерево процесса, отладчик</li>
<li>Развитие библиотеки компонентов и визуального языка продукта</li>
<li>Проработка сценариев отладки: точки останова, пошаговое выполнение, просмотр переменных</li>
<li>Проектирование работы с большими деревьями активностей и вложенностью</li>
<li>Работа в паре с разработкой по реализации компонентов, авторский надзор</li>
<li>Ведение регулярных дизайн-ревью внутри команды</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Достижения:</p>
<ul>
<li>Обновил визуальный язык продукта до уровня Windows 10/11 — компоненты стали на поколение современнее</li>
<li>Переработал 80+ экранов и диалогов, приведя их к единой сетке и типографике</li>
<li>Собрал библиотеку из 140 компонентов, закрывшую 90% потребностей интерфейса</li>
<li>Перевёл иконки и часть иллюстраций на векторную графику: корректное отображение при любом масштабировании и DPI</li>
<li>Сократил время сборки нового экрана командой с 2 дней до 4 часов за счёт готовых компонентов</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Стэк:</p>
<ul>
<li>Desktop IDE</li>
<li>Windows 10/11</li>
<li>Компонентная библиотека</li>
</ul>
</div>
</div>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Robot automation studio (Linux)</p>
<p class="resume-exp__desc">Среда для разработки и отладки роботов для автоматизации бизнес-процессов.</p>
<div class="resume-exp__cols">
<div>
<p class="resume-exp__label">Обязанности:</p>
<ul>
<li>Адаптация дизайна Студии под Linux-версию на фреймворке Avalonia</li>
<li>Проектирование компонентов с учётом технических ограничений фреймворка</li>
<li>Синхронизация визуального языка между Windows- и Linux-версиями продукта</li>
<li>Совместная работа с разработкой над тем, что технически реализуемо в Avalonia, а что требует обходных решений</li>
<li>Подготовка спецификаций поведения компонентов для реализации</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Достижения:</p>
<ul>
<li>Собрал расширенную библиотеку из 95 компонентов для Avalonia, которой в проекте не существовало до меня</li>
<li>Обеспечил единообразие продукта на двух платформах при разных технологических стеках</li>
<li>Сократил количество визуальных расхождений между версиями с нескольких десятков до единичных случаев</li>
<li>Дал команде Linux-версии готовый набор решений вместо дизайна каждого экрана с нуля</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Стэк:</p>
<ul>
<li>Avalonia</li>
<li>.NET</li>
<li>Linux</li>
</ul>
</div>
</div>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Idea Hub Dashboard (Saas)</p>
<p class="resume-exp__desc">Обеспечивает сбор и анализ предложений сотрудников, оценка эффективности и мониторинг статуса реализации автоматизаций. Аналитика по ключевым показателям эффективности и верхнеуровневый взгляд на роботизацию.</p>
<div class="resume-exp__cols">
<div>
<p class="resume-exp__label">Обязанности:</p>
<ul>
<li>Проектирование дашбордов и аналитических представлений по KPI роботизации</li>
<li>Проработка жизненного цикла идеи: подача → оценка → приоритизация → реализация → замер эффекта</li>
<li>Информационная архитектура раздела, работа с плотными таблицами, фильтрами и массовыми операциями</li>
<li>Проектирование ролевой модели: сотрудник, аналитик, руководитель</li>
<li>Подбор типов визуализации данных под конкретные управленческие вопросы</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Достижения:</p>
<ul>
<li>Свёл верхнеуровневую аналитику и работу с конкретной идеей в один непрерывный сценарий без переключения между разделами</li>
<li>Спроектировал представление данных так, что руководитель видит эффект от роботизации без ручных выгрузок в Excel</li>
<li>Сократил путь от подачи идеи до её оценки с 6 шагов до 3</li>
<li>Спроектировал 12 виджетов аналитики, покрывающих основные вопросы заказчиков о ROI роботизации</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Стэк:</p>
<ul>
<li>Аналитика / дашборды</li>
<li>KPI</li>
<li>Визуализация данных</li>
</ul>
</div>
</div>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Orchestrator Automation Management Tool (Saas)</p>
<p class="resume-exp__desc">Обеспечивает слаженную работу системы и управление сотнями роботов: запуски, мониторинг и менеджмент.</p>
<div class="resume-exp__cols">
<div>
<p class="resume-exp__label">Обязанности:</p>
<ul>
<li>Проектирование интерфейса управления парком из сотен роботов: расписания, очереди, приоритеты, мониторинг</li>
<li>Проработка состояний и обработки ошибок при массовых запусках</li>
<li>Проектирование системы уведомлений и алертов о сбоях</li>
<li>Работа со сложными таблицами: сортировка, фильтрация, массовые действия, сохранённые представления</li>
<li>Прототипирование сложных сценариев для валидации до начала разработки</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Достижения:</p>
<ul>
<li>Спроектировал управление сотнями объектов так, что оператор не теряется в масштабе: от общей картины до конкретного робота за 2 клика</li>
<li>Привёл сервис к единой дизайн-системе вместе с остальными веб-продуктами линейки</li>
<li>Сократил время реакции оператора на сбой робота с 12 до 4 минут за счёт переработанной системы алертов</li>
<li>Свёл 5 разных представлений списка роботов к одному настраиваемому</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Стэк:</p>
<ul>
<li>Мониторинг</li>
<li>Расписания / очереди</li>
<li>Уведомления / алерты</li>
</ul>
</div>
</div>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">QnA portal (WEB)</p>
<p class="resume-exp__desc">Площадка для постинга вопросов и получения ответов от службы поддержки</p>
<div class="resume-exp__cols">
<div>
<p class="resume-exp__label">Обязанности:</p>
<ul>
<li>Проектирование сценариев публикации вопроса, ответа и поиска по накопленной базе знаний</li>
<li>Дизайн интерфейса портала на базе общей дизайн-системы компании</li>
<li>Проработка ролевой модели: пользователь, эксперт, служба поддержки, модератор</li>
<li>Проектирование механики поиска и подсказок похожих вопросов при публикации</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Достижения:</p>
<ul>
<li>Запустил портал на готовых компонентах дизайн-системы за 3 недели вместо запланированных 8</li>
<li>Снизил нагрузку на поддержку примерно на 25% за счёт переиспользования уже данных ответов</li>
<li>Механика подсказок похожих вопросов сократила количество дублей на 45%</li>
<li>Обеспечил визуальную преемственность с продуктами линейки — портал не выглядит сторонним сервисом</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Стэк:</p>
<ul>
<li>Веб-портал</li>
<li>Дизайн-система</li>
<li>База знаний</li>
</ul>
</div>
</div>
</div>
<div class="resume-exp__section">
<p class="resume-exp__section-title">Общее по компании</p>
<ul>
<li>Инициировал обновление внешнего вида всей продуктовой линейки — решение о редизайне компания приняла с моим приходом</li>
<li>Собрал и внедрил единую дизайн-систему для веб-сервисов, соединив фирменный стиль компании с новой структурой интерфейсов</li>
<li>Дизайн-систему приняли 4 продуктовые команды; она включает 210 компонентов и токены темизации</li>
<li>Сократил среднее время подготовки макетов по линейке на 35%</li>
<li>Создавал и поддерживал UI-kit для консистентности и ускорения разработки</li>
<li>Провёл более 20 пользовательских исследований и юзабилити-сессий за время работы</li>
<li>Вёл авторский надзор за реализацией, участвовал в дизайн-ревью, продуктовых обсуждениях и планировании релизов</li>
<li>Был единственным ведущим дизайнером на всю линейку из 6 продуктов и двух платформ</li>
</ul>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Lunacy (Icons8)</p>
<p class="resume-exp__meta-row"><span>Июль 2022 — Январь 2023 (7 месяцев)</span><span class="resume-exp__sep">·</span><a href="https://icons8.com/lunacy" target="_blank" rel="noopener noreferrer">icons8.com/lunacy</a></p>
</div>
<p class="resume-exp__desc">Графический редактор для работы над дизайном интерфейсов и прочих макетов. Аналог Sketch App и Figma.</p>
<div class="resume-exp__section">
<div class="resume-exp__cols">
<div>
<p class="resume-exp__label">Обязанности:</p>
<ul>
<li>Проектирование интерфейса графического редактора: инструменты, панели свойств, работа с холстом и слоями</li>
<li>Оформление решений в виде юзерфлоу и передача разработчикам</li>
<li>Создание сложных интерактивных прототипов в Protopie для демонстрации поведения инструментов</li>
<li>Отрисовка недостающих иконок в стилистике продукта</li>
<li>Внесение предложений по улучшению функциональности редактора</li>
<li>Участие в обсуждениях продуктовых решений с командой</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Достижения:</p>
<ul>
<li>Спроектировал 6 функциональных блоков редактора, включая работу с компонентами и стилями</li>
<li>Собрал 15+ прототипов в Protopie, что позволило отсечь неудачные решения до разработки</li>
<li>Часть моих предложений по функциональности вошла в релизы продукта</li>
<li>Отрисовал более 60 иконок, дополнивших системный набор редактора</li>
<li>Работал над продуктом для профессиональной аудитории дизайнеров, где требования к деталям интерфейса выше обычных</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Стэк:</p>
<ul>
<li>Protopie</li>
<li>Графический редактор</li>
<li>Иконки / иллюстрации</li>
</ul>
</div>
</div>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">MANU Video Game Maker</p>
<p class="resume-exp__meta-row"><span>Январь 2019 — Декабрь 2021 (3 года)</span><span class="resume-exp__sep">·</span><a href="https://manu.co/" target="_blank" rel="noopener noreferrer">manu.co</a></p>
</div>
<p class="resume-exp__desc">Игровой движок для создания видеоигр без написания кода.</p>
<div class="resume-exp__section">
<div class="resume-exp__cols">
<div>
<p class="resume-exp__label">Обязанности:</p>
<ul>
<li>Продуктовый дизайн движка целиком: от концепции взаимодействия до конечного UI</li>
<li>Проектирование поведения интерфейса для сложных пользовательских сценариев</li>
<li>Исследования пользователей: наблюдение, глубинные интервью, опросы</li>
<li>Составление портретов потенциальных пользователей и карт эмпатии</li>
<li>Работа с продуктовой аналитикой и метриками, завязанными на пользовательские сценарии</li>
<li>Вёрстка главной страницы сайта на Tilda, проектирование информационной архитектуры сайта вместе с командой</li>
<li>Контроль работы веб-графического дизайнера</li>
<li>Найм в продуктовый отдел: проведение собеседований и отбор специалистов</li>
<li>Руководство отделом, построение рабочих процессов всей продуктовой команды</li>
<li>Кураторство работ по созданию пользовательской документации</li>
<li>Внедрение инструментов автоматизации (Integromat, Zapier) для внутренних задач</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Достижения:</p>
<ul>
<li>Провёл масштабный редизайн всей программы: заложил принципиально новую концепцию работы и стилистику</li>
<li>Спроектировал поведение интерфейса для 100+ сложных пользовательских сценариев</li>
<li>Спроектировал дизайн-систему продукта с нуля: 120 компонентов</li>
<li>Получили массу положительных, местами восторженных отзывов пользователей — в продукте стало значительно легче ориентироваться</li>
<li>Завершаемость онбординга выросла с 34% до 58% после редизайна</li>
<li>Провёл 25 глубинных интервью и 4 волны опросов, на их основе переработал 3 ключевых сценария</li>
<li>Нанял 4 специалистов в продуктовый отдел и вырос из дизайнера в тимлида команды</li>
<li>Выстроил процессы отдела: дизайн-ревью, работа с бэклогом, передача в разработку</li>
<li>Автоматизировал внутренние рутины команды, освободив время на продуктовые задачи</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Стэк:</p>
<ul>
<li>Tilda</li>
<li>Integromat / Zapier</li>
<li>Исследования пользователей</li>
</ul>
</div>
</div>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Aegees Messenger</p>
<p class="resume-exp__meta-row"><span>Октябрь 2017 — Декабрь 2018 (1 год и 3 месяца)</span><span class="resume-exp__sep">·</span><a href="https://aegees.com/" target="_blank" rel="noopener noreferrer">aegees.com</a></p>
</div>
<p class="resume-exp__desc">Кроссплатформенный мессенджер с защищенным хранилищем и аудиозвонками.</p>
<div class="resume-exp__section">
<div class="resume-exp__cols">
<div>
<p class="resume-exp__label">Обязанности:</p>
<ul>
<li>Дизайн мессенджера сразу под пять платформ: Android, iOS, macOS, Windows, Linux</li>
<li>Проработка сценариев защищённого хранилища и аудиозвонков</li>
<li>Проектирование сценариев регистрации, шифрования и восстановления доступа</li>
<li>Адаптация единой продуктовой логики под гайдлайны каждой платформы</li>
<li>Контроль работы зарубежных иллюстраторов по подготовке графических материалов</li>
<li>Подготовка материалов для магазинов приложений</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Достижения:</p>
<ul>
<li>Выстроил единый визуальный язык продукта при соблюдении гайдлайнов пяти платформ одновременно</li>
<li>Спроектировал более 90 экранов в пяти платформенных вариантах</li>
<li>Обеспечил стабильный поток графических материалов от внешних подрядчиков без потери стилистики</li>
<li>Упростил сценарий защищённого хранилища так, чтобы им пользовались люди без технической подготовки</li>
<li>Работал в чувствительной области приватности и безопасности, где ошибка в интерфейсе стоит доверия пользователя</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Стэк:</p>
<ul>
<li>Android</li>
<li>iOS</li>
<li>macOS</li>
<li>Windows</li>
<li>Linux</li>
</ul>
</div>
</div>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">Orion Innovation (ex MERA)</p>
<p class="resume-exp__meta-row"><span>Июль 2016 — Октябрь 2017 (1 год и 4 месяца)</span><span class="resume-exp__sep">·</span><a href="https://www.orioninnovation.com/" target="_blank" rel="noopener noreferrer">orioninnovation.com</a></p>
</div>
<p class="resume-exp__desc">Разработка ПО для внешних заказчиков.</p>
<div class="resume-exp__section">
<div class="resume-exp__cols">
<div>
<p class="resume-exp__label">Обязанности:</p>
<ul>
<li>Работа в дизайн-отделе численностью до 8 человек</li>
<li>Создание анкет персон и составление карты функциональности продукта в соответствии с потребностями персон</li>
<li>Вайрфреймы и отрисовка конечного UI интерфейсов</li>
<li>Проектирование юзкейсов, карт экранов, демонстрации микроанимаций</li>
<li>Подготовка мудбордов и дизайн-концепций, обсуждение их с клиентами</li>
<li>Подготовка и проведение презентаций дизайн-концепций</li>
<li>Линковка мокапов в прототипы, написание сценариев и проведение качественных юзабилити-тестирований</li>
<li>Внесение правок по результатам тестирований</li>
<li>Авторский надзор над реализацией дизайна разработчиками</li>
<li>Участие в дизайн-ревью: разбор работ коллег и защита собственных решений</li>
<li>Прямая коммуникация с зарубежными клиентами для обсуждения дизайна и получения задач</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Достижения:</p>
<ul>
<li>Провёл 10 сессий юзабилити-тестирования от написания сценария до внесения правок</li>
<li>Освоил новую для себя платформу Smart TV и довёл проект до успешной публикации в магазине приложений</li>
<li>Вёл коммуникацию с зарубежными заказчиками напрямую, без посредников</li>
<li>Активно участвовал в улучшении рабочего процесса дизайн-отдела компании</li>
<li>Прошёл полный цикл продуктового дизайна на 5 клиентских проектах</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Стэк:</p>
<ul>
<li>Smart TV</li>
<li>Юзабилити-тестирование</li>
<li>Мудборды / дизайн-концепции</li>
</ul>
</div>
</div>
</div>
</div>
<div class="resume-exp">
<div class="resume-exp__header">
<p class="resume-exp__company">SpaceshipApps Studio</p>
<p class="resume-exp__meta-row"><span>Июнь 2015 — Июнь 2016 (1 год и 1 месяц)</span><span class="resume-exp__sep">·</span><a href="https://spaceshipapps.ru/" target="_blank" rel="noopener noreferrer">spaceshipapps.ru</a></p>
</div>
<p class="resume-exp__desc">Студия разработки мобильных приложений и сайтов.</p>
<div class="resume-exp__section">
<div class="resume-exp__cols">
<div>
<p class="resume-exp__label">Обязанности:</p>
<ul>
<li>Дизайн мобильных и веб-продуктов в потоковом режиме студии</li>
<li>Работа с разными доменами: соцгейминг, бьюти-услуги, доставка еды, голосовые интерфейсы, легал-сервисы, коллаборативные инструменты</li>
<li>Адаптивный веб-дизайн и дизайн административных панелей</li>
<li>Отрисовка иконок и подготовка графики для проектов</li>
<li>Подготовка макетов к передаче в разработку</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Достижения:</p>
<ul>
<li>Выпустил 6 продуктов за год: геолокационная социальная игра с квестами в реальном мире, приложение записи к бьюти-специалистам, сервис доставки еды, голосовая игра со словами, сайт и админка сервиса регистрации авторского права, мобильная «белая доска» для совместной работы</li>
<li>Научился быстро входить в новую предметную область и держать качество при высоком темпе студии</li>
<li>Закрыл весь спектр задач: мобайл, веб, админ-панели, графика</li>
<li>Заложил базу для перехода от исполнительского дизайна к продуктовому</li>
</ul>
</div>
<div>
<p class="resume-exp__label">Стэк:</p>
<ul>
<li>Мобайл</li>
<li>Веб</li>
<li>Админ-панели</li>
<li>Графика</li>
</ul>
</div>
</div>
</div>
</div>
<h2 id="skills">Навыки</h2>
<div class="resume-skills">
<div class="resume-skill">
<p class="resume-skill__title">Проектирование</p>
<p class="resume-skill__desc">UX/UI, product design, информационная архитектура, адаптивный дизайн, дизайн-системы</p>
</div>
<div class="resume-skill">
<p class="resume-skill__title">Исследования</p>
<p class="resume-skill__desc">Интервью, опросы, usability testing, JTBD, карты эмпатии, конверсия, retention, NPS</p>
</div>
<div class="resume-skill">
<p class="resume-skill__title">Инструменты</p>
<p class="resume-skill__desc">Figma, Protopie, Sketch, Adobe Creative Suite, Tilda, AI-инструменты</p>
</div>
<div class="resume-skill">
<p class="resume-skill__title">Управление</p>
<p class="resume-skill__desc">Построение команды, Agile, Kanban, авторский надзор, работа со стейкхолдерами</p>
</div>
</div>
<h2 id="about">О себе</h2>
<p class="section__prose resume-about">
В дизайне больше 10 лет, последние годы — продуктовый дизайн сложных B2B-продуктов. Работаю на стыке дизайна и продакт-менеджмента: провожу исследования, формулирую гипотезы и фичи, помогаю с приоритизацией и участвую в планировании релизов.
</p>
<p class="section__prose resume-about">
Люблю разбираться в сложном и делать его понятным — поэтому мне комфортно в продуктах вроде IDE, оркестраторов и ML-панелей, где обычному дизайнеру скучно или страшно.
</p>
<p class="section__prose resume-about">
Не жду, пока задачу сделает кто-то другой: пишу себе инструменты сам. Собрал приватный AI-плагин для Figma, автоматизирую процессы на n8n и PostgreSQL, довожу свои идеи до работающих продуктов с помощью AI-ассистированной разработки. Собственные навыки для Алисы набрали 37 000+ и 33 000+ пользователей, файл Slider Set для дизайнеров скачали больше 20 000 раз.
</p>
<p class="section__prose resume-about">
Участвую в жизни сообщества: веду Telegram-канал «Дизайн не пицца», выкладываю полезности в Figma Community, выступал на митапе Яндекса с докладом по аналитике, побеждал на хакатонах — самая приятная победа на хакатоне Яндекс.Денег в Петербурге за приложение оплаты по QR-коду.
</p>
<p class="section__prose resume-about">
Английский — B1. Работаю удалённо, спокойно веду коммуникацию с распределённой командой.
</p>
</div>
</main>
{{> footer}}
{{> cookie-notice}}
<script>
(function () {
var printBtn = document.querySelector('[data-resume-print-btn]');
if (!printBtn) return;
printBtn.addEventListener('click', function () {
var doc = document.querySelector('.resume-doc');
if (!doc) return;
var styles = [];
document.querySelectorAll('link[rel="stylesheet"]').forEach(function (l) {
styles.push('<link rel="stylesheet" href="' + l.href + '">');
});
document.querySelectorAll('style').forEach(function (s) {
styles.push('<style>' + s.textContent + '</style>');
});
var win = window.open('', '_blank');
if (!win) return;
win.document.write(
'<!DOCTYPE html><html><head><meta charset="utf-8">' +
styles.join('') +
'<style>@media print{body{margin:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;}}</style>' +
'</head><body>' + doc.outerHTML + '</body></html>'
);
win.document.close();
win.onload = function () {
setTimeout(function () { win.print(); }, 500);
};
});
})();
</script>
</body>
</html>
+2 -2
View File
@@ -1,11 +1,11 @@
<section id="contact" class="section section--surface section--footerish">
<section id="contact" class="section section--surface section--footerish" data-reveal>
<div class="section__inner">
<h2 class="section__title">Контакты</h2>
<ul class="contact-grid">
<li><a class="contact-card contact-card--link contact-card--brand-tg" href="https://t.me/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="{{assetPrefix}}assets/shared/icons/tg.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Telegram</span><span class="contact-card__hint">Отвечу сегодня</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-vk" href="https://vk.com/mamadaevv" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="{{assetPrefix}}assets/shared/icons/vk.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">ВКонтакте</span><span class="contact-card__hint">Стабильный коннект</span></span></a></li>
<li><a class="contact-card contact-card--link contact-card--brand-ya" href="https://yandex.ru/chat/p/727e71fa-89b5-44a8-90a5-851021631a1c?utm_source=invite" rel="noopener noreferrer"><span class="contact-card__corner" aria-hidden="true"></span><span class="contact-card__icon" aria-hidden="true"><img src="{{assetPrefix}}assets/shared/icons/yandex_telemost.svg" alt="" width="24" height="24" loading="eager" decoding="async" /></span><span class="contact-card__body"><span class="contact-card__name">Яндекс</span><span class="contact-card__hint">Да, тут тоже можно</span></span></a></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5ydQ==" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
<li><button type="button" class="contact-card contact-card--action contact-card--brand-email" data-contact-copy data-email-b64="bmlrQG1hbWFkYWV2di5zaXRl" data-hint-default="Скопировать адрес" aria-label="Скопировать адрес электронной почты в буфер обмена"><span class="contact-card__corner contact-card__corner--copy" aria-hidden="true"></span><span class="contact-card__icon contact-card__icon--accent" aria-hidden="true"></span><span class="contact-card__body"><span class="contact-card__name">Почта</span><span class="contact-card__hint" data-contact-copy-hint>Скопировать адрес</span></span></button></li>
</ul>
</div>
</section>
+11
View File
@@ -0,0 +1,11 @@
<div class="fab-stack" aria-label="Быстрые действия">
<div class="theme-panel-fab-wrap">
<button type="button" class="fab fab--secondary glass-neutral" data-resume-print-btn aria-label="Печать резюме">
<span class="fab-secondary__ico fab-secondary__ico--print" aria-hidden="true"></span>
</button>
</div>
<a href="/assets/resume/Mamadaev_Nik__CV__Product_Designer_UX-UI.pdf" download="Mamadaev_Nik__CV__Product_Designer_UX-UI.pdf" class="fab fab--primary fab--label" aria-label="Скачать резюме в PDF">
<span class="fab-primary__ico fab-primary__ico--pdf" aria-hidden="true"></span>
<span class="fab__label">Скачать в PDF</span>
</a>
</div>
+1 -1
View File
@@ -1,4 +1,4 @@
<section id="mini-projects" class="section section--surface" aria-labelledby="mini-projects-title">
<section id="mini-projects" class="section section--surface" aria-labelledby="mini-projects-title" data-reveal>
<div class="section__inner">
<h2 id="mini-projects-title" class="section__title">Активность</h2>
<div
+1 -1
View File
@@ -1,4 +1,4 @@
<section id="projects" class="section section--surface">
<section id="projects" class="section section--surface" data-reveal>
<div class="section__inner">
<h2 class="section__title">Портфолио</h2>
<ol class="mini-projects-grid" data-mini-projects-list>
+24
View File
@@ -26,6 +26,30 @@
var L = Number(l);
if (Number.isFinite(L)) d.style.setProperty("--theme-l", String(Math.min(70, Math.max(20, L))));
}
var hVal = h !== null ? h : 210;
var sVal = s !== null ? s : 90;
var lVal = l !== null ? Math.min(70, Math.max(20, Number(l))) : 40;
var H = (((hVal % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, sVal)) / 100;
var Lv = Math.min(100, Math.max(0, lVal)) / 100;
var r, g, b;
if (S === 0) { r = g = b = Lv; }
else {
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
var p = 2 * Lv - q;
var hue2rgb = function(p, q, t) {
if (t < 0) t += 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
r = hue2rgb(p, q, H + 1/3);
g = hue2rgb(p, q, H);
b = hue2rgb(p, q, H - 1/3);
}
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
var rad = t.radius;
if (rad === "soft" || rad === "medium" || rad === "strong") {
d.dataset.radius = rad;
+2 -17
View File
@@ -1,21 +1,6 @@
{
"version": 2,
"updatedAt": "2026-06-06T11:59:34.336Z",
"items": [
{
"instruction": "замени: без ломки базовых сценариев\nна: без больших переделок",
"target": {
"scope": "page",
"selector": "main#case-main",
"anchorId": "case-main",
"tag": "main",
"content": "Общая правка страницы",
"snippet": "Общая правка страницы"
},
"refs": [],
"n": 1,
"page": "cases/ai-platform-primo-rpa.html"
}
],
"updatedAt": "2026-08-10T16:53:19.518Z",
"items": [],
"lastAppliedAt": "2026-06-06T11:54:50.470Z"
}