/* ============================================================
   中层干部平时考核系统 · 通用样式
   ============================================================ */
:root{
  --red:#b4231f;
  --red-dark:#8e1a17;
  --red-soft:#fdf2f1;
  --ink:#1f2328;
  --ink-2:#4b5563;
  --ink-3:#6b7280;   /* 2026-10-19：原 #8b929c 在 12px .tiny 上对比度约 3.1:1，低于 WCAG AA(4.5:1)，加深到此处 */
  --line:#e5e7eb;
  --bg:#f4f5f7;
  --card:#ffffff;
  --blue:#1d4ed8;
  --green:#0f7b3f;
  --amber:#b45309;
  --radius:10px;
  --sidebar-w:216px;
}
*{box-sizing:border-box;}
html,body{margin:0;padding:0;height:100%;}
body{
  font-family:"Microsoft YaHei","PingFang SC","Hiragino Sans GB",-apple-system,"Segoe UI",sans-serif;
  background:var(--bg); color:var(--ink); font-size:14px; line-height:1.6;
}
a{color:var(--red); text-decoration:none;}
@media (hover:hover) and (pointer:fine){ a:hover{text-decoration:underline;} }

/* ---------- 布局 ---------- */
.layout{display:flex; min-height:100vh;}
.sidebar{
  width:var(--sidebar-w); flex:0 0 var(--sidebar-w);
  background:linear-gradient(180deg,#8e1a17 0%, #6f1310 100%);
  color:#fff; display:flex; flex-direction:column; position:sticky; top:0; height:100vh;
}
.sidebar .brand{padding:18px 16px 14px; border-bottom:1px solid rgba(255,255,255,.14);}
.sidebar .brand .t1{font-size:14.5px; font-weight:600; line-height:1.35;}
.sidebar .brand .t2{font-size:11.5px; opacity:.72; margin-top:4px;}
.sidebar nav{padding:10px 8px; overflow-y:auto; flex:1;}
.sidebar nav .grp{font-size:11px; opacity:.6; padding:10px 10px 4px; letter-spacing:1px;}
.sidebar nav a{
  display:flex; align-items:center; gap:9px; padding:9px 12px; border-radius:8px;
  color:rgba(255,255,255,.88); font-size:13.5px; margin-bottom:2px; text-decoration:none;
}
@media (hover:hover) and (pointer:fine){ .sidebar nav a:hover{background:rgba(255,255,255,.1); text-decoration:none; color:#fff;} }
.sidebar nav a.active{background:#fff; color:var(--red-dark); font-weight:600;}
.sidebar .foot{padding:12px 16px; font-size:11px; opacity:.6; border-top:1px solid rgba(255,255,255,.14);}

.mainwrap{flex:1; display:flex; flex-direction:column; min-width:0;}
.appbar{
  background:#fff; border-bottom:1px solid var(--line); padding:12px 22px;
  display:flex; align-items:center; gap:14px; flex-wrap:wrap; position:sticky; top:0; z-index:20;
}
.appbar .page-title{font-size:16px; font-weight:600;}
.appbar .crumb{font-size:12px; color:var(--ink-3); margin-top:1px;}
.appbar .spacer{flex:1;}
.appbar .quarter{font-size:13px;}
.appbar .quarter input{width:170px;}
.userchip{display:flex; align-items:center; gap:8px; font-size:13px;}
.userchip .avatar{
  width:30px; height:30px; border-radius:50%; background:var(--red); color:#fff;
  display:flex; align-items:center; justify-content:center; font-size:13px; font-weight:600;
}
.content{padding:18px 22px 60px; flex:1;}

/* ---------- 卡片 ---------- */
.card{background:var(--card); border:1px solid var(--line); border-radius:var(--radius); padding:18px 20px; margin-bottom:16px;}
.card h2{font-size:15px; margin:0 0 12px; padding-left:10px; border-left:4px solid var(--red); line-height:1.3;}
.card h3{font-size:14px; margin:16px 0 8px;}
.card .card-actions{margin-left:auto; display:flex; gap:8px;}
.card-head{display:flex; align-items:center; gap:10px; margin-bottom:12px; flex-wrap:wrap;}
.card-head h2{margin:0;}
.muted{color:var(--ink-2); font-size:13px;}
.tiny{font-size:12px; color:var(--ink-3);}
.grid{display:grid; gap:14px;}
.grid.c2{grid-template-columns:repeat(auto-fit,minmax(320px,1fr));}
.grid.c3{grid-template-columns:repeat(auto-fit,minmax(240px,1fr));}
.grid.c4{grid-template-columns:repeat(auto-fit,minmax(190px,1fr));}

/* ---------- 按钮 ---------- */
button{font-family:inherit;}
.btn{border:1px solid var(--line); background:#fff; color:var(--ink); padding:7px 14px; border-radius:7px; cursor:pointer; font-size:13px; transition:.15s;}
@media (hover:hover) and (pointer:fine){ .btn:hover{border-color:#c9ccd1; background:#fafafa;} }
.btn.primary{background:var(--red); border-color:var(--red); color:#fff;}
@media (hover:hover) and (pointer:fine){ .btn.primary:hover{background:var(--red-dark);} }
.btn.sm{padding:4px 10px; font-size:12px;}
.btn.danger{color:var(--red); border-color:#f0c9c7;}
.btn.block{width:100%;}
.btn:disabled{opacity:.5; cursor:not-allowed;}
.row{display:flex; gap:10px; flex-wrap:wrap; align-items:center;}
.spacer{flex:1;}

/* ---------- 表单 ---------- */
input[type=text],input[type=number],input[type=password],input[type=file],select,textarea{
  border:1px solid var(--line); border-radius:7px; padding:6px 10px; font-size:13px;
  font-family:inherit; color:var(--ink); background:#fff; outline:none;
}
input:focus,select:focus,textarea:focus{border-color:var(--red); box-shadow:0 0 0 2px rgba(180,35,31,.08);}
label{font-size:13px; color:var(--ink-2);}
.field-row{display:flex; gap:12px; flex-wrap:wrap; margin-bottom:10px;}
.field-row .f{display:flex; flex-direction:column; gap:4px; flex:1; min-width:150px;}

/* ---------- 表格 ---------- */
table{width:100%; border-collapse:collapse; font-size:13px;}
th,td{border:1px solid var(--line); padding:7px 9px; text-align:left; vertical-align:top;}
th{background:#faf6f5; font-weight:600; white-space:nowrap;}
tbody tr:nth-child(even){background:#fcfcfd;}
td.num,th.num{text-align:center;}
/* 工作台「各部门评价进度」的合计行：加一道顶线把它与明细行分开（列数与表头一致） */
tbody tr.sumrow td{border-top:2px solid var(--ink-3); background:#fafafa;}
.table-scroll{overflow-x:auto;}

/* ---------- 身份证号（脱敏展示 + 点击显示） ---------- */
/* 等宽字体：18 位号码在比例字体下极易看错位（对账时会真的看错） */
.idc{display:inline-flex; align-items:center; gap:2px; white-space:nowrap;}
.idc .idv{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:12px; letter-spacing:.2px;}
.idc .idv.shown{font-weight:600;}
.lnk{border:none; background:none; padding:0 0 0 6px; margin:0; font-size:12px; cursor:pointer;
     color:var(--red); text-decoration:underline; text-underline-offset:2px; font-family:inherit;}
@media (hover:hover) and (pointer:fine){ .lnk:hover{color:var(--red-dark);} }

/* ---------- 徽标 / 提示 ---------- */
.badge{display:inline-block; padding:1px 8px; border-radius:999px; font-size:12px; border:1px solid transparent;}
.badge.excellent{background:#fdeceb; color:var(--red); border-color:#f3c9c6;}
.badge.pass{background:#eaf5ee; color:var(--green); border-color:#c4e3d0;}
.badge.basic{background:#fdf3e3; color:var(--amber); border-color:#f2dcb3;}
.badge.fail{background:#eef0f2; color:#4b5563; border-color:#d8dce0;}
.badge.warn{background:#fdf3e3; color:var(--amber); border-color:#f2dcb3;}
.badge.role{background:#eff4fd; color:#1e40af; border-color:#d5e0f7;}
.badge.gray{background:#f2f3f5; color:#5b6167; border-color:#e2e4e8;}
.notice{padding:9px 14px; border-radius:8px; font-size:13px; margin-bottom:12px;}
.notice.info{background:#eff4fd; color:#1e40af; border:1px solid #d5e0f7;}
.notice.warn{background:#fdf6e9; color:#92610a; border:1px solid #f3e0bb;}
.notice.ok{background:#eaf5ee; color:var(--green); border:1px solid #c9e6d5;}
.notice.err{background:#fdeceb; color:var(--red); border:1px solid #f3c9c6;}

/* ---------- 统计卡 ---------- */
.stat{background:#fff; border:1px solid var(--line); border-radius:9px; padding:14px 16px;}
.stat .k{font-size:12.5px; color:var(--ink-2);}
.stat .v{font-size:24px; font-weight:600; color:var(--red); margin-top:2px; line-height:1.2;}
.stat .v.sm{font-size:17px;}
.stat .d{font-size:11.5px; color:var(--ink-3); margin-top:2px;}

/* ---------- 进度条 / 柱图 ---------- */
.bar{height:8px; background:#eef0f2; border-radius:999px; overflow:hidden; min-width:70px;}
.bar > i{display:block; height:100%; background:var(--red); border-radius:999px;}
.bar.green > i{background:var(--green);}
.bar.blue > i{background:var(--blue);}
.barline{display:flex; align-items:center; gap:10px; margin-bottom:7px; font-size:12.5px;}
.barline .lbl{width:120px; flex:0 0 120px; color:var(--ink-2); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
.barline .bar{flex:1;}
.barline .val{width:56px; text-align:right; color:var(--ink-2);}

/* ---------- 打分卡 ---------- */
/* 🔴 overflow 必须是 visible（不是原来的 hidden）：`.head` 要做 sticky 吸顶，
   而祖先 overflow:hidden 会让 sticky 的吸附容器变成卡片自己（不随页面滚动）→ 吸顶失效。
   圆角改由 `.head` / `.ref` 自己承担，视觉与原来逐像素一致。 */
.person-score{border:1px solid var(--line); border-radius:9px; margin-bottom:12px; overflow:visible; background:#fff;}
.person-score .head{display:flex; align-items:center; gap:12px; padding:9px 14px; background:#fafafa; border-bottom:1px solid var(--line); flex-wrap:wrap; border-radius:9px 9px 0 0;}
/* 被考核对象要"一眼认出是谁"：姓名放大加粗 + 红色竖条做视觉锚点。
   2026-10-22 需求：用户打分时被考核对象不够明显。 */
.person-score .head .name{font-weight:700; font-size:17px; line-height:1.3; padding-left:10px; border-left:4px solid var(--red);}
.person-score .head .total{margin-left:auto; font-size:13px; color:var(--ink-2);}
.person-score .head .total b{color:var(--red); font-size:16px;}
/* 自动保存状态提示（2026-10-26）：打分后自动落库，卡片头给一行轻提示。
   空的时候不占位（:empty）—— 平时完全不出现，只有"保存中 / 已自动保存 HH:MM / 失败"时才有字，
   所以不会改变卡片头的常规布局（也不会把 44px 的折叠摘要行撑高）。 */
.autosave-tip{font-size:11.5px; color:var(--green); white-space:nowrap;}
.autosave-tip:empty{display:none;}
.autosave-tip.is-fail{color:var(--red);}
.person-score .items{display:grid; grid-template-columns:repeat(auto-fill,minmax(200px,1fr)); gap:10px; padding:12px 14px;}
.item{display:flex; flex-direction:column; gap:3px;}
.item .label{font-size:12.5px; color:var(--ink-2);}
.item .label b{color:var(--ink);}
.item input{width:100%;}
.item .hint{font-size:11.5px; color:var(--ink-3);}

/* ---- 桌面端打分输入区：label 与输入框**同排**（2026-10-22）----
   原来是 label 在上、输入框在下，一项约 53px；桌面 3 列时 6 项要占 142px。
   同排后一项约 40px，且输入框定宽 78px（放 3 位数字足够），label 吃剩余宽度。
   ⚠️ 只作用于 ≥769px：手机端（≤768px）保持竖排全宽，手指才好点。 */
@media (min-width:769px){
  .person-score .item{flex-direction:row; align-items:center; gap:10px;}
  .person-score .item .label{flex:1 1 auto; min-width:0;}
  .person-score .item input{flex:0 0 78px; width:78px; text-align:center;}
  .person-score .items{gap:10px 18px;}
}
.ref{font-size:12px; color:var(--ink-2); background:#fbfbfc; border-top:1px dashed var(--line); padding:8px 14px; border-radius:0 0 9px 9px;}
.ref b{color:var(--red);}
/* 「评分档次参考」折叠态：压成一行「▸ 评分档次参考（点击展开）」。
   ⚠️ 这三条规则**故意写在媒体查询之外**（2026-10-22 从 ≤768px 块里提出来）：
     桌面端每张卡也挂这段 454 字参考（实测高 113px，占卡片总高 37.5%，8 张卡就是 8 段文字墙），
     桌面端也要默认折叠；class 由 score.html 的 JS 加（移动端走逐人模式、桌面端走 initRefFoldDesktop）。 */

/* ---------- 对话框 ---------- */
dialog{border:none; border-radius:12px; padding:0; box-shadow:0 20px 60px rgba(0,0,0,.25); max-width:580px; width:92%;}
dialog::backdrop{background:rgba(20,20,20,.45);}
dialog .dlg-head{padding:14px 18px; border-bottom:1px solid var(--line); font-weight:600;}
dialog .dlg-body{padding:16px 18px; max-height:62vh; overflow:auto;}
dialog .dlg-foot{padding:12px 18px; border-top:1px solid var(--line); display:flex; justify-content:flex-end; gap:10px;}
dialog textarea{width:100%; min-height:150px; font-family:Consolas,Monaco,monospace;}

/* ---------- 登录页（首页） ----------
   政务风格：深红底 + 金色点缀 + 全屏纹理。
   所有装饰均为纯 CSS / 内联 SVG —— 不引用任何外部资源，也不用 data: URI
   （CSP 为 default-src 'self' blob:，data: 图片会被浏览器直接拦掉）。
   ⚠️ 契约：本页必须保留 id=account / password / btnLogin / msg，
      且脚本引入顺序 xlsx → config → api → store → shell 不可变。 */
.login-page{
  min-height:100vh; display:flex; flex-direction:column;
  position:relative; overflow-x:hidden; color:#fff; background:#2a0807;
}
/* 顶部金色发丝线（仪式感） */
.login-page::before{
  content:''; position:fixed; left:0; right:0; top:0; height:2px; z-index:5;
  background:linear-gradient(90deg,
    transparent 0%, rgba(230,192,115,.75) 16%, rgba(246,224,168,.95) 50%,
    rgba(230,192,115,.75) 84%, transparent 100%);
}
.login-bg{
  position:fixed; inset:0; z-index:0;
  background:
    radial-gradient(880px 620px at 84% 6%, rgba(226,124,62,.28), transparent 62%),
    radial-gradient(1100px 720px at 6% 98%, rgba(180,35,31,.44), transparent 66%),
    linear-gradient(160deg,#5c1210 0%, #3a0c0a 46%, #1c0605 100%);
}
.login-bg .grid{
  position:absolute; inset:0; opacity:.18;
  background-image:
    linear-gradient(rgba(255,255,255,.16) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.16) 1px, transparent 1px);
  background-size:66px 66px;
  -webkit-mask-image:radial-gradient(circle at 50% 42%, #000 0%, transparent 76%);
  mask-image:radial-gradient(circle at 50% 42%, #000 0%, transparent 76%);
}
.login-bg .glow{position:absolute; border-radius:50%;}
.login-bg .glow-1{width:460px; height:460px; right:-120px; top:-160px;
  background:radial-gradient(circle, rgba(246,224,168,.20), transparent 68%);}
.login-bg .glow-2{width:520px; height:520px; left:-180px; bottom:-220px;
  background:radial-gradient(circle, rgba(200,53,47,.28), transparent 70%);}

/* 页眉 */
.login-top{position:relative; z-index:2; padding:22px 44px 0;}
.login-top .top-inner{max-width:1140px; margin:0 auto; display:flex; align-items:center; gap:16px;}
.login-top .top-org{font-size:13px; letter-spacing:1.6px; color:rgba(246,224,168,.92);}
.login-top .top-org::before{
  content:''; display:inline-block; width:30px; height:1px; margin-right:12px;
  vertical-align:middle; background:linear-gradient(90deg,#f6e0a8,rgba(230,192,115,.15));
}
.login-top .top-tag{margin-left:auto; font-size:12px; letter-spacing:2px; color:rgba(255,255,255,.5);}

/* 主区 */
.login-wrap{
  position:relative; z-index:2; flex:1; padding:34px 44px 26px;
  display:flex; align-items:center; justify-content:center;
}
.login-card{
  width:100%; max-width:1140px; display:flex; overflow:hidden; border-radius:18px;
  border:1px solid rgba(230,192,115,.26);
  box-shadow:0 42px 96px -22px rgba(0,0,0,.68), 0 2px 10px rgba(0,0,0,.28);
}
/* 左：品牌墙 */
.login-left{
  flex:1.16; padding:52px 46px; position:relative; overflow:hidden;
  display:flex; flex-direction:column; justify-content:center;
  background:linear-gradient(155deg, rgba(186,38,33,.95) 0%, rgba(126,23,20,.97) 56%, rgba(74,15,13,.99) 100%);
  border-right:1px solid rgba(230,192,115,.22);
}
.login-left::after{
  content:''; position:absolute; z-index:0; width:440px; height:440px; right:-170px; top:-200px;
  border-radius:50%; background:radial-gradient(circle, rgba(246,224,168,.20), transparent 68%);
}
.login-left .left-fg{position:relative; z-index:1;}
/* 校徽：用白色圆盘承载。
   校徽含中英文校名（黑字）+ 彩色图形，直接放在深红底上黑字会糊掉，垫白底才清晰。
   资源本身已带约 11% 白边，所以这里的 border-radius:50% 只会裁到白边，
   不会切到校徽的青蓝色外环（这一点由 scripts 生成时的留白保证）。 */
.brand-mark{
  width:104px; height:104px; margin-bottom:26px; border-radius:50%;
  overflow:hidden; background:#fff;
  box-shadow:0 14px 30px -10px rgba(0,0,0,.62), 0 0 0 1px rgba(246,224,168,.42);
}
.brand-mark img{display:block; width:100%; height:100%;}
.login-left .kicker{font-size:12.5px; letter-spacing:5px; color:rgba(246,224,168,.86); margin-bottom:12px;}
.login-left h1{
  font-size:31px; line-height:1.42; letter-spacing:2.4px; font-weight:700;
  margin:0; color:#fff; text-shadow:0 2px 16px rgba(0,0,0,.28);
}
.login-left .rule{
  width:58px; height:2px; margin:20px 0 16px; border-radius:2px;
  background:linear-gradient(90deg,#f6e0a8,#c99a4e);
}
.login-left .s{font-size:12.5px; letter-spacing:2px; color:rgba(255,255,255,.72);}
/* 右：登录表单 */
.login-right{
  flex:1; padding:52px 46px; background:#fff; color:var(--ink);
  display:flex; flex-direction:column; justify-content:center;
}
.login-right h2{margin:0; font-size:22px; letter-spacing:1px; color:var(--ink);}
.login-right h2::after{
  content:''; display:block; width:36px; height:3px; margin-top:12px; border-radius:2px;
  background:linear-gradient(90deg,var(--red),var(--red-dark));
}
.login-right .tip{font-size:12.5px; color:var(--ink-3); margin:16px 0 28px;}
.login-right .f{display:flex; flex-direction:column; gap:8px; margin-bottom:16px;}
.login-right label{font-size:12.5px; color:var(--ink-2); letter-spacing:.5px;}
.login-right input{width:100%; padding:13px 14px; font-size:14px; border-radius:8px;}
.login-right .btn.primary{
  height:46px; font-size:15px; letter-spacing:6px; border:none; border-radius:8px;
  background:linear-gradient(135deg,#b4231f,#8e1a17);
  box-shadow:0 12px 26px -10px rgba(180,35,31,.65);
}
@media (hover:hover) and (pointer:fine){ .login-right .btn.primary:hover{background:linear-gradient(135deg,#8e1a17,#6f1310);} }
.login-right .btn.primary:active{transform:translateY(1px);}
.login-right .hint-foot{
  margin-top:20px; text-align:center; font-size:11.5px; letter-spacing:.4px; color:var(--ink-3);
}
/* 页脚 */
.login-copy{
  position:relative; z-index:2; padding:0 44px 26px; text-align:center;
  font-size:11.5px; letter-spacing:1.4px; color:rgba(255,255,255,.42);
}

/* ---------- 空状态 ---------- */
.empty{padding:26px 10px; text-align:center; color:var(--ink-3); font-size:13px;}

/* ---------- 干部选拔推荐（2026-10-17 新增） ---------- */
.sel-count{font-size:13px; color:var(--ink-2); font-weight:600;}
.sel-list{display:flex; flex-direction:column; gap:8px; max-height:520px; overflow-y:auto; padding:4px 2px;}
.sel-item{display:flex; align-items:center; gap:10px; padding:10px 12px; border:1px solid var(--line); border-radius:8px; background:#fff; cursor:pointer; transition:border-color .12s, background .12s;}
@media (hover:hover) and (pointer:fine){ .sel-item:hover{border-color:#d5d8dd; background:#fafbfc;} }
.sel-item input{width:16px; height:16px; flex:0 0 auto; cursor:pointer;}
.sel-item input:disabled{cursor:not-allowed;}
.sel-item .sel-body{display:flex; flex-direction:column; gap:2px; min-width:0;}
.sel-item .sel-name{font-weight:600;}
.sel-item .sel-meta{font-size:12px; color:var(--ink-3);}
.sel-item.sm{padding:8px 10px;}
.stat-cards{display:flex; gap:12px; flex-wrap:wrap; margin-top:14px;}
.stat-card{flex:1; min-width:150px; background:var(--bg); border:1px solid var(--line); border-radius:10px; padding:16px; text-align:center;}
.stat-card .num{font-size:26px; font-weight:700; color:var(--red); line-height:1.2;}
.stat-card .lbl{font-size:12.5px; color:var(--ink-2); margin-top:4px;}
.switch-row{display:inline-flex; align-items:center; gap:8px; font-weight:400; cursor:pointer;}
.switch-row input{width:16px; height:16px; cursor:pointer;}

@media (max-width:820px){
  /* 首页：单列紧凑版（窄屏优先保证登录区可用） */
  .login-top{padding:16px 18px 0;}
  .login-top .top-org{font-size:11.5px; letter-spacing:2px;}
  .login-top .top-tag{display:none;}
  .login-wrap{padding:20px 18px 16px;}
  .login-card{flex-direction:column; border-radius:14px;}
  .login-left{padding:32px 24px; border-right:none; border-bottom:1px solid rgba(230,192,115,.22);}
  .login-left h1{font-size:22px; letter-spacing:1px;}
  .login-left .kicker{letter-spacing:3px;}
  /* 窄屏校徽略缩小，但仍保留可辨认尺寸 —— 它是这一栏唯一的图形标识 */
  .brand-mark{width:76px; height:76px; margin-bottom:20px;}
  .login-right{padding:32px 24px;}
  .login-copy{padding:0 18px 18px; letter-spacing:.6px;}
}
@media print{
  .sidebar,.appbar,.no-print{display:none !important;}
  .content{padding:0;}
  .card{border:none; padding:0; margin-bottom:12px;}
  body{background:#fff;}
}

/* ===== 干部选拔 · 投票进度（2026-10-19） ===== */
.progress-group{border:1px solid var(--line); border-radius:8px; padding:10px 12px; margin-bottom:10px;}
.progress-group summary{cursor:pointer; font-size:14px;}
.progress-cols{display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-top:10px;}
.progress-list{margin:6px 0 0; padding-left:18px; max-height:260px; overflow:auto;}
.progress-list li{margin:3px 0; font-size:13px;}
.progress-list .tiny{display:inline;}
@media (max-width:768px){.progress-cols{grid-template-columns:1fr;}}

/* ===== 页内 Tab 栏（2026-10-20：系统设置 / 干部选拔管理） =====
   纯 CSS 类名约定：.tabs 是按钮组，.tab-panel 是面板；面板显隐靠 hidden 属性
   （JS 只切 hidden 与按钮的 active 类，不做任何动画/高度计算）。 */
.tabs{display:flex;gap:6px;flex-wrap:wrap;border-bottom:1px solid var(--line);margin-bottom:16px;}
.tabs button{border:1px solid transparent;border-bottom:none;background:transparent;padding:8px 14px;border-radius:8px 8px 0 0;cursor:pointer;font-size:14px;color:var(--ink);}
@media (hover:hover) and (pointer:fine){ .tabs button:hover{background:var(--bg);} }
.tabs button.active{background:var(--card);border-color:var(--line);font-weight:600;}
.tabs button:focus-visible{outline:2px solid var(--red);outline-offset:2px;}
.tab-panel[hidden]{display:none;}

/* 打印时展开全部 Tab 面板（组织部常需整页打印设置/选拔结果） */
@media print{.tab-panel[hidden]{display:block !important;}.tabs{display:none;}}

/* 2026-10-20：管理员「评价人搜索」结果行的悬停反馈（面板本身是内联定位） */
@media (hover:hover) and (pointer:fine){ #evalPicker [data-pick]:hover { background: #f3f4f6; } }

/* ============================================================
   移动端适配（≤768px）· 2026-06-02
   ------------------------------------------------------------
   断点纪律：桌面（≥769px）像素零变化 —— 本段所有**增强**规则都在
   @media(max-width:768px) 内，桌面端不命中。
   ⚠️ 现有 @media(max-width:820px) 拆分为两半：登录页那半段保留 820px；
      侧栏那半段（.layout/.sidebar/.sidebar nav 系列）已删除，改由本段
      在 ≤768px 时用抽屉重做（见 P0-1）。
   ⚠️ 下面三条「桌面隐藏」规则必须写在 @media **之外**：
      写在里面 ⇒ 桌面端汉堡/遮罩/抽屉底栏会显示出来，桌面像素对比必挂。
   ============================================================ */

/* 汉堡按钮：桌面端隐藏（移动端在 P0-1 里改成 inline-flex） */
.nav-toggle{display:none;}
/* 抽屉遮罩：桌面端永不显示 */
.nav-mask{display:none;}
/* 抽屉底栏（修改密码 / 退出）：桌面端不显示（顶栏已有同功能按钮） */
.nav-foot{display:none;}
/* 逐人模式步进器（score.html 的 #pagerMobile）：桌面端不显示。
   ⚠️ 2026-10-27 审计补：这条原先漏了 —— `.pager-mobile` 的样式全写在下面 @media 内，
   `@media` 外没有隐藏规则 ⇒ 手机加载后转横屏/把窗口拉宽到 >768px 时，
   桌面端会残留一条 48px 高的「第 k / N 位 · 姓名 · 部门」步进器，
   且文案永久冻结在切宽前那个人（renderPagerMobile 只在移动端被调）。
   桌面**直载**不受影响（initPersonMode 首行 isMobileView() 就早退），所以像素对比测不出来。 */
.pager-mobile{display:none;}

/* 滑动提示：表格的**兄弟**节点（不是表格内部）⇒ 绝不污染 <tbody> */
.scroll-hint{
  display:none; font-size:12px; color:var(--ink-3);
  padding:0 2px 4px; white-space:nowrap;
}

/* ---------- P0-1 导航：侧栏 → 左侧抽屉 ---------- */
@media (max-width:768px){
  /* 布局：侧栏脱离文档流（position:fixed），主内容独占整宽 */
  .layout{display:block;}
  .sidebar{
    position:fixed; top:0; left:0; bottom:0;
    width:min(78vw,320px); height:100vh;
    flex:none; z-index:60;
    transform:translateX(-100%);
    transition:transform .22s ease;
    box-shadow:2px 0 16px rgba(0,0,0,.28);
  }
  body.nav-open .sidebar{transform:translateX(0);}
  body.nav-open{overflow:hidden;}
  .nav-mask{
    position:fixed; inset:0; z-index:55;
    background:rgba(0,0,0,.45);
  }
  body.nav-open .nav-mask{display:block;}
  /* 顶栏：55px（汉堡 44 + 上下内边距 5×2 + 下边框 1 = 55，≤56px 达标） */
  .appbar{padding:5px 10px; gap:10px; min-height:55px; flex-wrap:nowrap;}
  .appbar .appbar-title{min-width:0; overflow:hidden;}
  .appbar .page-title{font-size:15px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  .appbar .crumb{display:none;}
  .appbar .quarter{display:none;}
  .appbar .userchip{min-width:0;}
  .appbar .userchip > div:last-child{min-width:0; overflow:hidden;}
  .appbar .userchip > div > div:first-child{display:none;}
  .appbar .userchip .tiny{white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  .appbar .userchip .avatar{width:28px; height:28px; font-size:12px; flex:0 0 auto;}
  .appbar #shellPwd,.appbar #shellLogout{display:none;}
  .nav-toggle{
    display:inline-flex; align-items:center; justify-content:center;
    width:44px; height:44px; min-width:44px; flex:0 0 44px;
    border:1px solid var(--line); background:#fff; border-radius:8px;
    font-size:20px; line-height:1; cursor:pointer; color:var(--ink);
  }
  .nav-toggle:active{background:#f3f4f6;}
  /* 抽屉底栏：修改密码 / 退出（顶栏那两颗在移动端隐藏）
     ⚠️ .sidebar .foot 自身有 opacity:.6（"考核方案 · 百分制"那行），
        .nav-foot 挂在它里面 ⇒ 按钮会被一起变淡（截图里是粉白按钮）。
        这里把 .nav-foot 自身的透明度拉回 1 ⇒ 按钮恢复白底（桌面端不受影响：
        .nav-foot 在桌面 display:none，整段规则都在 ≤768px 内）。 */
  .nav-foot{display:flex; gap:8px; padding:10px 12px 14px; opacity:1;}
  .nav-foot .btn{flex:1;}
}

/* ---------- P0-2 表格：横向滚动 + 身份列吸左 + 滑动提示 ---------- */
@media (max-width:768px){
  /* 身份列（姓名/被考核人/考核对象/评价主体/操作人）由 shell.js 按
     **表头文字**判定后打标记 .t-fix-1/2/3：只冻结一列 ⇒ 偏移量恒为 0
     （不需要知道前一列多宽 ⇒ 最稳，也不会出现两列吸左互相重叠）。 */
  .t-fix-1 > thead > tr > th:nth-child(1),
  .t-fix-2 > thead > tr > th:nth-child(2),
  .t-fix-3 > thead > tr > th:nth-child(3),
  .t-fix-1 > tbody > tr > td:nth-child(1),
  .t-fix-2 > tbody > tr > td:nth-child(2),
  .t-fix-3 > tbody > tr > td:nth-child(3){
    position:sticky; left:0; z-index:2;
    white-space:nowrap;      /* 姓名不得竖排一字一行 */
    min-width:88px;          /* 身份列不被压扁 */
  }
  /* 表头格：z-index 高于表体格（3 > 2）。
     ⚠️ 表头格**不能**用 background:inherit —— thead tr 没有底色，
     继承过来是透明，右侧内容会从表头底下透出来；表头沿用自身的
     #faf6f5 底色（app.css 基础规则），此处不动。 */
  .t-fix-1 > thead > tr > th:nth-child(1),
  .t-fix-2 > thead > tr > th:nth-child(2),
  .t-fix-3 > thead > tr > th:nth-child(3){ z-index:3; }
  /* 表体吸左格必须不透字：继承 tr 的实底（tr 在下面铺了底） */
  .t-fix-1 > tbody > tr > td:nth-child(1),
  .t-fix-2 > tbody > tr > td:nth-child(2),
  .t-fix-3 > tbody > tr > td:nth-child(3){ background:inherit; }
  .t-fix-1 > tbody > tr,.t-fix-2 > tbody > tr,.t-fix-3 > tbody > tr{background:#fff;}
  .t-fix-1 > tbody > tr:nth-child(even),
  .t-fix-2 > tbody > tr:nth-child(even),
  .t-fix-3 > tbody > tr:nth-child(even){background:#fcfcfd;}
  /* 合计行（工作台进度表）的吸左格：沿用合计行自己的底色 */
  .t-fix-1 > tbody > tr.sumrow > td:nth-child(1),
  .t-fix-2 > tbody > tr.sumrow > td:nth-child(2),
  .t-fix-3 > tbody > tr.sumrow > td:nth-child(3){background:#fafafa;}
  /* 滑动提示：仅当真的横向溢出（+2px 容差，避免亚像素抖动闪烁）才显示 */
  .scroll-hint.is-on{display:block;}
}

/* ---------- P0-3 逐人打分（仅移动端） ---------- */
@media (max-width:768px){
  /* 折叠态的卡：只留摘要行（姓名 + 部门 + 职务 + 已评分/未评分 + 合计分） */
  .person-score.is-collapsed .items{display:none;}
  .person-score.is-collapsed .ref{display:none;}
  .person-score.is-collapsed .head{min-height:44px; cursor:pointer;}
  /* 折叠态隐藏卡头的三个操作按钮（改为分项录入 / 保存 / 清空）。
     ① 为什么必须隐藏：折叠态是**只读摘要行**，但这三个按钮仍可点 ——
        窄屏下「清空」还单独占一行，手指一碰就可能清掉该对象的分数（误触）。
     ② 为什么用属性选择器而不是给按钮组套一个 <div class="head-actions">：
        .head 是 flex 容器（app.css:156），三个按钮是它的**直接子元素**。
        套 div 会把 7 个 flex item 变成 6 个 ⇒ **桌面端 .head 布局改变**
        ⇒ 桌面像素对比会挂。属性选择器只在 .is-collapsed 下生效，桌面零影响。
     ③ 为什么用 display:none 而不是删元素：R3 契约要求 data-save / data-clear
        等元素**留在渲染后的 HTML 字符串里**（自检用正则
        /data-save="p1"[^>]*disabled/ 断言）。display:none 只改样式、不改 DOM
        ⇒ 136/136 不受影响。
     ④ data-mode / data-save / data-clear 全仓仅出现在 score.html:1395-1397
        （卡头内），选择器不会误伤别处。展开态（无 .is-collapsed）不受影响。 */
  .person-score.is-collapsed .head button[data-mode],
  .person-score.is-collapsed .head button[data-save],
  .person-score.is-collapsed .head button[data-clear]{display:none;}
  .person-score.is-collapsed .autosave-tip{display:none;}
  /* 摘要行压到一行：按钮移除后 .total 的 margin-left:auto 会把它推到最右，
     这里收紧间距并允许省略，保证 ≤72px（PRD P0-3 验收③「摘要行 ≥44px」）。
     ⚠️ padding 上下 6px（不是 8px）：姓名放大到 20px 后两行摘要会到 73px，
     收 2px 换回来，仍保住「≤72px」这条验收线。 */
  .person-score.is-collapsed .head{gap:4px 8px; padding:6px 12px;}
  .person-score.is-collapsed .head .name{flex:0 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .person-score.is-collapsed .head .tiny{white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:40%;}
  /* 参考区折叠的三条规则已提升到全局（见 L167 附近），这里不再重复 */

  /* ===== 被考核对象「更明显」（2026-10-22 需求）=====
     手机端打分是滚着填的：滚到输入框时卡片头已滚出屏幕，用户会忘了在给谁打分。
     所以这里做三件事：
       ① 卡片头 sticky 吸顶（top=55px 正好停在 appbar 下方，appbar 是 sticky top:0 z-index:20，
          这里 z-index 必须低于它，否则会盖住顶栏）；
       ② 姓名再放大一档（桌面 17px → 手机 20px），红条锚点已在桌面规则里；
       ③ 当前展开的卡用红边 + 淡红底标出来；还没评分的人左侧给一条琥珀边（一眼看到待办）。 */
  .person-score .head{position:sticky; top:55px; z-index:5;}
  .person-score .head .name{font-size:20px;}
  .person-score.is-current{border-color:var(--red); box-shadow:0 0 0 1px var(--red);}
  .person-score.is-current .head{background:#fdf1f1;}
  /* :has() 不被支持时（老浏览器）只是没有这条边，不影响任何功能 */
  .person-score:has(.badge.warn){border-left:3px solid #d97706;}
  /* 移动端人位步进器 */
  .pager-mobile{
    display:flex; flex-direction:column; gap:8px; align-items:stretch;
    margin:10px 0; padding:8px 10px;
    background:#fff; border:1px solid var(--line); border-radius:9px;
  }
  .pager-mobile-info{font-size:13px; color:var(--ink-2); text-align:center;}
  .pager-mobile-btns{display:flex; gap:8px;}
  .pager-mobile-btns .btn{flex:1;}
}

/* ---------- P1-1 弹窗近全屏 + 按钮组换行 ---------- */
@media (max-width:768px){
  /* ⚠️ 必须带 !important：score.html 的 <dialog> 用的是**行内样式**
     （style="max-width:760px; width:94%;"），行内样式优先级高于普通 CSS。 */
  dialog{width:96vw !important; max-width:96vw !important; max-height:90vh;}
  dialog .dlg-body{max-height:64vh; padding:12px;}
  .dlg-foot{flex-wrap:wrap;}
  .dlg-foot .btn{flex:1 1 140px; min-height:44px;}
}

/* ---------- P1-2 触摸基线：命中区 ≥44px / 输入 ≥16px ---------- */
@media (max-width:768px){
  button,.btn{min-height:44px;}
  .btn.sm{min-height:44px; padding:10px 12px; font-size:13px;}
  .lnk{display:inline-flex; align-items:center; min-height:44px; padding:0 6px;}
  .tabs button{min-height:44px;}
  .sidebar nav a{min-height:44px; display:flex; align-items:center;}
  input[type=checkbox],input[type=radio]{width:20px; height:20px; min-width:20px; min-height:20px;}
  .sel-item input{width:20px; height:20px;}
  /* 字号 ≥16px：选择器必须与基础规则同特异度且更靠后，否则被覆盖 */
  input[type=text],input[type=number],input[type=password],input[type=file],select,textarea{font-size:16px;}
  /* .login-right input 的特异度高于上面的属性选择器 ⇒ 必须单独再写一条 */
  .login-right input{font-size:16px;}
}

/* ---------- P1-3 密度：表单单列 / 卡片收窄 / Tab 横滑 ---------- */
@media (max-width:768px){
  .field-row{flex-direction:column; gap:8px;}
  .field-row .f{min-width:0; width:100%;}
  .grid.c2,.grid.c3,.grid.c4{grid-template-columns:1fr;}
  .card{padding:12px;}
  .content{padding:12px 12px 40px;}
  .tabs{flex-wrap:nowrap; overflow-x:auto; -webkit-overflow-scrolling:touch;}
  .tabs button{flex:0 0 auto; white-space:nowrap;}
}

/* ---------- 汇总页移动端排名摘要（#mRankBox，PRD A4 / 架构 §5.1 P1-1） ----------
   目的：手机上不必横滑 640px 的宽表，首屏 2 行内看到「姓名 · 总分 · 排名 · 等次」。
   ⚠️ 桌面隐藏规则**必须写在 @media 之外**（与 .nav-toggle / .nav-mask / .nav-foot /
      .pager-mobile 同构）：写进 @media 里桌面就会把它露出来，桌面像素对比必挂。 */
.m-rank-box{display:none;}

@media (max-width:768px){
  .m-rank-box{
    display:block; background:var(--card); border:1px solid var(--line);
    border-radius:var(--radius); padding:10px 12px; margin-bottom:12px;
  }
  .m-rank-head{font-size:13px; font-weight:600; color:var(--ink-2); margin-bottom:6px;}
  /* 一行一人：名次（定宽居中）+ 姓名（弹性、超长省略）+ 分数（等宽数字右对齐）+ 等次徽标 */
  .m-rank-row{
    display:flex; align-items:center; gap:8px;
    padding:7px 0; border-top:1px solid var(--line); font-size:14px;
  }
  /* 第一行不加分隔线：用相邻兄弟选择器，不能用 :first-of-type
     （.m-rank-head 也是 div，:first-of-type 命中的是标题而非首行）。 */
  .m-rank-head + .m-rank-row{border-top:none;}
  .m-rank-no{flex:0 0 24px; text-align:center; font-weight:700; color:var(--ink-3); font-variant-numeric:tabular-nums;}
  .m-rank-name{flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .m-rank-score{flex:0 0 auto; font-weight:700; color:var(--red); font-variant-numeric:tabular-nums;}
  .m-rank-row .badge{flex:0 0 auto;}
}
