/* ==========================================================================
   门禁管理系统 · 平台管理端样式
   设计约束：
     1. 单一来源 —— 所有颜色/圆角/阴影走 CSS 变量，禁止散落硬编码
     2. 与《三端落地方案》一致：物业运营视角，信息密度优先于装饰
     3. 危险操作（停用/撤销/删除）一律显式配色，不能与普通按钮混淆
   ========================================================================== */

:root{
  --bg:#f6f7f9; --panel:#fff; --line:#e5e7eb; --text:#1f2328; --muted:#6b7280;
  --brand:#1a56db; --brand-soft:#eef3fe; --warn:#b45309; --warn-soft:#fef3c7;
  --danger:#b91c1c; --danger-soft:#fee2e2; --ok:#047857; --ok-soft:#d1fae5;
  --radius:10px; --shadow:0 1px 2px rgba(16,24,40,.06),0 1px 3px rgba(16,24,40,.1);
  --shadow-lg:0 10px 30px rgba(16,24,40,.14);
  --nav-w:186px;
}

*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--text);
  font:14px/1.6 -apple-system,"PingFang SC","Microsoft YaHei",sans-serif}
button{font:inherit;cursor:pointer;border:1px solid var(--line);background:#fff;
  border-radius:8px;padding:7px 14px;color:var(--text)}
button:hover{background:#f9fafb}
button:disabled{opacity:.5;cursor:not-allowed}
button.primary{background:var(--brand);border-color:var(--brand);color:#fff}
button.primary:hover{filter:brightness(1.06)}
button.danger{color:var(--danger);border-color:#fca5a5}
button.danger:hover{background:var(--danger-soft)}
button.ok{color:var(--ok);border-color:#6ee7b7}
button.ok:hover{background:var(--ok-soft)}
button.sm{padding:3px 9px;font-size:12.5px;border-radius:6px}
button.link{border:none;background:none;color:var(--brand);padding:2px 0;border-radius:0}
button.link:hover{background:none;text-decoration:underline}
input,select,textarea{font:inherit;padding:8px 10px;border:1px solid var(--line);
  border-radius:8px;background:#fff;color:var(--text);min-width:0;font-family:inherit}
input:focus,select:focus,textarea:focus{outline:2px solid var(--brand-soft);border-color:var(--brand)}
a{color:var(--brand)}

/* ---------------------------------------------------------------- 登录 */
#login{position:fixed;inset:0;display:grid;place-items:center;background:var(--bg);z-index:50}
#login .card{width:370px;background:var(--panel);border:1px solid var(--line);
  border-radius:14px;padding:30px;box-shadow:var(--shadow-lg)}
#login h1{font-size:19px;margin:0 0 4px}
#login p{color:var(--muted);margin:0 0 20px;font-size:13px}
#login input{width:100%;margin-bottom:12px}
#login button{width:100%}
#loginMsg{margin-top:12px;font-size:13px;color:var(--danger);min-height:20px;text-align:left}

/* ------------------------------------------- 登录页（2026-09-19 收口为纯密码）
   原先这里还有一套 #login .tabs / #login .coderow 的样式支撑「密码 / 短信验证码」
   双 Tab，两条路都撤了（见 admin/index.html 的注释），样式一并删除 ——
   留着无主样式只会在下次改主题时让人以为还有第二个入口。
   将来若要恢复短信登录，样式从 git 历史取回即可。 */
#login .hint{margin-top:12px;font-size:12.5px;color:var(--muted);line-height:1.7}

/* ------------------------------------------------------ 强制改密 / 修改密码
   与登录页同一套外观。它是要把人挡在门外的，不能让人误以为是普通弹窗。 */
#pwdChange{position:fixed;inset:0;display:grid;place-items:center;background:var(--bg);z-index:50}
#pwdChange .card{width:370px;background:var(--panel);border:1px solid var(--line);
  border-radius:14px;padding:30px;box-shadow:var(--shadow-lg)}
#pwdChange h1{font-size:19px;margin:0 0 4px}
#pwdChange p{color:var(--muted);margin:0 0 20px;font-size:13px}
#pwdChange input{width:100%;margin-bottom:12px}
#pwdChange button{width:100%}
#pwdMsg{margin-top:12px;font-size:13px;color:var(--danger);min-height:20px;text-align:left}
#pwdMsg.ok{color:var(--ok)}

/* ---------------------------------------------------------------- 布局 */
header{background:#fff;border-bottom:1px solid var(--line);padding:0 20px;
  height:56px;display:flex;align-items:center;gap:14px;position:sticky;top:0;z-index:20}
header .logo{font-weight:600}
header .who{margin-left:auto;color:var(--muted);font-size:13px}
.wrap{display:flex;align-items:flex-start;gap:18px;padding:18px;max-width:1400px;margin:0 auto}
nav{width:var(--nav-w);flex:none;background:var(--panel);border:1px solid var(--line);
  border-radius:var(--radius);padding:8px;position:sticky;top:74px;max-height:calc(100vh - 92px);overflow:auto}
nav a{display:block;padding:9px 12px;border-radius:8px;color:var(--text);
  text-decoration:none;font-size:13.5px;margin-bottom:2px}
nav a:hover{background:#f3f4f6}
nav a.on{background:var(--brand-soft);color:var(--brand);font-weight:600}
nav a .dot{float:right;background:var(--danger);color:#fff;border-radius:9px;
  padding:0 6px;font-size:11px;line-height:17px}
nav .grp{font-size:11.5px;color:var(--muted);padding:10px 12px 4px;letter-spacing:.04em}
main{flex:1;min-width:0}
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  padding:18px;margin-bottom:16px;box-shadow:var(--shadow)}
.card h2{margin:0 0 14px;font-size:16px;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.card h2 .sub{font-size:13px;font-weight:400;color:var(--muted)}
.card h3{margin:18px 0 10px;font-size:14px;color:var(--muted);font-weight:600}
.card:first-child h2{margin-top:0}

.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px}
.kpi{border:1px solid var(--line);border-radius:var(--radius);padding:14px}
.kpi .n{font-size:24px;font-weight:600;line-height:1.2}
.kpi .l{color:var(--muted);font-size:12.5px;margin-top:2px}
.kpi.hot{border-color:#fca5a5;background:#fff7f7}

table{width:100%;border-collapse:collapse;font-size:13.5px}
th,td{text-align:left;padding:9px 10px;border-bottom:1px solid var(--line);vertical-align:middle}
th{color:var(--muted);font-weight:600;white-space:nowrap;background:#fafbfc}
tr:last-child td{border-bottom:none}
tbody tr:hover{background:#fcfcfd}
.table-wrap{overflow-x:auto}

.tag{display:inline-block;padding:1px 8px;border-radius:999px;font-size:12px;white-space:nowrap}
.t-ok{background:var(--ok-soft);color:var(--ok)}
.t-warn{background:var(--warn-soft);color:var(--warn)}
.t-danger{background:var(--danger-soft);color:var(--danger)}
.t-mute{background:#f3f4f6;color:var(--muted)}
.t-info{background:var(--brand-soft);color:var(--brand)}

/* 人员列表「最后通行」列：久未通行分级变色。
   用文字变色而不是色块 —— 这一列是给人「扫一眼挑出异常」的，
   满屏彩色标签反而看不出重点。 */
.idle-3m{color:var(--warn);font-weight:600}
.idle-6m{color:var(--danger);font-weight:600}
.idle-never{color:var(--danger);font-weight:600}

/* 门的勾选清单（权限设置面板 / 待授权名单通过抽屉共用） */
.door-list{display:grid;gap:6px;border:1px solid var(--line);border-radius:var(--radius);
  padding:10px 12px;background:#fcfcfd;max-height:220px;overflow:auto}
.door-list .cb{display:flex;align-items:center;gap:8px;font-size:13.5px}
.door-list .cb input{width:auto}

.row{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-bottom:14px}
.row:last-child{margin-bottom:0}
.row.between{justify-content:space-between}
.row .grow{flex:1;min-width:0}
.muted{color:var(--muted)}
.strong{font-weight:600}
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
.empty{padding:30px;text-align:center;color:var(--muted)}
.note{background:var(--brand-soft);border-left:3px solid var(--brand);
  padding:10px 14px;border-radius:0 8px 8px 0;color:#1e3a8a;font-size:13px;margin-bottom:14px}
.err{background:var(--danger-soft);border-left:3px solid var(--danger);
  padding:10px 14px;border-radius:0 8px 8px 0;color:#7f1d1d;font-size:13px;margin-bottom:14px}
.warn{background:var(--warn-soft);border-left:3px solid var(--warn);
  padding:10px 14px;border-radius:0 8px 8px 0;color:#78350f;font-size:13px;margin-bottom:14px}
code{background:#f3f4f6;padding:1px 5px;border-radius:4px;font-size:12.5px}
.bar{height:7px;background:#eef1f5;border-radius:4px;overflow:hidden;min-width:70px}
.bar>i{display:block;height:100%;background:var(--brand)}
tr.row-manual{background:#fff7f7}
.badge{display:inline-block;padding:1px 7px;border-radius:6px;font-size:11.5px;margin:1px 2px}
.b-yes{background:var(--ok-soft);color:var(--ok)}
.b-no{background:var(--danger-soft);color:var(--danger)}
.b-opt{background:var(--warn-soft);color:var(--warn)}
.b-unk{background:#f3f4f6;color:var(--muted)}

.grid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px}
.grid3{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px}
.grid2 label,.grid3 label{display:block;font-size:12.5px;color:var(--muted);margin-bottom:4px}
.grid2 input,.grid2 select,.grid3 input,.grid3 select{width:100%}
.grid2 .cb,.grid3 .cb{display:flex;align-items:center;gap:8px;font-size:13.5px;color:var(--text)}
.grid2 .cb input,.grid3 .cb input{width:auto}

/* ---------------------------------------------------------------- 分页 */
.pager{display:flex;gap:8px;align-items:center;justify-content:flex-end;
  margin-top:14px;font-size:13px;color:var(--muted)}

/* ---------------------------------------------------------------- 抽屉 */
#drawer-mask{position:fixed;inset:0;background:rgba(16,24,40,.42);z-index:40;display:none}
#drawer-mask.on{display:block}
#drawer{position:fixed;top:0;right:0;bottom:0;width:min(620px,94vw);background:#fff;
  z-index:41;box-shadow:var(--shadow-lg);transform:translateX(100%);
  transition:transform .22s ease;display:flex;flex-direction:column}
#drawer.on{transform:translateX(0)}
#drawer header.dh{height:56px;flex:none;border-bottom:1px solid var(--line);
  padding:0 18px;display:flex;align-items:center;gap:12px;position:static}
#drawer header.dh .t{font-weight:600}
#drawer .db{padding:18px;overflow:auto;flex:1}
#drawer .df{border-top:1px solid var(--line);padding:12px 18px;display:flex;gap:10px;
  justify-content:flex-end;flex:none;background:#fafbfc}

/* 组织树 */
.tree{font-size:13.5px}
.tree .node{border:1px solid var(--line);border-radius:8px;padding:8px 12px;
  margin-bottom:6px;background:#fff;display:flex;align-items:center;gap:10px}
.tree .node:hover{background:#fcfcfd}
.tree .node.dis{opacity:.55}
.tree .node .nm{font-weight:600}
.tree .node .sp{flex:1}
.tree .children{margin-left:20px;border-left:2px dashed var(--line);padding-left:12px}
.tree .node .ops{display:flex;gap:6px;opacity:0;transition:opacity .12s}
.tree .node:hover .ops{opacity:1}

/* 模态确认框 */
#modal-mask{position:fixed;inset:0;background:rgba(16,24,40,.42);z-index:45;
  display:none;place-items:center;padding:20px}
#modal-mask.on{display:grid}
#modal{background:#fff;border-radius:12px;box-shadow:var(--shadow-lg);
  width:min(480px,94vw);padding:22px;max-height:92vh;overflow:auto}
#modal h3{margin:0 0 10px;font-size:16px;color:var(--text)}
#modal .mb{font-size:13.5px;color:var(--text);white-space:pre-wrap;line-height:1.7}
#modal .mf{display:flex;gap:10px;justify-content:flex-end;margin-top:20px}
#modal .mf input{flex:1}

/* 提示条 */
#toasts{position:fixed;top:70px;right:20px;z-index:60;display:flex;
  flex-direction:column;gap:8px;max-width:380px}
#toasts>div{border-radius:8px;padding:10px 14px;font-size:13px;box-shadow:var(--shadow-lg);
  animation:slidein .18s ease}
@keyframes slidein{from{opacity:0;transform:translateX(16px)}to{opacity:1;transform:none}}
#toasts .t-note{background:#eff6ff;border-left:3px solid var(--brand);color:#1e3a8a}
#toasts .t-ok{background:var(--ok-soft);border-left:3px solid var(--ok);color:#065f46}
#toasts .t-err{background:var(--danger-soft);border-left:3px solid var(--danger);color:#7f1d1d}
#toasts .t-warn{background:var(--warn-soft);border-left:3px solid var(--warn);color:#78350f}

.spin{display:inline-block;width:13px;height:13px;border:2px solid var(--line);
  border-top-color:var(--brand);border-radius:50%;animation:sp .7s linear infinite;
  vertical-align:-2px;margin-right:6px}
@keyframes sp{to{transform:rotate(360deg)}}

details summary{cursor:pointer;font-size:13.5px}
details[open] summary{margin-bottom:8px}
.kv{display:grid;grid-template-columns:110px 1fr;gap:8px 12px;font-size:13.5px}
.kv dt{color:var(--muted)}
.kv dd{margin:0;word-break:break-all}
