@charset "UTF-8";
/* ===== N3000 Web — дизайн-система (тёмная тема СКУД) ===== */
:root {
    --bg:            #0e1116;
    --bg-panel:      #161b22;
    --bg-panel-2:    #1c2230;
    --bg-elev:       #212a38;
    --border:        #2a3340;
    --border-strong: #3a4656;
    --text:          #e6edf3;
    --text-dim:      #9aa7b4;
    --text-mute:     #64707d;
    --accent:        #2dd4bf;
    --accent-2:      #22a89a;
    --accent-ink:    #06231f;
    --danger:        #f26d6d;
    --danger-bg:     #3a1f22;
    --ok:            #4ec98b;
    --ok-bg:         #16311f;
    --warn:          #e2b23c;
    --warn-bg:       #33290f;
    --radius:        9px;
    --radius-sm:     6px;
    --sidebar-w:     236px;
    --shadow:        0 8px 28px rgba(0,0,0,.45);
    --login-glow:    #16202b;
    --sidebar-bg:    linear-gradient(180deg, #12161d, #0d1014);
    --door-opening:  #0a0e13;
    --door-panel:    linear-gradient(135deg, #33404f, #232c39);
    color-scheme: dark;
    font-synthesis: none;
}

/* ===== Светлая тема (переключается через data-theme на <html>) ===== */
:root[data-theme="light"] {
    --bg:            #eef1f6;
    --bg-panel:      #ffffff;
    --bg-panel-2:    #f4f6fa;
    --bg-elev:       #ffffff;
    --border:        #dfe4ec;
    --border-strong: #c6cedb;
    --text:          #17202e;
    --text-dim:      #566072;
    --text-mute:     #8b95a5;
    --accent:        #0f9e8f;
    --accent-2:      #0c7d72;
    --accent-ink:    #ffffff;
    --danger:        #d64545;
    --danger-bg:     #fdeaea;
    --ok:            #1f9d57;
    --ok-bg:         #e8f6ed;
    --warn:          #c98a12;
    --warn-bg:       #f7ecd0;
    --shadow:        0 10px 30px rgba(26,38,60,.12);
    --login-glow:    #d3e0ea;
    --sidebar-bg:    linear-gradient(180deg, #ffffff, #eef1f6);
    --door-opening:  #7c8b9c;
    --door-panel:    linear-gradient(135deg, #eef2f7, #dbe3ec);
    color-scheme: light;
}

* { box-sizing: border-box; }

/* ===== Анимации появления страниц ===== */
@keyframes rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

/* Спиннер (напр. на кнопке поиска во время сканирования). */
@keyframes spin { to { transform: rotate(360deg); } }
.spinner { display: inline-block; width: 13px; height: 13px; border: 2px solid rgba(127,127,127,.35); border-top-color: currentColor; border-radius: 50%; animation: spin .7s linear infinite; vertical-align: -2px; margin-right: 6px; }

/* Скелетон-заглушка таблицы (мерцание) во время загрузки. */
@keyframes shimmer { 0% { background-position: -360px 0; } 100% { background-position: calc(100% + 360px) 0; } }
.skeleton-row { height: 40px; border-radius: 8px; margin: 8px 14px;
    /* бегущий блик поверх нейтральной подложки — виден и в светлой, и в тёмной теме
       (прежний градиент panel→panel-2 в светлой теме был практически неразличим) */
    background-color: var(--bg-panel-2);
    background-image: linear-gradient(90deg, transparent 0, rgba(127,127,127,.25) 180px, transparent 360px);
    background-repeat: no-repeat; background-size: 360px 100%;
    animation: shimmer 1.15s infinite linear; }
.skeleton-row:last-child { margin-bottom: 14px; }
.page-head { animation: rise .3s ease both; }
/* backwards, не both: после анимации transform возвращается к none. При both Chrome оставляет
   единичную matrix(1,0,0,1,0,0) — а любой transform≠none делает .card containing-block'ом и
   stacking-контекстом, из-за чего всплывающее меню строки (position:fixed) смещалось и уходило
   под соседние ячейки. Вход сохраняется (to == базовое состояние, «прыжка» нет). */
.card { animation: rise .34s ease backwards; }
.stats .stat { animation: rise .34s ease both; }
.stats .stat:nth-child(2) { animation-delay: .04s; }
.stats .stat:nth-child(3) { animation-delay: .08s; }
.stats .stat:nth-child(4) { animation-delay: .12s; }
.stats .stat:nth-child(5) { animation-delay: .16s; }
/* backwards, не both: заполняющая (both) анимация держит строку постоянным stacking-контекстом,
   и следующая строка рисуется поверх всплывающего меню предыдущей. backwards оставляет вход,
   но в покое строка — не stacking-контекст. */
.grid tbody tr { animation: fade .3s ease backwards; }
@media (prefers-reduced-motion: reduce) {
    .page-head, .card, .stats .stat, .grid tbody tr, .modal, .modal-backdrop { animation: none !important; transition: none !important; }
}

html, body {
    margin: 0;
    padding: 0;
    background: var(--bg);
    color: var(--text);
    font-family: "Segoe UI", "Inter", system-ui, -apple-system, sans-serif;
    font-size: 14px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3 { margin: 0 0 .4em; font-weight: 600; letter-spacing: -.01em; }
h1:focus, h1:focus-visible { outline: none; }   /* убрать фокус-рамку от FocusOnNavigate */

/* Кнопки-иконки в топбаре (тема, звук) */
.icon-btn {
    width: 32px; height: 32px; display: inline-flex; align-items: center; justify-content: center;
    background: var(--bg-panel-2); border: 1px solid var(--border); border-radius: var(--radius-sm);
    color: var(--text-dim); font-size: 15px; cursor: pointer; padding: 0; line-height: 1;
    transition: background .15s, color .15s, border-color .15s;
}
.icon-btn:hover { background: var(--bg-elev); color: var(--text); border-color: var(--border-strong); }
.icon-btn.muted { color: var(--text-mute); }

/* Триггер командной палитры в сайдбаре */
.cmdk-trigger {
    display: flex; align-items: center; gap: 8px;
    margin: 6px 12px 4px; padding: 8px 10px;
    background: var(--bg-panel-2); border: 1px solid var(--border); border-radius: var(--radius-sm);
    color: var(--text-mute); font-size: 12.5px; font-family: inherit; cursor: pointer;
    transition: border-color .15s, color .15s;
}
.cmdk-trigger:hover { border-color: var(--border-strong); color: var(--text-dim); }
.cmdk-trigger .cmdk-ico { font-size: 14px; }
.cmdk-trigger .cmdk-kbd { margin-left: auto; }
.cmdk-kbd {
    font-size: 10px; color: var(--text-mute); border: 1px solid var(--border-strong);
    border-radius: 4px; padding: 1px 5px; letter-spacing: .04em; white-space: nowrap;
}

h1 { font-size: 1.4rem; }
h2 { font-size: 1.1rem; }

/* ===== Каркас ===== */
.app-shell { display: flex; min-height: 100vh; }

.sidebar {
    width: var(--sidebar-w);
    flex: 0 0 var(--sidebar-w);
    background: var(--sidebar-bg);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
}
.brand {
    display: flex; align-items: center; justify-content: center; gap: 10px;
    padding: 18px 18px 16px;
    border-bottom: 1px solid var(--border);
}
.brand-logo {
    width: 32px; height: 32px; border-radius: 8px;
    background: linear-gradient(135deg, var(--accent), var(--accent-2));
    display: grid; place-items: center;
    color: var(--accent-ink); font-weight: 800; font-size: 15px;
    box-shadow: 0 0 0 1px rgba(45,212,191,.25), 0 4px 14px rgba(45,212,191,.25);
}
.brand-name { font-weight: 700; font-size: 15px; line-height: 1; }
.brand-sub { color: var(--text-mute); font-size: 11px; letter-spacing: .04em; text-transform: uppercase; }
/* Логотип бренда (ControlledCare) — на боковой панели и на странице входа */
.brand-img { max-width: 100%; height: 30px; width: auto; object-fit: contain; }
.login-card .brand-img { height: 40px; }

.nav { padding: 8px 10px; overflow-y: auto; flex: 1; }
.nav a {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 10px; margin: 2px 0;
    border-radius: var(--radius-sm);
    color: var(--text-dim); font-weight: 500; text-decoration: none;
    transition: background .12s, color .12s;
}
.nav a:hover { background: var(--bg-panel-2); color: var(--text); }
.nav a .ico { width: 18px; text-align: center; opacity: .9; font-size: 15px; }

/* Верхнеуровневые пункты (Dashboard + заголовки секций) */
.nav-top { font-weight: 600; }
/* Заголовок секции — <button>, а не якорь: повторяем вид пунктов навигации и сбрасываем стиль кнопки. */
.nav .nav-sec-head {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 10px; margin: 2px 0; border-radius: var(--radius-sm);
    color: var(--text-dim); font-weight: 600;
    background: none; border: none; width: 100%;
    font-family: inherit; font-size: inherit; text-align: left; cursor: pointer;
    transition: background .12s, color .12s;
}
.nav .nav-sec-head:hover { background: var(--bg-panel-2); color: var(--text); }
.nav .nav-sec-head .ico { width: 18px; text-align: center; opacity: .9; font-size: 15px; }
.nav-sec-head .sec-count {
    margin-left: auto; font-size: 10.5px; font-weight: 600; color: var(--text-mute);
    background: var(--bg-panel-2); border-radius: 10px; padding: 1px 7px; min-width: 20px; text-align: center;
}
/* Строка секции: заголовок (переход на хаб) + шеврон (только разворачивание) */
.nav-sec-row { display: flex; align-items: center; }
.nav-sec-row .nav-sec-head { flex: 1; min-width: 0; }
.nav-sec-toggle {
    background: none; border: none; cursor: pointer; color: var(--text-mute);
    font-size: 11px; padding: 6px 8px; margin: 2px 0; border-radius: var(--radius-sm);
    transition: transform .15s ease, color .12s, background .12s; line-height: 1;
}
.nav-sec-toggle:hover { color: var(--text); background: var(--bg-panel-2); }
.nav-sec-toggle.open { transform: rotate(90deg); color: var(--text-dim); }
.nav-section.active .nav-sec-head {
    color: var(--text);
    background: linear-gradient(90deg, rgba(45,212,191,.12), transparent);
}
.nav-section.active .nav-sec-head .sec-count { color: var(--accent); }

/* Дочерние пункты активной секции */
.nav-children { margin: 2px 0 8px; padding-left: 8px; border-left: 1px solid var(--border); margin-left: 16px; animation: fade .18s ease both; }
.nav-child { font-size: 13px; padding: 6px 10px; }
.nav a.active {
    background: linear-gradient(90deg, rgba(45,212,191,.16), rgba(45,212,191,.03));
    color: var(--text);
    box-shadow: inset 2px 0 0 var(--accent);
}
/* Заголовок секции не должен подсвечиваться как «активный» из-за префиксного совпадения — только точное */
.nav-sec-head.active { box-shadow: none; }

/* ===== Командная палитра ===== */
.cmdk-backdrop {
    position: fixed; inset: 0; z-index: 200;
    background: rgba(4,7,11,.55); backdrop-filter: blur(2px);
    display: flex; justify-content: center; align-items: flex-start;
    padding-top: 12vh; animation: fade .12s ease both;
}
.cmdk-panel {
    width: min(560px, 92vw); background: var(--bg-panel); border: 1px solid var(--border-strong);
    border-radius: 12px; box-shadow: var(--shadow); overflow: hidden; animation: rise .16s ease both;
}
.cmdk-search { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--border); }
.cmdk-search .cmdk-ico { font-size: 17px; color: var(--text-mute); }
.cmdk-field {
    flex: 1; background: none; border: none; outline: none; color: var(--text);
    font-size: 15px; font-family: inherit;
}
.cmdk-results { max-height: 52vh; overflow-y: auto; padding: 6px; }
.cmdk-empty { padding: 20px; text-align: center; color: var(--text-mute); }
.cmdk-item {
    display: flex; align-items: center; gap: 11px; width: 100%;
    padding: 9px 11px; border: none; background: none; border-radius: var(--radius-sm);
    color: var(--text-dim); font-family: inherit; font-size: 14px; cursor: pointer; text-align: left;
}
.cmdk-item .ico { width: 20px; text-align: center; font-size: 15px; }
.cmdk-item .cmdk-label { color: var(--text); }
.cmdk-item .cmdk-sec { margin-left: auto; font-size: 11px; color: var(--text-mute); }
.cmdk-item.sel { background: linear-gradient(90deg, rgba(45,212,191,.16), rgba(45,212,191,.04)); }
.cmdk-item.sel .cmdk-sec { color: var(--accent); }

.text-danger { color: var(--danger); }

/* Пейджер списков */
.pager { display: flex; align-items: center; justify-content: center; gap: 14px; }

/* ===== Вкладки (контейнеры разделов) ===== */
.tabstrip { display: flex; gap: 2px; border-bottom: 1px solid var(--border); margin-bottom: 18px; overflow-x: auto; }
.tabx {
    background: none; border: none; border-bottom: 2px solid transparent; color: var(--text-dim);
    font-family: inherit; font-size: 14px; font-weight: 600; padding: 10px 16px; cursor: pointer; white-space: nowrap;
    transition: color .12s, border-color .12s;
}
.tabx:hover { color: var(--text); }
.tabx.active { color: var(--accent); border-bottom-color: var(--accent); }
/* У вложенной страницы убираем верхний отступ заголовка — таб-полоса уже сверху */
.tabbody .page-head { margin-top: 0; }

/* ===== Устройства (карточки контроллеров) ===== */
.dev-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); gap: 16px; }
.dev-card { background: var(--bg-panel); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; animation: rise .3s ease backwards; }
.dev-head { padding: 13px 15px; border-bottom: 1px solid var(--border); }
.dev-headrow { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.dev-headbadges { display: flex; align-items: center; gap: 6px; flex: none; flex-wrap: wrap; justify-content: flex-end; }
.dev-title { font-weight: 600; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dev-meta { color: var(--text-mute); font-size: 12px; margin-top: 3px; word-break: break-word; }  /* SN/IP во всю ширину — не обрезается */
.dev-body { padding: 8px 15px 14px; }
.dev-sub { font-size: 10.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--text-mute); margin: 6px 0 2px; font-weight: 600; }
/* Строки дверей/этажей/ридеров в карточке — компактные по вертикали: высоту задают ужатые кнопки/бейджи. */
.dev-row { display: flex; align-items: center; gap: 8px; padding: 1px 0; border-bottom: 1px solid var(--border); font-size: 12.5px; }
.dev-row:last-child { border-bottom: none; }
.dev-row .n { color: var(--text-mute); width: 18px; text-align: center; font-family: ui-monospace, monospace; }
.dev-row .grow { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dev-row .btn-sm { padding: 1px 7px; font-size: 11.5px; line-height: 1.5; }
.dev-row .badge { padding: 0 6px; font-size: 10.5px; }

/* ===== Дашборд ===== */
.stat.stat-alarm { border-color: var(--danger); box-shadow: 0 0 0 1px var(--danger) inset; }
.stat.stat-alarm .value { color: var(--danger); }
.dash-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 16px; margin-bottom: 16px; }

/* Dashboard charts */
.chart-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 16px; margin-bottom: 16px; }
.chart-card .card-head { margin-bottom: 4px; }
.chart-legend { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-dim); }
.chart-legend .lg { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }
.chart-legend .lg:not(:first-child) { margin-left: 8px; }
.lg.granted, .bseg.granted { background: var(--ok); }
.lg.denied, .bseg.denied { background: var(--warn); }
.barchart { display: flex; align-items: flex-end; gap: 8px; height: 150px; padding: 6px 2px 0; }
.barchart.hourly { gap: 2px; }
.barcol { flex: 1 1 0; display: flex; flex-direction: column; align-items: center; height: 100%; min-width: 0; }
.barval { font-size: 11px; color: var(--text-dim); height: 14px; line-height: 14px; }
.barstack { flex: 1; width: 100%; max-width: 34px; display: flex; flex-direction: column; justify-content: flex-end;
    background: var(--bg-panel-2); border-radius: 4px 4px 0 0; overflow: hidden; }
.barchart.hourly .barstack { max-width: none; border-radius: 2px 2px 0 0; }
.bseg { width: 100%; transition: height .3s ease; }
.bseg.granted { border-radius: 0; }
.barlbl { font-size: 10px; color: var(--text-mute); margin-top: 4px; height: 12px; line-height: 12px; white-space: nowrap; }
.att-summary { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; padding: 4px 2px; }
.att-item { text-align: center; padding: 14px 8px; background: var(--bg-panel-2); border-radius: var(--radius-sm); }
.att-item .n { font-size: 26px; font-weight: 700; }
.att-item .t { font-size: 11.5px; color: var(--text-mute); text-transform: uppercase; letter-spacing: .05em; margin-top: 2px; }
.att-item.ok .n { color: var(--ok); }
.att-item.warn .n { color: var(--warn); }
.att-item.danger .n { color: var(--danger); }
.feed { list-style: none; margin: 0; padding: 0; }
.feed li { display: flex; align-items: center; gap: 10px; padding: 8px 2px; border-bottom: 1px solid var(--border); font-size: 13px; }
.feed li:last-child { border-bottom: none; }
.feed .feed-main { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ===== Плеер архивного видео (Nx) ===== */
.video-box {
    width: min(860px, 94vw); background: var(--bg-panel); border: 1px solid var(--border-strong);
    border-radius: 12px; box-shadow: var(--shadow); overflow: hidden; animation: rise .16s ease both;
}
.video-head { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; border-bottom: 1px solid var(--border); }
.video-title { font-weight: 600; }
.video-head .close { background: none; border: none; color: var(--text-mute); font-size: 16px; cursor: pointer; }
.video-head .close:hover { color: var(--text); }
.video-player { width: 100%; max-height: 70vh; background: #000; display: block; cursor: pointer; }
.video-sub { padding: 8px 16px 14px; font-size: 12px; }

/* Центральная кнопка play/pause поверх видео (визуальная; клик переключает сам <video>). */
.vp-wrap { position: relative; display: block; line-height: 0; }
.vp-toggle {
    position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
    width: 80px; height: 80px; border-radius: 50%; background: rgba(15, 20, 32, .55);
    display: flex; align-items: center; justify-content: center; pointer-events: none;
    opacity: 1; transition: opacity .2s ease;
}
.vp-toggle svg { width: 38px; height: 38px; fill: #fff; }
.vp-toggle .ico-pause { display: none; }
.vp-wrap.is-playing .vp-toggle .ico-play { display: none; }
.vp-wrap.is-playing .vp-toggle .ico-pause { display: block; }
/* На паузе — крупный ▶ по центру постоянно; во время игры кнопка скрыта, но проявляется при наведении. */
.vp-wrap.is-playing .vp-toggle { opacity: 0; }
.vp-wrap.is-playing:hover .vp-toggle { opacity: 1; }
/* Вспышка иконки при каждом переключении play/pause. */
.vp-wrap.vp-flash .vp-toggle { animation: vpflash .55s ease; }
@keyframes vpflash {
    0% { opacity: 0; transform: translate(-50%, -50%) scale(.7); }
    18% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
    100% { opacity: 0; transform: translate(-50%, -50%) scale(1.3); }
}

/* ===== Диалог подтверждения ===== */
.confirm-backdrop { align-items: center; padding-top: 0; }
.confirm-box {
    width: min(420px, 92vw); background: var(--bg-panel); border: 1px solid var(--border-strong);
    border-radius: 12px; box-shadow: var(--shadow); padding: 22px; animation: rise .16s ease both;
}
.confirm-title { font-weight: 700; font-size: 16px; margin-bottom: 8px; }
.confirm-msg { color: var(--text-dim); font-size: 14px; line-height: 1.5; }
.confirm-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; }

/* ===== Хаб-страница секции ===== */
.hub-h-ico { margin-right: 6px; }
.hub-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 14px; }
.hub-card {
    display: flex; flex-direction: column; gap: 12px;
    padding: 18px; background: var(--bg-panel); border: 1px solid var(--border);
    border-radius: var(--radius); color: var(--text); text-decoration: none;
    transition: border-color .15s, transform .15s, box-shadow .15s;
    animation: rise .3s ease both;
}
.hub-card:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: var(--shadow); text-decoration: none; }
.hub-ico {
    width: 44px; height: 44px; display: grid; place-items: center; font-size: 22px;
    background: var(--bg-panel-2); border-radius: 10px;
}
.hub-name { font-weight: 600; font-size: 14.5px; }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.topbar {
    height: 56px; flex: 0 0 56px;
    display: flex; align-items: center; justify-content: space-between;
    padding: 0 22px;
    background: var(--bg-panel);
    border-bottom: 1px solid var(--border);
    position: sticky; top: 0; z-index: 20;
}
.topbar .crumb { color: var(--text-dim); font-size: 13px; }
.topbar .user { display: flex; align-items: center; gap: 8px; color: var(--text-dim); font-size: 13px; }
.content { padding: 22px; flex: 1; }

/* ===== Карточки / панели ===== */
.card {
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}
.card-head {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 14px 18px; border-bottom: 1px solid var(--border);
}
.card-head h2 { margin: 0; }
.card-body { padding: 18px; }
/* position+z-index: чтобы поповер (i) всплывал над последующими карточками, а не под ними */
.page-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; gap: 16px; flex-wrap: wrap; position: relative; z-index: 30; }
.page-head .subtitle { color: var(--text-dim); font-size: 13px; margin-top: 2px; }

/* KPI-плитки */
.stats { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 14px; margin-bottom: 22px; }
.stat { background: var(--bg-panel); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px 18px; }
.stat .label { color: var(--text-mute); font-size: 12px; text-transform: uppercase; letter-spacing: .05em; }
.stat .value { font-size: 28px; font-weight: 700; margin-top: 6px; letter-spacing: -.02em; }
.stat .value .u { font-size: 14px; color: var(--text-dim); font-weight: 500; margin-left: 4px; }

/* ===== Кнопки ===== */
.btn {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 8px 14px; border-radius: var(--radius-sm);
    border: 1px solid var(--border-strong); background: var(--bg-elev); color: var(--text);
    font-size: 13px; font-weight: 600; cursor: pointer; text-decoration: none;
    transition: background .12s, border-color .12s, transform .05s;
}
.btn:hover { background: var(--bg-panel-2); text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn-primary { background: linear-gradient(135deg, var(--accent), var(--accent-2)); border-color: transparent; color: var(--accent-ink); }
.btn-primary:hover { filter: brightness(1.07); background: linear-gradient(135deg, var(--accent), var(--accent-2)); }
.btn-danger { border-color: #6a2b2f; color: var(--danger); background: transparent; }
.btn-danger:hover { background: var(--danger-bg); }
.btn-sm { padding: 5px 9px; font-size: 12px; }
.btn-icon { padding: 6px 8px; }
.btn:disabled { opacity: .5; cursor: not-allowed; }

/* ===== Таблицы / QuickGrid ===== */
.table-wrap { overflow-x: auto; border-radius: var(--radius); border: 1px solid var(--border); }
table.grid, .table-wrap table { width: 100%; border-collapse: collapse; font-size: 13px; background: var(--bg-panel); }
.grid th, .table-wrap th {
    text-align: left; padding: 11px 14px; background: var(--bg-panel-2);
    color: var(--text-dim); font-weight: 600; font-size: 12px;
    text-transform: uppercase; letter-spacing: .03em;
    border-bottom: 1px solid var(--border); white-space: nowrap; position: sticky; top: 0;
}
.grid td, .table-wrap td { padding: 10px 14px; border-bottom: 1px solid var(--border); vertical-align: middle; }
/* Компактный вариант таблицы (список найденных контроллеров и т.п.): ужатые ячейки и кнопки. */
.grid.compact td { padding: 3px 14px; font-size: 12.5px; }
.grid.compact th { padding-top: 6px; padding-bottom: 6px; }
.grid.compact .btn-sm { padding: 1px 8px; font-size: 11.5px; line-height: 1.6; }
.grid.compact .badge { padding: 1px 7px; font-size: 10.5px; }
.grid tbody tr { transition: background .1s; }
.grid tbody tr:hover { background: var(--bg-panel-2); }
.grid tbody tr:last-child td { border-bottom: none; }

/* QuickGrid: сортировка/пагинация */
::deep .col-title, .col-title { display: inline-flex; align-items: center; gap: 4px; }
.quickgrid .sort-indicator, .col-sort-button { background: none; border: none; color: inherit; cursor: pointer; font: inherit; }
.paginator { display: flex; align-items: center; gap: 12px; margin-top: 14px; color: var(--text-dim); font-size: 13px; }
.paginator button { background: var(--bg-elev); border: 1px solid var(--border-strong); color: var(--text); border-radius: var(--radius-sm); padding: 5px 10px; cursor: pointer; }
.paginator button:disabled { opacity: .4; cursor: not-allowed; }

.empty { text-align: center; color: var(--text-mute); padding: 40px 20px; }

/* ===== Пояснение назначения страницы — кнопка (i) в строке заголовка, текст всплывает поповером ===== */
.page-help-wrap { position: relative; display: inline-flex; vertical-align: middle; margin-left: 8px; }
.page-help-btn {
    width: 22px; height: 22px; border-radius: 50%; cursor: pointer; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1.5px solid var(--accent); background: color-mix(in srgb, var(--accent) 14%, var(--bg-panel));
    color: var(--accent); font-family: Georgia, "Times New Roman", serif; font-style: italic; font-weight: 700;
    font-size: 13px; line-height: 1; animation: helpBreathe 2.6s ease-in-out infinite;
    transition: background .15s, transform .1s, color .15s;
}
.page-help-btn:hover { transform: scale(1.1); background: color-mix(in srgb, var(--accent) 26%, var(--bg-panel)); }
.page-help-btn.open { animation: none; background: var(--accent); color: var(--accent-ink); }
/* «Дыхание» — пульсирующее кольцо-подсветка, привлекает внимание к скрытой подсказке */
@keyframes helpBreathe {
    0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 50%, transparent); }
    70%      { box-shadow: 0 0 0 7px color-mix(in srgb, var(--accent) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .page-help-btn { animation: none; } }
/* Поповер: всплывает под кнопкой, не влияет на поток; сбрасываем крупный шрифт заголовка */
.page-help {
    position: absolute; top: calc(100% + 8px); left: 0; z-index: 40;
    display: block; padding: 10px 14px; width: max-content; max-width: min(560px, 80vw);
    background: var(--bg-panel);
    border: 1px solid var(--border); border-left: 3px solid var(--accent);
    border-radius: var(--radius-sm); box-shadow: var(--shadow-md, 0 8px 24px rgba(0,0,0,.18));
    color: var(--text-dim); font: 400 13px/1.5 var(--font, system-ui, sans-serif);
    letter-spacing: normal; text-transform: none; white-space: normal;
    animation: rise .16s ease both;
}
.page-help-text a { color: var(--accent); }

/* Блок кода / copy-paste примеров (API) */
.code-block {
    margin: 0; padding: 10px 12px; border-radius: var(--radius-sm);
    background: var(--bg-elev, var(--bg-panel-2)); border: 1px solid var(--border);
    color: var(--text); font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 12px; line-height: 1.5; white-space: pre; overflow-x: auto;
}

/* ===== Пустое состояние с призывом к действию ===== */
.empty-state { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.empty-state .empty-ico { font-size: 30px; opacity: .55; line-height: 1; }
.empty-state .empty-text { color: var(--text-mute); max-width: 42ch; }
.empty-state .empty-cta { margin-top: 4px; }
.empty-state .empty-extra { font-size: 12.5px; }
.empty-state .empty-extra a { color: var(--accent); }

/* ===== Тосты (всплывающие уведомления) ===== */
.toast-stack {
    position: fixed; right: 18px; bottom: 18px; z-index: 400;
    display: flex; flex-direction: column; gap: 10px; max-width: min(380px, 92vw);
}
.toast {
    display: flex; align-items: flex-start; gap: 10px;
    padding: 11px 14px; border-radius: 10px; cursor: pointer;
    background: var(--bg-panel); border: 1px solid var(--border-strong);
    box-shadow: var(--shadow); color: var(--text); font-size: 13.5px;
    animation: rise .16s ease both; border-left-width: 3px;
}
.toast .toast-ico { font-weight: 700; line-height: 1.3; }
.toast .toast-msg { flex: 1; }
.toast-success { border-left-color: var(--accent); }
.toast-success .toast-ico { color: var(--accent); }
.toast-error { border-left-color: var(--danger, #f87171); }
.toast-error .toast-ico { color: var(--danger, #f87171); }
.toast-info { border-left-color: var(--text-mute); }
.toast-info .toast-ico { color: var(--text-dim); }

.grid tbody tr.rowedit { cursor: pointer; }
.grid tbody tr.rowedit:hover { background: var(--bg-elev); }

/* Поля даты: удобный вызов календаря, тёмный индикатор */
input[type=date], input[type=time] { cursor: pointer; position: relative; }
input[type=date]::-webkit-calendar-picker-indicator,
input[type=time]::-webkit-calendar-picker-indicator {
    filter: invert(.75) sepia(1) saturate(4) hue-rotate(120deg);
    cursor: pointer; opacity: .8;
}
input[type=date]::-webkit-calendar-picker-indicator:hover { opacity: 1; }

/* ===== Бейджи / статусы ===== */
.badge { display: inline-flex; align-items: center; gap: 5px; padding: 3px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 600; }
.badge.ok { background: var(--ok-bg); color: var(--ok); }
.badge.off { background: var(--bg-panel-2); color: var(--text-mute); }
.badge.danger { background: var(--danger-bg); color: var(--danger); }
.badge.warn { background: var(--warn-bg); color: var(--warn); }

/* Лог-вьювер — плотный (dense) вид */
.logs-grid td.log-msg { font-family: "Cascadia Code", "Consolas", ui-monospace, monospace; white-space: pre-wrap; word-break: break-word; }
.logs-grid th, .dense-grid th { padding: 6px 10px; }
.logs-grid td, .dense-grid td { padding: 2px 10px; vertical-align: top; font-size: 12px; line-height: 1.35; }
.logs-grid tbody tr, .dense-grid tbody tr { animation: none; }
.logs-grid tbody tr:hover, .dense-grid tbody tr:hover { background: var(--bg-panel-2); }
.logs-grid .badge, .dense-grid .badge { padding: 0 6px; font-size: 10.5px; }
.dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.dot.ok { background: var(--ok); box-shadow: 0 0 8px rgba(78,201,139,.7); }
.dot.off { background: var(--text-mute); }

/* ===== Формы ===== */
.form-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px 18px; }
.form-grid.one { grid-template-columns: 1fr; }
.field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.field input, .field select, .field textarea { min-width: 0; }
.field.full { grid-column: 1 / -1; }
.field label { font-size: 12.5px; color: var(--text-dim); font-weight: 600; }
.input, input:not([type]), input[type=text], input[type=number], input[type=password], input[type=email], input[type=tel], input[type=search], input[type=time], input[type=url], input[type=date], select, textarea {
    background: var(--bg); border: 1px solid var(--border-strong); color: var(--text);
    border-radius: var(--radius-sm); padding: 9px 11px; font-size: 13px; font-family: inherit; width: 100%;
    transition: border-color .12s, box-shadow .12s;
}
.input:focus, input:focus, select:focus, textarea:focus {
    outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(45,212,191,.15);
}
.check { display: flex; align-items: center; gap: 8px; }
.check input[type=checkbox] { width: 16px; height: 16px; accent-color: var(--accent); }
.form-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border); }

.toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.toolbar .search { position: relative; }
.toolbar .search input { width: 260px; padding-left: 32px; }
.toolbar .search .ico { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--text-mute); }
.spacer { flex: 1; }

/* ===== Модальное окно (с анимацией открытия/закрытия) ===== */
.modal-backdrop {
    position: fixed; inset: 0; background: rgba(4,7,11,.66); backdrop-filter: blur(2px);
    z-index: 100; display: grid; place-items: center; padding: 20px;
    opacity: 0; transition: opacity .2s ease;
}
.modal-backdrop.shown { opacity: 1; }
.modal {
    width: 100%; max-width: 640px; max-height: 90vh; overflow-y: auto;
    background: var(--bg-panel); border: 1px solid var(--border-strong);
    border-radius: var(--radius); box-shadow: var(--shadow);
    opacity: 0; transform: translateY(14px) scale(.97);
    transition: opacity .22s ease, transform .22s cubic-bezier(.2,.9,.3,1);
}
.modal.shown { opacity: 1; transform: none; }
.modal-head { display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; border-bottom: 1px solid var(--border); }
.modal-head h2 { margin: 0; }
.modal-body { padding: 20px; }
.modal .close { background: none; border: none; color: var(--text-dim); font-size: 20px; cursor: pointer; line-height: 1; }

/* Логин */
.login-wrap { min-height: 100vh; display: grid; place-items: center; background: radial-gradient(1200px 600px at 50% -10%, var(--login-glow), var(--bg)); }
.login-card { width: 360px; }
.login-card .brand { justify-content: center; border-bottom: none; padding-bottom: 6px; }

.validation-message { color: var(--danger); font-size: 12px; }
.invalid { border-color: var(--danger) !important; }
.mono { font-family: "Cascadia Code", "Consolas", monospace; }
.text-dim { color: var(--text-dim); }
.nowrap { white-space: nowrap; }

/* ===== Мониторинг дверей (нарисованные двери) ===== */
.mon-toolbar { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; flex-wrap: wrap; }
/* Карточка контроллера всегда достаточно широка (никогда не тесная); min(…,100%) — не вылезает на узких экранах */
.mon-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(480px, 100%), 1fr)); gap: 18px; }
.ctrl-card { background: var(--bg-panel); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; }
.ctrl-card .head { display: flex; align-items: center; justify-content: space-between; padding: 13px 16px; border-bottom: 1px solid var(--border); background: var(--bg-panel-2); }
.ctrl-card .head .title { font-weight: 700; }
.ctrl-card .head .meta { color: var(--text-mute); font-size: 12px; }
/* Двери переносятся (wrap), а НЕ вылезают: каждая не уже своего ряда кнопок (min-width) */
.ctrl-card .doors-row { display: flex; gap: 10px 8px; padding: 18px 14px 16px; flex-wrap: wrap; justify-content: center; }

.door { display: flex; flex-direction: column; align-items: center; gap: 6px; flex: 1 0 104px; min-width: 104px; max-width: 134px; }
/* Сетка 2×2: максимум две кнопки в ряд — ровные пары вместо случайного переноса 3+1
   (ряд из четырёх кнопок в узкую колонку двери не влезает и раньше налезал на соседей). */
.door-actions { display: grid; grid-template-columns: repeat(2, max-content); justify-content: center; gap: 2px; max-width: 100%; }
/* Одна кнопка — по центру; у нечётного числа кнопок последняя тоже центрируется. */
.door-actions > *:only-child,
.door-actions > *:nth-child(odd):last-child { grid-column: 1 / -1; justify-self: center; }
.door-actions .btn-icon { min-width: 19px; padding: 3px 2px; font-size: 11px; }
.door-scene { width: 52px; height: 82px; perspective: 620px; position: relative; }

/* Оверлей-статус в углу изображения двери */
.door-status {
    position: absolute; top: -7px; right: -7px; z-index: 5;
    width: 23px; height: 23px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
    font-size: 11px; line-height: 1; background: var(--bg-elev); border: 2px solid var(--border);
    box-shadow: 0 1px 5px rgba(0, 0, 0, .3); pointer-events: none;
}
.door-status.closed { border-color: var(--ok); }
.door-status.unlocked { border-color: var(--accent); }
.door-status.open { border-color: #5b9bff; }
.door-status.offline { border-color: var(--text-mute); color: var(--text-mute); }
.door-status.alarm { border-color: var(--danger); background: var(--danger); animation: stPulse 1s ease-in-out infinite; }
@keyframes stPulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, .5); } 50% { box-shadow: 0 0 0 5px rgba(239, 68, 68, 0); } }

/* Выпадашка смены режима двери (Online / NO / NC) — прячем опции, чтобы не нажать RC случайно */
.mode-dd { position: relative; display: inline-flex; }
.mode-trigger.mode-on { border-color: #5b9bff; color: #5b9bff; }
.mode-trigger.mode-no { border-color: var(--ok); color: var(--ok); }
.mode-trigger.mode-nc { border-color: var(--danger); color: var(--danger); }
.mode-pop {
    position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%); z-index: 60;
    background: var(--bg-elev); border: 1px solid var(--border); border-radius: 10px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, .34); padding: 5px; display: flex; flex-direction: column; gap: 2px; min-width: 184px;
}
.mode-opt {
    display: flex; align-items: center; gap: 9px; padding: 7px 10px; border: none; background: none; color: var(--text);
    border-radius: 7px; cursor: pointer; font-size: 12.5px; white-space: nowrap; text-align: left; width: 100%;
}
.mode-opt:hover { background: var(--bg-panel-2); }
.mode-opt .mo-dot { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.mode-opt.on .mo-dot { background: #5b9bff; }
.mode-opt.no .mo-dot { background: var(--ok); }
.mode-opt.nc .mo-dot { background: var(--danger); }
.mode-opt.nc { color: var(--danger); }
.mode-opt.sel { font-weight: 700; }
.mode-opt.sel::after { content: "\2713"; margin-left: auto; opacity: .65; }
.mode-backdrop { position: fixed; inset: 0; z-index: 55; background: transparent; }

/* Плавающая авто-камера: видео при открытии двери + фото сотрудника, авто-скрытие */
.auto-cam {
    position: fixed; right: 20px; bottom: 20px; z-index: 70; width: 360px; max-width: calc(100vw - 40px);
    background: var(--bg-panel); border: 1px solid var(--border); border-radius: 14px; overflow: hidden;
    box-shadow: 0 18px 50px rgba(0, 0, 0, .45); animation: acIn .3s ease both;
}
@keyframes acIn { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
.auto-cam-head { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-bottom: 1px solid var(--border); background: var(--bg-panel-2); }
.ac-title { font-weight: 700; font-size: 13px; }
.ac-live { display: flex; align-items: center; gap: 5px; font-size: 11px; color: var(--ok); }
.ac-close { margin-left: auto; background: none; border: none; color: var(--text-dim); cursor: pointer; font-size: 15px; line-height: 1; }
.ac-close:hover { color: var(--text); }
.auto-cam-stage { position: relative; aspect-ratio: 16 / 9; background: #000; }
.ac-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; background: #000; z-index: 2; }
.ac-video.failed { display: none; }
.ac-video-fallback { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; z-index: 1; font-size: 12px; }
.ac-person { position: absolute; left: 10px; bottom: 10px; z-index: 3; display: flex; align-items: center; gap: 10px; background: rgba(0, 0, 0, .55); border-radius: 10px; padding: 6px 12px 6px 6px; }
.ac-photo { position: relative; width: 46px; height: 46px; border-radius: 8px; overflow: hidden; background: var(--bg-elev); flex: none; }
.ac-photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.ac-avatar { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-weight: 700; color: #fff; font-size: 16px; }
.ac-name { color: #fff; font-weight: 600; font-size: 13px; }
.ac-time { font-size: 11px; color: rgba(255, 255, 255, .7) !important; }

/* Дверь-картинка = кнопка открытия: кастомный курсор «открыть дверь» + подсветка на ховере */
.door-scene.openable {
    cursor: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'><rect x='5' y='4' width='11' height='22' rx='1.5' fill='%232dd4bf' fill-opacity='0.22' stroke='%232dd4bf' stroke-width='2'/><circle cx='13' cy='15' r='1.4' fill='%232dd4bf'/><path d='M19 15h7M22 11l4 4-4 4' fill='none' stroke='%232dd4bf' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/></svg>") 6 6, pointer;
    transition: filter .15s ease;
}
.door-scene.openable:hover { filter: drop-shadow(0 0 7px rgba(45, 212, 191, .55)); }
.door:not(.open) .door-scene.openable:hover .door-leaf { transform: rotateY(-20deg); }   /* приоткрыть на ховере — намёк */
.door-frame {
    position: relative; width: 100%; height: 100%;
    border: 3px solid var(--border-strong); border-radius: 7px 7px 2px 2px;
    background: var(--door-opening);              /* тёмный проём — виден, когда дверь открыта */
    box-shadow: inset 0 0 16px rgba(0,0,0,.5);
    transform-style: preserve-3d;
}
.door-leaf {
    position: absolute; inset: 4px;
    background: var(--door-panel);                /* полотно двери */
    border: 1px solid var(--border-strong); border-radius: 3px;
    transform-origin: left center; transform: rotateY(0deg);
    transition: transform .65s cubic-bezier(.35,.9,.25,1);
    box-shadow: 2px 2px 6px rgba(0,0,0,.35);
    display: flex; align-items: center; justify-content: flex-end;
}
.door-leaf::before { /* филёнка */
    content: ""; position: absolute; inset: 9px; border: 1px solid rgba(128,140,160,.22); border-radius: 2px;
}
.door-leaf .handle { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); margin-right: 7px; box-shadow: 0 0 6px rgba(45,212,191,.6); }
/* Открыто: полотно распахнуто (цвет не меняем — виден тёмный проём за ним) + глубже тень проёма */
.door.open .door-leaf { transform: rotateY(-72deg); }
.door.open .door-frame { box-shadow: inset 5px 0 14px rgba(0,0,0,.6); }
.door.unlocked .door-leaf { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset, 2px 2px 6px rgba(0,0,0,.35); }
.door.alarm .door-frame { border-color: var(--danger); box-shadow: inset 0 0 18px rgba(242,109,109,.35), 0 0 14px rgba(242,109,109,.3); animation: alarmPulse 1s ease-in-out infinite; }
.door.offline { opacity: .5; filter: grayscale(.8); }
@keyframes alarmPulse { 0%,100% { box-shadow: inset 0 0 18px rgba(242,109,109,.3), 0 0 8px rgba(242,109,109,.2);} 50% { box-shadow: inset 0 0 22px rgba(242,109,109,.55), 0 0 20px rgba(242,109,109,.5);} }

.door .caption { font-size: 12px; text-align: center; color: var(--text-dim); line-height: 1.25; }
/* маркер «нет датчика открытия» — отдельная неконбинирующая иконка (перечёркнутый круг),
   вместо U+20E0, который как комбинирующий символ налезал на имя двери */
.door .caption .no-sensor { display: inline-flex; vertical-align: -2px; margin-left: 3px; color: var(--text-mute); }
.door .led-row { display: flex; align-items: center; gap: 6px; font-size: 11px; }
.door .led { width: 9px; height: 9px; border-radius: 50%; background: var(--text-mute); }
.door.online .led { background: var(--ok); box-shadow: 0 0 7px rgba(78,201,139,.7); }
.door.open.online .led { background: var(--accent); box-shadow: 0 0 8px rgba(45,212,191,.8); }
.door.alarm .led { background: var(--danger); box-shadow: 0 0 8px rgba(242,109,109,.8); }
.door .btn { padding: 4px 10px; font-size: 11px; }

.legend { display: flex; gap: 16px; flex-wrap: wrap; color: var(--text-dim); font-size: 12px; align-items: center; }
.legend .item { display: flex; align-items: center; gap: 6px; }
.legend .sw { width: 12px; height: 12px; border-radius: 3px; }

/* ===== E-map (графический план) ===== */
.map-wrap { position: relative; display: inline-block; max-width: 100%; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--bg-panel-2); }
.map-wrap.placing { cursor: crosshair; }
.map-wrap img { display: block; max-width: 100%; height: auto; }
.map-empty { display: grid; place-items: center; width: 640px; max-width: 100%; height: 360px; color: var(--text-mute); }
.map-marker {
    position: absolute; transform: translate(-50%, -50%);
    width: 34px; height: 34px; border-radius: 9px; display: grid; place-items: center;
    cursor: pointer; border: 2px solid var(--text-mute); background: rgba(100,112,125,.25);
    font-size: 15px; transition: transform .1s;
}
.map-marker:hover { transform: translate(-50%, -50%) scale(1.12); z-index: 2; }
.map-marker.ok { background: rgba(78,201,139,.22); border-color: var(--ok); }
.map-marker.open { background: rgba(45,212,191,.28); border-color: var(--accent); box-shadow: 0 0 12px rgba(45,212,191,.5); }
.map-marker.alarm { background: rgba(242,109,109,.28); border-color: var(--danger); animation: alarmPulse 1s ease-in-out infinite; }
/* Маркеры считывателей (точки обхода): круглые, отличаются от квадратных дверей */
.map-marker.reader { border-radius: 50%; }
.map-marker.neutral { background: rgba(100,112,125,.22); border-color: var(--text-mute); }
.map-marker.pending { background: rgba(226,178,60,.22); border-color: var(--warn); }   /* точка обхода не посещена */
.map-marker.sel { outline: 2px dashed var(--accent); outline-offset: 2px; }             /* выбрана в режиме правки */
.map-marker .lbl {
    position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
    white-space: nowrap; font-size: 10px; color: var(--text); margin-top: 3px;
    background: rgba(4,7,11,.7); padding: 1px 5px; border-radius: 3px;
}

.blazor-error-boundary { background: var(--danger-bg); color: var(--danger); padding: 12px 16px; border-radius: var(--radius-sm); }
.blazor-error-boundary::after { content: "An error has occurred."; }

@media (max-width: 820px) {
    .sidebar { position: fixed; z-index: 50; transform: translateX(-100%); transition: transform .2s; }
    .sidebar.open { transform: none; }
    .form-grid { grid-template-columns: 1fr; }
}

/* ===== Живая панель проходов (Monitor) ===== */
.access-panel { margin-top: 16px; background: var(--bg-panel); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px 16px; }
.access-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.access-head h2 { margin: 0; font-size: 16px; }
.access-empty { color: var(--text-mute); padding: 22px; text-align: center; }
.access-strip { display: flex; gap: 12px; overflow-x: auto; padding-bottom: 6px; }
.acc-card {
    flex: 0 0 262px; display: flex; gap: 12px; padding: 12px; border-radius: 14px;
    background: var(--bg-panel-2); border: 1px solid var(--border); border-left: 4px solid var(--text-mute);
    position: relative; animation: accIn .35s ease both;
    opacity: calc(1 - min(var(--age), 8) * 0.085);   /* старые события тускнеют */
}
.acc-card.granted { border-left-color: var(--ok); }
.acc-card.denied  { border-left-color: var(--danger); }
@keyframes accIn { from { opacity: 0; transform: translateX(-16px); } to { opacity: 1; transform: none; } }
.acc-photo { position: relative; width: 58px; height: 58px; flex: none; border-radius: 12px; overflow: hidden; background: var(--bg-elev); }
.acc-avatar { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 21px; color: var(--text-dim); }
.acc-photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.acc-dot { position: absolute; right: 3px; bottom: 3px; width: 12px; height: 12px; border-radius: 50%; border: 2px solid var(--bg-panel-2); }
.acc-dot.ok { background: var(--ok); }
.acc-dot.no { background: var(--danger); }
.acc-info { min-width: 0; flex: 1; }
.acc-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.acc-sub { font-size: 11.5px; color: var(--text-mute); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.acc-meta { font-size: 11.5px; color: var(--text-dim); margin-top: 2px; }
.acc-result { font-size: 12px; margin-top: 5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acc-result.ok { color: var(--ok); }
.acc-result.no { color: var(--danger); }
.acc-cam { position: absolute; top: 8px; right: 8px; width: 26px; height: 26px; border-radius: 8px; border: 1px solid var(--border); background: var(--bg-elev); color: var(--text); cursor: pointer; font-size: 11px; display: flex; align-items: center; justify-content: center; }
.acc-cam:hover { border-color: var(--accent); color: var(--accent); }

/* Текущий режим двери (Monitor): чип + подсветка активной кнопки */
.door-mode { display: inline-block; font-size: 10.5px; font-weight: 700; padding: 2px 9px; border-radius: 20px; margin: 3px auto 5px; text-transform: uppercase; letter-spacing: .03em; }
.door-mode.on { background: rgba(91, 155, 255, .16); color: #5b9bff; }        /* Online — синий */
.door-mode.no { background: rgba(45, 212, 191, .16); color: var(--ok); }       /* Normally open — зелёный */
.door-mode.nc { background: rgba(239, 68, 68, .16); color: var(--danger); }    /* Normally closed — красный */
.door-actions .btn-icon.mode-on { border-color: #5b9bff; color: #5b9bff; }
.door-actions .btn-icon.mode-no { border-color: var(--ok); color: var(--ok); }
.door-actions .btn-icon.mode-nc { border-color: var(--danger); color: var(--danger); }

/* Редактор времени анлока прямо в карточке двери */
.door-delay { display: flex; align-items: center; gap: 5px; justify-content: center; font-size: 12px; color: var(--text-dim); margin: 2px 0 6px; }
.door-delay input { width: 56px; padding: 3px 6px; text-align: center; }

/* ===== Раскладка монитора: двери слева, колонка «живых» проходов справа, лог снизу ===== */
.mon-layout { display: flex; gap: 16px; align-items: flex-start; }
.mon-doors { flex: 1 1 auto; min-width: 0; }
.mon-live {
    flex: 0 0 340px; width: 340px; box-sizing: border-box;
    background: var(--bg-panel); border: 1px solid var(--border); border-radius: var(--radius);
    padding: 14px 16px; position: sticky; top: 12px; max-height: calc(100vh - 96px);
    display: flex; flex-direction: column;
}
.mon-live .access-head { margin-bottom: 10px; }
.acc-col { display: flex; flex-direction: column; gap: 12px; flex: 1 1 auto; min-height: 0; overflow-y: auto; padding-right: 4px; }
/* Крупные вертикальные плитки прохода: большая область под фото/видео сверху, данные снизу */
.acc-col .acc-card { flex: 0 0 auto; width: 100%; box-sizing: border-box; flex-direction: column; gap: 0; padding: 0; overflow: hidden; }
.acc-col .acc-photo { width: 100%; height: 168px; border-radius: 0; }
.acc-col .acc-avatar { font-size: 52px; }
.acc-col .acc-dot { right: 8px; bottom: 8px; width: 16px; height: 16px; }
.acc-col .acc-info { padding: 10px 13px 12px; width: 100%; box-sizing: border-box; }
.acc-col .acc-name { font-size: 15px; }
.acc-col .acc-cam { top: 12px; right: 12px; width: 42px; height: 42px; border-radius: 50%; border: none; background: rgba(0, 0, 0, .55); color: #fff; font-size: 15px; padding-left: 3px; box-shadow: 0 2px 8px rgba(0, 0, 0, .35); }
.acc-col .acc-cam:hover { background: var(--accent); color: #071312; }
/* Действия на карточке live-события: столбик кнопок (открыть дверь, видео) в правом верхнем углу */
.acc-actions { position: absolute; top: 12px; right: 12px; display: flex; flex-direction: column; gap: 6px; z-index: 2; }
.acc-col .acc-actions .acc-cam, .acc-actions .acc-open { position: static; top: auto; right: auto; }
.acc-open { width: 42px; height: 42px; border-radius: 50%; border: none; cursor: pointer; color: #fff; font-size: 15px;
    background: rgba(0, 0, 0, .55); display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 8px rgba(0, 0, 0, .35); }
.acc-open:hover { background: var(--ok); color: #071312; }
.acc-open:disabled { opacity: .5; cursor: not-allowed; }

/* Нижний текстовый лог проходов */
.mon-log { margin-top: 16px; }

/* Охрана двери: активная кнопка-щит и маркер у имени. */
.btn.armed-on { background: var(--warn-bg); color: var(--warn); border-color: var(--warn); }
.armed-mark { margin-right: 4px; }

/* ===== Lift Monitoring ===== */
.mon-side { flex: 0 0 360px; min-width: 0; }
@media (max-width: 1100px) { .mon-side { flex: 1 1 auto; width: 100%; } }
.lift-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 14px; }
.lift-card { padding: 14px 16px; }
.lift-shaftwrap { display: flex; gap: 6px; }
.lift-cabcol { position: relative; width: 14px; flex: 0 0 14px; border-left: 2px dotted var(--border); margin-left: 4px; }
/* Кабина-индикатор: «едет» к последнему открытому этажу (bottom анимируется CSS-переходом). */
.lift-cab { position: absolute; left: 2px; width: 9px; height: 18px; border-radius: 3px;
    background: var(--accent); box-shadow: 0 0 6px rgba(13,138,106,.55); transition: bottom .8s cubic-bezier(.4,0,.2,1); }
/* Шахта: этажи снизу вверх, фиксированная высота строки = FloorRowPx на странице. */
.lift-shaft { flex: 1; min-width: 0; display: flex; flex-direction: column-reverse; gap: 3px; }
.lift-floor { display: flex; align-items: center; gap: 8px; height: 24px; padding: 0 8px;
    border: 1px solid var(--border); border-radius: 7px; background: var(--bg-panel-2); font-size: 12px; }
.lift-floor .n { width: 18px; color: var(--text-mute); font-family: ui-monospace, monospace; text-align: center; }
.lift-floor .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lift-floor .st { font-size: 10.5px; color: var(--text-dim); }
.lift-floor.open { background: var(--ok-bg); border-color: color-mix(in srgb, var(--ok) 30%, transparent); }
.lift-floor.open .st { color: var(--ok); font-weight: 600; }
.lift-floor.granted { outline: 2px solid var(--warn); outline-offset: -2px; }
.lift-floor.locked { background: color-mix(in srgb, var(--danger) 9%, var(--bg-panel)); border-color: color-mix(in srgb, var(--danger) 30%, transparent); }
.lift-floor.locked .st { color: var(--danger); font-weight: 600; }
.lift-floor .act { font-size: 10.5px; border: 1px solid var(--border); background: var(--bg-panel);
    border-radius: 6px; padding: 0 7px; cursor: pointer; color: var(--text); line-height: 1.7; }
.lift-floor .act:hover { border-color: var(--accent); color: var(--accent); }
/* Лента лифтовых событий — карточки с фото (тот же вид, что Live access дверного монитора). */
.lift-feed { display: flex; flex-direction: column; gap: 10px; max-height: 680px; overflow-y: auto; padding-right: 4px; }
.mon-log .card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.log-table { width: 100%; }
.log-table td, .log-table th { padding: 6px 10px; }
/* Плотный (dense) вид таблицы журнала */
.log-table.dense td, .log-table.dense th { padding: 3px 9px; font-size: 12px; line-height: 1.35; }
.log-table.dense .log-result { font-size: 11.5px; }
.log-pager { display: flex; align-items: center; gap: 8px; }
/* Стрелки ‹ › сидят выше базовой линии — центрируем содержимое кнопок флексом. */
.log-pager .btn-icon { min-width: 24px; padding: 2px 6px; display: inline-flex; align-items: center; justify-content: center; line-height: 1; }
.log-result { font-weight: 600; }
.log-result.ok { color: var(--ok); }
.log-result.no { color: var(--danger); }
.tnum { font-variant-numeric: tabular-nums; }

@media (max-width: 1100px) {
    .mon-layout { flex-direction: column; }
    .mon-live { flex: 1 1 auto; width: 100%; position: static; max-height: none; }
    .acc-col { flex-direction: row; overflow-x: auto; overflow-y: hidden; }
    .acc-col .acc-card { width: 262px; flex: 0 0 262px; }
}

/* Мастер-деталь (список слева, детали справа): на узких экранах — в одну колонку */
.split-master { display: grid; grid-template-columns: 300px 1fr; gap: 18px; align-items: start; }
@media (max-width: 760px) { .split-master { grid-template-columns: 1fr; } }

/* Двухступенчатые подсказки (tooltips) */
.n3k-tip {
    position: fixed; z-index: 9999; max-width: 280px;
    background: var(--bg-elev); color: var(--text);
    border: 1px solid var(--border); border-radius: 9px; padding: 7px 11px;
    font-size: 12px; line-height: 1.4; box-shadow: 0 8px 28px rgba(0, 0, 0, .3);
    pointer-events: none; opacity: 0; transform: translateY(4px);
    transition: opacity .12s ease, transform .12s ease;
}
.n3k-tip.show { opacity: 1; transform: none; }
.n3k-tip-short { font-weight: 600; }
.n3k-tip-more { margin-top: 5px; padding-top: 5px; border-top: 1px solid var(--border); color: var(--text-dim); font-weight: 400; font-size: 11.5px; }

/* Поле с активным «бессрочно»: гасим саму дату (метку и input), но чекбокс оставляем активным */
.field-disabled > label:first-of-type { opacity: .45; }
.field-disabled input[type="date"] { opacity: .45; pointer-events: none; }

/* Выбор дверей для прав доступа в редакторе сотрудника */
.rights-pick { display: flex; flex-wrap: wrap; gap: 12px; margin: 4px 0 6px; }
.rights-group { flex: 1 1 150px; min-width: 0; border: 1px solid var(--border); border-radius: 10px; padding: 8px 10px; background: var(--bg-panel-2); }
.rights-group-head { font-size: 11.5px; font-weight: 700; color: var(--text-dim); text-transform: uppercase; letter-spacing: .03em; margin-bottom: 5px; }
.rights-group .check { display: flex; margin: 3px 0; font-size: 13px; }

/* ===== Мобильная навигация (гамбургер + выдвижной сайдбар) ===== */
.nav-toggle {
    display: none;
    background: var(--bg-panel-2); border: 1px solid var(--border); color: var(--text);
    border-radius: var(--radius-sm); width: 34px; height: 34px; font-size: 18px;
    cursor: pointer; margin-right: 10px; align-items: center; justify-content: center; flex: none;
}
.nav-toggle:hover { border-color: var(--border-strong); }
.nav-backdrop { display: none; }

@media (max-width: 800px) {
    .nav-toggle { display: inline-flex; }
    .sidebar {
        position: fixed; top: 0; left: 0; height: 100dvh; width: min(280px, 80vw);
        transform: translateX(-100%); transition: transform .2s ease; z-index: 200; overflow-y: auto;
    }
    .app-shell.nav-open .sidebar { transform: translateX(0); box-shadow: 0 0 40px rgba(0,0,0,.5); }
    .app-shell.nav-open .nav-backdrop { display: block; position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 190; }
    .main { width: 100%; min-width: 0; }
    .content { padding-left: 12px; padding-right: 12px; }
    .topbar { position: sticky; top: 0; z-index: 100; padding: 0 12px; }
    /* Длинный заголовок в шапке скрываем — контекст даёт логотип и заголовок страницы */
    .topbar .crumb { display: none; }
    /* На узких экранах сводка посещаемости — 2×2 вместо 4 в ряд */
    .att-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ===== Журнал проходов: мультивыбор фильтров, инлайн-поля ===== */
.field-inline { flex-direction: row; align-items: center; gap: 6px; }
.ms { position: relative; }
.ms > summary {
    list-style: none; cursor: pointer; user-select: none;
    background: var(--bg); border: 1px solid var(--border-strong); color: var(--text);
    border-radius: var(--radius-sm); padding: 9px 11px; font-size: 13px; white-space: nowrap;
}
.ms > summary::-webkit-details-marker { display: none; }
.ms > summary:hover { border-color: var(--accent); }
.ms[open] > summary { border-color: var(--accent); }
.ms-panel {
    position: absolute; z-index: 50; margin-top: 6px; min-width: 220px; max-height: 320px; overflow-y: auto;
    background: var(--bg-panel); border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
    padding: 8px; box-shadow: 0 8px 30px rgba(0,0,0,.35);
}
.ms-item { display: flex; align-items: center; gap: 8px; padding: 5px 6px; border-radius: var(--radius-sm); font-size: 13px; cursor: pointer; }
.ms-item:hover { background: var(--bg-panel-2); }
.ms-item input { width: auto; }

/* Шапка для печати — скрыта на экране, видна только при печати */
.print-only { display: none; }

/* ===== Версия для печати журнала проходов ===== */
@media print {
    /* Убираем «хром» приложения и интерактивные элементы */
    .sidebar, .topbar, .nav-toggle, .nav-backdrop, .pager, .no-print { display: none !important; }
    .app-shell, .main, .content { display: block !important; width: auto !important; margin: 0 !important; padding: 0 !important; }
    .card { border: none !important; box-shadow: none !important; background: #fff !important; margin: 0 !important; }
    .print-only { display: block !important; }
    .print-head { margin-bottom: 10px; }
    .print-head h2 { margin: 0 0 4px; }
    .print-head div { font-size: 12px; color: #333; }
    /* Читаемая ч/б таблица на бумаге */
    body, .grid, .table-wrap table { background: #fff !important; color: #000 !important; }
    .grid th, .table-wrap th { background: #eee !important; color: #000 !important; border-bottom: 1px solid #999 !important; }
    .grid td, .table-wrap td { border-bottom: 1px solid #ccc !important; }
    .grid tbody tr, .badge { animation: none !important; }
    .badge { border: 1px solid #999 !important; color: #000 !important; background: transparent !important; }
    @page { margin: 12mm; }
}

/* --- Access matrix (many employees × many doors) --- */
.matrix-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 860px) { .matrix-grid { grid-template-columns: 1fr; } }
.matrix-grid .card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.matrix-filters { display: flex; gap: 8px; margin-bottom: 8px; flex-wrap: wrap; }
.matrix-filters select, .matrix-filters input { flex: 1 1 140px; min-width: 0; }
.matrix-actions-row { display: flex; gap: 8px; margin-bottom: 8px; }
.matrix-list { max-height: 320px; overflow-y: auto; display: flex; flex-direction: column; gap: 6px;
    border: 1px solid var(--border); border-radius: 8px; padding: 8px; background: var(--bg); }
.matrix-list .check { padding: 3px 4px; border-radius: 6px; }
.matrix-list .check:hover { background: var(--bg-elev); }
.matrix-list .muted, .muted { color: var(--text-dim); }
.matrix-apply { margin-top: 16px; display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap; }
.matrix-apply .seg-field { min-width: 220px; }
.matrix-buttons { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.matrix-buttons .sep { width: 1px; height: 26px; background: var(--border-strong); margin: 0 4px; }
.matrix-hint { color: var(--text-dim); font-size: 12.5px; margin-left: auto; }
.pill { background: var(--bg-elev); border: 1px solid var(--border); border-radius: 999px;
    padding: 2px 10px; font-size: 12px; color: var(--text-dim); font-weight: 600; }
.banner { padding: 10px 14px; border-radius: 8px; margin-bottom: 14px; font-size: 13.5px; font-weight: 500; }
.banner-ok { background: var(--ok-bg); color: var(--ok); border: 1px solid var(--ok); }
.banner-error { background: var(--danger-bg); color: var(--danger); border: 1px solid var(--danger); }

/* ===== Каталог фото (галерея сотрудников) ===== */
.photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 14px; }
.photo-card { display: flex; flex-direction: column; background: var(--bg-panel-2); border: 1px solid var(--border);
    border-radius: var(--radius); overflow: hidden; text-decoration: none; color: inherit; transition: border-color .15s, transform .15s, box-shadow .15s; }
.photo-card:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: var(--shadow); }
.photo-thumb { position: relative; aspect-ratio: 1 / 1; background: var(--bg-elev);
    display: flex; align-items: center; justify-content: center; overflow: hidden; }
.photo-thumb img { width: 100%; height: 100%; object-fit: cover; }
.photo-initials { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;
    font-size: 34px; font-weight: 700; color: var(--accent); letter-spacing: .04em; text-transform: uppercase; }
.photo-meta { padding: 8px 10px; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.photo-name { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.photo-sub { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 11.5px; color: var(--text-dim); }
.photo-sub .photo-dept { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ===== Access Rights: группировка прав по сотруднику (аккордеон) ===== */
.priv-toolbar { display: flex; align-items: center; gap: 14px; margin-bottom: 14px; flex-wrap: wrap; }
.priv-toolbar .search { position: relative; }
.priv-toolbar .search input { width: 300px; max-width: 100%; padding-left: 32px; }
.priv-toolbar .search .ico { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--text-mute); }
.priv-group { border: 1px solid var(--border); border-radius: var(--radius-sm); margin-bottom: 8px;
    background: var(--bg-panel); overflow: hidden; animation: rise .28s ease both; }
.priv-group-head { display: flex; align-items: center; gap: 10px; cursor: pointer; user-select: none;
    background: var(--bg-panel-2); padding: 10px 14px; font-weight: 600; transition: background .12s; }
.priv-group-head:hover { background: var(--bg-elev); }
.priv-group-head .chev { color: var(--text-dim); font-size: 12px; transition: transform .18s ease; width: 12px; }
.priv-group.open .priv-group-head .chev { transform: rotate(90deg); }
.priv-group-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.priv-group-body table.grid { border-radius: 0; }
.priv-group-body table.grid thead th { background: var(--bg); }
.priv-door-list { max-height: 360px; overflow-y: auto; display: flex; flex-direction: column;
    border: 1px solid var(--border); border-radius: 8px; background: var(--bg); }
/* Дети flex-колонки с ограниченной высотой по умолчанию СЖИМАЮТСЯ (flex-shrink:1) вместо прокрутки —
   группы контроллеров плющились друг на друга (overflow:hidden дорезал). Запрещаем сжатие: пусть скроллится. */
.priv-door-list > * { flex-shrink: 0; }
.priv-door-row { display: flex; align-items: center; gap: 10px; padding: 6px 10px; border-bottom: 1px solid var(--border); }
.priv-door-row:last-child { border-bottom: none; }
.priv-door-row .check { flex: 1; min-width: 0; padding: 0; }
.priv-door-row select { flex: 0 0 200px; max-width: 200px; }
/* Групповое управление правами по контроллерам */
.priv-edit-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 10px; flex-wrap: wrap; }
.priv-bulk { display: inline-flex; align-items: center; gap: 6px; }
.priv-ctrl-group { margin-bottom: 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
.priv-ctrl-head { display: flex; align-items: center; gap: 8px; padding: 6px 10px; background: rgba(127,127,127,.06); border-bottom: 1px solid var(--border); }
.priv-ctrl-name { font-weight: 600; font-size: 13px; }

/* Действия строки за «⋮» (kebab-меню, как в EMS) */
.rowmenu { position: relative; display: inline-block; }
.rowmenu-trigger { width: 30px; height: 28px; border: 1px solid var(--border); background: var(--bg-panel); border-radius: 6px; cursor: pointer; color: var(--text-dim); font-size: 16px; line-height: 1; }
.rowmenu-trigger:hover { background: rgba(127,127,127,.1); color: var(--text); }
.rowmenu-backdrop { position: fixed; inset: 0; z-index: 8000; }
.rowmenu-pop { position: fixed; z-index: 8001; min-width: 160px; max-height: 70vh; overflow-y: auto; background: var(--bg-panel); border: 1px solid var(--border); border-radius: var(--radius-sm); box-shadow: 0 8px 24px rgba(0,0,0,.35); padding: 4px; display: flex; flex-direction: column; }
.rowmenu-item { display: flex; align-items: center; gap: 8px; padding: 8px 12px; background: none; border: 0; text-align: left; cursor: pointer; border-radius: 6px; font-size: 13px; color: var(--text); width: 100%; white-space: nowrap; text-decoration: none; }
.rowmenu-item:hover { background: rgba(127,127,127,.12); }
.rowmenu-item.danger { color: var(--danger); }
/* Иконка пункта меню: фиксированная колонка, иначе подписи «пляшут» из-за разной ширины глифов/эмодзи */
.rowmenu-item .mi { flex: 0 0 20px; width: 20px; text-align: center; line-height: 1; }

/* Миниатюра кадра камеры в таблице Cameras */
.cam-thumb { width: 90px; height: 54px; border-radius: 6px; overflow: hidden; background: #0c0c12; display: flex; align-items: center; justify-content: center; }
.cam-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cam-thumb-ph { font-size: 22px; opacity: .4; }

/* Выбор дверей монитора (модалка Monitors) */
.mon-doors-pick { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px; max-height: 240px; overflow-y: auto; padding: 8px; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.mon-ctrl-name { font-size: 12px; font-weight: 600; color: var(--text-dim); margin-bottom: 4px; }
.mon-ctrl .check { display: flex; align-items: center; gap: 6px; font-size: 13px; padding: 2px 0; }

/* ============================================================
   Monitor Wall — киоск-стена живых проходов и тревог
   (в стиле EMS/runexe MonitorUi). Всегда тёмная, на весь экран,
   для ТВ/планшета на посту охраны. Классы namespaced `mw-`.
   ============================================================ */
.mw {
    --mw-bg: #07070b; --mw-bar: #0c0d13; --mw-card: #111219;
    --mw-line: rgba(255,255,255,.09);
    --mw-text: #fff; --mw-dim: rgba(255,255,255,.72);
    --mw-grant: 34,197,94; --mw-deny: 255,82,82; --mw-alarm: 255,64,64;
    --mw-idle: rgba(255,255,255,.4); --mw-idle-ring: rgba(255,255,255,.18);
    position: fixed; inset: 0; z-index: 1000;
    display: flex; flex-direction: column;
    background: var(--mw-bg); color: var(--mw-text);
    font-family: var(--font, system-ui, "Segoe UI", sans-serif);
    overflow: hidden; user-select: none; -webkit-user-select: none; touch-action: manipulation;
}

/* ---------- Светлая тема стены (переключатель ☀/☾ в панели) ---------- */
.mw.mw-light {
    --mw-bg: #eef1f6; --mw-bar: #ffffff; --mw-card: #ffffff;
    --mw-line: rgba(0,0,0,.1);
    --mw-text: #16202e; --mw-dim: rgba(22,32,46,.6);
    --mw-idle: rgba(22,32,46,.4); --mw-idle-ring: rgba(0,0,0,.18);
}
.mw-light .mw-bar { border-bottom-color: rgba(0,0,0,.08); box-shadow: 0 1px 6px rgba(16,20,26,.08); }
.mw-light .mw-clock { color: #b26a00; }
.mw-light .mw-iconbtn { border-color: rgba(0,0,0,.14); background: rgba(0,0,0,.04); color: #16202e; }
.mw-light .mw-iconbtn:hover { background: rgba(0,0,0,.09); }
.mw-light .mw-iconbtn.is-on { background: rgba(0,0,0,.12); }
.mw-light .mw-sel, .mw-light .mw-sel option { background: #fff; color: #16202e; border-color: rgba(0,0,0,.16); }
.mw-light .mw-fresh { background: rgba(0,0,0,.05); border-color: rgba(0,0,0,.14); color: #1a7a4a; }
.mw-light .mw-hist { background: #f4f6fa; border-left-color: rgba(0,0,0,.08); }
.mw-light .mw-hist-head { background: #f4f6fa; }
.mw-light .mw-hrow { border-color: rgba(0,0,0,.08); }
.mw-light .mw-hrow.deny { background: #fdecec; }
.mw-light .mw-hrow-av { background: #e3e7ee; color: rgba(22,32,46,.5); }
.mw-light .mw-pip-ini { color: rgba(22,32,46,.5); }

/* ---------- Верхняя панель ---------- */
.mw-bar {
    display: flex; align-items: center; gap: 14px;
    height: 54px; flex: 0 0 54px; padding: 0 16px;
    background: var(--mw-bar); border-bottom: 1px solid var(--mw-line);
}
.mw-brand { display: flex; align-items: center; gap: 9px; font-weight: 800; letter-spacing: .01em; white-space: nowrap; }
.mw-brand img { height: 24px; width: auto; }
.mw-live-dot { width: 8px; height: 8px; border-radius: 50%; background: #4ade80; box-shadow: 0 0 0 0 rgba(74,222,128,.5); animation: mwPulseDot 1.6s ease-in-out infinite; }
@keyframes mwPulseDot { 0%,100% { opacity: 1; } 50% { opacity: .35; } }
.mw-clock { margin: 0 auto; font-size: 1.5rem; font-weight: 800; font-variant-numeric: tabular-nums; letter-spacing: .06em; color: #ffd54f; }
.mw-tools { display: flex; align-items: center; gap: 8px; white-space: nowrap; }

.mw-fresh {
    padding: 2px 9px; border: 1px solid rgba(255,255,255,.28); border-radius: 12px;
    background: rgba(0,0,0,.4); color: #69f0ae; font-size: .78rem; font-weight: 700;
    font-variant-numeric: tabular-nums; transition: color .3s, background .3s, border-color .3s;
}
.mw-fresh.is-warn { color: #ffd54f; border-color: rgba(255,213,79,.7); }
.mw-fresh.is-stale { color: #fff; background: #c62828; border-color: #ff5252; animation: mwAlert 1.1s ease-in-out infinite alternate; }
@keyframes mwAlert { from { opacity: 1; } to { opacity: .45; } }

.mw-iconbtn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; border-radius: 8px; cursor: pointer;
    border: 1px solid var(--mw-line); background: rgba(255,255,255,.05);
    color: var(--mw-text); font-size: 15px; line-height: 1; text-decoration: none;
    transition: background .15s, border-color .15s;
}
.mw-iconbtn:hover { background: rgba(255,255,255,.12); }
.mw-iconbtn.is-off { color: #ff8a80; border-color: rgba(255,138,128,.45); }

.mw-cols { display: inline-flex; border: 1px solid var(--mw-line); border-radius: 8px; overflow: hidden; }
.mw-cols button { width: 28px; height: 32px; border: 0; background: transparent; color: var(--mw-dim); cursor: pointer; font-size: 13px; font-weight: 700; }
.mw-cols button.sel { background: rgba(255,255,255,.14); color: #fff; }

.mw-hold { display: inline-flex; align-items: center; gap: 5px; color: var(--mw-dim); font-size: 13px; }
/* тёмный фон И у самого select, И у раскрытого списка опций — иначе на светлой ОС был белый текст на белом */
.mw-sel { height: 32px; padding: 0 6px; border-radius: 8px; border: 1px solid var(--mw-line); background: #14161d; color: #fff; font-size: 12px; }
.mw-sel option { background: #14161d; color: #fff; }
.mw-demo { display: inline-flex; align-items: center; gap: 5px; color: var(--mw-dim); font-size: 12px; }
.mw-iconbtn.is-on { background: rgba(255,255,255,.16); border-color: rgba(255,255,255,.3); }

/* ---------- Тело: сцена + панель истории ---------- */
.mw-body { flex: 1 1 auto; min-height: 0; display: flex; }
.mw-stage { position: relative; flex: 1 1 auto; min-width: 0; min-height: 0; }

/* ---------- Панель истории (справа, как в EMS) ---------- */
.mw-hist { flex: 0 0 320px; overflow-y: auto; padding: 10px; display: flex; flex-direction: column; gap: 7px; background: #0a0b10; border-left: 1px solid var(--mw-line); }
.mw-hist-head { font-size: .72rem; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; color: var(--mw-dim); padding: 2px 4px 6px; position: sticky; top: -10px; background: #0a0b10; }
.mw-hist-empty { padding: 24px 8px; text-align: center; font-size: .78rem; letter-spacing: .08em; text-transform: uppercase; opacity: .4; }
.mw-hrow { position: relative; display: flex; align-items: center; gap: 9px; padding: 7px 10px 7px 11px; border-radius: 10px; background: var(--mw-card); border: 1px solid var(--mw-line); border-left: 3px solid rgba(var(--accent), .85); --accent: var(--mw-grant); animation: mwHrowIn .3s ease both; }
.mw-hrow.grant { --accent: var(--mw-grant); }
.mw-hrow.deny  { --accent: var(--mw-deny); background: #1c0709; }
@keyframes mwHrowIn { from { opacity: 0; transform: translateX(10px); } to { opacity: 1; transform: none; } }
/* миниатюра-фото в строке истории (или инициалы, если фото нет) */
.mw-hrow-av { position: relative; flex: 0 0 auto; width: 38px; height: 38px; border-radius: 8px; overflow: hidden; background: #000; display: flex; align-items: center; justify-content: center; font-size: .78rem; font-weight: 700; color: rgba(255,255,255,.4); }
.mw-hrow-av img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.mw-hrow-main { flex: 1 1 auto; min-width: 0; }
.mw-hrow-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.mw-hrow-name { font-size: .9rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mw-hrow-time { font-size: .72rem; font-variant-numeric: tabular-nums; opacity: .6; white-space: nowrap; }
.mw-hrow-sub { margin-top: 2px; font-size: .74rem; opacity: .62; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.mw-idle { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.mw-idle-ring { width: 96px; height: 96px; border-radius: 50%; border: 1px solid var(--mw-idle-ring); display: flex; align-items: center; justify-content: center; margin-bottom: 20px; font-size: 40px; color: var(--mw-idle-ring); animation: mwFloat 4s ease-in-out infinite; }
@keyframes mwFloat { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-9px); } }
.mw-idle-clock { font-size: clamp(3rem, 10vw, 8rem); font-weight: 800; color: var(--mw-idle); font-variant-numeric: tabular-nums; letter-spacing: .04em; line-height: 1; }
.mw-idle-label { margin-top: 14px; font-size: .75rem; color: var(--mw-idle); letter-spacing: .22em; text-transform: uppercase; }

.mw-grid { height: 100%; display: grid; gap: 10px; padding: 10px; grid-auto-rows: 1fr; }

/* ---------- Плитка ---------- */
.mw-tile {
    position: relative; overflow: hidden; border-radius: 16px; min-width: 0; min-height: 0;
    background: var(--mw-card); border: 1px solid rgba(var(--accent), .38);
    --accent: var(--mw-grant);
    animation: mwIn .42s cubic-bezier(.22,1,.36,1) both;
}
.mw-tile-grant { --accent: var(--mw-grant); }
.mw-tile-deny  { --accent: var(--mw-deny); }
.mw-tile-alarm { --accent: var(--mw-alarm); animation: mwIn .42s cubic-bezier(.22,1,.36,1) both, mwGlow 3s ease-in-out .4s infinite alternate; }
@keyframes mwIn { from { opacity: 0; transform: scale(.94) translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes mwGlow {
    from { box-shadow: 0 0 0 1px rgba(var(--mw-alarm),.3), 0 0 22px rgba(var(--mw-alarm),.08); }
    to   { box-shadow: 0 0 0 1px rgba(var(--mw-alarm),.6), 0 0 48px rgba(var(--mw-alarm),.22); }
}
/* уход плитки: проход «состарился» — плавно гаснет вместо резкого исчезновения */
.mw-tile.mw-leaving { animation: mwOut .5s cubic-bezier(.4,0,1,1) forwards; }
@keyframes mwOut { from { opacity: 1; transform: none; } to { opacity: 0; transform: scale(.9) translateY(-8px); } }

.mw-media { position: absolute; inset: 0; overflow: hidden; }
/* фото поверх аватар-инициалов (позже в DOM) — при наличии снимка он полностью перекрывает буквы */
.mw-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.mw-avatar { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-weight: 800; color: rgba(255,255,255,.14); font-size: clamp(2rem, 8vw, 7rem); }
.mw-tile-alarm .mw-avatar { color: rgba(255,64,64,.18); }

/* PiP (только админ-стена): по умолчанию камера крупно, фото человека маленьким в углу.
   Клик по уголку меняет их местами. Уголок — контейнер с картинкой/инициалами внутри. */
.mw-pip { position: absolute; z-index: 3; top: 10px; right: 10px; width: 40%; height: 30%; border-radius: 10px; overflow: hidden; border: 1px solid rgba(255,255,255,.3); box-shadow: 0 4px 16px rgba(0,0,0,.5); cursor: pointer; background: #0c0c12; display: flex; align-items: center; justify-content: center; transition: box-shadow .15s, transform .12s; }
.mw-pip:hover { box-shadow: 0 0 0 2px rgba(var(--mw-grant), .7), 0 4px 16px rgba(0,0,0,.5); transform: scale(1.03); }
.mw-pip img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mw-pip-ini { font-weight: 800; color: rgba(255,255,255,.5); font-size: 1.3rem; }

/* верхний бейдж-статус (иконка + слово: статус не только цветом) */
.mw-top { position: absolute; top: 10px; left: 10px; z-index: 3; }
.mw-badge { display: inline-flex; align-items: center; gap: .4em; padding: .3em .7em; border: 2px solid currentColor; border-radius: 6px; font-size: .72rem; font-weight: 900; line-height: 1; letter-spacing: .12em; text-transform: uppercase; }
.mw-badge-grant { color: #7ef0ad; background: rgba(0,52,22,.7); }
.mw-badge-deny  { color: #ff9a9a; background: rgba(80,0,0,.7); }
.mw-badge-alarm { color: #ff8080; background: rgba(90,0,0,.75); }
.mw-tile-alarm .mw-badge-ico { animation: mwBlink 1.1s steps(1,end) infinite; }
@keyframes mwBlink { 0%,55% { opacity: 1; } 56%,100% { opacity: .25; } }

/* нижний оверлей с текстом */
.mw-overlay { position: absolute; inset: 0; z-index: 2; display: flex; flex-direction: column; justify-content: flex-end; padding: 14px 16px; background: linear-gradient(to top, rgba(0,0,0,.94) 0%, rgba(0,0,0,.55) 40%, transparent 72%); pointer-events: none; }
.mw-name { font-weight: 800; line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-shadow: 0 2px 14px rgba(0,0,0,.9); }
.mw-desc { color: var(--mw-dim); line-height: 1.3; margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-shadow: 0 1px 8px rgba(0,0,0,.85); }

/* масштаб текста от числа колонок */
.mw[data-cols='1'] .mw-name { font-size: clamp(1.6rem, 3.4vw, 3.6rem); }
.mw[data-cols='1'] .mw-desc { font-size: clamp(1rem, 2vw, 2rem); }
.mw[data-cols='2'] .mw-name { font-size: clamp(1.2rem, 2.2vw, 2.4rem); }
.mw[data-cols='2'] .mw-desc { font-size: clamp(.9rem, 1.3vw, 1.4rem); }
.mw[data-cols='3'] .mw-name { font-size: clamp(1rem, 1.7vw, 1.7rem); }
.mw[data-cols='3'] .mw-desc { font-size: clamp(.78rem, 1vw, 1.15rem); }
.mw[data-cols='4'] .mw-name { font-size: clamp(.85rem, 1.3vw, 1.35rem); }
.mw[data-cols='4'] .mw-desc { font-size: clamp(.72rem, .9vw, 1rem); }

/* пилюля-длительность (для тревоги) */
.mw-pill { position: absolute; bottom: 12px; right: 12px; z-index: 3; background: rgba(0,0,0,.6); backdrop-filter: blur(8px); border: 1px solid rgba(255,255,255,.16); border-radius: 20px; padding: 3px 12px; font-size: .8rem; font-weight: 700; font-variant-numeric: tabular-nums; color: #ff5252; border-color: rgba(255,82,82,.45); animation: mwAlert 1.4s ease-in-out infinite alternate; }

/* кнопка реплея видео */
.mw-replay { position: absolute; top: 10px; right: 10px; z-index: 4; width: 30px; height: 30px; border-radius: 50%; border: 1px solid rgba(255,255,255,.25); background: rgba(0,0,0,.5); color: #fff; cursor: pointer; font-size: 13px; display: inline-flex; align-items: center; justify-content: center; opacity: .85; }
.mw-replay:hover { opacity: 1; transform: scale(1.08); }

/* ---------- Полноэкранные плашки (создаются из n3kWall) ---------- */
.mw-conn { position: fixed; inset: 0; z-index: 2147482000; display: none; align-items: center; justify-content: center; padding: 4vmin; background: rgba(0,0,0,.9); text-align: center; }
.mw-conn.is-visible { display: flex; }
.mw-conn-box { max-width: 90vw; padding: 5vmin 7vmin; border: 4px solid #ff5252; border-radius: 20px; background: rgba(45,0,0,.92); box-shadow: 0 0 80px rgba(255,82,82,.4); }
.mw-conn-title { font-size: clamp(2rem, 10vmin, 8rem); font-weight: 900; line-height: 1; letter-spacing: .06em; color: #ff5252; animation: mwAlert 1.2s ease-in-out infinite alternate; }
.mw-conn-sub { margin-top: .5em; font-size: clamp(1rem, 3vmin, 2.2rem); font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: #fff; }
.mw-conn-stamp { margin-top: .8em; font-size: clamp(1rem, 4vmin, 2.6rem); font-weight: 800; font-variant-numeric: tabular-nums; color: #ffd54f; }

.mw-audio { position: fixed; inset: 0; z-index: 2147483000; display: flex; align-items: center; justify-content: center; padding: 4vmin; background: rgba(0,0,0,.82); backdrop-filter: blur(3px); text-align: center; cursor: pointer; }
.mw-audio-box { max-width: 24em; padding: 5vmin 6vmin; border: 3px solid #ffb300; border-radius: 18px; background: rgba(30,20,0,.9); box-shadow: 0 0 60px rgba(255,179,0,.35); }
.mw-audio-ico { font-size: clamp(3rem, 9vmin, 6rem); line-height: 1; }
.mw-audio-title { margin-top: .3em; font-size: clamp(1.4rem, 5vmin, 3rem); font-weight: 900; color: #ffb300; }
.mw-audio-sub { margin-top: .7em; font-size: clamp(.9rem, 2.2vmin, 1.4rem); color: rgba(255,255,255,.88); }

@media (prefers-reduced-motion: reduce) {
    .mw-tile, .mw-tile-alarm, .mw-idle-ring, .mw-pill, .mw-live-dot, .mw-fresh.is-stale, .mw-conn-title, .mw-badge-ico { animation: none; }
}


/* ===== Фильтры журнала событий: одна строка, перенос по одному на узких экранах ===== */
.records-filters { flex-wrap: wrap; row-gap: 8px; }
.records-filters select { width: auto; flex: 0 0 auto; }        /* глобальный select { width:100% } растягивал «Any result» на всю строку */
.records-filters .field, .records-filters .ms { flex: 0 0 auto; }

/* Подсветка найденной подстроки в результатах поиска */
mark { background: rgba(255, 213, 79, .45); color: inherit; border-radius: 3px; padding: 0 1px; }
/* Сортируемые заголовки таблицы журнала */
.th-sort { cursor: pointer; user-select: none; white-space: nowrap; }
.th-sort:hover { color: var(--text); }
.sort-mark { font-size: 9px; opacity: .8; }
/* ===== Страница Buildings (живая схема здания, тач-плитки) ===== */
.bld-layout { display: flex; gap: 14px; align-items: flex-start; }
.bld-main { flex: 1 1 auto; min-width: 0; position: relative; }

/* Канвас этажа: план/сетка + панель свободных дверей одной строкой (панель — часть канваса, не оверлей) */
.bld-canvas { display: flex; align-items: stretch; min-height: 0; }
.bld-canvas-main { flex: 1 1 auto; min-width: 0; }
.bld-doorlist { flex: 0 0 260px; align-self: stretch; overflow-y: auto; max-height: 640px;
    background: var(--bg-elev); border-left: 1px solid var(--border); padding: 10px; margin: 0; }
.bld-doorlist-head { display: flex; align-items: center; justify-content: space-between; font-weight: 800;
    font-size: 13px; letter-spacing: .04em; padding: 2px 4px 8px; }
.bld-dl-item { display: flex; align-items: center; gap: 6px; padding: 9px 10px; margin-bottom: 6px;
    border: 1px dashed var(--border); border-radius: 9px; background: var(--bg-panel-2); cursor: grab;
    font-size: 13.5px; user-select: none; -webkit-user-select: none; }
.bld-dl-item:active { cursor: grabbing; }
.bld-dl-item:hover { border-color: var(--accent); }
.bld-dl-grip { opacity: .45; }
.bld-doorlist-hint { font-size: 11.5px; color: var(--text-dim); padding: 6px 4px 2px; }

/* Контекстное меню плитки/маркера */
.bld-ctx-overlay { position: fixed; inset: 0; z-index: 90; }
.bld-ctx { position: fixed; z-index: 91; min-width: 220px; background: var(--bg-elev); color: var(--text);
    border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 16px 44px rgba(0,0,0,.35); padding: 6px; }
.bld-ctx-title { font-weight: 800; font-size: 13px; padding: 6px 10px 8px; border-bottom: 1px solid var(--border);
    margin-bottom: 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bld-ctx-item { display: block; width: 100%; text-align: left; padding: 9px 10px; border: none; background: transparent;
    color: inherit; border-radius: 8px; cursor: pointer; font-size: 13.5px; }
.bld-ctx-item:hover { background: rgba(127,127,127,.14); }
.bld-ctx-item.danger { color: var(--danger); }
.bld-ctx-rename { display: flex; gap: 6px; padding: 4px; }
.bld-ctx-rename input { flex: 1; min-width: 0; }
.bld-ctx-hint { font-size: 11.5px; color: var(--text-dim); padding: 4px 8px 6px; }
.bld-side { flex: 0 0 300px; display: flex; flex-direction: column; gap: 12px; position: sticky; top: 10px;
    max-height: calc(100vh - 90px); overflow-y: auto; }
@media (max-width: 900px) { .bld-layout { flex-direction: column-reverse; } .bld-side { position: static; flex-basis: auto; width: 100%; max-height: none; } }

.bld-floor-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap;
    padding: 12px 16px; border-bottom: 1px solid var(--border); }
.bld-floor-head h2 { margin: 0; font-size: 18px; }

/* Сетка плиток: фиксированный минимум под палец; при сужении окна — вертикальная прокрутка. */
.bld-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; padding: 14px 16px; }
.bld-tile { position: relative; border: 2px solid var(--border); border-radius: 10px; padding: 14px 10px 10px;
    min-height: 74px; cursor: pointer; text-align: center; user-select: none; -webkit-user-select: none;
    background: var(--bg-panel-2); transition: border-color .15s, box-shadow .15s; touch-action: manipulation; }
.bld-tile:hover { box-shadow: 0 2px 10px rgba(0,0,0,.12); }
/* long-press перенос на таче: поднятая плитка и подсветка цели */
.bld-tile.bld-tile-lift { z-index: 30; box-shadow: 0 14px 34px rgba(0,0,0,.4); border-color: var(--accent); opacity: .92; transition: none; }
.bld-tile.bld-tile-target { border-style: dashed; border-color: var(--accent); }
.bld-tile-name { font-weight: 700; font-size: 14.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bld-tile-sub { display: flex; gap: 6px; align-items: center; justify-content: center; margin-top: 6px; font-size: 12px; color: var(--text-dim); }
.bld-tile-x { position: absolute; top: -8px; right: -8px; width: 22px; height: 22px; border-radius: 50%;
    border: 1px solid var(--border); background: var(--bg-elev); color: var(--danger); cursor: pointer; line-height: 1; }

/* Статусы плитки/маркера/шапки модалки */
.st-closed { border-color: var(--ok); }
.st-closed .bld-tile-state { color: var(--ok); }
.st-open { border-color: #5b9bff; }
.st-open .bld-tile-state { color: #5b9bff; font-weight: 700; }
.st-alarm { border-color: var(--danger); animation: bldPulse 1s infinite; }
.st-alarm .bld-tile-state { color: var(--danger); font-weight: 800; }
.st-off { border-color: var(--border); opacity: .55; }
@keyframes bldPulse { 0%,100% { box-shadow: 0 0 0 0 rgba(239,68,68,.5); } 50% { box-shadow: 0 0 0 7px rgba(239,68,68,0); } }

/* План этажа: пан/зум-канвас. Вьюпорт обрезает, канвас двигается transform'ом (n3kPlan в app.js). */
.bld-plan-outer { padding: 14px 16px; }
.bld-plan-vp { position: relative; overflow: hidden; height: clamp(380px, calc(100vh - 320px), 900px);
    border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); touch-action: none; }
.bld-plan { position: relative; width: 100%; transform-origin: 0 0; will-change: transform; cursor: grab; }
.bld-plan:active { cursor: grabbing; }
.bld-plan img { width: 100%; display: block; border-radius: 8px; user-select: none; -webkit-user-drag: none; }
.bld-plan-zoom { position: absolute; right: 10px; top: 10px; display: flex; flex-direction: column; gap: 6px; z-index: 6; }
.bld-plan-zoom .btn-icon { width: 34px; height: 34px; font-size: 17px; display: inline-flex; align-items: center; justify-content: center; background: var(--bg-elev); }
.bld-plan-empty { padding: 60px 16px; text-align: center; color: var(--text-dim); border: 1px dashed var(--border); border-radius: 8px; }
.bld-marker { position: absolute; transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center;
    padding: 3px 5px; border: 2px solid var(--border); border-radius: 8px;
    background: var(--bg-elev);                                        /* fallback для старых браузеров */
    background: color-mix(in srgb, var(--bg-elev) 55%, transparent);   /* полупрозрачный — план виден сквозь маркер */
    backdrop-filter: blur(2px);
    cursor: pointer; font-size: 15px; line-height: 1.1; user-select: none; }
.bld-marker .lbl { font-size: 10.5px; font-weight: 700; white-space: nowrap; }
.bld-marker.sel { outline: 3px solid var(--accent); }

/* Правая панель: здания/этажи/тикеры */
.bld-bcard { overflow: hidden; }
.bld-bhead { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--border); }
.bld-bhead input { flex: 1; min-width: 0; }
.bld-bhead-btns { margin-left: auto; display: inline-flex; gap: 3px; }
.bld-mass { display: flex; gap: 6px; padding: 8px 12px; border-bottom: 1px solid var(--border); }
.bld-frow { display: flex; align-items: center; gap: 8px; padding: 9px 12px; cursor: pointer; border-bottom: 1px solid var(--border); }
.bld-frow:last-child { border-bottom: none; }
.bld-frow:hover { background: rgba(127,127,127,.07); }
.bld-frow.active { background: rgba(91,155,255,.12); box-shadow: inset 3px 0 0 var(--accent); }
.bld-frow.alarming { background: rgba(239,68,68,.10); }
.bld-frow input { flex: 1; min-width: 0; }
.bld-fname { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bld-chips { margin-left: auto; display: inline-flex; gap: 4px; flex-shrink: 0; }
.bld-chip { font-size: 11px; font-weight: 700; padding: 2px 7px; border-radius: 20px; background: rgba(127,127,127,.13); color: var(--text-dim); }
.bld-chip.open { background: rgba(91,155,255,.16); color: #5b9bff; }
.bld-chip.armed { background: rgba(45,212,191,.16); color: var(--ok); }
.bld-chip.alarm { background: rgba(239,68,68,.18); color: var(--danger); }
.bld-chip.off { background: rgba(127,127,127,.2); }

/* Модалка действий (тач-стиль как оверлей «tap to enable sound») */
.bld-overlay { position: fixed; inset: 0; z-index: 1000; background: rgba(0,0,0,.55); display: flex; align-items: center; justify-content: center; padding: 16px; }
.bld-sheet { width: 100%; max-width: 420px; max-height: calc(100vh - 40px); overflow-y: auto; border-radius: 16px;
    opacity: 1; filter: none;   /* статус-классы (st-off и т.п.) приглушают плитки, но не модалку */
    background: var(--bg-elev); border-top: 6px solid var(--border); box-shadow: 0 18px 60px rgba(0,0,0,.4); padding: 18px; }
.bld-sheet.st-closed { border-top-color: var(--ok); }
.bld-sheet.st-open { border-top-color: #5b9bff; }
.bld-sheet.st-alarm { border-top-color: var(--danger); }
.bld-sheet-head { text-align: center; margin-bottom: 12px; }
.bld-sheet-title { font-size: 21px; font-weight: 800; }
.bld-sheet-state { color: var(--text-dim); font-weight: 600; margin-top: 2px; }
.bld-sheet-rename { display: flex; gap: 8px; margin-bottom: 12px; }
.bld-sheet-rename input { flex: 1; min-width: 0; }
.bld-sheet-btns { display: flex; flex-direction: column; gap: 8px; }
.bld-act { padding: 13px 14px; font-size: 15.5px; font-weight: 700; border-radius: 10px; border: 1px solid var(--border);
    background: var(--bg-panel-2); cursor: pointer; text-align: left; touch-action: manipulation; color: inherit; }
.bld-act:hover:not(:disabled) { filter: brightness(1.06); border-color: var(--accent); }
.bld-act:disabled { opacity: .45; cursor: not-allowed; }
.bld-act.open { border-color: var(--ok); }
.bld-act.armed { border-color: var(--ok); color: var(--ok); }
.bld-act.close { text-align: center; color: var(--text-dim); }

/* ===== Киоск здания (/b/{token} — настенный планшет) ===== */
.kiosk { height: 100vh; display: flex; flex-direction: column; background: var(--bg); color: var(--text); overflow: hidden; }
.kiosk-center { align-items: center; justify-content: center; }
.kiosk-title { font-size: 20px; font-weight: 800; }
.kiosk-clock { font-size: 22px; font-weight: 800; font-variant-numeric: tabular-nums; }
.kiosk-date { color: var(--text-dim); font-weight: 600; }
.kiosk-body { flex: 1; display: flex; gap: 14px; padding: 0 14px 0 0; min-height: 0; }
.kiosk-main { flex: 1 1 auto; min-width: 0; position: relative; overflow: hidden; }
/* HUD внутри канваса: слева заголовок+переключатель, справа часы — контент под ними на всю высоту */
.kiosk-hud { position: absolute; top: 10px; left: 12px; z-index: 30; display: flex; align-items: center; gap: 12px;
    padding: 7px 14px; border: 1px solid var(--border); border-radius: 12px;
    background: var(--bg-elev);
    background: color-mix(in srgb, var(--bg-elev) 72%, transparent);
    backdrop-filter: blur(5px); }
.kiosk-hud-right { left: auto; right: 12px; }
.kiosk-scroll { height: 100%; overflow-y: auto; padding: 62px 16px 16px; }
.kiosk-plan-fill { position: absolute; inset: 0; }
.kiosk-plan-fill .bld-plan-vp { height: 100%; }
.kiosk-plan-fill .bld-plan-zoom { top: auto; bottom: 14px; right: 14px; }   /* верхний правый угол занят часами HUD */
.kiosk-grid { padding: 0; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
.kiosk-grid .bld-tile { min-height: 88px; font-size: 16px; }
.kiosk-side { flex: 0 0 280px; overflow-y: auto; border-left: 1px solid var(--border); padding: 12px 0 12px 14px; }
.kiosk-side-head { font-size: 13px; font-weight: 800; letter-spacing: .12em; color: var(--text-dim); padding: 4px 0 10px; }
.kiosk-frow { display: flex; align-items: center; gap: 8px; padding: 12px 10px; border-radius: 10px; cursor: pointer;
    border: 1px solid transparent; touch-action: manipulation; }
.kiosk-frow:hover { background: rgba(127,127,127,.1); }
.kiosk-frow.active { border-color: var(--accent); background: rgba(91,155,255,.12); }
.kiosk-frow.alarming { background: rgba(239,68,68,.12); }
@media (max-width: 760px) { .kiosk-body { flex-direction: column-reverse; } .kiosk-side { border-left: none; padding-left: 0; flex-basis: auto; } }

/* Цифровая клавиатура PIN */
.kiosk-pin { text-align: center; }
.kiosk-pin-title { font-weight: 700; margin-bottom: 8px; }
.kiosk-pin-dots { min-height: 26px; font-size: 18px; letter-spacing: 5px; margin-bottom: 10px; }
.kiosk-pin-pad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.kiosk-key { padding: 14px 0; font-size: 19px; font-weight: 800; border-radius: 10px; border: 1px solid var(--border);
    background: var(--bg-panel-2); cursor: pointer; touch-action: manipulation; color: inherit; }
.kiosk-key.ok { border-color: var(--ok); color: var(--ok); }
.kiosk-key:disabled { opacity: .4; }

/* Перетаскивание маркеров плана в edit mode: без touch-action браузер скроллил бы вместо drag'а. */
.bld-plan.editable .bld-marker { touch-action: none; cursor: grab; }
.bld-plan.editable .bld-marker.dragging { cursor: grabbing; opacity: .85; outline: 3px solid var(--accent); z-index: 5; }

/* Мини-дверь в плитке Buildings: та же 3D-сцена, что в Door Monitoring, но компактная.
   Пропорции пересчитаны под мелкий размер: тонкая рамка, полотно почти на весь проём,
   «деревянный» градиент и латунная ручка — дверь остаётся узнаваемой даже в 22px. */
.door.mini { flex: none; min-width: 0; max-width: none; margin: 0 auto 8px; }
.door.mini .door-scene { width: 34px; height: 54px; }
.kiosk-grid .door.mini .door-scene { width: 42px; height: 66px; }
.door.mini .door-frame, .door.micro .door-frame { border-width: 2px; border-radius: 3px 3px 1px 1px; box-shadow: inset 0 0 7px rgba(0,0,0,.45); }
.door.micro .door-frame { border-width: 1.5px; }
.door.mini .door-leaf, .door.micro .door-leaf { inset: 2px; border-radius: 2px; background: linear-gradient(160deg, #c08a5c, #96683f); }
.door.micro .door-leaf { inset: 1.5px; }
.door.mini .door-leaf::before { inset: 4px 3px; border-color: rgba(60,35,15,.35); }
.door.micro .door-leaf::before { display: none; }
.door.mini .door-leaf .handle, .door.micro .door-leaf .handle { background: #ffd97a; box-shadow: 0 0 3px rgba(255,217,122,.8); }
.door.mini .door-leaf .handle { width: 4px; height: 4px; margin-right: 3px; }
.bld-addfloor { padding: 8px 12px; border-top: 1px solid var(--border); }

/* Заголовки секций в сводных режимах Buildings («All doors» / «All floors»). */
.bld-sect-head { padding: 12px 16px 0; font-weight: 800; font-size: 15px; cursor: pointer; }
.bld-sect-head:hover { color: var(--accent); }

/* Микро-дверь в маркере плана (ещё меньше мини-плитки). */
.door.micro { margin: 0 auto 2px; }
.door.micro .door-scene { width: 22px; height: 34px; }
.door.micro .door-leaf .handle { width: 3px; height: 3px; margin-right: 2px; }

/* Тревожная полоса Buildings/киоска: видна с любого экрана, ведёт к двери. */
.bld-alarmbar { display: flex; align-items: center; gap: 10px; padding: 10px 14px; margin-bottom: 12px;
    border: 1px solid var(--danger); border-radius: var(--radius); background: var(--danger-bg);
    animation: bldPulse 1s infinite; }
.bld-alarmbar-ico { font-size: 18px; }
.bld-alarmbar-text { font-weight: 800; color: var(--danger); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kiosk .bld-alarmbar { margin: 10px 20px 0; }

/* Поиск дверей на странице Buildings. */
.bld-search { width: 170px; }

/* Кнопка полноэкрана в шапке киоска. */
.kiosk-fs { border: 1px solid var(--border); background: transparent; color: var(--text-dim); border-radius: 8px;
    width: 38px; height: 38px; font-size: 18px; cursor: pointer; touch-action: manipulation; }
.kiosk-fs:hover { color: var(--text); border-color: var(--border-strong); }

/* Лента последних проходов этажа (Buildings). */
.bld-feed { border-top: 1px solid var(--border); padding: 10px 16px 14px; }
.bld-feed-head { font-size: 12px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--text-dim); margin-bottom: 6px; }
.bld-feed-row { display: flex; gap: 12px; align-items: baseline; padding: 3px 0; font-size: 13px; }
.bld-feed-who { font-weight: 600; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bld-feed-row .log-result { font-size: 12px; }

/* Тулбар этажа: компактные контролы, не растягиваются на всю ширину карточки. */
.bld-floor-head .toolbar { justify-content: flex-end; align-items: center; }
.bld-floor-head .toolbar select { max-width: 240px; }
.bld-floor-head .bld-search { flex: 0 0 170px; }

/* ===== Появление новой плитки в Live access ===== */
/* Новая карточка выдвигается из-под верхнего края панели (translateY из минуса, контейнер клипует),
   а рост max-height от нуля плавно раздвигает остальные плитки вниз. margin-top в старте
   компенсирует flex-gap контейнера, чтобы не было мгновенной 12px-ступеньки. */
@keyframes accSlideIn {
    from { max-height: 0; opacity: 0; transform: translateY(-44px); margin-top: -12px; }
    60%  { opacity: .65; }
    to   { max-height: 320px; opacity: 1; transform: translateY(0); margin-top: 0; }
}
.acc-col .acc-card.acc-in { animation: accSlideIn .45s cubic-bezier(.2, .8, .3, 1) both; }
@media (prefers-reduced-motion: reduce) { .acc-col .acc-card.acc-in { animation: none; } }

/* ===== Кейпад двери на стене монитора (плавающая кнопка + панель) ===== */
.mwk-fab { position: fixed; left: 22px; bottom: 22px; z-index: 60; width: 64px; height: 64px; border-radius: 50%;
    border: 1px solid rgba(255,255,255,.14); background: rgba(20, 27, 38, .82); color: #e8eef5; font-size: 26px;
    cursor: pointer; box-shadow: 0 10px 30px rgba(0,0,0,.5); backdrop-filter: blur(6px);
    transition: transform .15s, box-shadow .15s, border-color .15s; touch-action: manipulation; }
.mwk-fab:hover { transform: scale(1.07); border-color: var(--accent); box-shadow: 0 12px 34px rgba(45,212,191,.25); }
.mw-light .mwk-fab { background: rgba(255,255,255,.9); color: #17202e; border-color: rgba(0,0,0,.12); }

.mwk-overlay { position: fixed; inset: 0; z-index: 70; background: rgba(0,0,0,.6); backdrop-filter: blur(3px);
    display: flex; align-items: flex-end; justify-content: flex-start; padding: 22px; }
.mwk-sheet { width: 380px; max-width: calc(100vw - 44px); max-height: calc(100vh - 44px); overflow-y: auto;
    border-radius: 18px; background: #161c26; color: #e8eef5; border: 1px solid rgba(255,255,255,.1);
    box-shadow: 0 24px 70px rgba(0,0,0,.6); padding: 16px; animation: mwkIn .22s cubic-bezier(.2,.8,.3,1); }
@keyframes mwkIn { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: translateY(0); } }
.mw-light .mwk-sheet { background: #ffffff; color: #17202e; border-color: rgba(0,0,0,.1); }

.mwk-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.mwk-title { font-weight: 800; font-size: 17px; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mwk-title-sub { font-weight: 600; font-size: 12.5px; opacity: .55; margin-left: 6px; }
.mwk-x { border: none; background: transparent; color: inherit; opacity: .6; font-size: 17px; cursor: pointer;
    width: 34px; height: 34px; border-radius: 8px; touch-action: manipulation; }
.mwk-x:hover { opacity: 1; background: rgba(127,127,127,.15); }

.mwk-input { width: 100%; font-size: 19px; padding: 11px 13px; border-radius: 11px; margin-bottom: 10px;
    border: 1px solid rgba(255,255,255,.14); background: rgba(0,0,0,.25); color: inherit; }
.mw-light .mwk-input { background: #f4f6fa; border-color: rgba(0,0,0,.12); }
.mwk-input:focus { outline: none; border-color: var(--accent); }

.mwk-matches { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; min-height: 40px; }
.mwk-match { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-radius: 10px;
    border: 1px solid rgba(255,255,255,.1); background: rgba(255,255,255,.04); color: inherit;
    cursor: pointer; text-align: left; font-size: 14.5px; touch-action: manipulation; }
.mwk-match:hover { border-color: var(--accent); background: rgba(45,212,191,.08); }
.mw-light .mwk-match { border-color: rgba(0,0,0,.1); background: #f7f9fc; }
.mwk-match-door { font-weight: 700; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mwk-match-ctrl { opacity: .55; font-size: 12.5px; white-space: nowrap; }
.mwk-match-armed { font-size: 13px; }
.mwk-none { padding: 10px 4px; opacity: .55; font-size: 13.5px; }

.mwk-pad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.mwk-key { padding: 14px 0; font-size: 20px; font-weight: 800; border-radius: 11px;
    border: 1px solid rgba(255,255,255,.12); background: rgba(255,255,255,.05); color: inherit;
    cursor: pointer; touch-action: manipulation; }
.mwk-key:hover { border-color: var(--accent); }
.mw-light .mwk-key { border-color: rgba(0,0,0,.12); background: #f4f6fa; }

.mwk-video { width: 100%; border-radius: 12px; background: #000; margin-bottom: 10px; max-height: 240px; object-fit: cover; }
.mwk-cam { position: relative; }
.mwk-cam-live { position: absolute; top: 8px; left: 8px; font-size: 11px; font-weight: 800; letter-spacing: .06em;
    color: #fff; background: rgba(220,38,38,.85); padding: 2px 8px; border-radius: 999px; pointer-events: none; }
.mwk-acts { display: flex; flex-direction: column; gap: 8px; }
/* Кнопки действий не зависят от темы приложения — лист тёмный/светлый сам по себе */
.mwk-acts .bld-act { background: rgba(255,255,255,.07); border-color: rgba(255,255,255,.16); color: #e8eef5; }
.mwk-acts .bld-act.armed { color: var(--ok); }
.mw-light .mwk-acts .bld-act { background: #f4f6fa; border-color: rgba(0,0,0,.12); color: #17202e; }
.mw-light .mwk-acts .bld-act.armed { color: var(--ok); }
/* Подсветка выбора с клавиатуры (стрелки + Enter) */
.mwk-match.hi, .mwk-acts .bld-act.hi { border-color: var(--accent); box-shadow: inset 0 0 0 2px rgba(45,212,191,.4); }
.mwk-msg { margin-top: 10px; font-weight: 700; font-size: 13.5px; }
.mwk-msg.ok { color: var(--ok); }
.mwk-msg.no { color: var(--danger); }
