# Сервисный портал AegisOne — Единый стиль

> Этот документ ОБЯЗАН прочитать каждый AI-агент перед изменением шаблонов/CSS сервисного портала.

---

## 1. Структура страницы

Каждая страница наследует `page.html` и реализует блок `page_content`.

### Порядок элементов в правой части (main):

```
page.html main-header:
  left:   h1 (заголовок) + breadcrumb
  right:  page_actions block + дата {{ now }}

page_content:
  1. div.card                          — основной контент
     ├── div.card-header               — заголовок + кнопка действия
     ├── div.filter-bar                — фильтры (если нужны)
     └── div.table-wrap > table        — таблица данных

  2. div.modal-overlay#modal-xxx       — модалка создания/редактирования
  3. div.modal-overlay#confirm-delete-xxx — модалка подтверждения удаления
```

### Card Header:

```html
<div class="card-header">
    <h2>Название секции</h2>
    <button class="btn btn-primary btn-sm" onclick="openModal()">+ Действие</button>
</div>
```

---

## 2. Модалки

### Единые CSS-классы

| Класс | Назначение |
|-------|-----------|
| `.modal-overlay` | Затемнённый фон (position: fixed, z-index: 200) |
| `.modal-overlay.open` | Показать модалку (display: flex) |
| `.modal` | Контейнер модалки (фон, рамка, скругление) |
| `.modal-close` | Кнопка закрытия (✕) в правом верхнем углу |
| `.form-actions` | Блок кнопок внизу модалки (display: flex, gap: 10px) |

### Открытие/закрытие

```javascript
// Открыть
document.getElementById('modal-xxx').classList.add('open');

// Закрыть
document.getElementById('modal-xxx').classList.remove('open');

// Или изнутри кнопки
this.closest('.modal-overlay').classList.remove('open');
```

**ЗАПРЕЩЕНО:** использовать `style.display = 'flex'` / `style.display = 'none'`

### Модалка создания/редактирования (стандарт)

```html
<div class="modal-overlay" id="modal-xxx">
    <div class="modal">
        <button type="button" class="modal-close" 
            onclick="this.closest('.modal-overlay').classList.remove('open')">✕</button>
        <h2>Название</h2>
        <form method="post" action="/service/xxx/create">
            <div class="form-row">
                <div class="form-group"><label>Поле</label><input type="text" name="field"></div>
            </div>
            <div class="form-actions">
                <button type="submit" class="btn btn-primary">Сохранить</button>
                <button type="button" class="btn" 
                    onclick="this.closest('.modal-overlay').classList.remove('open')">Отмена</button>
            </div>
        </form>
    </div>
</div>
```

### Модалка подтверждения удаления (единый шаблон)

**ЗАПРЕЩЕНЫ:** `confirm()`, `alert()`, `prompt()` — только кастомные модалки!

```html
<div class="modal-overlay" id="confirm-delete-xxx">
    <div class="modal" style="max-width:420px;">
        <h2 style="font-size:16px;margin-bottom:8px;">Удалить [объект]?</h2>
        <p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
            <strong id="delete-xxx-name"></strong> будет удалён навсегда. 
            Это действие нельзя отменить.
        </p>
        <div class="form-actions" style="justify-content:flex-end;">
            <button type="button" class="btn btn-danger" onclick="confirmDeleteXxx()">Удалить</button>
            <button type="button" class="btn" onclick="closeConfirmDeleteXxx()">Отмена</button>
        </div>
    </div>
</div>
```

### Порядок кнопок в модалках

```
[ Действие (btn-danger / btn-primary) ]  [ Отмена (btn) ]
         слева                                   справа
```

---

## 3. Кнопки

### Иконки

| Иконка | Назначение | CSS-класс |
|--------|-----------|-----------|
| `+` | Создание (перед текстом) | `btn btn-primary btn-sm` |
| `✎` | Редактирование | `btn btn-secondary btn-sm` |
| `✕` | Удаление | `btn btn-danger btn-sm` |
| `✓` | Завершение/включение | `btn btn-success btn-sm` |
| `🗑` | Удаление (только в карточках) | `btn btn-danger btn-sm` |

### CSS-классы кнопок

| Класс | Назначение |
|-------|-----------|
| `.btn` | Базовая кнопка |
| `.btn-primary` | Основное действие (синий) |
| `.btn-secondary` | Вторичное действие (серый) |
| `.btn-danger` | Удаление/опасное действие (красный) |
| `.btn-success` | Успех/завершение (зелёный) |
| `.btn-warning` | Предупреждение (жёлтый) |
| `.btn-sm` | Маленький размер |

### Таблицы — колонка действий

```html
<th class="actions"></th>
<td class="actions">
    <button class="btn btn-secondary btn-sm" onclick="editXxx(...)" title="Редактировать">✎</button>
    <button class="btn btn-danger btn-sm" onclick="openConfirmDeleteXxx(...)" title="Удалить">✕</button>
</td>
```

---

## 4. Уведомления

### Показ уведомлений

```javascript
showNotification('Текст уведомления', 'success');  // зелёное
showNotification('Текст уведомления', 'error');     // красное
showNotification('Текст уведомления', 'warning');   // жёлтое
showNotification('Текст уведомления', 'info');       // синее
```

**ЗАПРЕЩЕНЫ:** `alert()`, `prompt()`, `confirm()` — только `showNotification()` и кастомные модалки!

---

## 5. Фильтры

```html
<div class="filter-bar">
    <input type="text" id="search-input" placeholder="Поиск..." oninput="filterItems()">
    <select id="status-filter" onchange="filterItems()" class="filter-select">
        <option value="">Все статусы</option>
    </select>
</div>
```

---

## 6. Таблицы

```html
<div class="table-wrap">
    <table>
        <thead>
            <tr>
                <th>Колонка 1</th>
                <th>Колонка 2</th>
                <th class="actions"></th>
            </tr>
        </thead>
        <tbody>
            {% for item in items %}
            <tr>
                <td>{{ item.field }}</td>
                <td>{{ item.field2 }}</td>
                <td class="actions">
                    <button class="btn btn-secondary btn-sm" onclick="editXxx(...)">✎</button>
                    <button class="btn btn-danger btn-sm" onclick="openConfirmDeleteXxx(...)">✕</button>
                </td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
</div>
```

---

## 7. Страницы с JS-рендерингом

Для страниц, где данные загружаются через `fetch()` (bot_consent, bot_dialogues, bot_kb, bot_tickets, bot_unknown, charts):

- Таблица рендерится через `renderXxx(data)` в JavaScript
- Фильтрация через `filterXxx()` на клиенте
- Модалки подтверждения удаления — те же HTML-шаблоны

---

## 8. Чек-лист перед коммитом

- [ ] Нет `confirm()`, `alert()`, `prompt()` в коде
- [ ] Модалки открываются через `classList.add('open')`
- [ ] Модалки закрываются через `classList.remove('open')`
- [ ] Кнопки удаления: `✕` (btn-danger)
- [ ] Кнопки редактирования: `✎` (btn-secondary)
- [ ] Порядок кнопок в модалках: Действие → Отмена
- [ ] Уведомления через `showNotification()`
- [ ] Таблицы используют `sort-table.js` (автоматически через base.html)
- [ ] Number input без спиннеров (CSS в service.css)
- [ ] CSS-классы модалок: `.modal-overlay` / `.modal`
