diff --git a/.env.example b/.env.example
index 73d19c1..8237c62 100644
--- a/.env.example
+++ b/.env.example
@@ -54,3 +54,10 @@ YOOKASSA_SECRET_KEY=
PLATEGA_ENABLED=false
PLATEGA_MERCHANT_ID=
PLATEGA_SECRET=
+
+# Device limit (HWID) — off by default. Requires the VPN client app to send an
+# x-hwid header on subscription fetch (Happ/v2rayTun-class apps do this); clients
+# that don't send it get refused once enabled, so only flip this on if your users'
+# apps actually support it.
+HWID_LIMIT_ENABLED=false
+HWID_FALLBACK_LIMIT=3
diff --git a/README.md b/README.md
index 9be6e18..962c553 100644
--- a/README.md
+++ b/README.md
@@ -100,6 +100,12 @@ bash <(curl -Ls https://panel.example.com/install/ТОКЕН.sh)
Заполни реальными данными `site/offer.html` (публичная оферта) и `site/privacy.html` (политика конфиденциальности) перед подачей заявки в ЮKassa — они нужны для их проверки, шаблоны уже на сайте (`/offer.html`, `/privacy.html`), но с плейсхолдерами вместо твоих реквизитов.
+## Лимит устройств (HWID)
+
+Как в Remnawave — ограничение, сколько разных устройств может использовать одну подписку. Работает не через сам VPN-протокол (Xray физически не видит "железо" клиента), а на уровне выдачи самой подписки: современные клиенты (Happ, v2rayTun и т.д.) при запросе `/sub/{token}` шлют заголовок `x-hwid` — уникальный ID устройства. Панель запоминает первые N увиденных hwid на юзера; при попытке добавить N+1-е устройство — отказ (404 + заголовок `x-hwid-max-devices-reached`).
+
+Выключено по умолчанию (`HWID_LIMIT_ENABLED=false`) — клиенты, которые не шлют `x-hwid`, при включённом лимите вообще не получат подписку, так что включай только если знаешь, что твои пользователи сидят на приложениях с поддержкой этого заголовка. `HWID_FALLBACK_LIMIT` — лимит по умолчанию для всех, в админке (Подписки → кнопка «Устройства» у юзера) можно посмотреть/удалить привязанные устройства и задать индивидуальный лимит.
+
## Разработка / вклад
Код простой — без сборки фронта, без ORM, без лишних абстракций. `admin.html` — один файл, vanilla JS. Питон-часть — обычные функции, SQLite напрямую.
diff --git a/admin.html b/admin.html
index 1f3af6f..068947d 100644
--- a/admin.html
+++ b/admin.html
@@ -237,6 +237,13 @@
.modal-close:hover { color: var(--text); background: var(--card2-tint); }
.modal-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 10px; }
+ .device-row {
+ display: flex; align-items: center; justify-content: space-between; gap: 10px;
+ padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; margin-bottom: 8px;
+ font-size: 13.5px;
+ }
+ .devices-list { max-height: 260px; overflow-y: auto; margin: 4px 0 16px; }
+
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
.reveal, .login-card, .splash-mark, .splash-title, .splash-tagline, .modal-overlay, .modal-card { opacity: 1 !important; transform: none !important; filter: none !important; }
@@ -411,6 +418,23 @@
+