📝 docs(channels): add ADR-HUB-0037 and SPEC-HUB-0027 with design baseline

Канал обработки становится объектом управления: список, карточка,
создание, политика, подключения и счётчики. Разделы AI-агентов и знаний
не затрагиваются — связь с агентом остаётся одной строкой со ссылкой.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
AndreyandClaude Opus 4.8 committed 2026-07-19 23:45:13 +03:00
1 parent 960cf24238
commit 11ad4f8eb3
13 files changed
+6958

No files matched your search

@@ -0,0 +1,80 @@
# Каналы обработки — design baseline (DG-02)
Макет раздела **Компания → Каналы** (CustoCRM / ООО «Эдевс») по SPEC-HUB-0027 / ADR-HUB-0037.
## Состав
```
Каналы Baseline.dc.html — макет (6 кадров: A–E + состояния)
support.js — рантайм Design Component (шаблон + логика)
_ds/edevs-hub-design-system-…/ — дизайн-система: токены, styles.css, _ds_bundle.js
assets/custocrm-mark.svg — логотип CustoCRM
```
## Запуск
Открыть `Каналы Baseline.dc.html` через локальный HTTP-сервер
(из-за загрузки внешних файлов `file://` не подойдёт):
```bash
python3 -m http.server 8080
# → http://localhost:8080/Каналы%20Baseline.dc.html
```
## Карта кадров (SPEC-HUB-0027 §11.6)
- **A** — Список каналов: полная оболочка (sidebar + topbar). Фильтры-`UnderlineTabs` с count
(`Все · Продажи · Поддержка · Без отдела`), поиск, тумблер «Показывать архивные».
Плотная `baseline-table` в `table-card`. Колонки `КАНАЛ / ПРОДУКТ / ПОДКЛЮЧЕНИЯ /
AI-АГЕНТ / ДИАЛОГИ / ⋯`. Показано открытое меню строки с заблокированным «Удалить»
и причиной. §11.1.
- **B** — Карточка канала **одной страницей, без вкладок**. Заголовок (`code · отдел ·
продукт`, действия «Изменить / Деактивировать / Удалить») и секции сверху вниз:
Назначение, Политика, Подключения, AI-агент (одна строка: имя · статус · модель +
ссылка «Открыть агента» на страницу агента наружу), Счётчики (открытые диалоги,
подключения + ссылка на диалоги). Настроек агента и знаний в карточке нет. §11.2.
- **C** — Секция «Политика» на **непродуктовом** канале «Партнёрская линия».
Пять флагов с однострочным пояснением следствия; три флага (checkout P1,
attribution P2, обязательная идентичность P3) выключены и заблокированы с причиной. §11.2.
- **D** — Секция «Подключения». Список подключений канала с отвязкой, действие
«Привязать» и модалка **переноса** подключения из другого канала (`force`),
с оговоркой, что диалоги остаются в прежнем канале. §11.1 / §6.6.
- **E** — Мастер создания, **три шага** (Канал · Назначение · Подключения). Показан
финальный экран: канал создан, ведут его операторы, ссылка в раздел AI для создания
агента отдельным действием. Настроек агента и знаний в мастере нет. §11.3.
- **S** — Состояния: пустой список (приглашение без «здесь пусто»), канал без агента
(секция AI-агент), архивный канал, ограниченный доступ (department scope), конфликт
удаления (409 с блокерами). §11.5 / §7.2.
## Зафиксированные решения по открытым вопросам (README §5 задания)
1. **Канал без отдела.** В колонке `КАНАЛ` под именем идёт `code · <чип «Без отдела»>` —
нейтральный чип на `--n-9`, а не пустая ячейка: канал читается как намеренно
безотдельный, а не как незаполненный черновик. Плюс отдельный таб-фильтр «Без отдела».
Такой канал виден только organization-scoped `channels.view` (§5.2).
2. **Архивный канал (`isActive=false`).** Отдельный статус `Архивный` (полая точка,
приглушённый текст, фон строки `#fcfcfc`), а не «Выключено». По умолчанию скрыт,
показывается тумблером «Показывать архивные». Меню строки предлагает только
«Активировать». История диалогов сохраняется и доступна ссылкой из карточки
(«История сохраняется даже после деактивации канала»).
3. **Запрещённый инвариантом флаг политики.** Флаг выключен **и** заблокирован, рядом —
бейдж «Запрещено инвариантом» / «Недоступно» и однострочная причина со ссылкой на
инвариант (P1/P2/P3) и способ разблокировать («Назначить продукт»). Причина
объясняется, а не игнорируется молча при сохранении. Кадр C, флаг checkout выделен.
4. **Колонка «Диалоги» в списке.** Оставлена. Обоснование: это дешёвый агрегат
(`counters.openConversations`, один запрос на список, §6.1), а открытые диалоги —
ключевой операционный сигнал канала. Полный разрез счётчиков (открытые диалоги и
подключения) остаётся в секции «Счётчики» карточки; в списке — только открытые
диалоги, numeric. Счётчика знаний в карточке канала нет: знания принадлежат агенту.
## Технические примечания
- Вёрстка — инлайн-стили поверх токенов дизайн-системы (`var(--*)` из `_ds/.../tokens`).
Цвета/типографика/отступы менять только через токены; сырые hex вне токенов не
используются (кроме служебного фона холста и подсветок строк из baseline-образца).
- `ChannelBadge` (точка + короткий лейбл MAX/TG/Web на токенах `--channel-*`) применяется
экономно — только в колонке «Подключения» списка и в секции «Подключения» карточки
(ADR-HUB-0013).
- Терминология: MAX/TG/Web — «Подключения»; «Канал» — сущность маршрутизации.
- Данные — примеры; авторизация, инварианты и счётчики вычисляются на backend
(frontend не источник прав), см. SPEC-HUB-0027 §5–§7.
@@ -0,0 +1,508 @@
{
"plugins": [
"react",
"import"
],
"rules": {
"react/forbid-elements": [
"warn",
{
"forbid": []
}
],
"no-restricted-imports": [
"warn",
{
"patterns": [
{
"group": [
"components/cards/**",
"components/core/**",
"components/inbox/**",
"components/status/**",
"ui_kits/checkout/**",
"ui_kits/internal-hub/**",
"ui_kits/web-chat/**"
],
"message": "Import design-system components from 'index.js', not component internals."
}
]
}
],
"no-restricted-syntax": [
"warn",
{
"selector": "Literal[value=/#[0-9a-fA-F]{3,8}\\b/]",
"message": "Raw hex color — use a design-system color token via var()."
},
{
"selector": "Literal[value=/\\b\\d+px\\b/]",
"message": "Raw px value — use a design-system spacing token via var()."
},
{
"selector": "JSXOpeningElement[name.name='ActorBadge'] > JSXAttribute > JSXIdentifier[name!=/^(?:actor|initials|color|key|ref|className|style|children)$/]",
"message": "<ActorBadge> doesn't accept that prop. Declared props: actor, initials, color."
},
{
"selector": "JSXOpeningElement[name.name='ActorBadge'] > JSXAttribute[name.name='actor'] > Literal[value!=/^(?:ai|human)$/]",
"message": "<ActorBadge> actor must be one of 'ai' | 'human'."
},
{
"selector": "JSXOpeningElement[name.name='AttentionStatus'] > JSXAttribute > JSXIdentifier[name!=/^(?:level|label|key|ref|className|style|children)$/]",
"message": "<AttentionStatus> doesn't accept that prop. Declared props: level, label."
},
{
"selector": "JSXOpeningElement[name.name='AttentionStatus'] > JSXAttribute[name.name='level'] > Literal[value!=/^(?:ok|attention|critical)$/]",
"message": "<AttentionStatus> level must be one of 'ok' | 'attention' | 'critical'."
},
{
"selector": "JSXOpeningElement[name.name='Avatar'] > JSXAttribute > JSXIdentifier[name!=/^(?:initials|color|size|key|ref|className|style|children)$/]",
"message": "<Avatar> doesn't accept that prop. Declared props: initials, color, size."
},
{
"selector": "JSXOpeningElement[name.name='Button'] > JSXAttribute > JSXIdentifier[name!=/^(?:children|variant|size|disabled|onClick|type|key|ref|className|style|children)$/]",
"message": "<Button> doesn't accept that prop. Declared props: children, variant, size, disabled, onClick, type."
},
{
"selector": "JSXOpeningElement[name.name='Button'] > JSXAttribute[name.name='variant'] > Literal[value!=/^(?:primary|secondary|ghost|danger)$/]",
"message": "<Button> variant must be one of 'primary' | 'secondary' | 'ghost' | 'danger'."
},
{
"selector": "JSXOpeningElement[name.name='Button'] > JSXAttribute[name.name='size'] > Literal[value!=/^(?:sm|md|lg)$/]",
"message": "<Button> size must be one of 'sm' | 'md' | 'lg'."
},
{
"selector": "JSXOpeningElement[name.name='Button'] > JSXAttribute[name.name='type'] > Literal[value!=/^(?:button|submit)$/]",
"message": "<Button> type must be one of 'button' | 'submit'."
},
{
"selector": "JSXOpeningElement[name.name='ChannelBadge'] > JSXAttribute > JSXIdentifier[name!=/^(?:channel|title|key|ref|className|style|children)$/]",
"message": "<ChannelBadge> doesn't accept that prop. Declared props: channel, title."
},
{
"selector": "JSXOpeningElement[name.name='ChannelBadge'] > JSXAttribute[name.name='channel'] > Literal[value!=/^(?:max|telegram|webchat)$/]",
"message": "<ChannelBadge> channel must be one of 'max' | 'telegram' | 'webchat'."
},
{
"selector": "JSXOpeningElement[name.name='Checkbox'] > JSXAttribute > JSXIdentifier[name!=/^(?:checked|onChange|label|size|key|ref|className|style|children)$/]",
"message": "<Checkbox> doesn't accept that prop. Declared props: checked, onChange, label, size."
},
{
"selector": "JSXOpeningElement[name.name='Checkbox'] > JSXAttribute[name.name='size'] > Literal[value!=/^(?:sm|md)$/]",
"message": "<Checkbox> size must be one of 'sm' | 'md'."
},
{
"selector": "JSXOpeningElement[name.name='CommerceStatusTimeline'] > JSXAttribute > JSXIdentifier[name!=/^(?:steps|key|ref|className|style|children)$/]",
"message": "<CommerceStatusTimeline> doesn't accept that prop. Declared props: steps."
},
{
"selector": "JSXOpeningElement[name.name='ConversationInboxItem'] > JSXAttribute > JSXIdentifier[name!=/^(?:name|preview|channel|lastActor|initials|color|time|waiting|active|onClick|key|ref|className|style|children)$/]",
"message": "<ConversationInboxItem> doesn't accept that prop. Declared props: name, preview, channel, lastActor, initials, color, time, waiting, active, onClick."
},
{
"selector": "JSXOpeningElement[name.name='ConversationInboxItem'] > JSXAttribute[name.name='channel'] > Literal[value!=/^(?:max|telegram|webchat)$/]",
"message": "<ConversationInboxItem> channel must be one of 'max' | 'telegram' | 'webchat'."
},
{
"selector": "JSXOpeningElement[name.name='ConversationInboxItem'] > JSXAttribute[name.name='lastActor'] > Literal[value!=/^(?:ai|human)$/]",
"message": "<ConversationInboxItem> lastActor must be one of 'ai' | 'human'."
},
{
"selector": "JSXOpeningElement[name.name='DepartmentCard'] > JSXAttribute > JSXIdentifier[name!=/^(?:name|meta|level|summary|icon|openLabel|onOpen|children|key|ref|className|style|children)$/]",
"message": "<DepartmentCard> doesn't accept that prop. Declared props: name, meta, level, summary, icon, openLabel, onOpen, children."
},
{
"selector": "JSXOpeningElement[name.name='DepartmentCard'] > JSXAttribute[name.name='level'] > Literal[value!=/^(?:ok|attention|critical)$/]",
"message": "<DepartmentCard> level must be one of 'ok' | 'attention' | 'critical'."
},
{
"selector": "JSXOpeningElement[name.name='Icon'] > JSXAttribute > JSXIdentifier[name!=/^(?:name|size|color|strokeWidth|key|ref|className|style|children)$/]",
"message": "<Icon> doesn't accept that prop. Declared props: name, size, color, strokeWidth."
},
{
"selector": "JSXOpeningElement[name.name='Icon'] > JSXAttribute[name.name='name'] > Literal[value!=/^(?:dashboard|departments|employees|products|ai|integrations|settings|search|chevronDown|chevronRight|moreVertical|check|checkCircle|alertTriangle|alertCircle|xCircle|clock|refresh|arrowRight|arrowLeft|mail|lock|eye|eyeOff|card|sbp|shield|download|columns|bell|trash|edit|merge|bolt|cart|history|team|package2)$/]",
"message": "<Icon> name must be one of 'dashboard' | 'departments' | 'employees' | 'products' | 'ai' | 'integrations' | 'settings' | 'search' | 'chevronDown' | 'chevronRight' | 'moreVertical' | 'check' | 'checkCircle' | 'alertTriangle' | 'alertCircle' | 'xCircle' | 'clock' | 'refresh' | 'arrowRight' | 'arrowLeft' | 'mail' | 'lock' | 'eye' | 'eyeOff' | 'card' | 'sbp' | 'shield' | 'download' | 'columns' | 'bell' | 'trash' | 'edit' | 'merge' | 'bolt' | 'cart' | 'history' | 'team' | 'package2'."
},
{
"selector": "JSXOpeningElement[name.name='IconButton'] > JSXAttribute > JSXIdentifier[name!=/^(?:children|size|badge|bare|label|onClick|key|ref|className|style|children)$/]",
"message": "<IconButton> doesn't accept that prop. Declared props: children, size, badge, bare, label, onClick."
},
{
"selector": "JSXOpeningElement[name.name='Input'] > JSXAttribute > JSXIdentifier[name!=/^(?:value|onChange|placeholder|label|required|type|disabled|error|hint|icon|suffix|fullWidth|key|ref|className|style|children)$/]",
"message": "<Input> doesn't accept that prop. Declared props: value, onChange, placeholder, label, required, type, disabled, error, hint, icon, suffix, fullWidth."
},
{
"selector": "JSXOpeningElement[name.name='Input'] > JSXAttribute[name.name='type'] > Literal[value!=/^(?:text|email|password|tel)$/]",
"message": "<Input> type must be one of 'text' | 'email' | 'password' | 'tel'."
},
{
"selector": "JSXOpeningElement[name.name='IntegrationHealthCard'] > JSXAttribute > JSXIdentifier[name!=/^(?:name|group|status|key|ref|className|style|children)$/]",
"message": "<IntegrationHealthCard> doesn't accept that prop. Declared props: name, group, status."
},
{
"selector": "JSXOpeningElement[name.name='IntegrationHealthCard'] > JSXAttribute[name.name='status'] > Literal[value!=/^(?:connected|degraded|error)$/]",
"message": "<IntegrationHealthCard> status must be one of 'connected' | 'degraded' | 'error'."
},
{
"selector": "JSXOpeningElement[name.name='KnowledgeDocumentEditor'] > JSXAttribute > JSXIdentifier[name!=/^(?:title|onTitleChange|docId|body|onBodyChange|rows|savedLabel|key|ref|className|style|children)$/]",
"message": "<KnowledgeDocumentEditor> doesn't accept that prop. Declared props: title, onTitleChange, docId, body, onBodyChange, rows, savedLabel."
},
{
"selector": "JSXOpeningElement[name.name='MetricCard'] > JSXAttribute > JSXIdentifier[name!=/^(?:label|value|valueColor|dotColor|key|ref|className|style|children)$/]",
"message": "<MetricCard> doesn't accept that prop. Declared props: label, value, valueColor, dotColor."
},
{
"selector": "JSXOpeningElement[name.name='ProductAIReleaseCard'] > JSXAttribute > JSXIdentifier[name!=/^(?:productName|productInitial|releaseId|live|iconBg|iconColor|stats|key|ref|className|style|children)$/]",
"message": "<ProductAIReleaseCard> doesn't accept that prop. Declared props: productName, productInitial, releaseId, live, iconBg, iconColor, stats."
},
{
"selector": "JSXOpeningElement[name.name='Tag'] > JSXAttribute > JSXIdentifier[name!=/^(?:children|tone|pill|dot|dotColor|key|ref|className|style|children)$/]",
"message": "<Tag> doesn't accept that prop. Declared props: children, tone, pill, dot, dotColor."
},
{
"selector": "JSXOpeningElement[name.name='Tag'] > JSXAttribute[name.name='tone'] > Literal[value!=/^(?:neutral|primary|success|warning|error|ai)$/]",
"message": "<Tag> tone must be one of 'neutral' | 'primary' | 'success' | 'warning' | 'error' | 'ai'."
}
]
},
"overrides": [
{
"files": [
"**/index.js"
],
"rules": {
"no-restricted-imports": "off"
}
}
],
"x-omelette": {
"components": {
"ActorBadge": {
"replaces": []
},
"AttentionStatus": {
"replaces": []
},
"Avatar": {
"replaces": []
},
"Button": {
"replaces": []
},
"ChannelBadge": {
"replaces": []
},
"Checkbox": {
"replaces": []
},
"CommerceStatusTimeline": {
"replaces": []
},
"ConversationInboxItem": {
"replaces": []
},
"DepartmentCard": {
"replaces": []
},
"Icon": {
"replaces": []
},
"IconButton": {
"replaces": []
},
"Input": {
"replaces": []
},
"IntegrationHealthCard": {
"replaces": []
},
"KnowledgeDocumentEditor": {
"replaces": []
},
"MetricCard": {
"replaces": []
},
"ProductAIReleaseCard": {
"replaces": []
},
"Tag": {
"replaces": []
}
},
"tokens": [
"--ai",
"--ai-bg",
"--ai-light",
"--ai-lighter",
"--border-default",
"--border-input",
"--border-strong",
"--channel-max",
"--channel-max-bg",
"--channel-telegram",
"--channel-telegram-bg",
"--channel-webchat",
"--channel-webchat-bg",
"--content-max",
"--duration-base",
"--duration-fast",
"--ease-standard",
"--error",
"--error-bg",
"--error-border",
"--error-text",
"--font-mono",
"--font-sans",
"--h-control",
"--h-control-2xl",
"--h-control-lg",
"--h-control-md",
"--h-control-sm",
"--h-control-xl",
"--h-topbar",
"--human",
"--info",
"--leading-loose",
"--leading-normal",
"--leading-relaxed",
"--leading-snug",
"--leading-tight",
"--n-1",
"--n-10",
"--n-11",
"--n-2",
"--n-3",
"--n-4",
"--n-5",
"--n-6",
"--n-7",
"--n-8",
"--n-9",
"--n-white",
"--primary",
"--primary-bg",
"--primary-border",
"--primary-hover",
"--primary-shadow",
"--product-firepage",
"--product-firepage-bg",
"--product-foxray",
"--product-foxray-bg",
"--radius-2xl",
"--radius-3xl",
"--radius-4xl",
"--radius-circle",
"--radius-lg",
"--radius-md",
"--radius-pill",
"--radius-sm",
"--radius-xl",
"--radius-xs",
"--shadow-lg",
"--shadow-md",
"--shadow-primary",
"--shadow-sm",
"--shadow-sticky",
"--shadow-xs",
"--sidebar-width",
"--space-1",
"--space-10",
"--space-11",
"--space-12",
"--space-13",
"--space-14",
"--space-15",
"--space-16",
"--space-17",
"--space-2",
"--space-3",
"--space-4",
"--space-5",
"--space-6",
"--space-7",
"--space-8",
"--space-9",
"--success",
"--success-bg",
"--success-bg-strong",
"--success-border",
"--success-text",
"--surface-card",
"--surface-chip",
"--surface-page",
"--surface-sunken",
"--text-2xl",
"--text-2xs",
"--text-2xs-tight",
"--text-base",
"--text-base-lg",
"--text-body",
"--text-disabled",
"--text-heading",
"--text-inverse",
"--text-lg",
"--text-link",
"--text-md",
"--text-secondary",
"--text-sm",
"--text-sm-lg",
"--text-sm-tight",
"--text-tertiary",
"--text-xl",
"--text-xs",
"--text-xs-tight",
"--tracking-tight",
"--tracking-tight-sm",
"--tracking-wide",
"--tracking-wider",
"--warning",
"--warning-bg",
"--warning-bg-strong",
"--warning-border",
"--warning-text",
"--weight-black",
"--weight-bold",
"--weight-medium",
"--weight-regular",
"--weight-semibold"
],
"tokenKinds": {
"--n-1": "color",
"--n-2": "color",
"--n-3": "color",
"--n-4": "color",
"--n-5": "color",
"--n-6": "color",
"--n-7": "color",
"--n-8": "color",
"--n-9": "color",
"--n-10": "color",
"--n-11": "color",
"--n-white": "color",
"--primary": "color",
"--primary-hover": "color",
"--primary-bg": "color",
"--primary-border": "color",
"--primary-shadow": "shadow",
"--success": "color",
"--success-text": "font",
"--success-bg": "color",
"--success-bg-strong": "color",
"--success-border": "color",
"--warning": "color",
"--warning-text": "font",
"--warning-bg": "color",
"--warning-bg-strong": "color",
"--warning-border": "color",
"--error": "color",
"--error-text": "font",
"--error-bg": "color",
"--error-border": "color",
"--info": "color",
"--ai": "color",
"--ai-light": "color",
"--ai-lighter": "color",
"--ai-bg": "color",
"--human": "color",
"--channel-max": "color",
"--channel-max-bg": "color",
"--channel-telegram": "color",
"--channel-telegram-bg": "color",
"--channel-webchat": "color",
"--channel-webchat-bg": "color",
"--product-firepage": "color",
"--product-firepage-bg": "color",
"--product-foxray": "color",
"--product-foxray-bg": "color",
"--surface-page": "color",
"--surface-card": "color",
"--surface-sunken": "color",
"--surface-chip": "color",
"--text-heading": "font",
"--text-body": "font",
"--text-secondary": "font",
"--text-tertiary": "font",
"--text-disabled": "font",
"--text-inverse": "font",
"--text-link": "font",
"--border-default": "color",
"--border-input": "color",
"--border-strong": "color",
"--font-sans": "font",
"--font-mono": "font",
"--text-2xl": "font",
"--text-xl": "font",
"--text-lg": "font",
"--text-md": "font",
"--text-base-lg": "font",
"--text-base": "font",
"--text-sm-lg": "font",
"--text-sm": "font",
"--text-sm-tight": "font",
"--text-xs": "font",
"--text-xs-tight": "font",
"--text-2xs": "font",
"--text-2xs-tight": "font",
"--weight-regular": "font",
"--weight-medium": "font",
"--weight-semibold": "font",
"--weight-bold": "font",
"--weight-black": "font",
"--tracking-tight": "font",
"--tracking-tight-sm": "font",
"--tracking-wide": "font",
"--tracking-wider": "font",
"--leading-tight": "font",
"--leading-snug": "font",
"--leading-normal": "font",
"--leading-relaxed": "font",
"--leading-loose": "font",
"--space-1": "spacing",
"--space-2": "spacing",
"--space-3": "spacing",
"--space-4": "spacing",
"--space-5": "spacing",
"--space-6": "spacing",
"--space-7": "spacing",
"--space-8": "spacing",
"--space-9": "spacing",
"--space-10": "spacing",
"--space-11": "spacing",
"--space-12": "spacing",
"--space-13": "spacing",
"--space-14": "spacing",
"--space-15": "spacing",
"--space-16": "spacing",
"--space-17": "spacing",
"--h-control-sm": "spacing",
"--h-control-md": "spacing",
"--h-control": "spacing",
"--h-control-lg": "spacing",
"--h-control-xl": "spacing",
"--h-control-2xl": "spacing",
"--h-topbar": "spacing",
"--sidebar-width": "spacing",
"--content-max": "spacing",
"--radius-xs": "radius",
"--radius-sm": "radius",
"--radius-md": "radius",
"--radius-lg": "radius",
"--radius-xl": "radius",
"--radius-2xl": "radius",
"--radius-3xl": "radius",
"--radius-4xl": "radius",
"--radius-pill": "radius",
"--radius-circle": "radius",
"--shadow-xs": "shadow",
"--shadow-sm": "shadow",
"--shadow-md": "shadow",
"--shadow-lg": "shadow",
"--shadow-sticky": "shadow",
"--shadow-primary": "shadow",
"--ease-standard": "other",
"--duration-fast": "other",
"--duration-base": "other"
},
"fontFamilies": []
}
}
@@ -0,0 +1 @@
{"namespace":"EdevsHubDesignSystem_e4c9df","components":[{"name":"CommerceStatusTimeline","sourcePath":"components/cards/CommerceStatusTimeline.jsx"},{"name":"DepartmentCard","sourcePath":"components/cards/DepartmentCard.jsx"},{"name":"IntegrationHealthCard","sourcePath":"components/cards/IntegrationHealthCard.jsx"},{"name":"MetricCard","sourcePath":"components/cards/MetricCard.jsx"},{"name":"ProductAIReleaseCard","sourcePath":"components/cards/ProductAIReleaseCard.jsx"},{"name":"Avatar","sourcePath":"components/core/Avatar.jsx"},{"name":"Button","sourcePath":"components/core/Button.jsx"},{"name":"Checkbox","sourcePath":"components/core/Checkbox.jsx"},{"name":"Icon","sourcePath":"components/core/Icon.jsx"},{"name":"ICON_NAMES","sourcePath":"components/core/Icon.jsx"},{"name":"IconButton","sourcePath":"components/core/IconButton.jsx"},{"name":"Input","sourcePath":"components/core/Input.jsx"},{"name":"Tag","sourcePath":"components/core/Tag.jsx"},{"name":"ConversationInbox","sourcePath":"components/inbox/ConversationInbox.jsx"},{"name":"KnowledgeDocumentEditor","sourcePath":"components/inbox/KnowledgeDocumentEditor.jsx"},{"name":"ActorBadge","sourcePath":"components/status/ActorBadge.jsx"},{"name":"AttentionStatus","sourcePath":"components/status/AttentionStatus.jsx"},{"name":"ChannelBadge","sourcePath":"components/status/ChannelBadge.jsx"}],"startingPoints":[{"name":"CommerceStatusTimeline","path":"components/cards/CommerceStatusTimeline.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Payment vs delivery step timeline for checkout/orders","viewport":"700x160"},{"name":"DepartmentCard","path":"components/cards/DepartmentCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Command Center department summary card","viewport":"900x360"},{"name":"IntegrationHealthCard","path":"components/cards/IntegrationHealthCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Single integration row (connected/degraded/error)","viewport":"700x90"},{"name":"MetricCard","path":"components/cards/MetricCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"Single KPI cell for metric grids","viewport":"700x120"},{"name":"ProductAIReleaseCard","path":"components/cards/ProductAIReleaseCard.jsx","previewPath":"components/cards/cards.card.html","kind":"component","section":"Cards","subtitle":"AI knowledge/prompt release snapshot for one product","viewport":"700x180"},{"name":"Button","path":"components/core/Button.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Primary/secondary/ghost/danger button","viewport":"700x220"},{"name":"IconButton","path":"components/core/IconButton.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Square icon-only button with optional badge","viewport":"700x150"},{"name":"Input","path":"components/core/Input.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Text field with label, icon and error state","viewport":"700x260"},{"name":"Tag","path":"components/core/Tag.jsx","previewPath":"components/core/core.card.html","kind":"component","section":"Core","subtitle":"Status pill and rectangular label tag","viewport":"700x150"},{"name":"KnowledgeDocumentEditor","path":"components/inbox/KnowledgeDocumentEditor.jsx","previewPath":"components/inbox/inbox.card.html","kind":"component","section":"Inbox","subtitle":"Plain-text knowledge base document editor","viewport":"700x380"},{"name":"ActorBadge","path":"components/status/ActorBadge.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"AI vs human avatar for conversation timelines","viewport":"700x110"},{"name":"AttentionStatus","path":"components/status/AttentionStatus.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"Company/department health chip (ok/attention/critical)","viewport":"700x120"},{"name":"ChannelBadge","path":"components/status/ChannelBadge.jsx","previewPath":"components/status/status.card.html","kind":"component","section":"Status","subtitle":"MAX / Telegram / Web Chat channel chip","viewport":"700x100"}],"cards":[{"path":"guidelines/logo-mark.card.html","group":"Brand","viewport":"700x160","subtitle":"Only mark found in the codebase — a blue rounded square with a bar-chart glyph","name":"Logo Mark"},{"path":"guidelines/radii-shadows.card.html","group":"Brand","viewport":"700x180","subtitle":"Soft, low-opacity shadows only — no glassmorphism","name":"Radii & Shadows"},{"path":"ui_kits/checkout/index.html","group":"Checkout","viewport":"440x760"},{"path":"guidelines/colors-ai-channels.card.html","group":"Colors","viewport":"700x160","subtitle":"AI/human split, MAX/Telegram/Web ChLine truncated
@@ -0,0 +1,216 @@
# Edevs Hub — Design System
Design system for **Edevs**, a Russian product IT company (`edevs.tech`) that builds applied
digital products for narrow professional niches — currently **FoxRay** (cephalometric/TRG
analysis for orthodontists) and **FirePage** (ready-made niche websites on a proprietary CMS,
sold as a one-time license). This design system, however, documents **Edevs Hub**
(`hub.edevs.tech`) — the internal company platform that runs sales, support, AI agents, and
commerce for those products, plus the two small public-facing surfaces it exposes (Web Chat
widget and Checkout).
## Sources
Everything here was extracted from the attached codebase, mounted read-only at
`hub.edevs.tech/`:
- `hub.edevs.tech/design/baseline/*.dc.html` — the team's own **approved HTML visual baseline**
(explicitly the canonical design source per `SPEC-HUB-0007`, section 3: *"Утверждённые
дизайн-файлы размещаются только в едином каноническом каталоге:
`code/hub.edevs.tech/design/baseline/`"*). ~35 screens covering Command Center, Sales
(overview/clients/dialogs/orders), Departments, Employees, Products, AI agents (list/create/
detail/knowledge), Integrations, Settings, Auth, the Web Chat widget, and the Checkout flow.
- `hub.edevs.tech/design/baseline/uploads/ADR-HUB-0013-Internal-UI-Design-System.md` — the
Internal Hub UI design-system decision record (Ant Design + Ant Design X + "Edevs Hub Theme").
- `hub.edevs.tech/design/baseline/uploads/SPEC-HUB-0007-Checkout-UI.md` — the public checkout
interface spec (`pay.hub.edevs.tech`).
- `hub.edevs.tech/design/baseline/uploads/SPEC-HUB-0003-Web-Chat.md`,
`SPEC-HUB-0004-Internal-Hub-UI.md`, `SPEC-HUB-0005-Implemented-Internal-UI-Baseline.md`,
`SPEC-HUB-0001-First-Iteration.md`, `ADR-HUB-0017-AI-Agent-Configuration-UX.md` — supporting
specs referenced but not individually quoted below.
- `hub.edevs.tech/packages/ui/src/theme.ts` — the actual Ant Design `ThemeConfig` ("Edevs Hub
Theme") used by the Internal UI: primary color, radii, per-component overrides.
`hub.edevs.tech/apps/internal-ui/src/styles/base.css` — global resets.
- `hub.edevs.tech/apps/internal-ui/public/favicon.svg` — the one brand mark present in the repo.
- `hub.edevs.tech/content/ai-content-company-filled.md` — the AI agent's system/persona prompts
for the main company site, used for the Content Fundamentals section below.
- `hub.edevs.tech/apps/checkout` and `hub.edevs.tech/apps/web-chat` — app shells for the public
surfaces (the checkout app has no implementation yet; the design baseline is ground truth for
both).
No Figma file or link was provided for this project — the HTML baseline above is the sole
design source, and per the team's own spec it *is* the canonical one.
## Products in scope
1. **Internal Hub** (`hub.edevs.tech`, `apps/internal-ui`) — the OWNER/OPERATOR back office:
Command Center, Departments, Employees, Products, Sales workspace (overview, clients,
dialogs, orders), AI agents & knowledge, Integrations, Settings, Auth. Built on Ant Design +
Ant Design X, desktop-first (1024px+, designed for 1440px).
2. **Web Chat** (`apps/web-chat`) — the embeddable public support/sales chat widget for
products like FoxRay, handling AI, human handoff, and inline checkout cards.
3. **Checkout** (`apps/checkout`, `pay.hub.edevs.tech`) — the public, mobile-first purchase flow
that hands off to Bank Tochka for payment and separately tracks payment vs. product delivery.
## Index
- `styles.css` — root stylesheet, imports everything under `tokens/`.
- `tokens/colors.css`, `typography.css`, `spacing.css`, `effects.css` — design tokens.
- `assets/logo-mark.svg`, `favicon.svg` — the one brand mark found in the codebase.
- `components/core/` — Button, IconButton, Input, Checkbox, Tag, Avatar, Icon (intentional
additions — see below).
- `components/status/` — AttentionStatus, ActorBadge, ChannelBadge.
- `components/cards/` — MetricCard, DepartmentCard, IntegrationHealthCard,
ProductAIReleaseCard, CommerceStatusTimeline.
- `components/inbox/` — ConversationInbox, KnowledgeDocumentEditor.
- `guidelines/` — foundation specimen cards (Colors, Type, Spacing, Brand).
- `ui_kits/internal-hub/` — Auth → Command Center → Sales · Clients, clickable.
- `ui_kits/web-chat/` — the embeddable chat widget, all 5 states.
- `ui_kits/checkout/` — the public checkout flow, all 8 states.
## Components
Full list (16), grouped by directory:
- **Core** (intentional additions, see below): `Button`, `IconButton`, `Input`, `Checkbox`,
`Tag`, `Avatar`, `Icon`.
- **Status** (from ADR-HUB-0013's local-component list): `AttentionStatus`, `ActorBadge`,
`ChannelBadge`.
- **Cards** (from ADR-HUB-0013): `MetricCard`, `DepartmentCard`, `IntegrationHealthCard`,
`ProductAIReleaseCard`, `CommerceStatusTimeline`.
- **Inbox** (from ADR-HUB-0013): `ConversationInbox`, `KnowledgeDocumentEditor`.
### Intentional additions
ADR-HUB-0013 states the Internal Hub is built on **Ant Design + Ant Design X**, with only ten
named local composite components on top (listed under "Status/Cards/Inbox" above — built
exactly as named). Ant Design itself isn't installable in this static-HTML environment, so to
make the UI kits and composite components actually renderable, this system also includes a
small set of Ant-Design-styled primitives that the ADR assumes but doesn't name:
`Button`, `IconButton`, `Input`, `Checkbox`, `Tag`, `Avatar`, `Icon`. Their visuals (radii,
heights, colors) are copied exactly from the approved HTML baseline, not invented — treat them
as a faithful stand-in for the real Ant Design instance, not a design decision of their own.
## Content fundamentals
Drawn from the AI agent system prompts (`content/ai-content-company-filled.md`) and the copy
throughout the baseline screens (Russian-language product, primary audience is Russian).
- **Language & register:** Russian, informal-but-respectful "вы" register — direct, calm,
no hard-sell. The agent prompt is explicit: "Пиши как нормальный человек в мессенджере. Не как объявление, не как пресс-релиз и не как робот, который сразу вываливает всю информацию."
- **Tone:** short, human paragraphs, answer the actual question first, then suggest a next
step: "Отвечай по сути вопроса, короткими живыми абзацами." and "Не дави на покупку. Главная задача общего агента — правильно понять потребность и направить человека туда, где он быстрее получит пользу."
- **Formatting discipline:** no markdown inside chat replies — "Не используй markdown-разметку внутри ответа: не ставь заголовки, списки с маркерами, жирный текст, таблицы и разделители." UI copy elsewhere (Hub, checkout) mirrors this: plain sentences, no bullet-heavy microcopy.
- **Emoji:** rare and situational, never decorative — "Уместные смайлики допустимы, но редко и по ситуации." No emoji appear anywhere in the Hub, Web Chat or Checkout baseline screens.
- **Cultural register:** "Учитывай российский контекст общения: уважительно, прямо, без давления и без чрезмерной рекламности."
- **Honesty/scope discipline:** never invent facts, prices, or promises outside the knowledge
base — "Если данных не хватает, не выдумывай. Скажи, что этот момент лучше уточнить у специалиста, и передай оператору." and pricing/legal specifics always come from the server, never the client: see Checkout spec §16 ("не доверять цене и составу из состояния браузера").
- **Handoff phrasing:** warm, not robotic, when passing to a human — "При передаче не отвечай сухо. Напиши по-человечески: понял задачу, здесь лучше подключить специалиста, передаю вопрос."
- **UI microcopy style (from the baseline):** short declarative status lines ("Готовим оплату",
"Оплата получена", "Требует внимания"), technical IDs always in monospace, money always as
`₽95 040` (₽ prefix, space thousands separator, no decimals for round sums).
- **Domains:** only `edevs.tech` is the confirmed public site; `edevs.ru` is explicitly
forbidden in agent replies.
## Visual foundations
- **Overall direction (ADR-HUB-0013):** *"светлая тема; премиальный минимализм; высокая, но
контролируемая информационная плотность; спокойная нейтральная основа; один основной
акцентный цвет; цвет используется прежде всего для статусов и действий; минимум декоративных
элементов; отсутствие градиентов, стекломорфизма, неоновых эффектов и визуального шума;
desktop-first."* (light theme, premium minimalism, one accent color, color reserved for
status/action, no gradients/glassmorphism/neon, desktop-first for the internal Hub).
- **Color:** one accent, `#1677ff` (Ant Design blue-6) with a `#0958d9` hover/active shade.
Semantic tokens are mandatory and separate from the accent: success/warning/error/info, plus
two Hub-specific roles — `ai` (purple, `#722ed1`) vs `human` (blue, same as primary) — and a
`channel-*` family (MAX purple, Telegram blue, Web Chat teal) used sparingly so multi-channel
screens don't turn into "a colorful mosaic" (ADR wording). Status color is never the sole
signal — always paired with text and, in tables, an icon or label.
- **Type:** system font stack only — no bespoke webfont is loaded
(`-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif`).
Technical identifiers (order/release/event IDs, emails, obscured phone numbers) switch to a
monospace stack. Headings use tight letter-spacing (−0.01 to −0.02em); table headers use wide
spacing (+0.03 to +0.06em) with all-caps and a muted gray.
Sizes are exact pixel values pulled from the baseline (26/24/20/18/16/14.5/13.5/13/12.5/12/
11/10.5px) — not snapped to a 4/8 grid.
- **Spacing / density:** "compact enterprise" density is an explicit rule — *"большие пустые
поля и oversized-карточки запрещены"*. Padding values are odd/precise (9px, 11px, 13px, 14px,
18px…), not rounded. Control heights: 30/34/36/42/44/48px; topbar is a fixed 56px.
- **Backgrounds:** flat solid colors only. Page background `#f0f2f5`, card surfaces pure white.
No photography, no illustrations, no repeating patterns/textures, no gradients anywhere
(buttons, cards, banners are all flat fills). The one "textured" pattern in the system is the
1px-gap metric grid (white cells on a `#f0f0f0` background, forming hairline dividers) — see
the Spacing → "Metric Grid In Use" card.
- **Corners:** 7–9px on controls/inputs, 8–9px on buttons, 10–14px on cards/modals, full pill
on chips/segmented controls, circle on avatars.
- **Cards:** white surface, 1px `#f0f0f0` border, soft shadow (`0 1px 3px rgba(0,0,0,.04)`),
12px radius as the default; no colored left-border accent except the Command Center's status
banner (a deliberate, singular exception tied to company health, not a general card pattern).
- **Shadows:** shallow and near-neutral throughout — hairline (`0 1px 2px rgba(0,0,0,.03)`),
card (`0 1px 3px rgba(0,0,0,.04)`), modal (`0 2px 12px rgba(0,0,0,.05)`), dropdown
(`0 6px 20px rgba(0,0,0,.12)`). The one colored shadow is the primary button's blue-tinted
`0 1px 2px rgba(22,119,255,.3)`, used to make the single CTA per screen pop slightly.
- **Animation:** minimal and functional only — a 3-dot typing indicator (`hub-typing`, opacity/
translateY loop), a spinner (`hub-spin`, rotate) for loading states, and a slow opacity pulse
(`hub-pulse`) for "in progress" states (e.g. delivering a purchased product). No entrance
animations, bounces, or parallax anywhere in the baseline.
- **Hover states:** buttons/links darken (primary `#1677ff → #0958d9`); neutral surfaces get a
light gray fill (`transparent → #f5f5f5`) on hover; secondary buttons swap border+text to the
accent color on hover. No lightening-on-hover pattern is used.
**Press/active states:** not distinctly styled in the baseline (no scale/shrink pattern
observed) — treat hover as the primary interactive affordance; focus-visible gets a solid
2px accent outline (see `apps/internal-ui/src/styles/base.css`).
**Disabled:** 55% opacity + `cursor: not-allowed`.
**Focus:** border-color changes to the accent (inputs) or a visible 2px outline (buttons) —
never a glow/box-shadow ring.
- **Borders:** hairline `#f0f0f0` almost everywhere (card edges, table row dividers, header
separators); slightly stronger `#d9d9d9`/`#e8e8e8` on interactive control outlines
(buttons, inputs) so they read as tappable against the flat background.
- **Transparency & blur:** no blur/glassmorphism anywhere. The only translucent surfaces are
the Web Chat header's icon buttons (`rgba(255,255,255,0.14–0.26)` over the solid blue header)
and a full-viewport `position:fixed` transparent scrim used to close open dropdowns/menus.
- **Imagery:** none — the product is data/status-dense enterprise software and transactional
flows, not marketing pages. No photography, no hand-drawn illustrations, no generic stock
imagery anywhere in the baseline; nothing to copy in for that reason.
- **Layout rules:** Internal Hub is a fixed sidebar (≈248px) + topbar (56px) + scrollable
content shell, min-width 1024–1180px depending on screen, content capped at 1200–1340px and
centered. Web Chat and Checkout are separate, chrome-free, mobile-first single-column flows
with no sidebar/topbar — explicitly not governed by the Internal Hub's layout rules
(SPEC-HUB-0007 §4).
## Iconography
- **System:** hand-authored inline SVG, Feather/Lucide-style stroke icons (round caps/joins,
1.7–2.2px stroke, 24×24 viewBox) — every baseline screen inlines its own `<svg>` rather than
referencing a shared font or sprite sheet, so there is no icon font or `.svg` sprite file in
the repo to copy wholesale. This design system's `Icon` component (`components/core/Icon.jsx`)
collects the ~35 recurring glyphs actually used across the baseline (nav icons, status icons,
form icons, payment icons) into one reusable primitive with the *exact* path data copied from
the source screens — nothing was redrawn from imagination.
- **Emoji:** never used anywhere in the product UI (only "rarely, situationally" in AI chat
replies per the content guidelines above).
**Unicode-as-icon:** limited to pagination chevrons (`‹ › …`) in table footers.
- **Color:** icons are almost always `currentColor`/neutral gray (`#8c8c8c`/`#595959`), tinted
to the semantic/accent color only when they sit inside a status chip or colored icon tile
(e.g. a purple AI bolt icon on a light-purple tile).
## Caveats & where I need your help
1. **No Figma was attached** — everything above comes from the approved HTML baseline in
`design/baseline/`, which the team's own spec names as canonical. If a Figma file exists,
attach it and I can cross-check/tighten values.
2. **No FoxRay/FirePage brand assets** — this system only covers Edevs Hub (the internal
platform + its two public surfaces). FoxRay/Foxray and FirePage are referenced only as
*product tags* inside Hub (colored labels, no logos). If you want their actual product UI
or marks in this system, please attach their codebases/design files.
3. **No logo beyond the one favicon mark** — I did not draw one. If Edevs has a real wordmark
or icon set beyond `favicon.svg`, please attach it and I'll swap it in everywhere.
4. **Ant Design isn't literally bundled** — see "Intentional additions" above; I built
faithful lightweight stand-ins instead of pulling in the real library, since only static
HTML/JS/CSS work in this environment.
5. **Internal Hub UI kit covers 2 of many screens** (Command Center + Sales · Clients, behind a
working Auth gate) rather than all ~35 baseline screens — tell me which screens matter most
(Departments, AI agents, Orders, Settings…) and I'll extend the kit.
**Ask:** tell me which of the ~35 baseline screens to turn into additional UI-kit pages next,
and whether the Ant-Design-styled primitives above should stay as lightweight stand-ins or be
swapped for real `antd` components if this ever moves into a real build environment.
@@ -0,0 +1,4 @@
@import "./tokens/colors.css";
@import "./tokens/typography.css";
@import "./tokens/spacing.css";
@import "./tokens/effects.css";
@@ -0,0 +1,88 @@
/* Edevs Hub — color tokens
Source: packages/ui/src/theme.ts (Ant Design ThemeConfig), apps/internal-ui/src/styles/base.css,
and design/baseline/*.dc.html (approved HTML baseline). Ant Design's default light palette,
customized with a single accent (#1677ff) per ADR-HUB-0013. */
:root {
/* ---- base neutrals (Ant Design neutral scale as used in the baseline) ---- */
--n-1: #1f1f1f; /* page/heading titles */
--n-2: #262626; /* primary body text */
--n-3: #595959; /* secondary text */
--n-4: #8c8c8c; /* tertiary text / captions */
--n-5: #bfbfbf; /* disabled / placeholder / faint */
--n-6: #d9d9d9; /* strong border, control border */
--n-7: #e8e8e8; /* input border */
--n-8: #f0f0f0; /* hairline border */
--n-9: #f5f5f5; /* hover surface */
--n-10: #fafafa; /* table header surface */
--n-11: #f0f2f5; /* app/page background */
--n-white: #ffffff;
/* ---- primary (blue-6 / blue-7) ---- */
--primary: #1677ff;
--primary-hover: #0958d9;
--primary-bg: #e6f4ff;
--primary-border: #91caff;
--primary-shadow: rgba(22, 119, 255, 0.3);
/* ---- semantic: success / warning / error / info ---- */
--success: #52c41a;
--success-text: #389e0d;
--success-bg: #f6ffed;
--success-bg-strong: #f1f9ec;
--success-border: #b7eb8f;
--warning: #faad14;
--warning-text: #d48806;
--warning-bg: #fffbe6;
--warning-bg-strong: #fff7e6;
--warning-border: #ffe58f;
--error: #ff4d4f;
--error-text: #cf1322;
--error-bg: #fff2f0;
--error-border: #ffccc7;
--info: #1677ff;
/* ---- role accents: AI vs human ---- */
--ai: #722ed1;
--ai-light: #9254de;
--ai-lighter: #b37feb;
--ai-bg: #f9f0ff;
--human: #1677ff;
/* ---- channel accents (MAX / Telegram / Web Chat) ---- */
--channel-max: #6b5be0;
--channel-max-bg: #f2f0ff;
--channel-telegram: #2f8fd0;
--channel-telegram-bg: #eaf6fd;
--channel-webchat: #0f9b8e;
--channel-webchat-bg: #e8f7f4;
/* ---- product accents (as tagged in tables/lists) ---- */
--product-firepage: #0958d9;
--product-firepage-bg: #e6f4ff;
--product-foxray: #722ed1;
--product-foxray-bg: #f9f0ff;
/* ---- surfaces ---- */
--surface-page: var(--n-11);
--surface-card: var(--n-white);
--surface-sunken: #fafafa;
--surface-chip: #f7f8fa;
/* ---- text aliases ---- */
--text-heading: var(--n-1);
--text-body: var(--n-2);
--text-secondary: var(--n-3);
--text-tertiary: var(--n-4);
--text-disabled: var(--n-5);
--text-inverse: var(--n-white);
--text-link: var(--primary);
/* ---- borders ---- */
--border-default: var(--n-8);
--border-input: var(--n-7);
--border-strong: var(--n-6);
}
@@ -0,0 +1,40 @@
/* Edevs Hub — radii, shadows, motion. "Премиальный минимализм": no gradients,
no glassmorphism/blur, no neon — shadows stay soft and near-black at low opacity. */
:root {
--radius-xs: 5px;
--radius-sm: 7px;
--radius-md: 8px;
--radius-lg: 9px;
--radius-xl: 10px;
--radius-2xl: 12px;
--radius-3xl: 13px;
--radius-4xl: 14px;
--radius-pill: 999px;
--radius-circle: 50%;
--shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.03);
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.04);
--shadow-md: 0 2px 12px rgba(0, 0, 0, 0.05);
--shadow-lg: 0 6px 20px rgba(0, 0, 0, 0.12);
--shadow-sticky: 0 -4px 16px rgba(0, 0, 0, 0.04);
--shadow-primary: 0 1px 2px rgba(22, 119, 255, 0.3);
--ease-standard: cubic-bezier(0.4, 0, 0.2, 1); /* @kind other */
--duration-fast: 0.15s; /* @kind other */
--duration-base: 0.2s; /* @kind other */
}
@keyframes hub-typing {
0%, 80%, 100% { opacity: 0.25; transform: translateY(0); }
40% { opacity: 1; transform: translateY(-2px); }
}
@keyframes hub-spin {
to { transform: rotate(360deg); }
}
@keyframes hub-pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
@@ -0,0 +1,36 @@
/* Edevs Hub — spacing tokens. Compact-enterprise density (ADR-HUB-0013):
"большие пустые поля и oversized-карточки запрещены". Values are the exact
paddings/gaps observed in the baseline, not snapped to a rounder grid. */
:root {
--space-1: 2px;
--space-2: 4px;
--space-3: 6px;
--space-4: 8px;
--space-5: 9px;
--space-6: 10px;
--space-7: 11px;
--space-8: 12px;
--space-9: 14px;
--space-10: 16px;
--space-11: 18px;
--space-12: 20px;
--space-13: 22px;
--space-14: 24px;
--space-15: 28px;
--space-16: 32px;
--space-17: 36px;
/* control heights */
--h-control-sm: 30px;
--h-control-md: 34px;
--h-control: 36px;
--h-control-lg: 42px;
--h-control-xl: 44px;
--h-control-2xl: 48px;
--h-topbar: 56px;
/* layout */
--sidebar-width: 248px;
--content-max: 1340px;
}
@@ -0,0 +1,42 @@
/* Edevs Hub — typography tokens
The internal Hub uses the Ant Design default system font stack — no bespoke webfont
is loaded (see ADR-HUB-0013: "используется системный font stack Ant Design без
обязательной внешней зависимости от загружаемого шрифта"). Technical identifiers
(order/release/event IDs, emails) use a monospace stack. */
:root {
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--font-mono: "SF Mono", ui-monospace, Menlo, Consolas, monospace;
/* type scale, taken verbatim from the baseline (px, not snapped to a 4/8 grid) */
--text-2xl: 26px; /* page hero title (Command Center) */
--text-xl: 24px; /* page title */
--text-lg: 20px; /* auth title */
--text-md: 18px; /* card title */
--text-base-lg: 16px;
--text-base: 14.5px; /* buttons, primary body */
--text-sm-lg: 13.5px;
--text-sm: 13px; /* table body */
--text-sm-tight: 12.5px;
--text-xs: 12px; /* meta */
--text-xs-tight: 11.5px;
--text-2xs: 11px; /* table header / eyebrow */
--text-2xs-tight: 10.5px;
--weight-regular: 400;
--weight-medium: 500;
--weight-semibold: 600;
--weight-bold: 700;
--weight-black: 800;
--tracking-tight: -0.02em; /* large headings */
--tracking-tight-sm: -0.01em;
--tracking-wide: 0.03em; /* table header eyebrows */
--tracking-wider: 0.06em; /* nav section labels */
--leading-tight: 1.15;
--leading-snug: 1.2;
--leading-normal: 1.4;
--leading-relaxed: 1.5;
--leading-loose: 1.55;
}
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1386 1386" fill="none">
<rect width="1386" height="1386" rx="300" fill="#1677FF"></rect>
<path d="M691.947 175C743.896 176.004 775.161 202.368 793.419 230.289C802.544 244.243 808.421 258.585 812.018 270.347C815.61 282.096 816.938 291.306 816.938 295.001C816.938 309.524 816.93 372.653 744.438 407.813V460.002H904.938V540.99L904.45 541.002L744.445 544.989L749.937 882.48C749.937 882.489 749.939 882.5 749.94 882.514C749.944 882.549 749.949 882.602 749.955 882.672C749.968 882.812 749.988 883.021 750.016 883.295C750.071 883.842 750.157 884.648 750.278 885.681C750.521 887.746 750.905 890.716 751.471 894.334C752.601 901.571 754.457 911.395 757.356 921.745C760.257 932.098 764.196 942.963 769.489 952.29C774.619 961.33 780.998 968.885 788.895 973.156L789.664 973.56L789.699 973.577L789.731 973.601C793.751 976.524 799.835 978.199 806.771 979.04C813.693 979.879 821.395 979.88 828.599 979.506C835.8 979.132 842.489 978.384 847.379 977.729C849.823 977.401 851.817 977.097 853.199 976.875C853.89 976.764 854.428 976.673 854.793 976.61C854.975 976.579 855.115 976.555 855.208 976.538C855.255 976.53 855.29 976.524 855.313 976.52C855.323 976.518 855.33 976.516 855.336 976.515C855.345 976.512 855.36 976.509 855.379 976.505C855.418 976.495 855.477 976.481 855.556 976.461C855.713 976.421 855.948 976.36 856.258 976.276C856.878 976.109 857.797 975.851 858.986 975.491C861.365 974.771 864.827 973.639 869.151 971.999C877.801 968.719 889.899 963.401 903.684 955.262C931.141 939.048 965.281 911.632 992.18 866.791C981.29 863.394 967.013 860.713 955.359 858.873C949.428 857.937 944.183 857.218 940.421 856.734C938.54 856.492 937.03 856.309 935.99 856.187C935.471 856.125 935.069 856.079 934.797 856.048C934.661 856.032 934.557 856.02 934.487 856.013C934.453 856.009 934.427 856.006 934.409 856.004C934.401 856.003 934.394 856.002 934.39 856.002C934.388 856.002 934.386 856.002 934.385 856.002L934.384 856.001H934.383L933.401 855.894L934.069 855.166L1073.57 703.165L1074.13 702.559L1074.41 703.333C1090.68 748.154 1096.94 802.964 1099.12 846.542C1100.22 868.336 1100.3 887.331 1100.1 900.879C1100 907.653 1099.84 913.065 1099.7 916.784C1099.63 918.644 1099.56 920.081 1099.51 921.053C1099.49 921.539 1099.47 921.909 1099.46 922.157C1099.45 922.282 1099.45 922.376 1099.44 922.438C1099.44 922.47 1099.44 922.494 1099.44 922.51C1099.44 922.517 1099.44 922.523 1099.44 922.527C1099.44 922.529 1099.44 922.531 1099.44 922.532C1099.43 922.533 1099.39 922.531 1098.94 922.505L1099.44 922.534L1099.39 923.361L1098.68 922.933L1048.66 892.726C1003.9 993.99 945.911 1044.08 883.83 1083.43C821.626 1122.85 755.486 1151.41 694.283 1209.87L693.948 1210.19L693.604 1209.88C626.889 1149.91 559.114 1118.72 497.414 1078.36C435.832 1038.08 380.46 988.73 338.686 892.68C328.31 897.648 315.933 905.371 306.086 911.902C301.091 915.215 296.752 918.217 293.662 920.391C292.117 921.478 290.883 922.358 290.037 922.966C289.614 923.269 289.288 923.505 289.067 923.665C288.957 923.745 288.874 923.806 288.817 923.847C288.789 923.867 288.768 923.883 288.754 923.894C288.747 923.899 288.741 923.903 288.737 923.905C288.736 923.906 288.734 923.907 288.733 923.907L288.732 923.908L288.048 924.408L287.941 923.567L288.438 923.505C287.942 923.568 287.942 923.567 287.941 923.566C287.941 923.566 287.941 923.564 287.94 923.562C287.94 923.559 287.94 923.555 287.939 923.549C287.938 923.537 287.936 923.518 287.933 923.494C287.927 923.446 287.918 923.373 287.906 923.277C287.884 923.086 287.851 922.8 287.81 922.424C287.727 921.67 287.611 920.551 287.478 919.085C287.21 916.153 286.872 911.834 286.587 906.28C286.016 895.173 285.656 879.126 286.5 859.358C288.189 819.824 294.695 765.402 313.962 705.85L314.224 705.041L314.803 705.662L455.303 856.163L455.976 856.884L454.997 857.001L397.147 863.923C397.186 864.016 397.228 864.119 397.276 864.232C397.53 864.832 397.917 865.718 398.445 866.858C399.502 869.139 401.127 872.437 403.397 876.495C407.939 884.612 415.061 895.773 425.381 907.932C446.013 932.242 479.425 960.545 530.546 976.515C553.481 979.493 570.422 978.743 581.621 977.252C587.224 976.506 591.391 975.575 594.151 974.832C595.531 974.461 596.561 974.137 597.242 973.906C597.583 973.791 597.836 973.699 598.004 973.637C598.088 973.606 598.151 973.581 598.191 973.565C598.211 973.558 598.227 973.552 598.236 973.548C598.241 973.546 598.244 973.544 598.246 973.543C598.249 973.542 598.254 973.54 598.26 973.537C598.274 973.531 598.297 973.521 598.326 973.508C598.386 973.48 598.477 973.436 598.598 973.376C598.839 973.256 599.199 973.068 599.661 972.8C600.586 972.264 601.923 971.408 603.553 970.142C606.812 967.608 611.246 963.425 615.904 956.842C625.218 943.678 635.442 920.895 638.938 882.477L642.432 544.989L482.925 541.002L482.438 540.99V460.002H642.483C642.506 459.763 642.536 459.433 642.572 459.019C642.654 458.09 642.768 456.741 642.895 455.058C643.147 451.691 643.45 446.988 643.652 441.648C644.054 431.045 644.053 417.961 642.48 407.824C603.762 387.517 586.111 359.35 578.152 336.227C574.167 324.647 572.613 314.338 572.056 306.921C571.777 303.212 571.748 300.226 571.788 298.164C571.808 297.133 571.846 296.333 571Line truncated
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

File diff suppressed because it is too large. Load diff
@@ -0,0 +1,609 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<meta name="design_doc_mode" content="canvas">
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/colors.css">
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/typography.css">
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/spacing.css">
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/tokens/effects.css">
<link rel="stylesheet" href="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/styles.css">
<script src="_ds/edevs-hub-design-system-e4c9df12-82c8-42b3-b819-63d92dfb8702/_ds_bundle.js"></script>
<style>
* { box-sizing: border-box; }
body { margin: 0; background: #e9ebee; }
a { color: var(--primary); text-decoration: none; }
a:hover { color: var(--primary-hover); }
.ch-scroll::-webkit-scrollbar { width: 10px; height: 10px; }
.ch-scroll::-webkit-scrollbar-thumb { background: #d0d3d8; border-radius: 8px; border: 3px solid transparent; background-clip: content-box; }
</style>
</helmet>
<div style="font-family: var(--font-sans); color: var(--text-body); padding: 40px 48px 80px; min-width: 1480px; display: flex; flex-direction: column; gap: 40px;">
<!-- DOC HEADER -->
<div style="max-width: 1340px;">
<div style="display: inline-flex; align-items: center; gap: 8px; padding: 4px 11px; border-radius: var(--radius-pill); background: var(--ai-bg); color: var(--ai); font-size: 11px; font-weight: 600; letter-spacing: 0.04em; margin-bottom: 14px;">
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
DG-02 · DESIGN BASELINE
</div>
<h1 style="margin: 0 0 8px; font-size: 26px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading);">Каналы обработки — канал как объект управления</h1>
<p style="margin: 0; font-size: 14px; line-height: 1.55; color: var(--text-secondary); max-width: 860px;">Утверждаемый макет раздела <b>Компания → Каналы</b> по SPEC-HUB-0027 / ADR-HUB-0037: список с фильтрами и меню строки, карточка канала одной страницей (без вкладок), секции «Политика» и «Подключения», мастер создания из трёх шагов, служебные состояния. Настройка агента и знания остаются в разделе AI и в этот baseline не входят. Терминология: MAX / TG / Web — это <b>подключения</b>; «канал» — сущность маршрутизации. Все данные — примеры.</p>
<div style="display: flex; gap: 8px; margin-top: 14px; flex-wrap: wrap;">
<a href="#A" style="font-size: 12.5px; padding: 5px 12px; border: 1px solid var(--n-6); border-radius: var(--radius-pill); background: #fff;">A · Список</a>
<a href="#B" style="font-size: 12.5px; padding: 5px 12px; border: 1px solid var(--n-6); border-radius: var(--radius-pill); background: #fff;">B · Карточка</a>
<a href="#C" style="font-size: 12.5px; padding: 5px 12px; border: 1px solid var(--n-6); border-radius: var(--radius-pill); background: #fff;">C · Политика</a>
<a href="#D" style="font-size: 12.5px; padding: 5px 12px; border: 1px solid var(--n-6); border-radius: var(--radius-pill); background: #fff;">D · Подключения</a>
<a href="#E" style="font-size: 12.5px; padding: 5px 12px; border: 1px solid var(--n-6); border-radius: var(--radius-pill); background: #fff;">E · Мастер</a>
<a href="#S" style="font-size: 12.5px; padding: 5px 12px; border: 1px solid var(--n-6); border-radius: var(--radius-pill); background: #fff;">S · Состояния</a>
</div>
</div>
<!-- ============ FRAME A — LIST (FULL SHELL) ============ -->
<section id="A" style="display: flex; flex-direction: column; gap: 12px;">
<div style="display: flex; align-items: baseline; gap: 12px;">
<span style="font-size: 12px; font-weight: 700; color: #fff; background: var(--text-heading); padding: 3px 9px; border-radius: 6px;">A</span>
<h2 style="margin: 0; font-size: 17px; font-weight: 600; color: var(--text-heading);">Список каналов — основной вид</h2>
<span style="font-size: 12.5px; color: var(--text-tertiary);">фильтры по отделу · поиск и архивные · плотная таблица · меню строки</span>
</div>
<div style="width: 1340px; height: 880px; background: var(--surface-page); border: 1px solid var(--n-6); border-radius: var(--radius-2xl); box-shadow: var(--shadow-md); overflow: hidden; display: flex;">
<!-- SIDEBAR -->
<aside style="width: 248px; flex: none; background: #fff; border-right: 1px solid var(--n-8); display: flex; flex-direction: column;">
<div style="height: 56px; flex: none; display: flex; align-items: center; gap: 11px; padding: 0 20px; border-bottom: 1px solid var(--n-9);">
<img src="assets/custocrm-mark.svg" alt="CustoCRM" style="width: 30px; height: 30px; border-radius: 8px; flex: none;">
<div style="display: flex; flex-direction: column; line-height: 1.15;">
<span style="font-size: 14px; font-weight: 600; color: var(--text-heading); letter-spacing: -0.01em;">CustoCRM</span>
<span style="font-size: 11px; color: var(--text-tertiary);">Управление компанией</span>
</div>
</div>
<nav style="flex: 1; overflow-y: auto; padding: 12px 12px 8px;">
<a href="#A" style="display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 8px; margin-bottom: 2px; font-size: 13.5px; font-weight: 500; color: var(--text-secondary);"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="9" rx="1.4"/><rect x="14" y="3" width="7" height="5" rx="1.4"/><rect x="14" y="12" width="7" height="9" rx="1.4"/><rect x="3" y="16" width="7" height="5" rx="1.4"/></svg>Обзор</a>
<div style="font-size: 11px; font-weight: 600; letter-spacing: 0.06em; color: var(--n-5); padding: 14px 12px 6px;">КОМПАНИЯ</div>
<a href="#A" style="display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 8px; margin-bottom: 2px; font-size: 13.5px; font-weight: 500; color: var(--text-secondary);"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21h18"/><path d="M5 21V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16"/><path d="M9 8h1.5M13.5 8H15M9 12h1.5M13.5 12H15M9 16h1.5M13.5 16H15"/></svg>Отделы</a>
<a href="#A" style="display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 8px; margin-bottom: 2px; font-size: 13.5px; font-weight: 500; color: var(--text-secondary);"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>Сотрудники</a>
<a href="#A" style="display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 8px; margin-bottom: 2px; font-size: 13.5px; font-weight: 500; color: var(--text-secondary);"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"/><path d="m3.3 7 8.7 5 8.7-5"/><path d="M12 22V12"/></svg>Продукты</a>
<a href="#A" style="display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 8px; margin-bottom: 2px; position: relative; font-size: 13.5px; font-weight: 600; background: var(--primary-bg); color: #0958d9;"><span style="position: absolute; left: 0; top: 8px; bottom: 8px; width: 3px; border-radius: 0 3px 3px 0; background: var(--primary);"></span><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></svg>Каналы</a>
<div style="font-size: 11px; font-weight: 600; letter-spacing: 0.06em; color: var(--n-5); padding: 14px 12px 6px;">ПЛАТФОРМА</div>
<a href="#A" style="display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 8px; margin-bottom: 2px; font-size: 13.5px; font-weight: 500; color: var(--text-secondary);"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="8" width="16" height="12" rx="2.5"/><path d="M12 8V4.5"/><circle cx="12" cy="3.5" r="1.2"/><circle cx="9" cy="13.5" r="1"/><circle cx="15" cy="13.5" r="1"/></svg>AI</a>
<div style="display: flex; flex-direction: column; padding: 2px 0 2px 30px; gap: 2px;">
<a href="#A" style="padding: 6px 12px; border-radius: 7px; font-size: 13px; color: var(--text-secondary);">AI-агенты</a>
<a href="#A" style="padding: 6px 12px; border-radius: 7px; font-size: 13px; color: var(--text-secondary);">Знания</a>
<a href="#A" style="padding: 6px 12px; border-radius: 7px; font-size: 13px; color: var(--text-secondary);">Использование AI</a>
</div>
<a href="#A" style="display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 8px; margin-bottom: 2px; font-size: 13.5px; font-weight: 500; color: var(--text-secondary);"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9 8V2.5M15 8V2.5M18 8v5.5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z"/><path d="M12 17.5V22"/></svg>Интеграции</a>
</nav>
<div style="flex: none; border-top: 1px solid var(--n-9); padding: 10px 12px;">
<div style="display: flex; align-items: center; gap: 11px; padding: 8px 10px; border-radius: 8px;">
<div style="width: 34px; height: 34px; border-radius: 50%; background: var(--ai-bg); color: var(--ai); display: flex; align-items: center; justify-content: center; font-weight: 600; font-size: 13px; flex: none;">ИП</div>
<div style="display: flex; flex-direction: column; line-height: 1.2; flex: 1;">
<span style="font-size: 13px; font-weight: 600;">Иван Петров</span>
<span style="font-size: 11px; color: var(--text-tertiary);">OWNER</span>
</div>
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="var(--text-tertiary)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
</div>
</div>
</aside>
<!-- MAIN -->
<div style="flex: 1; min-width: 0; display: flex; flex-direction: column;">
<header style="height: 56px; flex: none; background: #fff; border-bottom: 1px solid var(--n-8); display: flex; align-items: center; justify-content: space-between; padding: 0 24px;">
<div style="display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-tertiary);">
<span style="font-weight: 500; color: var(--text-secondary);">ООО «Эдевс»</span><span style="color: var(--n-6);">/</span>
<span style="font-weight: 500; color: var(--text-secondary);">Компания</span><span style="color: var(--n-6);">/</span>
<span style="font-weight: 600; color: var(--text-body);">Каналы</span>
</div>
<div style="display: flex; align-items: center; gap: 14px;">
<div style="position: relative; width: 36px; height: 36px; border-radius: 8px; border: 1px solid var(--n-8); background: #fff; display: flex; align-items: center; justify-content: center; color: var(--text-secondary);"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg><b style="position: absolute; top: -5px; right: -5px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px; background: var(--error); color: #fff; font-size: 10px; font-weight: 600; display: flex; align-items: center; justify-content: center; border: 1.5px solid #fff;">3</b></div>
</div>
</header>
<main class="ch-scroll" style="flex: 1; overflow-y: auto; padding: 22px 26px 32px;">
<!-- Page header -->
<div style="display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; margin-bottom: 18px;">
<div>
<h1 style="margin: 0 0 4px; font-size: 24px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading);">Каналы</h1>
<p style="margin: 0; font-size: 13.5px; color: var(--text-secondary);">Точка маршрутизации диалогов: связывает отдел, продукт, подключения и — необязательно — AI-агента</p>
</div>
<div style="display: flex; gap: 10px; flex: none;">
<button style="display: inline-flex; align-items: center; gap: 7px; height: 36px; padding: 0 14px; border-radius: var(--radius-lg); border: 1px solid transparent; background: var(--primary); color: #fff; font-size: 13px; font-weight: 600; box-shadow: var(--shadow-primary); cursor: pointer;"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Создать канал</button>
</div>
</div>
<!-- Filter tabs (UnderlineTabs with count) + tools -->
<div style="display: flex; align-items: center; justify-content: space-between; gap: 16px; border-bottom: 1px solid var(--n-8); margin-bottom: 14px;">
<div style="display: flex; gap: 4px;">
<button style="display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 4px 0 4px; margin: 0 8px; border: none; background: none; border-bottom: 2px solid var(--primary); font-size: 13.5px; font-weight: 600; color: #0958d9; cursor: pointer;">Все<span style="font-size: 11px; font-weight: 600; color: #0958d9; background: var(--primary-bg); padding: 0 6px; border-radius: var(--radius-pill);">5</span></button>
<button style="display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 4px; margin: 0 8px; border: none; background: none; border-bottom: 2px solid transparent; font-size: 13.5px; font-weight: 500; color: var(--text-secondary); cursor: pointer;">Продажи<span style="font-size: 11px; font-weight: 600; color: var(--text-tertiary); background: var(--n-9); padding: 0 6px; border-radius: var(--radius-pill);">2</span></button>
<button style="display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 4px; margin: 0 8px; border: none; background: none; border-bottom: 2px solid transparent; font-size: 13.5px; font-weight: 500; color: var(--text-secondary); cursor: pointer;">Поддержка<span style="font-size: 11px; font-weight: 600; color: var(--text-tertiary); background: var(--n-9); padding: 0 6px; border-radius: var(--radius-pill);">1</span></button>
<button style="display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 4px; margin: 0 8px; border: none; background: none; border-bottom: 2px solid transparent; font-size: 13.5px; font-weight: 500; color: var(--text-secondary); cursor: pointer;">Без отдела<span style="font-size: 11px; font-weight: 600; color: var(--text-tertiary); background: var(--n-9); padding: 0 6px; border-radius: var(--radius-pill);">1</span></button>
</div>
<div style="display: flex; align-items: center; gap: 10px; padding-bottom: 6px;">
<div style="width: 240px; display: flex; align-items: center; gap: 9px; height: 34px; padding: 0 12px; border: 1px solid var(--border-input); border-radius: var(--radius-lg); background: #fff;">
<svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="var(--text-tertiary)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<span style="flex: 1; font-size: 13px; color: var(--text-tertiary);">Поиск по имени и коду</span>
</div>
<label style="display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text-secondary); cursor: pointer;">
<span style="width: 34px; height: 20px; border-radius: var(--radius-pill); background: var(--n-6); position: relative; flex: none;"><span style="position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-xs);"></span></span>
Показывать архивные
</label>
</div>
</div>
<!-- Table card -->
<div style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); overflow: visible;">
<table style="width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px;">
<thead>
<tr style="background: var(--n-10); text-align: left;">
<th style="padding: 10px 12px 10px 16px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary); border-top-left-radius: var(--radius-2xl);">КАНАЛ</th>
<th style="padding: 10px 12px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary);">ПРОДУКТ</th>
<th style="padding: 10px 12px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary);">ПОДКЛЮЧЕНИЯ</th>
<th style="padding: 10px 12px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary);">AI-АГЕНТ</th>
<th style="padding: 10px 12px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary); text-align: right;">ДИАЛОГИ</th>
<th style="padding: 10px 16px 10px 12px; width: 44px; border-top-right-radius: var(--radius-2xl);"></th>
</tr>
</thead>
<tbody>
<!-- Row 1 — product sales, agent active, row menu OPEN -->
<tr style="border-top: 1px solid var(--n-8); cursor: pointer; position: relative;">
<td style="padding: 12px 12px 12px 16px;"><a href="#B" style="font-weight: 600; color: var(--text-body);">FoxRay — продажи</a><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;"><span style="font-family: var(--font-mono);">foxray-sales</span> · Продажи</div></td>
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 6px; padding: 2px 9px; border-radius: var(--radius-pill); background: var(--product-foxray-bg); font-size: 11.5px; font-weight: 600; color: var(--product-foxray);"><span style="width: 6px; height: 6px; border-radius: 50%; background: var(--product-foxray);"></span>FoxRay</span></td>
<td style="padding: 12px;"><span style="display: inline-flex; gap: 5px;"><span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-telegram-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-telegram);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-telegram);">TG</span></span><span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-webchat-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-webchat);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-webchat);">Web</span></span></span></td>
<td style="padding: 12px;"><div style="display: flex; flex-direction: column; align-items: flex-start; gap: 3px;"><a href="#" style="font-weight: 600; color: var(--primary);">FoxRay Sales</a><span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--success-text);"><span style="width: 7px; height: 7px; border-radius: 50%; background: var(--success);"></span>Активен</span></div></td>
<td style="padding: 12px; text-align: right; color: var(--text-body); font-variant-numeric: tabular-nums;">12</td>
<td style="padding: 12px 16px 12px 12px; position: relative;">
<span style="display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 7px; border: 1px solid var(--primary-border); background: var(--primary-bg); color: #0958d9;"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/></svg></span>
<!-- OPEN ROW MENU -->
<div style="position: absolute; top: 44px; right: 16px; z-index: 5; width: 246px; background: #fff; border: 1px solid var(--n-7); border-radius: var(--radius-xl); box-shadow: var(--shadow-lg); padding: 6px; text-align: left;">
<a href="#B" style="display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: 7px; font-size: 13px; color: var(--text-body);"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/></svg>Открыть</a>
<a href="#D" style="display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: 7px; font-size: 13px; color: var(--text-body);"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9 8V2.5M15 8V2.5M18 8v5.5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z"/><path d="M12 17.5V22"/></svg>Привязать подключение</a>
<div style="height: 1px; background: var(--n-8); margin: 5px 8px;"></div>
<div style="display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: 7px; font-size: 13px; color: var(--warning-text); cursor: pointer;"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="4" width="4" height="16" rx="1"/><rect x="14" y="4" width="4" height="16" rx="1"/></svg>Деактивировать</div>
<div style="display: flex; align-items: flex-start; gap: 9px; padding: 8px 10px; border-radius: 7px; font-size: 13px; color: var(--n-5); cursor: not-allowed;" title="Есть связанные записи">
<svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" style="flex:none;margin-top:1px;"><path d="M3 6h18"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2m3 0-1 14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2L4 6"/></svg>
<span style="line-height: 1.3;">Удалить<br><span style="font-size: 11px; color: var(--n-5);">Нельзя: 12 диалогов, агент</span></span>
</div>
</div>
</td>
</tr>
<!-- Row 2 — support, agent active -->
<tr style="border-top: 1px solid var(--n-8); cursor: pointer;">
<td style="padding: 12px 12px 12px 16px;"><a href="#B" style="font-weight: 600; color: var(--text-body);">FoxRay — поддержка</a><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;"><span style="font-family: var(--font-mono);">foxray-support</span> · Поддержка</div></td>
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 6px; padding: 2px 9px; border-radius: var(--radius-pill); background: var(--product-foxray-bg); font-size: 11.5px; font-weight: 600; color: var(--product-foxray);"><span style="width: 6px; height: 6px; border-radius: 50%; background: var(--product-foxray);"></span>FoxRay</span></td>
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-webchat-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-webchat);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-webchat);">Web</span></span></td>
<td style="padding: 12px;"><div style="display: flex; flex-direction: column; align-items: flex-start; gap: 3px;"><a href="#" style="font-weight: 600; color: var(--primary);">FoxRay Support</a><span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--success-text);"><span style="width: 7px; height: 7px; border-radius: 50%; background: var(--success);"></span>Активен</span></div></td>
<td style="padding: 12px; text-align: right; color: var(--text-body); font-variant-numeric: tabular-nums;">7</td>
<td style="padding: 12px 16px 12px 12px; text-align: right;"><span style="display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 7px; color: var(--text-tertiary);"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/></svg></span></td>
</tr>
<!-- Row 3 — FirePage sales, MAX -->
<tr style="border-top: 1px solid var(--n-8); cursor: pointer;">
<td style="padding: 12px 12px 12px 16px;"><a href="#B" style="font-weight: 600; color: var(--text-body);">FirePage — продажи</a><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;"><span style="font-family: var(--font-mono);">firepage-sales</span> · Продажи</div></td>
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 6px; padding: 2px 9px; border-radius: var(--radius-pill); background: var(--product-firepage-bg); font-size: 11.5px; font-weight: 600; color: var(--product-firepage);"><span style="width: 6px; height: 6px; border-radius: 50%; background: var(--product-firepage);"></span>FirePage</span></td>
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-max-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-max);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-max);">MAX</span></span></td>
<td style="padding: 12px;"><div style="display: flex; flex-direction: column; align-items: flex-start; gap: 3px;"><a href="#" style="font-weight: 600; color: var(--primary);">FirePage Sales</a><span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--success-text);"><span style="width: 7px; height: 7px; border-radius: 50%; background: var(--success);"></span>Активен</span></div></td>
<td style="padding: 12px; text-align: right; color: var(--text-body); font-variant-numeric: tabular-nums;">5</td>
<td style="padding: 12px 16px 12px 12px; text-align: right;"><span style="display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 7px; color: var(--text-tertiary);"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/></svg></span></td>
</tr>
<!-- Row 4 — non-product, NO AGENT (operator channel), no department -->
<tr style="border-top: 1px solid var(--n-8); cursor: pointer;">
<td style="padding: 12px 12px 12px 16px;"><a href="#B" style="font-weight: 600; color: var(--text-body);">Партнёрская линия</a><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;"><span style="font-family: var(--font-mono);">partners</span> · <span style="display: inline-flex; align-items: center; gap: 4px; padding: 0 7px; border-radius: var(--radius-pill); background: var(--n-9); font-size: 10.5px; font-weight: 600; color: var(--text-tertiary); vertical-align: middle;">Без отдела</span></div></td>
<td style="padding: 12px; color: var(--text-tertiary); font-size: 12.5px;">— непродуктовый</td>
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-telegram-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-telegram);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-telegram);">TG</span></span></td>
<td style="padding: 12px;"><span style="font-size: 12.5px; color: var(--text-tertiary);">Нет агента</span><div style="font-size: 11px; color: var(--n-5); margin-top: 2px;">операторский канал</div></td>
<td style="padding: 12px; text-align: right; color: var(--text-body); font-variant-numeric: tabular-nums;">3</td>
<td style="padding: 12px 16px 12px 12px; text-align: right;"><span style="display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 7px; color: var(--text-tertiary);"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/></svg></span></td>
</tr>
<!-- Row 5 — ARCHIVED (visible because toggle on) -->
<tr style="border-top: 1px solid var(--n-8); cursor: pointer; background: #fcfcfc;">
<td style="padding: 12px 12px 12px 16px;"><a href="#B" style="font-weight: 600; color: var(--text-tertiary);">FoxRay — вебинары</a><div style="font-size: 12px; color: var(--n-5); margin-top: 2px;"><span style="font-family: var(--font-mono);">foxray-webinars</span> · Продажи</div></td>
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 6px; padding: 2px 9px; border-radius: var(--radius-pill); background: var(--n-9); font-size: 11.5px; font-weight: 600; color: var(--n-5);"><span style="width: 6px; height: 6px; border-radius: 50%; background: var(--n-5);"></span>FoxRay</span></td>
<td style="padding: 12px; color: var(--n-5); font-size: 12.5px;">—</td>
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text-tertiary);"><span style="width: 7px; height: 7px; border-radius: 50%; border: 1.5px solid var(--n-5); background: transparent;"></span>Архивный</span></td>
<td style="padding: 12px; text-align: right; color: var(--text-tertiary); font-variant-numeric: tabular-nums;">0</td>
<td style="padding: 12px 16px 12px 12px; text-align: right;"><span style="display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 7px; color: var(--text-tertiary);"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/></svg></span></td>
</tr>
</tbody>
</table>
<div style="display: flex; align-items: center; justify-content: space-between; padding: 11px 16px; border-top: 1px solid var(--n-8); font-size: 12.5px; color: var(--text-tertiary);">
<span>5 каналов · 1 архивный</span>
<span>Счётчик «Диалоги» — открытые диалоги по <span style="font-family: var(--font-mono);">Conversation.channel</span></span>
</div>
</div>
</main>
</div>
</div>
</section>
<!-- ============ FRAME B — CARD (SINGLE PAGE, NO TABS) ============ -->
<section id="B" style="display: flex; flex-direction: column; gap: 12px;">
<div style="display: flex; align-items: baseline; gap: 12px;">
<span style="font-size: 12px; font-weight: 700; color: #fff; background: var(--text-heading); padding: 3px 9px; border-radius: 6px;">B</span>
<h2 style="margin: 0; font-size: 17px; font-weight: 600; color: var(--text-heading);">Карточка канала — одна страница</h2>
<span style="font-size: 12.5px; color: var(--text-tertiary);">без вкладок · секции сверху вниз: Назначение · Политика · Подключения · AI-агент · Счётчики</span>
</div>
<div style="width: 1180px; background: var(--surface-page); border: 1px solid var(--n-6); border-radius: var(--radius-2xl); box-shadow: var(--shadow-md); overflow: hidden; padding: 22px 24px 28px;">
<!-- breadcrumb -->
<div style="display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text-tertiary); margin-bottom: 14px;">
<a href="#A" style="color: var(--text-secondary); font-weight: 500;">Каналы</a><span style="color: var(--n-6);">/</span><span style="color: var(--text-body); font-weight: 600;">FoxRay — продажи</span>
</div>
<!-- HEADER -->
<div style="display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; margin-bottom: 22px;">
<div>
<h1 style="margin: 0 0 5px; font-size: 22px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading);">FoxRay — продажи</h1>
<div style="display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--text-tertiary);"><span style="font-family: var(--font-mono);">foxray-sales</span><span style="color: var(--n-6);">·</span>Продажи<span style="color: var(--n-6);">·</span><span style="display: inline-flex; align-items: center; gap: 5px;"><span style="width: 6px; height: 6px; border-radius: 50%; background: var(--product-foxray);"></span>FoxRay</span></div>
</div>
<div style="display: flex; align-items: center; gap: 10px; flex: none;">
<span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--success-text); background: var(--success-bg); border: 1px solid var(--success-border); padding: 5px 11px; border-radius: var(--radius-pill);"><span style="width: 7px; height: 7px; border-radius: 50%; background: var(--success);"></span>Активен</span>
<button style="display: inline-flex; align-items: center; gap: 7px; height: 36px; padding: 0 14px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; font-size: 13px; font-weight: 600; color: var(--text-body); cursor: pointer;"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>Изменить</button>
<button style="display: inline-flex; align-items: center; gap: 7px; height: 36px; padding: 0 14px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; font-size: 13px; font-weight: 600; color: var(--warning-text); cursor: pointer;"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="4" width="4" height="16" rx="1"/><rect x="14" y="4" width="4" height="16" rx="1"/></svg>Деактивировать</button>
<span style="display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; color: var(--error-text); cursor: pointer;" title="Удалить"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2m3 0-1 14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2L4 6"/></svg></span>
</div>
</div>
<!-- SECTIONS -->
<div style="display: flex; flex-direction: column; gap: 16px;">
<!-- Назначение -->
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 20px;">
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 14px;"><h3 style="margin: 0; margin-right: auto; font-size: 15px; font-weight: 600; color: var(--text-heading);">Назначение</h3><span style="font-size: 12px; color: var(--text-tertiary);">Отдел и продукт редактируются здесь</span></div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px 24px; font-size: 13px;">
<div style="display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid var(--n-9);"><span style="color: var(--text-tertiary);">Отдел</span><span style="color: var(--text-body); font-weight: 500;">Продажи</span></div>
<div style="display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid var(--n-9);"><span style="color: var(--text-tertiary);">Продукт</span><span style="color: var(--text-body); font-weight: 500;">FoxRay</span></div>
<div style="display: flex; justify-content: space-between; padding: 8px 0;"><span style="color: var(--text-tertiary);">Код</span><span style="color: var(--text-body); font-family: var(--font-mono);">foxray-sales</span></div>
<div style="display: flex; justify-content: space-between; padding: 8px 0;"><span style="color: var(--text-tertiary);">Создан</span><span style="color: var(--text-body);">02 июл 2026</span></div>
</div>
</section>
<!-- Политика -->
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 8px 20px 12px;">
<div style="display: flex; align-items: center; gap: 12px; padding: 12px 0 4px;"><h3 style="margin: 0; margin-right: auto; font-size: 15px; font-weight: 600; color: var(--text-heading);">Политика</h3><span style="font-size: 12px; color: var(--text-tertiary);">Пресет: Продажи</span></div>
<div style="display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 12px 0; border-top: 1px solid var(--n-9);">
<div><div style="font-size: 13.5px; font-weight: 600; color: var(--text-body);">Обязательная продуктовая идентичность</div><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;">Диалог требует авторизации как владелец продукта.</div></div>
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--n-8); position: relative;"><span style="position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: var(--n-5);"></span></span>
</div>
<div style="display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 12px 0; border-top: 1px solid var(--n-9);">
<div><div style="font-size: 13.5px; font-weight: 600; color: var(--text-body);">Анонимные сессии</div><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;">Разрешает диалоги без идентификации пользователя.</div></div>
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--primary); position: relative;"><span style="position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-xs);"></span></span>
</div>
<div style="display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 12px 0; border-top: 1px solid var(--n-9);">
<div><div style="font-size: 13.5px; font-weight: 600; color: var(--text-body);">Самозаявленный контакт</div><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;">Позволяет пользователю указать контакт вручную.</div></div>
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--primary); position: relative;"><span style="position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-xs);"></span></span>
</div>
<div style="display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 12px 0; border-top: 1px solid var(--n-9);">
<div><div style="font-size: 13.5px; font-weight: 600; color: var(--text-body);">Attribution продаж</div><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;">Связывает продажу с диалогом канала.</div></div>
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--primary); position: relative;"><span style="position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-xs);"></span></span>
</div>
<div style="display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 12px 0; border-top: 1px solid var(--n-9);">
<div><div style="font-size: 13.5px; font-weight: 600; color: var(--text-body);">Коммерческие действия (checkout)</div><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;">Разрешает оформление заказа в диалоге.</div></div>
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--primary); position: relative;"><span style="position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-xs);"></span></span>
</div>
</section>
<!-- Подключения -->
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 20px;">
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 12px;"><h3 style="margin: 0; margin-right: auto; font-size: 15px; font-weight: 600; color: var(--text-heading);">Подключения</h3><button style="display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; font-size: 12.5px; font-weight: 600; color: var(--text-body); cursor: pointer;"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Привязать подключение</button></div>
<div style="display: flex; flex-direction: column; gap: 8px;">
<div style="display: flex; align-items: center; gap: 11px; padding: 11px 12px; border: 1px solid var(--n-8); border-radius: var(--radius-lg);">
<span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-telegram-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-telegram);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-telegram);">TG</span></span>
<div style="flex: 1; line-height: 1.3;"><div style="font-size: 13px; font-weight: 600; color: var(--text-body);">FoxRay Sales Bot</div><div style="font-size: 11.5px; color: var(--text-tertiary);">Telegram · @foxray_sales_bot</div></div>
<span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--success-text);"><span style="width: 6px; height: 6px; border-radius: 50%; background: var(--success);"></span>OK</span>
<button style="height: 28px; padding: 0 11px; border-radius: 7px; border: 1px solid var(--n-6); background: #fff; font-size: 12px; font-weight: 600; color: var(--text-secondary); cursor: pointer;">Отвязать</button>
</div>
<div style="display: flex; align-items: center; gap: 11px; padding: 11px 12px; border: 1px solid var(--n-8); border-radius: var(--radius-lg);">
<span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-webchat-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-webchat);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-webchat);">Web</span></span>
<div style="flex: 1; line-height: 1.3;"><div style="font-size: 13px; font-weight: 600; color: var(--text-body);">Виджет на foxray.ru</div><div style="font-size: 11.5px; color: var(--text-tertiary);">Web Chat · embed foxray-sales</div></div>
<span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--success-text);"><span style="width: 6px; height: 6px; border-radius: 50%; background: var(--success);"></span>OK</span>
<button style="height: 28px; padding: 0 11px; border-radius: 7px; border: 1px solid var(--n-6); background: #fff; font-size: 12px; font-weight: 600; color: var(--text-secondary); cursor: pointer;">Отвязать</button>
</div>
</div>
</section>
<!-- AI-агент (one line) -->
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 18px 20px;">
<div style="font-size: 11px; font-weight: 600; letter-spacing: 0.05em; color: var(--text-tertiary); margin-bottom: 12px;">AI-АГЕНТ</div>
<div style="display: flex; align-items: center; gap: 12px;">
<span style="width: 34px; height: 34px; border-radius: 9px; background: var(--ai-bg); color: var(--ai); display: flex; align-items: center; justify-content: center; flex: none;"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="8" width="16" height="12" rx="2.5"/><path d="M12 8V4.5"/><circle cx="12" cy="3.5" r="1.2"/><circle cx="9" cy="13.5" r="1"/><circle cx="15" cy="13.5" r="1"/></svg></span>
<div style="display: flex; align-items: center; gap: 10px; flex: 1; font-size: 13.5px; min-width: 0;">
<b style="color: var(--text-body);">FoxRay Sales</b>
<span style="color: var(--n-6);">·</span>
<span style="display: inline-flex; align-items: center; gap: 6px; color: var(--success-text);"><span style="width: 7px; height: 7px; border-radius: 50%; background: var(--success);"></span>Активен</span>
<span style="color: var(--n-6);">·</span>
<code style="font-family: var(--font-mono); font-size: 12px; color: var(--text-tertiary);">claude-sonnet-4.6</code>
</div>
<a href="#" style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--primary); flex: none;">Открыть агента<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg></a>
</div>
</section>
<!-- Счётчики -->
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 20px;">
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 14px;"><h3 style="margin: 0; margin-right: auto; font-size: 15px; font-weight: 600; color: var(--text-heading);">Счётчики</h3><a href="#A" style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--primary);">Открыть диалоги канала<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg></a></div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;">
<div style="background: var(--n-10); border: 1px solid var(--n-8); border-radius: var(--radius-xl); padding: 16px 18px;"><div style="font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary); margin-bottom: 8px;">ОТКРЫТЫЕ ДИАЛОГИ</div><div style="font-size: 26px; font-weight: 700; color: var(--text-heading); font-variant-numeric: tabular-nums;">12</div></div>
<div style="background: var(--n-10); border: 1px solid var(--n-8); border-radius: var(--radius-xl); padding: 16px 18px;"><div style="font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary); margin-bottom: 8px;">ПОДКЛЮЧЕНИЯ</div><div style="font-size: 26px; font-weight: 700; color: var(--text-heading); font-variant-numeric: tabular-nums;">2</div></div>
</div>
</section>
</div>
</div>
</section>
<!-- ============ FRAME C — SECTION: POLICY (forbidden flag) ============ -->
<section id="C" style="display: flex; flex-direction: column; gap: 12px;">
<div style="display: flex; align-items: baseline; gap: 12px;">
<span style="font-size: 12px; font-weight: 700; color: #fff; background: var(--text-heading); padding: 3px 9px; border-radius: 6px;">C</span>
<h2 style="margin: 0; font-size: 17px; font-weight: 600; color: var(--text-heading);">Секция «Политика» — запрещённый инвариантом флаг</h2>
<span style="font-size: 12.5px; color: var(--text-tertiary);">пять флагов с пояснением следствия · флаг, запрещённый инвариантом, объясняет причину</span>
</div>
<div style="width: 1180px; background: var(--surface-page); border: 1px solid var(--n-6); border-radius: var(--radius-2xl); box-shadow: var(--shadow-md); overflow: hidden; padding: 22px 24px 28px;">
<div style="display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text-tertiary); margin-bottom: 14px;">
<a href="#A" style="color: var(--text-secondary); font-weight: 500;">Каналы</a><span style="color: var(--n-6);">/</span><span style="color: var(--text-body); font-weight: 600;">Партнёрская линия</span>
</div>
<div style="display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; margin-bottom: 18px;">
<div>
<h1 style="margin: 0 0 5px; font-size: 22px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading);">Партнёрская линия</h1>
<div style="display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--text-tertiary);"><span style="font-family: var(--font-mono);">partners</span><span style="color: var(--n-6);">·</span><span style="display: inline-flex; align-items: center; gap: 4px; padding: 0 7px; border-radius: var(--radius-pill); background: var(--n-9); font-size: 10.5px; font-weight: 600;">Без отдела</span><span style="color: var(--n-6);">·</span>— непродуктовый</div>
</div>
<span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--success-text); background: var(--success-bg); border: 1px solid var(--success-border); padding: 5px 11px; border-radius: var(--radius-pill);"><span style="width: 7px; height: 7px; border-radius: 50%; background: var(--success);"></span>Активен</span>
</div>
<div style="display: grid; grid-template-columns: 1fr 320px; gap: 18px; align-items: start;">
<!-- flags -->
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 8px 20px 12px;">
<div style="font-size: 11px; font-weight: 600; letter-spacing: 0.05em; color: var(--text-tertiary); padding: 12px 0 4px;">СЕКЦИЯ «ПОЛИТИКА» · 5 ФЛАГОВ</div>
<!-- P3 requires identity — locked off -->
<div style="display: flex; align-items: flex-start; gap: 14px; padding: 16px 0; border-top: 1px solid var(--n-9);">
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--n-8); position: relative; margin-top: 1px;"><span style="position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: var(--n-5);"></span></span>
<div style="flex: 1;">
<div style="display: flex; align-items: center; gap: 8px;"><span style="font-size: 13.5px; font-weight: 600; color: var(--text-tertiary);">Обязательная продуктовая идентичность</span><span style="display: inline-flex; align-items: center; gap: 4px; font-size: 10.5px; font-weight: 600; color: var(--warning-text); background: var(--warning-bg); border: 1px solid var(--warning-border); padding: 1px 7px; border-radius: var(--radius-pill);"><svg viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>Недоступно</span></div>
<div style="font-size: 12px; color: var(--text-tertiary); margin-top: 3px; line-height: 1.5;">Требует продукта <b>(инвариант P3)</b>. Пользователь должен быть авторизован как владелец продукта. Назначьте продукт каналу, чтобы включить.</div>
</div>
</div>
<!-- anonymous — on -->
<div style="display: flex; align-items: flex-start; gap: 14px; padding: 16px 0; border-top: 1px solid var(--n-9);">
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--primary); position: relative; margin-top: 1px;"><span style="position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-xs);"></span></span>
<div style="flex: 1;">
<div style="font-size: 13.5px; font-weight: 600; color: var(--text-body);">Анонимные сессии</div>
<div style="font-size: 12px; color: var(--text-tertiary); margin-top: 3px; line-height: 1.5;">Разрешает диалоги без идентификации пользователя — партнёр может написать без входа.</div>
</div>
</div>
<!-- self-reported — on -->
<div style="display: flex; align-items: flex-start; gap: 14px; padding: 16px 0; border-top: 1px solid var(--n-9);">
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--primary); position: relative; margin-top: 1px;"><span style="position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-xs);"></span></span>
<div style="flex: 1;">
<div style="font-size: 13.5px; font-weight: 600; color: var(--text-body);">Самозаявленный контакт</div>
<div style="font-size: 12px; color: var(--text-tertiary); margin-top: 3px; line-height: 1.5;">Позволяет пользователю указать email или телефон вручную для обратной связи.</div>
</div>
</div>
<!-- P2 attribution — locked off -->
<div style="display: flex; align-items: flex-start; gap: 14px; padding: 16px 0; border-top: 1px solid var(--n-9);">
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--n-8); position: relative; margin-top: 1px;"><span style="position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: var(--n-5);"></span></span>
<div style="flex: 1;">
<div style="display: flex; align-items: center; gap: 8px;"><span style="font-size: 13.5px; font-weight: 600; color: var(--text-tertiary);">Attribution продаж</span><span style="display: inline-flex; align-items: center; gap: 4px; font-size: 10.5px; font-weight: 600; color: var(--warning-text); background: var(--warning-bg); border: 1px solid var(--warning-border); padding: 1px 7px; border-radius: var(--radius-pill);"><svg viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>Недоступно</span></div>
<div style="font-size: 12px; color: var(--text-tertiary); margin-top: 3px; line-height: 1.5;">Attribution недоступна непродуктовому каналу <b>(инвариант P2)</b>. Свяжите канал с продуктом, чтобы включить.</div>
</div>
</div>
<!-- P1 checkout — locked off (KEY) -->
<div style="display: flex; align-items: flex-start; gap: 14px; padding: 16px 0; background: var(--warning-bg-strong); margin: 0 -20px; padding-left: 20px; padding-right: 20px; border-radius: var(--radius-lg);">
<span style="flex: none; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--n-8); position: relative; margin-top: 1px;"><span style="position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: var(--n-5);"></span></span>
<div style="flex: 1;">
<div style="display: flex; align-items: center; gap: 8px;"><span style="font-size: 13.5px; font-weight: 600; color: var(--text-tertiary);">Коммерческие действия (checkout)</span><span style="display: inline-flex; align-items: center; gap: 4px; font-size: 10.5px; font-weight: 600; color: var(--warning-text); background: #fff; border: 1px solid var(--warning-border); padding: 1px 7px; border-radius: var(--radius-pill);"><svg viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>Запрещено инвариантом</span></div>
<div style="font-size: 12px; color: var(--warning-text); margin-top: 3px; line-height: 1.5;">Коммерческие действия недоступны непродуктовому каналу <b>(инвариант P1)</b>. Флаг не будет сохранён включённым, пока каналу не назначен продукт — причина показана, а не игнорируется молча.</div>
<a href="#B" style="display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600; color: var(--primary); margin-top: 8px;">Назначить продукт<svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg></a>
</div>
</div>
</section>
<!-- side note -->
<div style="display: flex; flex-direction: column; gap: 16px;">
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 18px;">
<h4 style="margin: 0 0 12px; font-size: 13px; font-weight: 600; color: var(--text-heading);">Контекст политики</h4>
<div style="display: flex; flex-direction: column; gap: 10px; font-size: 12.5px;">
<div style="display: flex; justify-content: space-between;"><span style="color: var(--text-tertiary);">Продукт</span><span style="color: var(--text-tertiary);">— непродуктовый</span></div>
<div style="display: flex; justify-content: space-between;"><span style="color: var(--text-tertiary);">Отдел</span><span style="color: var(--text-body);">Без отдела</span></div>
<div style="display: flex; justify-content: space-between;"><span style="color: var(--text-tertiary);">Пресет</span><span style="color: var(--text-body);">Свой (CUSTOM)</span></div>
</div>
</section>
<section style="background: var(--primary-bg); border: 1px solid var(--primary-border); border-radius: var(--radius-2xl); padding: 16px 18px;">
<div style="font-size: 12.5px; color: #0958d9; line-height: 1.55;">Инварианты проверяются по итоговому состоянию: частичное сохранение запрещено. Чтобы включить коммерческие флаги, сначала назначьте продукт в секции «Назначение».</div>
</section>
</div>
</div>
</div>
</section>
<!-- ============ FRAME D — SECTION: CONNECTIONS + TRANSFER ============ -->
<section id="D" style="display: flex; flex-direction: column; gap: 12px;">
<div style="display: flex; align-items: baseline; gap: 12px;">
<span style="font-size: 12px; font-weight: 700; color: #fff; background: var(--text-heading); padding: 3px 9px; border-radius: 6px;">D</span>
<h2 style="margin: 0; font-size: 17px; font-weight: 600; color: var(--text-heading);">Секция «Подключения» — привязка и перенос</h2>
<span style="font-size: 12.5px; color: var(--text-tertiary);">список подключений канала · привязка · перенос между каналами с явным подтверждением (force)</span>
</div>
<div style="width: 1180px; height: 620px; position: relative; background: var(--surface-page); border: 1px solid var(--n-6); border-radius: var(--radius-2xl); box-shadow: var(--shadow-md); overflow: hidden; padding: 22px 24px 28px;">
<div style="display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text-tertiary); margin-bottom: 14px;">
<a href="#A" style="color: var(--text-secondary); font-weight: 500;">Каналы</a><span style="color: var(--n-6);">/</span><span style="color: var(--text-body); font-weight: 600;">FoxRay — продажи</span>
</div>
<div style="display: flex; align-items: center; justify-content: space-between; gap: 20px; margin-bottom: 18px;">
<h1 style="margin: 0; font-size: 22px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading);">FoxRay — продажи</h1>
</div>
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 20px;">
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 12px;"><h3 style="margin: 0; margin-right: auto; font-size: 15px; font-weight: 600; color: var(--text-heading);">Подключения</h3><button style="display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px; border-radius: var(--radius-lg); border: 1px solid transparent; background: var(--primary); color: #fff; font-size: 12.5px; font-weight: 600; box-shadow: var(--shadow-primary); cursor: pointer;"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Привязать подключение</button></div>
<table style="width: 100%; border-collapse: collapse; font-size: 13px;">
<thead>
<tr style="text-align: left;">
<th style="padding: 8px 12px 8px 0; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary);">ПОДКЛЮЧЕНИЕ</th>
<th style="padding: 8px 12px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary);">ПРОВАЙДЕР</th>
<th style="padding: 8px 12px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--text-tertiary);">СТАТУС</th>
<th style="padding: 8px 0 8px 12px; width: 110px; text-align: right;"></th>
</tr>
</thead>
<tbody>
<tr style="border-top: 1px solid var(--n-8);">
<td style="padding: 12px 12px 12px 0;"><div style="font-weight: 600; color: var(--text-body);">FoxRay Sales Bot</div><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;">@foxray_sales_bot</div></td>
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-telegram-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-telegram);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-telegram);">TG</span></span></td>
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--success-text);"><span style="width: 7px; height: 7px; border-radius: 50%; background: var(--success);"></span>OK</span></td>
<td style="padding: 12px 0 12px 12px; text-align: right;"><button style="height: 30px; padding: 0 12px; border-radius: 8px; border: 1px solid var(--n-6); background: #fff; font-size: 12.5px; font-weight: 600; color: var(--text-secondary); cursor: pointer;">Отвязать</button></td>
</tr>
<tr style="border-top: 1px solid var(--n-8);">
<td style="padding: 12px 12px 12px 0;"><div style="font-weight: 600; color: var(--text-body);">Виджет на foxray.ru</div><div style="font-size: 12px; color: var(--text-tertiary); margin-top: 2px;">embed foxray-sales</div></td>
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-webchat-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-webchat);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-webchat);">Web</span></span></td>
<td style="padding: 12px;"><span style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--success-text);"><span style="width: 7px; height: 7px; border-radius: 50%; background: var(--success);"></span>OK</span></td>
<td style="padding: 12px 0 12px 12px; text-align: right;"><button style="height: 30px; padding: 0 12px; border-radius: 8px; border: 1px solid var(--n-6); background: #fff; font-size: 12.5px; font-weight: 600; color: var(--text-secondary); cursor: pointer;">Отвязать</button></td>
</tr>
</tbody>
</table>
</section>
<!-- overlay + transfer modal -->
<div style="position: absolute; inset: 0; background: rgba(15,20,30,0.28);"></div>
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); width: 560px; background: #fff; border-radius: var(--radius-4xl); box-shadow: var(--shadow-lg); overflow: hidden;">
<div style="padding: 22px 24px 18px; border-bottom: 1px solid var(--n-8); display: flex; gap: 14px;">
<span style="flex: none; width: 40px; height: 40px; border-radius: 10px; background: var(--warning-bg); color: var(--warning-text); display: flex; align-items: center; justify-content: center;"><svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M17 1l4 4-4 4"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><path d="M7 23l-4-4 4-4"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg></span>
<div>
<h3 style="margin: 0 0 5px; font-size: 16px; font-weight: 600; color: var(--text-heading);">Перенести подключение в этот канал?</h3>
<p style="margin: 0; font-size: 13px; line-height: 1.55; color: var(--text-secondary);">Подключение <b>«FirePage MAX Bot»</b> уже привязано к каналу <b>«FirePage — продажи»</b>. Подключение принадлежит ровно одному каналу — перенос отвяжет его от прежнего.</p>
</div>
</div>
<div style="padding: 16px 24px;">
<div style="display: flex; align-items: center; gap: 12px; padding: 12px 14px; border: 1px solid var(--n-8); border-radius: var(--radius-lg); background: var(--n-10);">
<span style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 5px; background: var(--channel-max-bg);"><span style="width: 5px; height: 5px; border-radius: 50%; background: var(--channel-max);"></span><span style="font-size: 10.5px; font-weight: 600; color: var(--channel-max);">MAX</span></span>
<div style="flex: 1; display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--text-secondary);"><span style="color: var(--text-tertiary);">FirePage — продажи</span><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="var(--primary)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg><b style="color: var(--text-body);">FoxRay — продажи</b></div>
</div>
<p style="margin: 12px 2px 0; font-size: 12px; color: var(--text-tertiary); line-height: 1.5;">Существующие диалоги остаются в прежнем канале (<span style="font-family: var(--font-mono);">Conversation.connection</span> — PROTECT). Действие пишется в аудит как перенос.</p>
</div>
<div style="display: flex; align-items: center; gap: 10px; padding: 14px 24px; border-top: 1px solid var(--n-8);">
<span style="flex: 1;"></span>
<button style="height: 36px; padding: 0 16px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; font-size: 13px; font-weight: 600; color: var(--text-body); cursor: pointer;">Отмена</button>
<button style="height: 36px; padding: 0 16px; border-radius: var(--radius-lg); border: 1px solid transparent; background: var(--primary); color: #fff; font-size: 13px; font-weight: 600; box-shadow: var(--shadow-primary); cursor: pointer;">Перенести подключение</button>
</div>
</div>
</div>
</section>
<!-- ============ FRAME E — CREATE WIZARD (three steps) ============ -->
<section id="E" style="display: flex; flex-direction: column; gap: 12px;">
<div style="display: flex; align-items: baseline; gap: 12px;">
<span style="font-size: 12px; font-weight: 700; color: #fff; background: var(--text-heading); padding: 3px 9px; border-radius: 6px;">E</span>
<h2 style="margin: 0; font-size: 17px; font-weight: 600; color: var(--text-heading);">Мастер создания канала — три шага</h2>
<span style="font-size: 12.5px; color: var(--text-tertiary);">Канал · Назначение · Подключения · финальный экран операторского канала</span>
</div>
<div style="width: 1180px; background: var(--surface-page); border: 1px solid var(--n-6); border-radius: var(--radius-2xl); box-shadow: var(--shadow-md); overflow: hidden; padding: 24px 28px 26px;">
<h1 style="margin: 0 0 4px; font-size: 22px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading);">Создание канала</h1>
<p style="margin: 0 0 20px; font-size: 13.5px; color: var(--text-secondary);">Три шага. Настройка агента и знаний в мастер не входит — агент создаётся отдельным действием в разделе AI. Канал создаётся по завершении шага 2.</p>
<!-- stepper: 3 steps, all done -->
<div style="display: flex; align-items: center; gap: 0; margin-bottom: 24px; max-width: 720px;">
<div style="display: flex; align-items: center; gap: 10px;"><span style="width: 26px; height: 26px; border-radius: 50%; background: var(--success); color: #fff; display: flex; align-items: center; justify-content: center; flex: none;"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span><span style="font-size: 13px; font-weight: 600; color: var(--text-body);">Канал</span></div>
<div style="flex: 1; height: 2px; background: var(--success); margin: 0 12px;"></div>
<div style="display: flex; align-items: center; gap: 10px;"><span style="width: 26px; height: 26px; border-radius: 50%; background: var(--success); color: #fff; display: flex; align-items: center; justify-content: center; flex: none;"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span><span style="font-size: 13px; font-weight: 600; color: var(--text-body);">Назначение</span></div>
<div style="flex: 1; height: 2px; background: var(--success); margin: 0 12px;"></div>
<div style="display: flex; align-items: center; gap: 10px;"><span style="width: 26px; height: 26px; border-radius: 50%; background: var(--success); color: #fff; display: flex; align-items: center; justify-content: center; flex: none;"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span><span style="font-size: 13px; font-weight: 600; color: var(--text-body);">Подключения</span></div>
</div>
<!-- final screen -->
<div style="display: grid; grid-template-columns: 1fr 340px; gap: 18px; align-items: start;">
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 32px 28px; text-align: center;">
<div style="width: 52px; height: 52px; border-radius: 14px; background: var(--success-bg); color: var(--success-text); display: flex; align-items: center; justify-content: center; margin: 0 auto 16px;"><svg viewBox="0 0 24 24" width="28" height="28" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></div>
<h3 style="margin: 0 0 6px; font-size: 18px; font-weight: 700; color: var(--text-heading);">Канал создан</h3>
<p style="margin: 0 auto 20px; font-size: 13.5px; color: var(--text-secondary); line-height: 1.55; max-width: 440px;"><b style="color: var(--text-body);">Партнёрская линия</b> — операторский канал: AI-агента нет, диалоги ведут операторы. Канал принимает подключения, диалоги, заказы и attribution.</p>
<div style="display: flex; gap: 10px; justify-content: center;">
<a href="#B" style="display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 16px; border-radius: var(--radius-lg); border: 1px solid transparent; background: var(--primary); color: #fff; font-size: 13px; font-weight: 600; box-shadow: var(--shadow-primary);">Открыть карточку канала</a>
<a href="#A" style="display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 16px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; font-size: 13px; font-weight: 600; color: var(--text-body);">К списку каналов</a>
</div>
</section>
<div style="display: flex; flex-direction: column; gap: 16px;">
<section style="background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 18px;">
<h4 style="margin: 0 0 12px; font-size: 13px; font-weight: 600; color: var(--text-heading);">Сводка канала</h4>
<div style="display: flex; flex-direction: column; gap: 10px; font-size: 12.5px;">
<div style="display: flex; justify-content: space-between;"><span style="color: var(--text-tertiary);">Название</span><span style="color: var(--text-body); font-weight: 500;">Партнёрская линия</span></div>
<div style="display: flex; justify-content: space-between;"><span style="color: var(--text-tertiary);">Код</span><span style="color: var(--text-body); font-family: var(--font-mono);">partners</span></div>
<div style="display: flex; justify-content: space-between;"><span style="color: var(--text-tertiary);">Отдел</span><span style="color: var(--text-body);">Без отдела</span></div>
<div style="display: flex; justify-content: space-between;"><span style="color: var(--text-tertiary);">Продукт</span><span style="color: var(--text-tertiary);">— непродуктовый</span></div>
<div style="display: flex; justify-content: space-between;"><span style="color: var(--text-tertiary);">Подключения</span><span style="color: var(--text-body);">TG · 1</span></div>
</div>
</section>
<section style="background: var(--ai-bg); border: 1px solid #e4d4fb; border-radius: var(--radius-2xl); padding: 16px 18px;">
<div style="font-size: 12.5px; color: var(--ai); line-height: 1.55; margin-bottom: 12px;"><b>Нужен AI-агент?</b> Создайте его отдельным действием в разделе AI — он подключится к этому каналу.</div>
<a href="#A" style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--ai);">Перейти в раздел AI<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg></a>
</section>
</div>
</div>
</div>
</section>
<!-- ============ FRAME S — STATES ============ -->
<section id="S" style="display: flex; flex-direction: column; gap: 12px;">
<div style="display: flex; align-items: baseline; gap: 12px;">
<span style="font-size: 12px; font-weight: 700; color: #fff; background: var(--text-heading); padding: 3px 9px; border-radius: 6px;">S</span>
<h2 style="margin: 0; font-size: 17px; font-weight: 600; color: var(--text-heading);">Служебные состояния</h2>
<span style="font-size: 12.5px; color: var(--text-tertiary);">пустой список · канал без агента · архивный канал · ограниченный доступ · конфликт удаления</span>
</div>
<div style="display: flex; gap: 18px; flex-wrap: wrap;">
<!-- empty list -->
<div style="width: 372px; background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 40px 24px; text-align: center;">
<div style="width: 46px; height: 46px; border-radius: 12px; background: var(--primary-bg); color: var(--primary); display: flex; align-items: center; justify-content: center; margin: 0 auto 14px;"><svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></svg></div>
<div style="font-size: 14px; font-weight: 600; color: var(--text-body); margin-bottom: 5px;">Создайте первый канал</div>
<p style="margin: 0 0 16px; font-size: 12.5px; color: var(--text-tertiary); line-height: 1.5;">Канал маршрутизирует диалоги от подключений к отделу, продукту и — при необходимости — к AI-агенту.</p>
<button style="height: 34px; padding: 0 14px; border-radius: var(--radius-lg); border: 1px solid transparent; background: var(--primary); color: #fff; font-size: 12.5px; font-weight: 600; box-shadow: var(--shadow-primary); cursor: pointer;">Создать канал</button>
</div>
<!-- channel without agent -->
<div style="width: 372px; background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 24px;">
<div style="font-size: 11px; font-weight: 600; letter-spacing: 0.05em; color: var(--text-tertiary); margin-bottom: 14px;">СЕКЦИЯ «AI-АГЕНТ» · КАНАЛ БЕЗ АГЕНТА</div>
<div style="text-align: center; padding: 20px 8px;">
<div style="width: 44px; height: 44px; border-radius: 11px; background: var(--ai-bg); color: var(--ai); display: flex; align-items: center; justify-content: center; margin: 0 auto 12px;"><svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="8" width="16" height="12" rx="2.5"/><path d="M12 8V4.5"/><circle cx="12" cy="3.5" r="1.2"/><circle cx="9" cy="13.5" r="1"/><circle cx="15" cy="13.5" r="1"/></svg></div>
<div style="font-size: 14px; font-weight: 600; color: var(--text-body); margin-bottom: 5px;">Агента нет, канал ведут операторы</div>
<p style="margin: 0 0 16px; font-size: 12.5px; color: var(--text-tertiary); line-height: 1.5;">Валидное состояние канала. Агент создаётся отдельным действием в разделе AI.</p>
<a href="#A" style="display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--primary);">Создать агента в разделе AI<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg></a>
</div>
</div>
<!-- archived channel -->
<div style="width: 372px; background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 24px;">
<div style="font-size: 11px; font-weight: 600; letter-spacing: 0.05em; color: var(--text-tertiary); margin-bottom: 12px;">АРХИВНЫЙ КАНАЛ</div>
<div style="display: flex; align-items: center; gap: 12px; padding: 14px; border: 1px solid var(--n-8); border-radius: var(--radius-lg); background: #fcfcfc;">
<div style="flex: 1; line-height: 1.35;"><div style="font-size: 13.5px; font-weight: 600; color: var(--text-tertiary);">FoxRay — вебинары</div><div style="font-size: 11.5px; color: var(--n-5); font-family: var(--font-mono);">foxray-webinars</div></div>
<span style="display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 600; color: var(--text-tertiary); background: var(--n-9); padding: 3px 9px; border-radius: var(--radius-pill);"><span style="width: 7px; height: 7px; border-radius: 50%; border: 1.5px solid var(--n-5);"></span>Архивный</span>
</div>
<p style="margin: 12px 0 14px; font-size: 12px; color: var(--text-tertiary); line-height: 1.5;">Не принимает новые диалоги и не выбирается при привязке подключения. История диалогов сохранена и доступна.</p>
<button style="height: 32px; padding: 0 14px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; font-size: 12.5px; font-weight: 600; color: var(--text-body); cursor: pointer;">Активировать</button>
</div>
<!-- restricted access -->
<div style="width: 372px; background: #fff; border: 1px solid var(--n-8); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); padding: 40px 24px; text-align: center;">
<div style="width: 46px; height: 46px; border-radius: 12px; background: var(--warning-bg); color: var(--warning-text); display: flex; align-items: center; justify-content: center; margin: 0 auto 14px;"><svg viewBox="0 0 24 24" width="23" height="23" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg></div>
<div style="font-size: 14px; font-weight: 600; color: var(--text-body); margin-bottom: 5px;">Доступ ограничен отделом</div>
<p style="margin: 0; font-size: 12.5px; color: var(--text-tertiary); line-height: 1.5;">Ваш scope <span style="font-family: var(--font-mono);">channels.view</span> охватывает отдел «Поддержка». Каналы других отделов и канал без отдела не показываются; счётчики фильтров считаются по видимому подмножеству.</p>
</div>
<!-- delete conflict -->
<div style="width: 566px; background: #fff; border: 1px solid var(--error-border); border-radius: var(--radius-2xl); box-shadow: var(--shadow-sm); overflow: hidden;">
<div style="padding: 20px 22px 16px; display: flex; gap: 14px; border-bottom: 1px solid var(--n-8);">
<span style="flex: none; width: 40px; height: 40px; border-radius: 10px; background: var(--error-bg); color: var(--error-text); display: flex; align-items: center; justify-content: center;"><svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2m3 0-1 14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2L4 6"/></svg></span>
<div><h3 style="margin: 0 0 4px; font-size: 15px; font-weight: 600; color: var(--text-heading);">Канал нельзя удалить</h3><p style="margin: 0; font-size: 12.5px; color: var(--text-secondary); line-height: 1.5;">Есть связанные записи. Вместо удаления используйте деактивацию — история сохранится.</p></div>
</div>
<div style="padding: 16px 22px;">
<div style="font-size: 11px; font-weight: 600; letter-spacing: 0.05em; color: var(--text-tertiary); margin-bottom: 10px;">БЛОКИРУЮЩИЕ СВЯЗИ</div>
<div style="display: flex; flex-direction: column; gap: 8px;">
<div style="display: flex; align-items: center; justify-content: space-between; padding: 9px 12px; border: 1px solid var(--n-8); border-radius: var(--radius-md); font-size: 12.5px;"><span style="color: var(--text-body);">Диалоги</span><span style="font-weight: 600; color: var(--text-body); font-variant-numeric: tabular-nums;">143</span></div>
<div style="display: flex; align-items: center; justify-content: space-between; padding: 9px 12px; border: 1px solid var(--n-8); border-radius: var(--radius-md); font-size: 12.5px;"><span style="color: var(--text-body);">Подключения</span><span style="font-weight: 600; color: var(--text-body); font-variant-numeric: tabular-nums;">1</span></div>
<div style="display: flex; align-items: center; justify-content: space-between; padding: 9px 12px; border: 1px solid var(--n-8); border-radius: var(--radius-md); font-size: 12.5px;"><span style="color: var(--text-body);">Агент</span><span style="font-weight: 600; color: var(--text-body); font-variant-numeric: tabular-nums;">1</span></div>
</div>
</div>
<div style="display: flex; align-items: center; gap: 10px; padding: 14px 22px; border-top: 1px solid var(--n-8);">
<span style="flex: 1;"></span>
<button style="height: 36px; padding: 0 16px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; font-size: 13px; font-weight: 600; color: var(--text-body); cursor: pointer;">Закрыть</button>
<button style="height: 36px; padding: 0 16px; border-radius: var(--radius-lg); border: 1px solid var(--n-6); background: #fff; font-size: 13px; font-weight: 600; color: var(--warning-text); cursor: pointer;">Деактивировать вместо удаления</button>
</div>
</div>
</div>
</section>
</div>
</x-dc>
</body>
</html>