Files
site-portfolio/public/cases/ai-platform-primo-rpa-2/index.html
T
Nikolay Mamadaev f383ec350a feat: llms.txt — карта сайта для LLM-агентов + link-relation describedby в head
Генерируется в build-pages.mjs из тех же страниц, что и sitemap.xml, с ручными описаниями по каждому URL. Страницы-каталоги дизайн-системы (noindex) в файл не попадают.
2026-10-07 14:01:09 +02:00

1194 lines
72 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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="Кейс: интерфейс AI Server в Primo RPA — OCR на корпоративных документах, дообучение моделей, skills, UX/UI."
/>
<title>AI Server в Primo RPA — кейс (черновик 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 DEF = { h: 210, s: 90, l: 40 };
function pickAccent(o) {
if (!o) return null;
var h = typeof o.h === "number" ? o.h : typeof o.hue === "number" ? o.hue : null;
var s = typeof o.s === "number" ? o.s : typeof o.sat === "number" ? o.sat : null;
var l = typeof o.l === "number" ? o.l : typeof o.light === "number" ? o.light : null;
if (h === null && s === null && l === null) return null;
return {
h: h === null ? DEF.h : h,
s: s === null ? DEF.s : Math.min(100, Math.max(30, s)),
l: l === null ? DEF.l : Math.min(70, Math.max(20, l)),
};
}
// Текущий формат: отдельный акцент для светлой и тёмной темы ({light, dark}).
// Старый плоский формат ({h, s, l}) остаётся совместимым.
var acc =
pickAccent(eff === "dark" ? t.dark : t.light) ||
pickAccent(eff === "dark" ? t.light : t.dark) ||
pickAccent(t) ||
DEF;
d.style.setProperty("--theme-h", String(acc.h));
d.style.setProperty("--theme-s", String(acc.s));
d.style.setProperty("--theme-l", String(acc.l));
var H = (((acc.h % 360) + 360) % 360) / 360;
var S = Math.min(100, Math.max(0, acc.s)) / 100;
var Lv = Math.min(100, Math.max(0, acc.l)) / 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 = "geologica";
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="modulepreload" href="/js/modules/ui/page-mesh-shader.js" />
<link rel="stylesheet" href="/css/main.css" />
<link rel="canonical" href="https://mamadaevv.site/cases/ai-platform-primo-rpa-2/" />
<link rel="alternate" hreflang="ru" href="https://mamadaevv.site/cases/ai-platform-primo-rpa-2/" />
<link rel="alternate" hreflang="en" href="https://mamadaevv.site/en/cases/ai-platform-primo-rpa-2/" />
<link rel="alternate" hreflang="x-default" href="https://mamadaevv.site/cases/ai-platform-primo-rpa-2/" />
<link rel="describedby" href="https://mamadaevv.site/llms.txt" title="llms.txt" />
<meta name="author" content="Николай Мамадаев" />
<meta name="robots" content="index, follow" />
<meta name="theme-color" content="#0f1115" />
<!-- Open Graph -->
<meta property="og:type" content="article" />
<meta property="og:site_name" content="Николай Мамадаев — продуктовый дизайнер" />
<meta property="og:locale" content="ru_RU" />
<meta property="og:locale:alternate" content="en_US" />
<meta property="og:title" content="AI Server в Primo RPA — кейс (черновик 2)" />
<meta property="og:description" content="Кейс: интерфейс AI Server в Primo RPA — OCR на корпоративных документах, дообучение моделей, skills, UX/UI." />
<meta property="og:url" content="https://mamadaevv.site/cases/ai-platform-primo-rpa-2/" />
<meta property="og:image" content="https://mamadaevv.site/assets/og/og-default.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="AI Server в Primo RPA — кейс (черновик 2)" />
<!-- Twitter / X -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="AI Server в Primo RPA — кейс (черновик 2)" />
<meta name="twitter:description" content="Кейс: интерфейс AI Server в Primo RPA — OCR на корпоративных документах, дообучение моделей, skills, UX/UI." />
<meta name="twitter:image" content="https://mamadaevv.site/assets/og/og-default.png" />
<meta name="twitter:image:alt" content="AI Server в Primo RPA — кейс (черновик 2)" />
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Person",
"@id": "https://mamadaevv.site/#person",
"name": "Николай Мамадаев",
"url": "https://mamadaevv.site",
"jobTitle": "Продуктовый дизайнер",
"description": "Продуктовый дизайнер с опытом более 10 лет. Проектирую цифровые продукты, интерфейсы и дизайн-системы.",
"knowsAbout": [
"UX/UI-дизайн",
"продуктовый дизайн",
"дизайн-системы",
"прототипирование",
"Figma",
"no-code"
],
"sameAs": [
"https://t.me/mamadaevv",
"https://vk.com/mamadaevv",
"https://github.com/mamadaevv"
]
},
{
"@type": "WebSite",
"@id": "https://mamadaevv.site/#website",
"url": "https://mamadaevv.site/",
"name": "Николай Мамадаев — продуктовый дизайнер",
"inLanguage": "ru",
"author": {
"@id": "https://mamadaevv.site/#person"
},
"publisher": {
"@id": "https://mamadaevv.site/#person"
}
},
{
"@type": "CreativeWork",
"@id": "https://mamadaevv.site/cases/ai-platform-primo-rpa-2/#page",
"url": "https://mamadaevv.site/cases/ai-platform-primo-rpa-2/",
"name": "AI Server в Primo RPA — кейс (черновик 2)",
"description": "Кейс: интерфейс AI Server в Primo RPA — OCR на корпоративных документах, дообучение моделей, skills, UX/UI.",
"isPartOf": {
"@id": "https://mamadaevv.site/#website"
},
"author": {
"@id": "https://mamadaevv.site/#person"
},
"inLanguage": "ru",
"creator": {
"@id": "https://mamadaevv.site/#person"
},
"datePublished": "2026-09-24",
"about": "UX/UI-дизайн и проектирование интерфейсов"
},
{
"@type": "BreadcrumbList",
"@id": "https://mamadaevv.site/cases/ai-platform-primo-rpa-2/#breadcrumbs",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Николай Мамадаев — продуктовый дизайнер",
"item": "https://mamadaevv.site/"
},
{
"@type": "ListItem",
"position": 2,
"name": "Кейсы",
"item": "https://mamadaevv.site/cases/"
},
{
"@type": "ListItem",
"position": 3,
"name": "AI Server в Primo RPA — кейс (черновик 2)",
"item": "https://mamadaevv.site/cases/ai-platform-primo-rpa-2/"
}
]
}
]
}
</script>
<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 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;
}
.case-article a:not(.btn) {
color: var(--accent);
}
.case-block {
margin-top: 3rem;
padding-top: 2.5rem;
border-top: 1px solid color-mix(in srgb, var(--text) 14%, transparent);
}
.case-block:first-of-type {
margin-top: 0;
padding-top: 0;
border-top: 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>
<a class="skip-link" href="#case-main">К содержимому кейса</a>
<header class="header" data-theme-picker>
<div class="header__inner">
<a class="logo" href="../../" aria-label="На главную">НМ</a>
<div class="header__cluster">
<nav class="nav" aria-label="Разделы страницы">
<a href="#contact">Контакты</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="#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="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">Разработка интерфейса для&nbsp;Primo&nbsp;RPA&nbsp;AI&nbsp;Server</h1>
<p class="case-page__sub">
Платформа интеллектуальной обработки документов<br />
и оркестрации ИИ-агентов
</p>
<div class="case-block" id="obzor">
<h2>Обзор</h2>
<p class="section__prose">
Внутри компании появился сервис, который заметно улучшил работу с моделями для распознавания текста на документах: загрузка датасета из документов компании, разметка полей, обучение модели и дальнейшее использование модели в других продуктах. Такой подход давал более высокое качество распознавания и соответствовал требованиям безопасности — данные оставались внутри контура компании. Уже в ходе работы в продукте появился функционал дообучения (fine-tuning) базовых нейросетей под задачи компании и работы со скилами: суммаризация, извлечение, генерация и другие сценарии.
</p>
<p class="section__prose">
В проект меня пригласили как UX/UI дизайнера: интерфейс до этого собирали разработчики своими силами. В результате работы у сервиса снизился порог входа — продуктом могли пользоваться существенно больше людей без специальной подготовки в области ИИ и OCR.
</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>
Главный эффект для бизнеса — не «красивая картинка», а возможность масштабировать решение: меньше зависимости от узкого круга экспертов и отдела внедрения на каждом шаге.
</p>
</div>
</aside>
</div>
<div class="case-block" id="bylo-stalo">
<h2>Было и стало</h2>
<p class="section__prose">
Сервис был собран на <a href="https://ant.design/components/overview" target="_blank" rel="noopener noreferrer">Ant Design</a> под React с визуальной темой <a href="https://templates.iqonic.design/hope-ui/html/dist/" target="_blank" rel="noopener noreferrer">Hope UI</a> для Bootstrap. У компании уже было несколько веб-продуктов с задачей унифицировать и освежить интерфейс, поэтому в разработке опирались на компоненты этих систем.
</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>
<p class="section__prose">
Я погрузился в продукт и вместе с командой детально разобрал весь функционал.
</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>
<strong>Мой опыт в ИИ</strong> и в веб-платформах со схожей логикой сильно ускорил работу: проще было синхронизироваться с разработкой и не теряться в терминологии домена.
</p>
</div>
</aside>
<p class="section__prose">
По текущим сценариям собрал юзерфлоу: они показали команде, где в интерфейсе и в маршрутах пользователя возникает путаница. На этой основе переработали сами процессы настройки: часть функций автоматизировали и спрятали, чтобы снизить риск ошибок и убрать лишнюю рутину.
</p>
<p class="section__prose">
Новый подход изменил и восприятие продукта, и процесс настройки. Интерфейс ведёт по этапам настройки, при этом не ломает привычные сценарии: полностью линейный визард здесь невозможен — пользователю всё равно нужно возвращаться назад и уточнять параметры ради качества результата.
</p>
<h3>Вопросы к команде по текущему состоянию</h3>
<p class="section__prose">Ответы помогут зафиксировать эффект от внедрения в цифрах и фактах.</p>
<ul>
<li>Сократилось ли количество обращений в поддержку.</li>
<li>Получается ли у пользователей самостоятельно пройти настройку проекта от начала до конца.</li>
<li>Позволяет ли новый интерфейс заводить новые типы проектов, опираясь на уже заложенные паттерны.</li>
</ul>
</div>
<div class="case-block" id="patterns">
<h2>Паттерны интерфейса</h2>
<p class="section__prose">
Ниже — ключевые зоны продукта: как они поддерживают сценарии обучения и работы с моделью и чем отличаются от прежнего подхода.
</p>
<h3>Сопоставление полей (маппинг)</h3>
<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>
<h3>Датасет, обучение и контроль качества</h3>
<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/dataset-editor.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-old.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-lerning.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-quality.webp"
alt="Контроль качества модели после обучения"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Качество и проверка результата</figcaption>
</figure>
<h3>Inference в проекте</h3>
<p class="section__prose">
Отдельный фокус — запуск и контроль модели внутри проекта: пользователь должен понимать состояние прогона и не терять связь с остальными настройками.
</p>
<figure class="case-media case-media--wide">
<img
src="../../assets/ai-platform-primo-rpa/in-project-inference.webp"
alt="Интерфейс inference модели внутри проекта"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Inference в проекте</figcaption>
</figure>
<figure class="case-media" data-case-tall-media data-case-tall-width="wide">
<div class="case-media-tall" data-case-tall-root>
<div class="case-media-tall__clip" id="ai-case-tall-inference-full" data-case-tall-clip>
<img
src="../../assets/ai-platform-primo-rpa/in-project-inference-full.webp"
alt="Inference в проекте — полный экран интерфейса"
width="1200"
loading="lazy"
decoding="async"
data-image-viewer
/>
<div class="case-media-tall__fog" aria-hidden="true"></div>
</div>
<div class="case-media-tall__actions">
<button
type="button"
class="case-media-tall__btn btn btn--ghost btn--flat"
data-case-tall-toggle
aria-expanded="false"
aria-controls="ai-case-tall-inference-full"
>
<span class="case-media-tall__btn-chev" aria-hidden="true"></span>
<span data-case-tall-label-more>Развернуть</span>
<span data-case-tall-label-less hidden>Свернуть</span>
</button>
</div>
</div>
<figcaption>Полный вертикальный кадр экрана inference</figcaption>
</figure>
<figure class="case-media case-media--wide">
<img
src="../../assets/ai-platform-primo-rpa/in-project-inference-old.webp"
alt="Предыдущая версия экрана inference в проекте"
width="1200"
height="675"
loading="lazy"
decoding="async"
data-image-viewer
/>
<figcaption>Предыдущая версия inference</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>
<h3>Полноэкранный режим и импорт</h3>
<p class="section__prose">
Речь не о «длинных задачах», а о процессах в отдельном контексте: одни до завершения блокируют работу с проектом, другие идут параллельно в отдельном окне, и при этом можно продолжать настраивать параметры проекта. Функционал вынесли в отдельное окно, потому что точек входа в такие задачи было несколько, а обычной модалки было недостаточно — нужно было пройти отдельный процесс в стороне и затем вернуться к настройкам проекта. Такой подход сократил объём разработки и тестирования.
</p>
<p class="section__prose">
Ниже — три варианта полноэкранного холста: импорт в отдельном окне, режим с панелями и минималистичный «zen».
</p>
<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>
<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>Минимальный режим без лишнего chrome</figcaption>
</figure>
<h3>Дальнейшее развитие</h3>
<p class="section__prose">
В дорожной карте оставались отдельные крупные куски: сценарии вокруг LLM (списки, статусы, действия), пошаговый мастер обучения с прогрессом и отменой, а также полноценный контур OCR с разметкой регионов и превью качества на странице. Они не входили в минимальный набор для первого промышленного релиза интерфейса, но заложенные паттерны должны их принять без больших переделок.
</p>
</div>
<div class="case-block" id="process">
<h2>Процесс и передача</h2>
<p class="section__prose">
Работа шла через регулярные синхронизации с разработкой: макеты, спецификации и поэтапный handoff во фронт. После моего выхода из проекта команда искала следующего дизайнера и выстраивала онбординг по уже оформленным артефактам и правилам компоновки.
</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>
<h3>Вопросы следующему дизайнеру</h3>
<ul>
<li>Что оказалось неочевидным в первые две недели в проекте.</li>
<li>Какие артефакты и правила передачи пригодились больше всего.</li>
<li>Что пришлось пересобрать и по какой причине.</li>
<li>Как в трёх предложениях описать текущее состояние UX.</li>
</ul>
</div>
<div class="case-block" id="zaklyuchenie">
<h2>Итог</h2>
<p class="section__prose">
Интерфейс AI Server в Primo RPA перевели от «инженерного интерфейса разработчиков» к продукту с понятной логикой настройки и сопровождения пользователя. Упор на юзерфлоу и автоматизацию рутины снял часть нагрузки с внедрения и открыл дорогу к более широкому использованию внутри компании и у клиентов.
</p>
</div>
</div>
</main>
<section 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" data-mp-cells-sm="2" data-related-slug="ai-platform-primo-rpa">
<a class="mp-card mp-card--link mp-card--stack" href="../ai-platform-primo-rpa/" aria-label="Платформа для работы с AI — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../../assets/ai-platform-primo-rpa/cover-star.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Primo AI Server</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" data-mp-cells-sm="2" data-related-slug="lunacy">
<a class="mp-card mp-card--link mp-card--stack" href="../lunacy/" 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="3" data-mp-cells-sm="2" data-related-slug="manu-game-maker" hidden>
<a class="mp-card mp-card--link mp-card--stack" href="../manu-game-maker/" 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="3" data-mp-cells-sm="2" data-related-slug="mobile-clinic-app" hidden>
<a class="mp-card mp-card--link mp-card--stack" href="../mobile-clinic-app/" 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="3" data-mp-cells-sm="2" data-related-slug="orc-automation-panel">
<a class="mp-card mp-card--link mp-card--stack" href="../orc-automation-panel/" aria-label="Веб-панель для оркестрации автоматизаций — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../../assets/orc-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
loading="lazy"
decoding="async"
/>
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Primo Orc</h3>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Менторство и наставничество</li>
</ul>
<p class="mp-card__desc">Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под продакшен без остановки релизов.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3" data-mp-cells-sm="2" data-related-slug="task-distribution-concept" hidden>
<a class="mp-card mp-card--link mp-card--stack" href="../task-distribution-concept/" aria-label="Концепт сервиса распределения задач — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../../assets/task-distribution-concept/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">Analytics</li>
</ul>
<p class="mp-card__desc">Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность процессов и удобство командной работы.</p>
</div>
</a>
</li>
<li class="mini-projects-grid__item" data-mp-cells="3" data-mp-cells-sm="2" data-related-slug="task-tracker" hidden>
<a class="mp-card mp-card--link mp-card--stack" href="../task-tracker/" aria-label="Таск-трекер для бек-офис системы — открыть кейс">
<div class="mp-card__media" aria-hidden="true">
<img
class="mp-card__image"
src="../../assets/task-tracker/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">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">
<h2 class="section__title projects__title">Портфолио</h2>
<div class="projects__controls" aria-label="Навигация по карточкам портфолио">
<button type="button" class="projects__nav-btn" data-projects-prev aria-label="Прокрутить влево" aria-controls="projects-viewport">
<span class="projects__nav-ico projects__nav-ico--left" aria-hidden="true"></span>
</button>
<button type="button" class="projects__nav-btn" data-projects-next aria-label="Прокрутить вправо" aria-controls="projects-viewport">
<span class="projects__nav-ico projects__nav-ico--right" aria-hidden="true"></span>
</button>
</div>
</div>
<div class="projects-carousel">
<div id="projects-viewport" class="projects-carousel__viewport" data-projects-viewport>
<div class="projects-carousel__track">
<div class="projects-carousel__spacer" aria-hidden="true"></div>
<article class="projects-carousel__item">
<a class="portfolio-card" data-glass="false" href="../orc-automation-panel/">
<div class="portfolio-card__body">
<h3 class="portfolio-card__title">Веб-панель для оркестрации автоматизаций</h3>
<p class="portfolio-card__summary">
Веб-кабинет оркестратора Primo RPA: проекты, запуск и контроль RPA-роботов. Редизайн ключевых экранов под
продакшен без остановки релизов.
</p>
<ul class="portfolio-card__tags" aria-label="Ключевые теги">
<li class="portfolio-card__tag">UX/UI</li>
<li class="portfolio-card__tag">Web App</li>
</ul>
</div>
<div class="portfolio-card__cover" aria-hidden="true">
<img
class="portfolio-card__image"
src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
data-defer-src="../../assets/orc-primo-rpa/cover.webp"
alt=""
width="400"
height="225"
decoding="async"
/>
</div>
</a>
</article>
<article class="projects-carousel__item">
<a class="portfolio-card" data-glass="false" href="../ai-platform-primo-rpa/">
<div class="portfolio-card__body">
<h3 class="portfolio-card__title">Платформа для работы с AI</h3>
<p class="portfolio-card__summary">
Интерфейс для обучения и использования AI‑моделей в бизнес‑процессах: работа с данными, сценариями
автоматизации и Smart OCR.
</p>
<ul class="portfolio-card__tags" aria-label="Ключевые теги">
<li class="portfolio-card__tag">UX/UI</li>
<li class="portfolio-card__tag">Web App</li>
</ul>
</div>
<div class="portfolio-card__cover" aria-hidden="true">
<img
class="portfolio-card__image"
src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
data-defer-src="../../assets/ai-platform-primo-rpa/cover-star.webp"
alt=""
width="400"
height="225"
decoding="async"
/>
</div>
</a>
</article>
<article class="projects-carousel__item">
<a class="portfolio-card" data-glass="false" href="../task-tracker/">
<div class="portfolio-card__body">
<h3 class="portfolio-card__title">Таск-трекер для бек-офис системы</h3>
<p class="portfolio-card__summary">
Интерфейс для планирования и распределения задач в операционном отделе: общий пул, личный ToDo, обзор по
исполнителям; вкладки, фильтры, виды доска / список / таблица, Drag&amp;Drop.
</p>
<ul class="portfolio-card__tags" aria-label="Ключевые теги">
<li class="portfolio-card__tag">Product Design</li>
<li class="portfolio-card__tag">Web App</li>
</ul>
</div>
<div class="portfolio-card__cover" aria-hidden="true">
<img
class="portfolio-card__image"
src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
data-defer-src="../../assets/task-tracker/cover.webp"
alt=""
width="400"
height="225"
decoding="async"
/>
</div>
</a>
</article>
<article class="projects-carousel__item">
<a class="portfolio-card" data-glass="false" href="../manu-game-maker/">
<div class="portfolio-card__body">
<h3 class="portfolio-card__title">Игровой движок MANU</h3>
<p class="portfolio-card__summary">
Редизайн и развитие интерфейса игрового движка: новая концепция работы, обновлённая визуальная система и
проработка сотен сложных пользовательских сценариев.
</p>
<ul class="portfolio-card__tags" aria-label="Ключевые теги">
<li class="portfolio-card__tag">Product Design</li>
<li class="portfolio-card__tag">Desktop App</li>
</ul>
</div>
<div class="portfolio-card__cover" aria-hidden="true">
<img
class="portfolio-card__image"
src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
data-defer-src="../../assets/manu-game-maker/cover.webp"
alt=""
width="400"
height="225"
decoding="async"
/>
</div>
</a>
</article>
<article class="projects-carousel__item">
<a class="portfolio-card" data-glass="false" href="../lunacy/">
<div class="portfolio-card__body">
<h3 class="portfolio-card__title">Графический редактор Lunacy</h3>
<p class="portfolio-card__summary">
Работа над интерфейсом Lunacy в команде Icons8: user flow, сложные прототипы, улучшение функциональности и
интерфейсной логики.
</p>
<ul class="portfolio-card__tags" aria-label="Ключевые теги">
<li class="portfolio-card__tag">UX/UI</li>
<li class="portfolio-card__tag">Desktop App</li>
</ul>
</div>
<div class="portfolio-card__cover" aria-hidden="true">
<img
class="portfolio-card__image"
src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
data-defer-src="../../assets/lunacy/cover.webp"
alt=""
width="400"
height="225"
decoding="async"
/>
</div>
</a>
</article>
<article class="projects-carousel__item">
<a class="portfolio-card" data-glass="false" href="../mobile-clinic-app/">
<div class="portfolio-card__body">
<h3 class="portfolio-card__title">Мобильное приложение для сети клиник</h3>
<p class="portfolio-card__summary">
Дизайн мобильного приложения для записи к врачам и работы с медицинскими услугами. Фокус на простом
пользовательском пути, понятной навигации и быстром доступе к нужным действиям.
</p>
<ul class="portfolio-card__tags" aria-label="Ключевые теги">
<li class="portfolio-card__tag">UX/UI</li>
<li class="portfolio-card__tag">Mobile App</li>
</ul>
</div>
<div class="portfolio-card__cover" aria-hidden="true">
<img
class="portfolio-card__image"
src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
data-defer-src="../../assets/mobile-clinic-app/cover.webp"
alt=""
width="400"
height="225"
decoding="async"
/>
</div>
</a>
</article>
<article class="projects-carousel__item">
<a class="portfolio-card" data-glass="false" href="../task-distribution-concept/">
<div class="portfolio-card__body">
<h3 class="portfolio-card__title">Концепт сервиса распределения задач</h3>
<p class="portfolio-card__summary">
Продуктовый концепт сервиса для постановки, распределения и отслеживания задач, с акцентом на прозрачность
процессов и удобство командной работы.
</p>
<ul class="portfolio-card__tags" aria-label="Ключевые теги">
<li class="portfolio-card__tag">UX/UI</li>
<li class="portfolio-card__tag">Analytics</li>
</ul>
</div>
<div class="portfolio-card__cover" aria-hidden="true">
<img
class="portfolio-card__image"
src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
data-defer-src="../../assets/task-distribution-concept/cover.webp"
alt=""
width="400"
height="225"
decoding="async"
/>
</div>
</a>
</article>
<article class="projects-carousel__item">
<a class="portfolio-card" data-glass="false" href="../obsidian-plugin-columns-view/">
<div class="portfolio-card__body">
<h3 class="portfolio-card__title">Колоночный вид — плагин для Obsidian</h3>
<p class="portfolio-card__summary">
Интерфейс для многоколоночной работы с заметками: удобная навигация, фильтрация и настройка
колончатого отображения прямо в редакторе Obsidian.
</p>
<ul class="portfolio-card__tags" aria-label="Ключевые теги">
<li class="portfolio-card__tag">UX/UI</li>
<li class="portfolio-card__tag">Plugin</li>
</ul>
</div>
<div class="portfolio-card__cover" aria-hidden="true">
<img
class="portfolio-card__image"
src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
data-defer-src="../../assets/obsidian-plugin-columns-view/filter use.webp"
alt=""
width="400"
height="225"
decoding="async"
/>
</div>
</a>
</article>
<div class="projects-carousel__spacer" aria-hidden="true"></div>
</div>
</div>
<button
type="button"
class="projects-carousel__edge-hit projects-carousel__edge-hit--left"
data-projects-edge-prev
aria-label="Прокрутить портфолио влево"
></button>
<button
type="button"
class="projects-carousel__edge-hit projects-carousel__edge-hit--right"
data-projects-edge-next
aria-label="Прокрутить портфолио вправо"
></button>
</div>
</div>
</section>
<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><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>
<footer class="footer">
<div class="footer__inner">
<span class="footer__chunk footer__chunk--date">© 2015–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/">Design System</a><span class="footer__sep" aria-hidden="true"> · </span><a href="../../cookie-policy/">Политика cookie</a></span>
<span class="footer__chunk footer__chunk--lang"><span class="footer__sep" aria-hidden="true"> · </span><nav class="lang-switch" aria-label="Выбор языка" data-lang-switch>
<a class="lang-switch__btn" data-lang="en" href="/en/">English</a>
</nav>
<script>
(function () {
var p = location.pathname.replace(/^\/+/, "");
var isEn = p.indexOf("en/") === 0;
var base = isEn ? p.slice(3) : p;
var links = document.querySelectorAll("[data-lang-switch] [data-lang]");
for (var i = 0; i < links.length; i++) {
var l = links[i].getAttribute("data-lang");
links[i].setAttribute("href", (l === "en" ? "/en/" : "/") + base);
}
})();
</script>
</span>
</div>
</footer>
<aside class="cookie-notice glass-neutral" hidden data-cookie-notice>
<p class="cookie-notice__text">
Сайт использует cookie для комфортной работы. Подробнее — в
<a href="../../cookie-policy/" data-cookie-policy-link>cookie policy</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>
<div id="nav-more-menu-floating" class="nav-more__floating" hidden data-nav-more-menu-floating aria-hidden="true"></div>
</body>
</html>