# SKN Cutline — иконки админки

Собственный векторный набор админки. Иконки — контурные, с мягкими соединениями и короткими геометрическими штрихами; маленькие срезы углов повторяют характер контролов. Цвет наследуется от элемента. Эмоджи, изображения с встроенным фоном и разные стили иконок в административном интерфейсе не используются.

## Контракт

- Исходник: `manager/assets/admin-icons.svg` — один SVG-спрайт с `<symbol id="…">`.
- PHP: `manager/ui-icons.php`, подключать через `require_once`.
- Сетка — 24×24; основной контур — 1,65 px; концы и соединения — круглые.
- Основной видимый размер — 20 px; для компактных элементов допустимо 16 или 18 px через CSS. Не менять толщину контура для отдельных разделов.
- Все символы используют `currentColor`, без растровых частей, встроенных подписей, шрифтовых глифов и собственного фона.
- `adminIcon('search')` возвращает декоративный SVG с `aria-hidden="true"` и `focusable="false"`.
- `adminIcon('search', 'additional-class')` добавляет экранированный класс. Неизвестное имя возвращает `info`.
- Кликабельность задаёт внешний `<button>` или `<a>`. Иконка сама не является интерактивным элементом. Кнопка только с иконкой обязательно получает `aria-label` и `title`; видимая площадь нажатия больше самого контура.
- `adminIconText($plainText)` — вспомогательный миграционный метод для статических подписей UI: экранирует весь текст, заменяет эмоджи на SVG. Его нельзя применять к HTML, содержимому новостей, пользовательскому вводу, значениям полей или сохранённым данным.
- `adminIconNameForLegacyGlyph($glyph)` возвращает семантическое имя для устаревшего глифа; вариационные селекторы не влияют на выбор.
- `adminIconLegacyMap()` возвращает карту глифов для JSON-экспорта клиентскому слою UI. При экспорте использовать `JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT`.

Пример:

```php
<button type="button" class="btn btn-icon" aria-label="Найти новости" title="Найти новости">
    <?= adminIcon('search') ?>
</button>
<button type="submit" class="btn btn-primary"><?= adminIcon('save') ?><span>Сохранить</span></button>
```

## Семантика набора

| Область | Имена |
| --- | --- |
| Действия | `search`, `plus`, `minus`, `edit`, `pen`, `rewrite`, `trash`, `save`, `refresh`, `copy`, `archive` |
| Перемещение | `back`, `arrow-left`, `arrow-right`, `arrow-up`, `arrow-down`, `chevron-down`, `chevron-up`, `chevron-left`, `chevron-right`, `external` (также `external-link`), `logout` |
| Состояния | `check`, `check-circle`, `close`, `warning`, `info`, `help`, `lock`, `unlock`, `eye`, `eye-off` |
| Контент | `news`, `file`, `book`, `image`, `video`, `film`, `meme`, `banner`, `folder`, `category`, `tag`, `link` |
| Редакция и подкаст | `mic`, `sparkles`, `robot`, `queue`, `disk`, `broadcast`, `headphones`, `play`, `pause` |
| Разделы и управление | `dashboard`, `settings`, `source`, `plug`, `inbox`, `download`, `upload`, `compass`, `chart`, `list`, `menu`, `filter`, `more`, `grip` |
| Коммуникация | `user`, `users`, `mail`, `chat`, `log` |
| Служебные | `clock`, `calendar`, `history`, `sun`, `moon`, `globe`, `bolt`, `heart` |

## Добавление иконки

1. Выбрать короткое английское имя по назначению действия, а не внешнему виду.
2. Добавить `<symbol>` в спрайт с `viewBox="0 0 24 24"`; держать основной рисунок внутри 2–22 px.
3. Унаследовать `stroke`, `fill` и цвет. Предпочитать 2–5 ясных линий мелким деталям. Внутренние элементы должны читаться при 16 px.
4. Включить имя в `adminIconNames()` и соответствующую строку таблицы выше.
5. Если заменяется старый глиф UI, добавить его в карту `adminIconNameForLegacyGlyph()`.
6. Обновить версию спрайта в `adminIcon()` при публикации, чтобы браузер забрал новый файл.
7. Проверить на светлой и тёмной поверхности, в 16/20/24 px, с клавиатурным фокусом на родительской кнопке.

Границы: набор предназначен только для админки. Публичный дизайн-код развивается отдельно.
