:root{
  --bg:#f3f6fb;--card:#fff;--text:#1f2937;--muted:#6b7280;--line:#e5e9f0;
  --primary:#1a6fb5;--primary-d:#14568c;--ok:#1d9e75;--warn:#ba7517;
  --danger:#c0392b;--info:#378add;--radius:12px;
  /* 主色的四档衍生色，随主题整体切换：
     soft=选中态/浅底，line=描边，glow=聚焦框，tint=极浅底 */
  --primary-soft:#e8f1fb;--primary-line:#cfe2f5;--primary-glow:#bcd8f2;--primary-tint:#f7fbff;
}
/* 四套子系统主题，色值和工作台卡片色块一一对应：进哪个系统就是哪个色系。
   调配中心用默认蓝（--primary 本身就是它），所以不用单独覆盖。 */
body.app-quote{--primary:#0f8a8a;--primary-d:#0a6b6b;--primary-soft:#e2f4f3;--primary-line:#c2e6e3;--primary-glow:#b3e0dd;--primary-tint:#f5fcfb}
body.app-core{--primary:#6a5acd;--primary-d:#5546b3;--primary-soft:#ece9fb;--primary-line:#d5cff3;--primary-glow:#cdc5f2;--primary-tint:#f9f8fe}
body.app-purchase{--primary:#b8721a;--primary-d:#96590f;--primary-soft:#fbeed9;--primary-line:#f0dcc0;--primary-glow:#efd7b4;--primary-tint:#fffbf5}
*{box-sizing:border-box}
body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Microsoft YaHei",sans-serif;background:var(--bg);color:var(--text);font-size:14px;line-height:1.6}
a{color:var(--primary);text-decoration:none}
/* 全站内容宽度。2026-10-26 从 1180 统一放宽到 1600：
   1180 只比 1024 宽一点，列多的列表（设备台账、采购申请）字会被挤到换行。
   1600 在 1920 屏上两侧各留 160，既铺得开又不会贴边。
   屏幕窄于 1600 时自动按屏幕宽（margin:auto + max-width 的默认行为），不用另写断点。 */
.wrap{max-width:1600px;margin:0 auto;padding:0 20px}
.topbar{background:#fff;border-bottom:1px solid var(--line);position:sticky;top:0;z-index:10}
.topbar-inner{display:flex;flex-direction:column;gap:2px;padding:10px 0 0}
.topbar-main{display:flex;align-items:center;gap:18px;min-height:38px}
.topbar-main .userbox{margin-left:auto}
.brand{display:flex;align-items:center;gap:8px;font-weight:700;color:var(--text);font-size:16px;white-space:nowrap}
.brand-mark{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:8px;background:var(--primary);color:#fff;font-size:14px;font-weight:700}
.nav{display:flex;gap:2px;overflow-x:auto;padding-bottom:8px;border-top:1px solid #f0f3f8;padding-top:6px}
.nav a{padding:8px 10px;border-radius:8px;color:var(--muted);white-space:nowrap;font-size:13px}
.nav a:hover{background:var(--primary-soft);color:var(--text)}
.nav a.active{background:var(--primary-soft);color:var(--primary);font-weight:600}
.userbox{display:flex;align-items:center;gap:10px;white-space:nowrap}
.username{color:var(--muted);font-size:13px}
.username em{display:inline-block;font-style:normal;margin-left:6px;padding:1px 6px;border-radius:999px;background:#eef2f7;font-size:11px;color:#556}
.logout{font-size:13px;color:var(--muted)}
.campus-switch select{padding:6px 10px;border:1px solid var(--line);border-radius:8px;font-size:13px;font-family:inherit;background:#fff;color:var(--text);max-width:170px}
.campus-tag{font-size:12px;color:var(--primary-d);background:var(--primary-soft);border-radius:999px;padding:3px 10px}
.campus-chip{display:inline-block;margin-top:2px;font-size:11px;color:#556;background:#eef2f7;border-radius:999px;padding:1px 8px}
.main{padding:24px 20px 48px}
.page-head{display:flex;justify-content:space-between;align-items:flex-end;gap:16px;margin-bottom:20px;flex-wrap:wrap}
.page-head h1{font-size:22px;margin:0 0 4px}
.page-head p{margin:0}
.head-actions{display:flex;gap:8px;flex-wrap:wrap}
.stat-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:14px;margin-bottom:20px}
.stat-card{background:#fff;border:1px solid var(--line);border-radius:var(--radius);padding:16px 18px;display:flex;flex-direction:column;gap:2px}
.stat-label{font-size:12px;color:var(--muted)}
.stat-card strong{font-size:26px;line-height:1.2}
.stat-sub{font-size:12px;color:var(--muted)}
.stat-card.ok strong{color:var(--ok)}
.stat-card.warn strong{color:var(--warn)}
.stat-card.danger strong{color:var(--danger)}
.stat-card.info strong{color:var(--info)}
.grid-2{display:grid;grid-template-columns:1.15fr .85fr;gap:16px;margin-bottom:16px}
.card{background:#fff;border:1px solid var(--line);border-radius:var(--radius);padding:18px;margin-bottom:16px}
.card-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;gap:10px}
.card-head h2{font-size:16px;margin:0}
.table-wrap{overflow-x:auto}
/* 手机上按列收窄的表格：.col-m-hide 在 ≤760px 隐藏，.col-m-show（单元格）/
   .col-m-block（块）只在 ≤760px 出现。用它把表格列数减下来，而不是让表格横向滚。
   目前只有采购概览的「最近单据」在用（2026-10-29）。 */
.col-m-show{display:none}
.col-m-block{display:none}
@media(max-width:760px){
  .col-m-hide{display:none}
  .col-m-show{display:table-cell}
  .col-m-block{display:block;margin-top:2px}
  /* 这张表手机上只剩 单号/状态/设备名称/申请人 四列，内边距和字号收一点，
     单号与状态不折行——否则一行会被拆成三行，「CG-202610-021」读起来很费劲。
     .table.table-m 是双类选择器：本段写在 .table 基础规则前面，靠它压过后面的内边距。 */
  .table.table-m th,.table.table-m td{padding:8px 4px;font-size:12.5px}
  .table.table-m tbody td:nth-child(1),.table.table-m tbody td:nth-child(5){white-space:nowrap}
  .table.table-m .pill{white-space:nowrap}
}
.table{width:100%;border-collapse:collapse;font-size:13px}
.table th,.table td{padding:10px 8px;border-bottom:1px solid var(--line);text-align:left;vertical-align:top}
.table th{color:var(--muted);font-weight:500;background:#fafbfd;white-space:nowrap}
.table tr:last-child td{border-bottom:0}
/* 孤儿数据：未挂项目的医院、未关联医院的资产等，列表里标红提醒补维护 */
.table tr.row-orphan td{background:#fdf7f6}
.table tr.row-orphan td:first-child{box-shadow:inset 3px 0 0 var(--danger)}
.badge{display:inline-block;padding:2px 8px;border-radius:999px;font-size:12px;white-space:nowrap}
.badge.ok{background:#e6f7f0;color:var(--ok)}
.badge.warn{background:#fdf0e0;color:var(--warn)}
.badge.info{background:var(--primary-soft);color:var(--info)}
.badge.danger{background:#fdecea;color:var(--danger)}
.hc-badge{display:inline-block;padding:1px 8px;border-radius:6px;font-size:12px;font-weight:600;color:var(--primary-d);background:var(--primary-soft);border:1px solid var(--primary-line);white-space:nowrap}
.badge.muted{background:#f0f1f4;color:var(--muted)}
.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:9px 16px;border-radius:9px;border:1px solid var(--line);background:#fff;color:var(--text);font-size:14px;cursor:pointer;font-family:inherit}
.btn:hover{background:#f7f9fc}
.btn.primary{background:var(--primary);border-color:var(--primary);color:#fff}
.btn.primary:hover{background:var(--primary-d)}
.btn.ghost{background:transparent}
/* 危险动作按钮（删除等不可撤销操作）。只用于超管可见的入口，配色别拿来做普通强调。 */
.btn.danger{background:var(--danger);border-color:var(--danger);color:#fff}
.btn.danger:hover{background:#b02a1f;border-color:#b02a1f}
.btn.danger[disabled]{opacity:.45;cursor:not-allowed}
.btn.block{width:100%}
.link{border:0;background:none;padding:0;color:var(--primary);cursor:pointer;font-size:13px;font-family:inherit}
.link.danger{color:var(--danger)}
.muted{color:var(--muted)}
.small{font-size:12px}
.mono{font-family:ui-monospace,Consolas,monospace}
.empty{color:var(--muted);padding:24px 8px;text-align:center}
.flash{padding:11px 14px;border-radius:9px;margin-bottom:14px;font-size:13px}
.flash.success{background:#e6f7f0;color:#0f6e56;border:1px solid #b9e8d6}
.flash.error{background:#fdecea;color:#a32d2d;border:1px solid #f5c4b3}
.filter-bar{display:flex;gap:8px;margin-bottom:14px;flex-wrap:wrap}
.filter-bar input,.filter-bar select{padding:9px 12px;border:1px solid var(--line);border-radius:9px;font-size:14px;font-family:inherit;background:#fff}
.filter-bar input{flex:1;min-width:200px}
/* 日期区间：label 包住「起始/截止」和日期框。日期框必须退出 .filter-bar input 的
   flex:1 通配（否则两个日期框各吃掉半行，把按钮挤到下一行）。 */
.filter-bar label.sq-date{display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--muted);white-space:nowrap}
.filter-bar label.sq-date input{flex:0 0 auto;min-width:0;width:148px}
.form label{display:flex;flex-direction:column;gap:6px;font-size:13px;color:var(--muted)}
.form input,.form select,.form textarea{padding:9px 12px;border:1px solid var(--line);border-radius:9px;font-size:14px;font-family:inherit;background:#fff;color:var(--text)}
.form input:focus,.form select:focus,.form textarea:focus{outline:2px solid var(--primary-glow);border-color:var(--primary)}
.form input:disabled,.form select:disabled{background:#f5f7fa;color:var(--muted)}
.grid-form{display:grid;grid-template-columns:repeat(2,1fr);gap:14px 16px}
.grid-form .full{grid-column:1/-1}
.req{color:var(--danger)}
.field-hint{font-size:12px;color:var(--muted)}
.duration-view{min-height:40px;padding:9px 12px;border:1px solid var(--line);border-radius:9px;background:#f8fafc;color:var(--text);font-weight:600;display:flex;align-items:center}
.log-json{margin:0;padding:12px;background:#f8fafc;border:1px solid var(--line);border-radius:9px;font-size:12px;line-height:1.55;white-space:pre-wrap;word-break:break-word;max-height:520px;overflow:auto}
.log-diff{grid-template-columns:1fr 1fr}
.log-summary{padding:12px 14px;border:1px solid var(--line);border-radius:9px;background:#f8fafc;margin-bottom:16px;font-weight:600}
.log-file-list{max-height:340px;overflow:auto;margin:0;padding-left:20px;font-size:12px;line-height:1.8;columns:2;column-gap:24px}
.log-file-list li{break-inside:avoid}
.log-file-list code{background:none;padding:0;color:var(--text)}
.log-diff-table th{width:150px}
.log-diff-table td{vertical-align:top}
.log-inline-json{white-space:pre-wrap;word-break:break-word;font-size:12px}
.log-raw{margin-top:18px}
.log-raw summary{cursor:pointer;color:var(--primary);font-weight:600;font-size:13px;margin-bottom:10px}
@media(max-width:900px){
  .log-diff{grid-template-columns:1fr}
  .log-file-list{columns:1}
}
.form-actions{display:flex;gap:10px;margin-top:18px}
.split{border:0;border-top:1px dashed var(--line);margin:22px 0 16px}
.signature-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-top:18px}
.signature-box{border:1px dashed #cbd5e1;border-radius:10px;padding:10px;background:#fbfdff}
.signature-head{display:flex;justify-content:space-between;align-items:center;font-size:13px;color:var(--muted);margin-bottom:6px}
.signature-canvas{width:100%;height:150px;background:#fff;border:1px solid var(--line);border-radius:8px;touch-action:none;cursor:crosshair;display:block}
.signature-name{margin-top:8px}
.inline{display:inline}
.actions-col{white-space:nowrap}
.actions-col form{display:inline;margin-left:6px}
.sig-links a{margin-right:6px}
.bar-list{display:flex;flex-direction:column;gap:10px}
.bar-row{display:grid;grid-template-columns:110px 1fr 60px;align-items:center;gap:10px;font-size:13px}
.bar-row.sb{grid-template-columns:96px 1fr 74px auto}
.bar-note{font-size:11px;color:var(--muted);white-space:nowrap}
.bar-name{color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bar-track{height:10px;background:#eef2f7;border-radius:999px;overflow:hidden}
.bar-fill{height:100%;background:var(--primary);border-radius:999px;min-width:2px}
.bar-fill.c-in_stock{background:var(--ok)}
.bar-fill.c-borrowed{background:var(--warn)}
.bar-fill.c-repair{background:var(--info)}
.bar-fill.c-scrapped{background:#9aa0a6}
.bar-val{text-align:right;color:var(--muted)}
.month-chart{display:flex;align-items:flex-end;gap:18px;padding:12px 4px 0;overflow-x:auto}
.month-col{display:flex;flex-direction:column;align-items:center;gap:6px;min-width:56px}
.month-val{font-size:12px;color:var(--muted)}
.month-bar{width:34px;background:var(--primary);border-radius:6px 6px 0 0;min-height:2px}
.month-label{font-size:12px;color:var(--muted)}
.month-sub{font-size:11px;color:#98a2b3}
.info-strip{background:var(--primary-tint);border:1px solid var(--primary-line);color:var(--primary-d);padding:10px 12px;border-radius:9px;font-size:13px}
.auth-page{display:flex;align-items:center;justify-content:center;min-height:100vh;background:#eef3f9;padding:20px}
.auth-card{background:#fff;border:1px solid var(--line);border-radius:16px;padding:32px;width:100%;max-width:380px;box-shadow:0 10px 30px rgba(15,61,92,.08)}
.auth-card h1{font-size:20px;margin:8px 0 4px;text-align:center}
.auth-sub{text-align:center;margin:0 0 18px}
.auth-brand{text-align:center}
.auth-card .form{display:flex;flex-direction:column;gap:14px}
.auth-card .btn{margin-top:4px}
.footer{border-top:1px solid var(--line);padding:16px 0;color:var(--muted);font-size:12px;text-align:center}
/* 页脚备案号：跟页脚同色，不吃链接默认蓝 */
.footer a,.v2-footer a{color:inherit;text-decoration:none}
.footer a:hover,.v2-footer a:hover{color:var(--primary);text-decoration:underline}
.auth-icp{margin-top:6px}
.auth-icp a{color:var(--muted);text-decoration:none}
.auth-icp a:hover{color:var(--primary);text-decoration:underline}
@media(max-width:1024px){
  .nav a{padding:8px}
  .campus-switch select{max-width:120px}
}
@media(max-width:900px){
  .stat-grid{grid-template-columns:repeat(2,1fr)}
  .grid-2{grid-template-columns:1fr}
  .grid-form{grid-template-columns:1fr}
  .signature-grid{grid-template-columns:1fr}
}
@media(max-width:640px){
  .topbar-inner{padding:8px 0 0;gap:0}
  .topbar-main{flex-wrap:wrap;gap:8px;min-height:0}
  .nav{width:100%}
  .userbox{margin-left:auto;flex-wrap:wrap;gap:8px}
  .stat-grid{grid-template-columns:repeat(2,1fr)}
  .page-head h1{font-size:19px}
  .main{padding:16px 14px 40px}
  .wrap{padding:0 14px}
  .bar-row{grid-template-columns:88px 1fr 48px}
  .bar-row.sb{grid-template-columns:80px 1fr 70px}
  .bar-row.sb .bar-note{grid-column:1/-1;margin-top:-4px}
  .month-chart{gap:10px}
}

/* 台账批量选择 */
.check-col{width:36px;text-align:center;padding-left:4px!important;padding-right:4px!important}
.check-col input{width:16px;height:16px;cursor:pointer;margin:0;vertical-align:middle}
.bulk-bar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:10px 12px;margin-bottom:14px;background:#f7fafd;border:1px solid #e2ecf6;border-radius:10px}
.bulk-count{font-size:13px;color:var(--muted)}
.bulk-count b{color:var(--primary);font-size:15px}
.bulk-bar .btn{padding:7px 14px;font-size:13px}
.bulk-bar .btn[disabled]{opacity:.45;cursor:not-allowed}

/* 导入结果明细 */
.plain-list{margin:6px 0 0;padding-left:20px;font-size:13px;color:var(--muted)}
.plain-list li{margin-bottom:3px}
.row-click{cursor:pointer}
.row-click:hover td{background:#f7fafd}

/* 个人签名维护 */
.signature-canvas-wrap{margin-top:6px;border:1px dashed #cbd5e1;border-radius:10px;padding:10px;background:#fbfdff}
.sig-current{display:flex;align-items:center;gap:14px;margin:14px 0 4px;padding:12px 14px;background:#f7fafd;border:1px solid #e2ecf6;border-radius:10px}
.sig-current-label{font-size:13px;color:var(--muted);flex:none}
.sig-current-img{max-height:64px;max-width:260px;background:#fff;border:1px solid var(--line);border-radius:6px;padding:2px}
.sig-empty{margin:14px 0 4px;padding:12px 14px;background:#fffaf0;border:1px solid #f2e0bb;border-radius:10px;font-size:13px;color:#8a6100}
.sig-upload{margin-top:14px}
.sig-upload input[type="file"]{display:block;margin-top:6px;font-size:13px}
.sig-hint{display:none;margin-top:6px;font-size:12px;color:#0b7a55}
.sig-flag{font-size:12px;color:var(--muted)}
.sig-block{margin-top:10px;padding-top:14px;border-top:1px dashed var(--line)}
.sig-block-head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:6px}
.small-btn{padding:5px 12px;font-size:13px}
.sig-note{margin:6px 0 0;font-size:12px;color:#a32d2d}

/* 系统权限勾选 */
.sys-block{margin-top:10px;padding-top:14px;border-top:1px dashed var(--line)}
.sys-block-head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:8px}
.sys-checks{display:flex;gap:10px;flex-wrap:wrap}
.sys-check{display:flex;align-items:center;gap:8px;padding:9px 14px;border:1px solid var(--line);border-radius:10px;background:#fbfdff;cursor:pointer;font-size:14px}
.sys-check input{width:16px;height:16px;margin:0;cursor:pointer}
.sys-check:has(input:checked){border-color:var(--primary);background:#eef6fd}
.sys-tag{font-size:11px;color:var(--muted);background:#eef2f7;border-radius:999px;padding:1px 7px;font-style:normal}
.sys-badge{display:inline-block;font-size:11px;background:#eef6fd;color:var(--primary-d);border-radius:999px;padding:1px 8px;margin:1px 3px 1px 0;white-space:nowrap}

/* 必填星号贴到标签右上角，避免纵向 flex 下单独占一行 */
.form label{position:relative}
.form label > .req{position:absolute;right:2px;top:0;color:var(--danger)}
/* 复选框组标签不要纵向排列 */
.form label.sys-check{flex-direction:row;align-items:center;gap:8px;color:var(--text);font-size:14px}

/* 数据备份页 */
.backup-actions{display:flex;gap:12px;flex-wrap:wrap;margin:14px 0 6px}
.backup-note{margin:14px 0 0;padding:12px 14px;background:#fffaf0;border:1px solid #f2e0bb;border-radius:10px;font-size:13px;line-height:1.9;color:#7a5800}
.backup-note strong{color:#a32d2d}
.table td.num,.table th.num{text-align:right;font-variant-numeric:tabular-nums}
.link.danger-link{color:var(--danger)}

/* ---------- 内部办公区：工作台与跨系统导航 ---------- */
.oa-back{font-size:13px;color:var(--muted);padding:5px 10px;border:1px solid var(--line);border-radius:8px;white-space:nowrap;flex:0 0 auto}
.oa-back:hover{background:var(--primary-soft);color:var(--primary);border-color:#cfe0f2}
.topbar-main .oa-back+.brand{border-left:1px solid var(--line);padding-left:16px}
.app-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:16px;margin-bottom:20px}
.app-card{display:flex;flex-direction:column;gap:8px;background:#fff;border:1px solid var(--line);border-radius:var(--radius);padding:20px;color:inherit;transition:border-color .15s,box-shadow .15s}
a.app-card:hover{border-color:var(--primary-line);box-shadow:0 6px 18px rgba(15,61,92,.07)}
.app-card h2{font-size:16px;margin:0;display:flex;align-items:center;gap:8px;color:var(--text)}
.app-card p{margin:0;color:var(--muted);font-size:13px;line-height:1.55;min-height:40px}
.app-mark{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:10px;background:var(--primary-soft);color:var(--primary);font-size:15px;font-weight:700}
.app-go{margin-top:auto;font-size:13px;color:var(--primary);font-weight:500}
.app-card.disabled{background:#fafbfc}
.app-card.disabled:hover{border-color:var(--line);box-shadow:none}
.app-card.disabled .app-mark{background:#eef0f3;color:var(--muted)}
.app-card.disabled .app-go{color:var(--muted);font-weight:400}

/* 工作台四宫格：一行四个、比内页卡片小一号，四个子系统各一套色系。
   列数与尺寸都挂在 .app-grid-home 上——admin/core/quote 内页仍用上面的
   auto-fill 白卡，别让这几条把那些页面一起改了。 */
/* minmax(0,1fr) 不能写成 1fr：描述用了 -webkit-box 截断，固有最小宽度会把列撑破，
   手机上就变成两列加起来比屏幕还宽、右侧被裁 */
.app-grid.app-grid-home{grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;margin-bottom:22px}
.app-grid-home .app-card{
  --ac:var(--primary);--ac-bg:#e6f0fa;--ac-soft:#f4f9ff;
  position:relative;overflow:hidden;min-width:0;gap:6px;padding:14px 15px 13px;border-radius:10px;
  background:linear-gradient(168deg,var(--ac-bg) 0%,#fff 66%);
}
/* 顶部 3px 色条：四张卡靠这一条区分系统，比整块染底更轻 */
.app-grid-home .app-card::before{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:var(--ac)}
.app-grid-home a.app-card:hover{border-color:var(--ac);box-shadow:0 6px 16px rgba(15,61,92,.09)}
.app-grid-home .app-card h2{font-size:15px}
/* 描述统一两行截断，四张卡高度就齐了，不用逐条算字数 */
.app-grid-home .app-card p{font-size:12.5px;line-height:1.5;min-height:38px;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
/* 图标反白：卡片底已经是淡色，图标再用淡色就糊成一片 */
.app-grid-home .app-mark{width:32px;height:32px;border-radius:9px;background:#fff;color:var(--ac);font-size:13px;
  box-shadow:0 1px 2px rgba(15,61,92,.08)}
.app-grid-home .app-go{font-size:12.5px;color:var(--ac)}
/* 蓝 / 青 / 紫 / 橙，明度接近，四张摆一起不打架 */
.app-grid-home .app-dispatch{--ac:var(--primary);--ac-bg:#e6f0fa;--ac-soft:#f4f9ff}
.app-grid-home .app-quote{--ac:#0f8a8a;--ac-bg:#e2f4f3;--ac-soft:#f2fbfa}
.app-grid-home .app-core{--ac:#6a5acd;--ac-bg:#ece9fb;--ac-soft:#f7f6fe}
.app-grid-home .app-purchase{--ac:#b8721a;--ac-bg:#fbeed9;--ac-soft:#fffaf2}
/* 规划中 / 无权进入：连色条一起压灰，别用彩色吊人胃口 */
.app-grid-home .app-card.disabled{--ac:#94a3b8;--ac-bg:#eef1f5;--ac-soft:#fbfcfd}
.pill{display:inline-block;font-size:11px;font-weight:500;padding:2px 9px;border-radius:999px}
.pill.planned{background:#f0f1f4;color:var(--muted)}
/* 重要通知标记：橙底深橙字，和「规划中」的灰底一眼能分开 */
.pill.imp{background:#fdf0e0;color:var(--warn);font-weight:600}
/* pill 语义配色提到通用层（2026-10-27）。
   原先 ok/warn/bad/info 只在 purchase.css 的 .req-table 和 .view-pick 作用域里定义，
   供应商档案这类普通 .table 用 <span class="pill ok"> 会得到一颗没有底色的透明药丸，
   状态全靠一行灰字。配色上移，各页不必再各自声明一遍。 */
.pill.ok{background:#e6f7f0;color:var(--ok)}
.pill.warn{background:#fdf0e0;color:var(--warn)}
.pill.bad{background:#fdeaea;color:var(--danger)}
.pill.info{background:var(--primary-soft);color:var(--info)}
.pill.muted{background:#f0f1f4;color:var(--muted)}
.oa-tools .sep{color:#c8ced8;margin:0 8px}
.auth-back{margin-top:14px;padding-top:12px;border-top:1px solid var(--line)}
@media(max-width:1000px){
  /* 四列在平板上每张只剩 230px 左右，描述要折三行，提前收到两列 */
  .app-grid.app-grid-home{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media(max-width:720px){
  .oa-back{padding:4px 8px;font-size:12px}
  .topbar-main .oa-back+.brand{padding-left:10px}
  .app-grid:not(.app-grid-home){grid-template-columns:1fr}
  /* 手机上保持两列两行，一屏看全四个入口，只把卡片再压一号 */
  .app-grid.app-grid-home{gap:10px;margin-bottom:18px}
  .app-grid-home .app-card{padding:11px 12px 10px;gap:4px;border-radius:9px}
  .app-grid-home .app-card::before{height:2px}
  .app-grid-home .app-card h2{font-size:13px;gap:6px}
  .app-grid-home .app-card p{font-size:11.5px;line-height:1.45;min-height:33px}
  .app-grid-home .app-mark{width:26px;height:26px;border-radius:7px;font-size:12px}
  .app-grid-home .app-go{font-size:11.5px}
  /* 窄屏下标题不再跟右侧说明抢宽度：标题不换行，说明整行落到下一行 */
  .card-head{flex-wrap:wrap;gap:4px 10px}
  .card-head h2{white-space:nowrap}
}

/* ---------- 可搜索下拉框 assets/search-select.js ---------- */
/* 外层容器。原生 select 透明铺满、不挡点击，所以 required 校验气泡
   还能落在正确位置，表单提交与原有 onchange 全部照旧。 */
.ss{position:relative;display:block;width:100%}
/* 关键：is-ready 由 JS 增强成功后加上。JS 没跑或被拦住时这个类不存在，
   页面显示的就是原生 select，功能不受影响——不能因为脚本挂了就让下拉框消失。 */
.ss.is-ready > select{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;
  margin:0;padding:0;border:0;background:transparent;opacity:0;pointer-events:none;
  appearance:none;-webkit-appearance:none;-moz-appearance:none}
.ss:not(.is-ready) .ss-input{display:none}
/* 高度与 .form select 对齐：都是 padding 9px + 14px 字 + 1px 边框 */
.ss-input{width:100%;box-sizing:border-box;padding:9px 32px 9px 12px;border:1px solid var(--line);
  border-radius:9px;font-size:14px;font-family:inherit;background:#fff;color:var(--text);
  line-height:21px;cursor:pointer}
.ss-input:focus{outline:2px solid var(--primary-glow);border-color:var(--primary)}
.ss-input:disabled{background:#f5f7fa;color:var(--muted);cursor:not-allowed}
.ss-input::placeholder{color:#9aa3af}
.ss.is-empty .ss-input{color:#9aa3af}
/* is-edit：方式二进行中，A 就是输入框，光标要正常 */
.ss.is-edit .ss-input{cursor:text}
.ss.is-open .ss-input{border-color:var(--primary)}
/* 箭头热区：点这里走方式一。做成右侧一整条 32px，比 9px 的三角好点 */
.ss-hit{position:absolute;top:0;right:0;bottom:0;width:32px;cursor:pointer}
/* 箭头用 border 画，不依赖字体里的三角字符（有些系统字体渲成一个小点） */
.ss-arrow{position:absolute;right:12px;top:50%;margin-top:-3px;width:0;height:0;
  border-left:4.5px solid transparent;border-right:4.5px solid transparent;
  border-top:6px solid #9aa3af;pointer-events:none;transition:transform .15s}
.ss.is-open .ss-arrow{transform:rotate(180deg);transform-origin:50% 40%}

/* 弹层挂在 body 下、position:fixed，绕开 .table-wrap 的 overflow 裁剪 */
.ss-pop{position:fixed;z-index:1000;background:#fff;border:1px solid var(--line);border-radius:10px;
  box-shadow:0 10px 28px rgba(15,30,60,.16);display:none;flex-direction:column;overflow:hidden}
/* 方式一的搜索框 C：贴在浮层顶部，与控件 A 上下紧邻，形成 A -> C -> B 的堆叠 */
.ss-search{position:relative;padding:6px 8px;background:#f8fafd;border-bottom:1px solid var(--line);
  flex:0 0 auto}
.ss-search-input{width:100%;box-sizing:border-box;padding:6px 10px 6px 28px;border:1px solid var(--line);
  border-radius:8px;font-size:13.5px;font-family:inherit;background:#fff;color:var(--text);line-height:1.3}
.ss-search-input:focus{outline:2px solid var(--primary-glow);border-color:var(--primary)}
.ss-search-input::placeholder{color:#9aa3af}
/* 放大镜用两个 CSS 图形拼，不依赖图标字体 */
.ss-mag{position:absolute;left:19px;top:50%;width:8px;height:8px;margin-top:-6px;
  border:1.4px solid #9aa3af;border-radius:50%;pointer-events:none}
.ss-mag::after{content:"";position:absolute;right:-4px;bottom:-3px;width:5px;height:1.4px;
  background:#9aa3af;transform:rotate(45deg)}
.ss-list{position:relative;overflow-y:auto;padding:4px;flex:1 1 auto;min-height:0;
  overscroll-behavior:contain}
.ss-item{padding:6px 10px;border-radius:7px;cursor:pointer;font-size:13.5px;line-height:20px;
  color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ss-item:hover{background:#f2f7fd}
.ss-item.active{background:var(--primary-soft);color:var(--primary-d)}
.ss-item[data-picked]{font-weight:600}
.ss-item[data-picked]::after{content:"\2713";float:right;margin-left:8px;color:var(--primary);font-weight:400}
.ss-item.off{color:#b8bfc9;cursor:not-allowed;background:none}
.ss-item mark{background:#fdf2c4;color:#6b4e00;padding:0 1px;border-radius:2px}
.ss-empty{padding:14px 12px;text-align:center;color:var(--muted);font-size:13px}
.ss-note{padding:6px 12px;font-size:12px;color:var(--muted);background:#fafbfd;
  border-top:1px solid var(--line);flex:0 0 auto}
@media(max-width:720px){
  .ss-pop{max-height:50vh!important}
}

/* ---------- 通用浮层（modal）—— 全系统共用，2026-10-25 ----------
   配套 assets/modal.js，两份都由 lib/ui.php 统一引入。
   页面上的表单不再常驻在列表上方，改为点「新增」/「编辑」时浮出。
   宽度两档：默认 620px 放短表单，加 .wide 用 1040px 放医院档案、账号管理等长表单。 */
.oa-modal{
  position:fixed;inset:0;z-index:900;
  display:flex;align-items:center;justify-content:center;
  padding:24px;
  background:rgba(23,32,48,.42);
  -webkit-backdrop-filter:blur(1px);backdrop-filter:blur(1px);
  animation:oaFade .16s ease;
}
.oa-modal[hidden]{display:none}
.oa-modal-box{
  width:620px;max-width:100%;max-height:88vh;
  display:flex;flex-direction:column;
  background:var(--card);border-radius:14px;overflow:hidden;
  box-shadow:0 24px 64px rgba(16,24,40,.26);
  animation:oaRise .2s cubic-bezier(.2,.8,.3,1);
}
.oa-modal-box.wide{width:1040px}
.oa-modal-head{
  flex:0 0 auto;display:flex;align-items:center;gap:12px;
  padding:15px 20px;border-bottom:1px solid var(--line);
}
.oa-modal-head h2{margin:0;font-size:16px;font-weight:600;flex:1 1 auto;line-height:1.35}
.oa-modal-x{
  flex:0 0 auto;width:30px;height:30px;border:0;border-radius:8px;padding:0;
  background:transparent;color:var(--muted);font-size:20px;line-height:1;cursor:pointer;
}
.oa-modal-x:hover{background:var(--bg);color:var(--text)}
/* form 夹在 box 与 body/foot 之间，自己也得撑成 flex 列，内部滚动才生效 */
.oa-modal-box > form{display:flex;flex-direction:column;min-height:0;flex:1 1 auto}
.oa-modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding:18px 20px}
.oa-modal-foot{
  flex:0 0 auto;display:flex;gap:10px;justify-content:flex-end;
  padding:13px 20px;border-top:1px solid var(--line);background:#fafbfd;
}
.oa-modal-box.is-shake{animation:oaShake .42s ease}
body.oa-modal-open{overflow:hidden}

/* 浮层里的栅格：窄卡片单列（左右结构留足输入宽度），宽卡片两列 */
.oa-modal-body .grid-form{grid-template-columns:1fr;gap:8px}
.oa-modal-box.wide .oa-modal-body .grid-form{grid-template-columns:repeat(auto-fit,minmax(380px,1fr));gap:8px 24px}

@keyframes oaFade{from{opacity:0}to{opacity:1}}
@keyframes oaRise{from{opacity:0;transform:translateY(10px) scale(.985)}to{opacity:1;transform:none}}
@keyframes oaShake{
  0%,100%{transform:translateX(0)}
  20%{transform:translateX(-7px)}
  40%{transform:translateX(6px)}
  60%{transform:translateX(-4px)}
  80%{transform:translateX(3px)}
}

@media (max-width:760px){
  .oa-modal{padding:0;align-items:stretch}
  .oa-modal-box{width:100%;max-width:none;max-height:100vh;height:100%;border-radius:0}
  .oa-modal-body{padding:14px 16px}
}

/* ---------- 保存后跳转定位到的那一行（配合 row_attrs / redirect_hl） ---------- */
.table tr.hl td{background:#fff8e1}
.table tr.hl td:first-child{box-shadow:inset 3px 0 0 var(--warn)}

/* ---------- 浮层表单：字段名与输入框左右同行（2026-10-25 从 quote.css 上移） ----------
   原先只有报价系统加载得到这段样式，core/dispatch 两个子系统的浮层仍是「字段名一行、
   输入框一行」，纵向多占三成高度。现在放通用层，四个子系统一套写法。
   注意只作用于 .grid-form 的直接子 label：医院档案、项目档案里的复选框组
   （.sys-block 内的 .sys-check）是 label 套 input，不能跟着变成两列栅格。 */
.form-hl .grid-form{grid-template-columns:repeat(auto-fit,minmax(340px,1fr));gap:6px 24px}
.form-hl .grid-form > label{
  display:grid;
  grid-template-columns:100px minmax(0,1fr);
  align-items:center;
  column-gap:10px;
  row-gap:1px;
}
.form-hl .grid-form > label > .fl{grid-column:1;justify-self:end;text-align:right;line-height:1.3}
.form-hl .grid-form > label > input,
.form-hl .grid-form > label > select,
.form-hl .grid-form > label > textarea{grid-column:2;width:100%}
/* 可搜索下拉会把原生 select 包进 .ss，包裹层也要落在第二列 */
.form-hl .grid-form > label > .ss{grid-column:2}
.form-hl .grid-form > label > .field-hint{grid-column:2;font-size:11.5px;line-height:1.35}
.form-hl .grid-form > label.full{grid-column:1/-1}
.form-hl .grid-form > label > input[type=hidden],
.form-hl .grid-form > label > datalist{display:none}
.form-hl .grid-form > input[type=hidden]{display:none}

/* 浮层表单里的分组小标题（2026-10-27，供应商档案字段变多后按块切开）
   必须自己声明 grid-column:1/-1 横跨整行——它不在 label 里，
   .form-hl .grid-form > label 的网格规则管不到它，不加会被挤进第一列。
   右边的 <em> 是块内说明，弱化成灰色小字。 */
.form-hl .grid-form > .form-group-title{
  grid-column:1/-1;
  display:flex;align-items:baseline;gap:10px;
  margin-top:10px;padding-bottom:6px;
  border-bottom:1px solid var(--line);
  font-size:13px;font-weight:600;color:var(--text);
}
.form-hl .grid-form > .form-group-title:first-child{margin-top:0}
.form-hl .grid-form > .form-group-title > em{
  font-style:normal;font-weight:400;font-size:11.5px;color:var(--muted);
}

/* ---------- 显式列数的栅格（2026-10-27） ----------
   默认 .grid-form 是 repeat(auto-fit,minmax(340px,1fr))，列数跟着容器宽度飘，
   字段一多每行几个说不准。供应商档案要按分组定死「一行四列 / 一行两列」，
   所以在同一个 form 里拆成多个 grid 容器，各自带 cols-* 类。
   注意：.form-hl 的 auto-fit 规则选择器是 .form-hl .grid-form，
   这里用 .form-hl .grid-form.cols-4 提一级特异性，能覆盖掉它。 */
.form-hl .grid-form.cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}
.form-hl .grid-form.cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}
/* 四列时每格只有三百多像素，标签再占 100px 就只剩两百给输入框，
   收窄到 80px 并允许换行（「许可证有效期」六个字会折成两行）。 */
.form-hl .grid-form.cols-4 > label{grid-template-columns:80px minmax(0,1fr)}
/* 多行输入：供货范围、代理品牌这类要能写好几行（textarea 默认两行太窄） */
.form-hl .grid-form > label > textarea{min-height:68px;resize:vertical;line-height:1.5}
/* 中屏四列挤不下，降到两列；窄屏一律单列。
   断点取 1200 而不是 1400：1366 笔记本屏是最常见的办公分辨率，
   1400 会让它直接掉成两列，四列布局在这些机器上等于没生效。
   1200 下每列约 300px（标签 80 + 输入 210），能填 18 位税号。 */
@media(max-width:1200px){
  .form-hl .grid-form.cols-4{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media(max-width:900px){
  .form-hl .grid-form.cols-4,
  .form-hl .grid-form.cols-2{grid-template-columns:1fr}
}

/* ---------- 分组块：每组包一层，视觉上隔开 ---------- */
.form-hl .form-panel{margin-bottom:18px}
.form-hl .form-panel:last-of-type{margin-bottom:0}

/* ---------- 资质附件槽位（供应商档案，2026-10-27） ----------
   每个预设证照类型一个槽：已上传的列在上面可下载/删除，下面是上传框。
   用 auto-fill 而不是定死列数——类型有六种，窄屏自动折行比横向滚动好。 */
.doc-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:12px;margin-top:8px}
.doc-slot{border:1px solid var(--line);border-radius:10px;padding:10px 12px;background:#fbfdff}
.doc-slot-head{font-size:12.5px;font-weight:600;color:var(--text);margin-bottom:8px}
.doc-slot-head .muted{font-weight:400}
.doc-files{list-style:none;margin:0 0 8px;padding:0}
.doc-files li{display:flex;align-items:center;gap:8px;font-size:12.5px;padding:4px 0;border-bottom:1px dashed var(--line)}
.doc-files li:last-child{border-bottom:0}
.doc-files li a{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.doc-files li .muted{flex:0 0 auto;font-size:11px}
.doc-del{border:0;background:none;color:var(--danger);cursor:pointer;font-size:15px;line-height:1;padding:2px 4px}
.doc-slot input[type=file]{width:100%;font-size:12px}

/* ---------- 行内图标按钮（报价单列表的打印/复用/删除，2026-10-25） ----------
   图标本身是内联 SVG（见 quote/functions.php 的 q_icon()），用 currentColor 上色，
   所以这里只管尺寸、间距和悬停态。放在通用层是因为将来别的列表也要用。
   注意：所在行通常整行可点（onclick 跳详情），td 上必须 stopPropagation，
   否则点图标会连带跳走。 */
.op-icons{white-space:nowrap;text-align:right}
.ico-btn{
  display:inline-flex;align-items:center;justify-content:center;
  width:26px;height:26px;padding:0;margin-left:2px;
  border:1px solid transparent;border-radius:6px;
  background:transparent;color:var(--muted);
  cursor:pointer;vertical-align:middle;text-decoration:none;
  transition:background .12s,color .12s,border-color .12s;
}
.ico-btn .ico{width:17px;height:17px;display:block}
.ico-btn:hover{background:var(--bg);color:var(--text);border-color:var(--line)}
.ico-btn.danger:hover{background:#fdecea;color:#b3261e;border-color:#f3c9c4}
.ico-btn:focus-visible{outline:2px solid var(--primary);outline-offset:1px}
form.inline + .ico-btn,form.inline{display:inline}

/* 电子印章预览：棋盘格底才能看出图片到底有没有透明区域 */
.seal-block{margin-top:4px;border:1px solid var(--line);border-radius:9px;padding:12px 14px;background:#fcfdff}
.seal-block-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px;margin-bottom:10px}
.seal-current{display:flex;gap:14px;align-items:center;margin-bottom:12px}
.seal-preview{
  width:96px;height:96px;flex:0 0 auto;border:1px dashed var(--line);border-radius:8px;
  display:flex;align-items:center;justify-content:center;overflow:hidden;
  background-image:
    linear-gradient(45deg,#e8edf3 25%,transparent 25%,transparent 75%,#e8edf3 75%),
    linear-gradient(45deg,#e8edf3 25%,transparent 25%,transparent 75%,#e8edf3 75%);
  background-size:12px 12px;
  background-position:0 0,6px 6px;
  background-color:#fff;
}
.seal-preview img{max-width:100%;max-height:100%;object-fit:contain}
.seal-current-meta{display:flex;flex-direction:column;gap:6px}
.seal-clear{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;color:#b3261e;cursor:pointer}
.seal-empty{margin:0 0 12px;font-size:12.5px;color:var(--muted)}
.seal-upload{display:block}
.seal-thumb{width:52px;height:52px;object-fit:contain;border:1px solid var(--line);border-radius:5px;background:#fff;vertical-align:middle}
.seal-thumb-link{display:inline-block;line-height:0}

/* 电子印章：选完文件后的即时预览（2026-10-25）
   和 .seal-current 并排，让"当前已生效的章"和"刚选还没保存的章"一眼能分开：
   前者常驻、后者带红字提示且只在选了文件后出现。 */
.seal-pick{display:flex;gap:18px;align-items:flex-start;flex-wrap:wrap}
.seal-pick .seal-upload{flex:1 1 260px;min-width:220px}
.seal-pick-preview{display:flex;gap:10px;align-items:center}
.seal-pick-preview[hidden]{display:none}
.seal-pick-tip{max-width:150px;font-size:12px;line-height:1.45;color:#b3261e}

/* ---------- 表头点击排序（2026-10-25） ----------
   给 <table data-sortable> 里的 <th class="th-sort"> 用。
   箭头走 ::after 绝对定位，不占文档流 —— 加了排序能力后表头文字宽度一点不变，
   不会把「项目名称」「关联医院」这些本来刚好放下的列挤到换行。
   未排序时显示淡的 ↕（U+2195，微软雅黑有字形），免得有人不知道这里能点。 */
.table th.th-sort{cursor:pointer;user-select:none;position:relative;padding-right:20px}
.table th.th-sort::after{
  content:'\2195';position:absolute;right:6px;top:50%;transform:translateY(-50%);
  font-size:11px;line-height:1;opacity:.3;
}
.table th.th-sort:hover{background:#eef3f9;color:var(--text)}
.table th.th-sort:hover::after{opacity:.6}
.table th.th-sort.sort-asc::after{content:'\25B2';font-size:9px;opacity:.85}
.table th.th-sort.sort-desc::after{content:'\25BC';font-size:9px;opacity:.85}

/* ---------- 列表分页（2026-10-25，四系统共用） ----------
   由 oa_pager() 输出，资产清单与报价单列表共用。
   原先这套样式只写在 quote.css 里，导致「基础资料」的资产清单
   根本不加载它 —— 上一页/下一页是两个没有任何排版的裸链接。
   放公共层才不会再犯。 */
.pg-wrap{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:16px 0 40px;padding:0 2px}
.pg{display:flex;align-items:center;gap:6px;flex-wrap:wrap;flex:1;justify-content:center}
.pg-item{
  min-width:34px;height:34px;padding:0 10px;box-sizing:border-box;
  display:inline-flex;align-items:center;justify-content:center;
  border:1px solid var(--line);border-radius:7px;background:#fff;
  font-size:13px;color:var(--text);text-decoration:none;line-height:1;cursor:pointer;
  transition:background .12s,border-color .12s,color .12s;
}
.pg-item:hover{background:#eef3f9;border-color:#bfd3e8}
.pg-item.cur{background:#1a4a7a;border-color:#1a4a7a;color:#fff;font-weight:600;cursor:default}
.pg-item.cur:hover{background:#1a4a7a;border-color:#1a4a7a}
/* 首末页时的禁用态：用 span 而非 a，同时保证不会被误点 */
.pg-item.off{color:#c2cbd6;background:#f8fafc;cursor:not-allowed}
.pg-item.off:hover{background:#f8fafc;border-color:var(--line)}
/* 「…」可点，虚线边框提示它不是纯装饰 */
.pg-gap{color:#7b8a9a;font-size:14px;letter-spacing:1px;border-style:dashed}
.pg-gap:hover{background:#eef3f9;color:#1a4a7a}
.pg-info{font-size:12.5px;color:var(--muted);white-space:nowrap;min-width:150px;text-align:right}
.pg-size{display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--muted)}
.pg-size select{height:32px;padding:0 6px;border:1px solid var(--line);border-radius:6px;font-size:13px}

/* 列表序号列（跨页连续，不按页重排） */
.seq-col{width:58px;text-align:center;color:var(--muted);font-variant-numeric:tabular-nums;font-size:12.5px}

/* ===== 货架标签页（2026-10-25 · 四系统共用） =====
   用于「一个仓库多个货架」这类同级视图切换，如日常共享 / 临时共享。
   列表页用 <a href="?shelf=xx"> 整页跳，表单页用 JS 切显示，样式复用这一套。 */
.oa-tabs{display:flex;gap:4px;margin:0 0 16px;border-bottom:1px solid var(--line);flex-wrap:wrap}
.oa-tabs a{display:inline-flex;align-items:center;gap:7px;padding:9px 16px;border:1px solid transparent;border-bottom:0;border-radius:9px 9px 0 0;color:var(--muted);font-size:13.5px;margin-bottom:-1px;white-space:nowrap}
.oa-tabs a:hover{background:var(--primary-soft);color:var(--text)}
.oa-tabs a.on{background:#fff;border-color:var(--line);border-bottom-color:#fff;color:var(--primary);font-weight:600}
.oa-tabs .cnt{display:inline-block;min-width:22px;padding:0 7px;border-radius:999px;background:#eef2f7;color:#556;font-size:11.5px;line-height:18px;text-align:center;font-weight:400}
.oa-tabs a.on .cnt{background:var(--primary);color:#fff}
.oa-tabs .cnt.zero{background:#f3f4f6;color:#aeb6bf}

/* 已退出调配的行：保留可查，视觉下沉，但不遮住 redirect_hl 的高亮 */
.table tr.row-retired:not(.hl) td{color:#aeb6bf;background:#fafbfc}
.table tr.row-retired:not(.hl) td strong{color:#aeb6bf}
.table tr.row-retired:not(.hl) .hc-badge{background:#f3f4f6;border-color:#e8eaed;color:#aeb6bf}

/* 设备来源标记（院内资产 / 院外供应商 / 手填） */
.src-chip{display:inline-block;padding:0 7px;border-radius:5px;font-size:11.5px;line-height:18px;background:#eef2f7;color:#556;white-space:nowrap}
.src-chip.vendor{background:#fdf3e7;color:#8a5a12}
.src-chip.asset{background:var(--primary-soft);color:var(--primary-d)}

/* 约定归还日期逾期 */
.due-overdue{color:var(--danger);font-weight:600}

/* ===== 多选搜索下拉（2026-10-25 · 公共组件） =====
   点开浮层勾选，收起后已选项以标签形式留在框内，不在页面上占一大块滚动区。
   数据仍然是 form 里的 checkbox，提交/校验都不用特殊处理。

   注意：所有选择器都带 .pm 前缀。因为 .form label / .form input 的特异性是 (0,1,1)，
   裸写 .pm-item / .pm-input（(0,1,0)）会被它们压过 —— 表现是列表项变成竖排、
   输入框被套上第二层边框。加 .pm 前缀后是 (0,2,0)，稳压。 */
.pm{position:relative;z-index:20}
.pm .pm-box{display:flex;flex-wrap:wrap;gap:6px;align-items:center;min-height:42px;padding:6px 10px;border:1px solid var(--line);border-radius:9px;background:#fff;cursor:text;transition:border-color .12s}
.pm .pm-box:hover{border-color:#c8d6e6}
.pm .pm-box.focus{border-color:var(--primary);box-shadow:0 0 0 3px #e3f0fb}
.pm .pm-chip{display:inline-flex;flex-direction:row;align-items:center;gap:4px;max-width:230px;padding:3px 5px 3px 9px;border-radius:7px;background:var(--primary-soft);color:var(--primary-d);font-size:12.5px;line-height:1.45}
.pm .pm-chip b{font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pm .pm-chip .x{border:0;background:transparent;color:#6b93bb;cursor:pointer;font-size:14px;line-height:1;padding:0 2px;font-family:inherit}
.pm .pm-chip .x:hover{color:var(--danger)}
.pm .pm-input{flex:1;min-width:110px;border:0;outline:0;box-shadow:none;font-family:inherit;font-size:13.5px;padding:3px 0;background:transparent;color:var(--text);border-radius:0}
.pm .pm-input:focus{outline:0;border:0;box-shadow:none}
.pm .pm-pop{position:absolute;left:0;right:0;top:calc(100% + 4px);z-index:30;background:#fff;border:1px solid var(--line);border-radius:10px;box-shadow:0 10px 26px rgba(20,45,75,.13);overflow:hidden}
.pm .pm-pop[hidden]{display:none}
.pm .pm-search{display:block;width:100%;border:0;border-bottom:1px solid var(--line);border-radius:0;outline:0;box-shadow:none;padding:10px 12px;font-family:inherit;font-size:13.5px;color:var(--text);background:#fff}
.pm .pm-search:focus{outline:0;border:0;border-bottom:1px solid var(--line);box-shadow:none}
.pm .pm-head{display:grid;grid-template-columns:16px minmax(0,1.6fr) minmax(92px,.9fr) minmax(104px,1fr) minmax(84px,.85fr);align-items:center;gap:12px;padding:6px 13px;border-bottom:1px solid #eef2f7;font-size:11px;color:#9aa7b4;letter-spacing:.2px;background:#fcfdfe}
.pm .pm-list{max-height:300px;overflow-y:auto;padding:0 4px 4px}
.pm .pm-item{display:grid;grid-template-columns:16px minmax(0,1.6fr) minmax(92px,.9fr) minmax(104px,1fr) minmax(84px,.85fr);align-items:center;gap:12px;padding:7px 9px;border-radius:7px;cursor:pointer;font-size:13px;color:var(--text)}
.pm .pm-item:hover{background:#f4f8fc}
.pm .pm-item.on{background:#eef5fd}
.pm .pm-item input{flex:none;margin:0;width:15px;height:15px}
.pm .pm-item .nm{display:flex;flex-direction:row;align-items:center;gap:6px;min-width:0}
.pm .pm-item .nm .t{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pm .pm-item .c-model,.pm .pm-item .c-sn,.pm .pm-item .c-dept{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11.5px;color:var(--muted)}
.pm .pm-item .c-sn{font-family:ui-monospace,Consolas,monospace;font-size:11px;color:#7b8894}
.pm .pm-item .blank{font-style:normal;color:#c4ccd6}
.pm .pm-item .tag{flex:none;font-style:normal;font-size:11px;color:#8a5a12;background:#fdf3e7;border-radius:5px;padding:0 6px;line-height:17px}
.pm .pm-empty{padding:18px;text-align:center;color:var(--muted);font-size:13px}
@media(max-width:760px){
  .pm .pm-head,.pm .pm-item{grid-template-columns:16px minmax(0,1.5fr) minmax(80px,.9fr) minmax(0,.9fr);gap:9px}
  .pm .pm-item .c-sn,.pm .pm-head .h-sn{display:none}
  .pm .pm-item .c-sn{display:none}
}

/* ---------- 工作台 · 我的待办 ---------- */
.todo-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:14px}
.todo-item{
  display:flex;align-items:center;gap:10px;min-width:0;
  /* 上下留白比左右大一点，一两条待办时不显得扁 */
  padding:17px 16px;border:1px solid var(--line);border-radius:10px;
  background:var(--card);text-decoration:none;color:var(--text);
  transition:border-color .15s,background .15s;
}
.todo-item:hover{border-color:var(--primary-line);background:var(--primary-tint);text-decoration:none}
.todo-item .ti-name{flex:1 1 auto;min-width:0;font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.todo-item .ti-num{
  flex:0 0 auto;min-width:28px;height:28px;padding:0 9px;border-radius:14px;
  display:inline-flex;align-items:center;justify-content:center;
  background:#fdeaea;color:var(--danger);font-size:14px;font-weight:700;line-height:1;
}
.todo-item .ti-unit{flex:0 0 auto;font-size:12px;color:var(--muted)}
.todo-item.zero .ti-num{background:#eef2f7;color:#94a3b8;font-weight:600}

/* ---------- 系统通知 ---------- */
.notice-list{display:flex;flex-direction:column;gap:12px;margin-bottom:16px}
.notice-item{border:1px solid var(--line);border-radius:10px;background:var(--card);padding:14px 16px}
/* 未读：淡主色底 + 实心圆点，扫一眼就知道哪几条没看 */
.notice-item.unread{border-color:var(--primary-line);background:var(--primary-tint)}
.notice-item.off{opacity:.72}
.notice-head{display:flex;align-items:center;gap:10px;cursor:pointer;flex-wrap:wrap}
.notice-head h3{margin:0;font-size:15px;font-weight:500;color:var(--text)}
.notice-item.unread .notice-head h3{font-weight:700}
.notice-dot{flex:0 0 auto;width:7px;height:7px;border-radius:50%;background:transparent;box-shadow:inset 0 0 0 1px var(--line)}
.notice-item.unread .notice-dot{background:var(--primary);box-shadow:none}
.notice-head time{margin-left:auto;font-size:12px;color:var(--muted);white-space:nowrap}
.notice-item .notice-by{white-space:nowrap}
.notice-ops{display:flex;align-items:center;gap:8px;white-space:nowrap}
.notice-ops form{display:inline}
.notice-body{margin-top:10px;padding-top:10px;border-top:1px dashed var(--line);
  font-size:13.5px;line-height:1.85;color:#374151}
@media(max-width:640px){
  .notice-head{gap:8px}
  .notice-head time{margin-left:0;order:9;flex-basis:100%}
}

/* ---------- 阅读情况（仅管理员可见，三级信息，故意做得不显眼） ---------- */
.read-stat{margin-top:14px;padding-top:10px;border-top:1px dashed var(--line);
  font-size:12px;line-height:1.5}
.read-stat>summary{display:inline-flex;align-items:center;gap:7px;cursor:pointer;
  color:var(--muted);list-style:none;user-select:none;padding:2px 0}
.read-stat>summary::-webkit-details-marker{display:none}
.read-stat>summary::before{content:'\25B8';font-size:10px;color:#9aa4b2;
  transition:transform .15s}
.read-stat[open]>summary::before{transform:rotate(90deg)}
.read-stat>summary:hover{color:var(--text)}
.rs-label{font-weight:500}
.rs-num{font-variant-numeric:tabular-nums;color:#475569;font-weight:600}
.rs-num.all{color:var(--ok)}
.rs-left{color:var(--warn)}
/* 名单用标签流，不用竖排列表：11 个人竖着排会把整块撑到半屏高，
   而这块本来就只是给管理员扫一眼的参考信息 */
.rs-body{display:flex;flex-direction:column;gap:7px;margin-top:10px;
  padding:10px 12px;border-radius:8px;background:#f8fafc;border:1px solid var(--line)}
.rs-row{display:flex;align-items:flex-start;gap:10px}
.rs-key{flex:0 0 auto;width:26px;padding-top:2px;font-size:11.5px;font-weight:600;color:var(--muted)}
.rs-tags{display:flex;flex-wrap:wrap;gap:6px;min-width:0}
.rs-tag{display:inline-flex;align-items:center;gap:5px;padding:1px 8px;border-radius:999px;
  font-size:12px;color:var(--muted);background:#fff;border:1px solid var(--line);white-space:nowrap}
.rs-tag.on{color:var(--text);border-color:#dbe4ee}
.rs-tag time{font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums}
.rs-tag em{font-style:normal;font-size:10px;color:#94a3b8}
.rs-none{font-size:12px;color:var(--muted);padding-top:1px}

/* ---------- 通知正文排版（富文本） ---------- */
/* 只作用于通知，别写成全局 p/ul 规则，否则会把表格页、打印页全带歪 */
.rt-view{overflow-wrap:anywhere}
.rt-view p{margin:0 0 8px}
.rt-view p:last-child{margin-bottom:0}
.rt-view h3,.rt-view h4{margin:14px 0 8px;font-size:14.5px;font-weight:600;color:var(--text);line-height:1.5}
.rt-view h3:first-child,.rt-view h4:first-child{margin-top:0}
.rt-view ul,.rt-view ol{margin:6px 0 10px;padding-left:22px}
.rt-view li{margin:3px 0}
.rt-view blockquote{margin:8px 0;padding:6px 12px;border-left:3px solid var(--primary-line);
  background:var(--primary-tint);color:#4b5563;border-radius:0 6px 6px 0}
.rt-view a{color:var(--primary);text-decoration:underline;text-underline-offset:2px}
.rt-view a:hover{color:var(--primary-d)}
/* 宽度交给 CSS 统一压，正文里不存 width，粘进来的大图才不会撑破版面；
   高度也封顶，不然一张长截图能把整条通知顶到屏幕外 */
.rt-view img{display:block;max-width:100%;max-height:520px;width:auto;height:auto;
  margin:8px 0;border-radius:8px;border:1px solid var(--line)}
.rt-view code{padding:1px 5px;border-radius:5px;background:#f1f3f7;font-size:12.5px;
  font-family:ui-monospace,Menlo,Consolas,monospace}
.rt-view pre{margin:8px 0;padding:10px 12px;background:#f6f8fb;border:1px solid var(--line);
  border-radius:8px;overflow:auto}
.rt-view pre code{padding:0;background:none}

/* ---------- 富文本编辑区 ---------- */
.field-block{display:flex;flex-direction:column;gap:6px;font-size:13px;color:var(--muted)}
.rt-wrap{border:1px solid var(--line);border-radius:9px;background:#fff;overflow:hidden}
.rt-wrap:focus-within{border-color:var(--primary);box-shadow:0 0 0 3px var(--primary-glow)}
.rt-tool{display:flex;flex-wrap:wrap;align-items:center;gap:2px;padding:6px 8px;
  border-bottom:1px solid var(--line);background:#fafbfd}
.rt-tool button{border:0;background:none;cursor:pointer;padding:4px 8px;border-radius:6px;
  font-size:12.5px;color:#4b5563;line-height:1.4;font-family:inherit}
.rt-tool button:hover{background:var(--primary-soft);color:var(--primary-d)}
.rt-tool button:active{transform:translateY(1px)}
.rt-sep{width:1px;height:16px;background:#d9e0ea;margin:0 5px}
.rt-editor{min-height:170px;max-height:440px;overflow:auto;padding:12px 14px;
  font-size:14px;line-height:1.85;color:var(--text);outline:none}
.rt-editor:empty::before{content:attr(data-ph);color:#9aa5b1;pointer-events:none}
.rt-editor p{margin:0 0 8px}
.rt-editor ul,.rt-editor ol{margin:6px 0 10px;padding-left:22px}
.rt-editor blockquote{margin:8px 0;padding:6px 12px;border-left:3px solid var(--primary-line);
  background:var(--primary-tint);border-radius:0 6px 6px 0}
.rt-editor h3,.rt-editor h4{margin:12px 0 8px;font-size:15px;font-weight:600}
.rt-editor img{max-width:100%;height:auto;border-radius:8px;margin:6px 0;border:1px solid var(--line)}
.rt-editor a{color:var(--primary);text-decoration:underline}

/* ---------- 附件 ---------- */
.attach-edit{border:1px dashed var(--line);border-radius:9px;padding:10px 12px;background:#fbfcfe}
.attach-list{display:flex;flex-direction:column;gap:6px}
.attach-row{display:flex;align-items:center;gap:9px;padding:6px 9px;
  border:1px solid var(--line);border-radius:8px;background:#fff}
.attach-thumb{flex:0 0 auto;width:30px;height:30px;object-fit:cover;
  border-radius:5px;border:1px solid var(--line);background:#fff}
.af-ext{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
  min-width:36px;height:22px;padding:0 5px;border-radius:5px;
  background:var(--primary-soft);color:var(--primary-d);
  font-size:10px;font-weight:700;letter-spacing:.02em}
.af-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:13px;color:var(--text)}
.af-size{flex:0 0 auto;font-size:11.5px;color:var(--muted)}
.attach-row .link{flex:0 0 auto;font-size:12px}
.attach-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:8px}
.attach-actions .btn{padding:6px 12px;font-size:13px}
.attach-empty{margin:2px 0}

.attach-files{display:flex;flex-direction:column;gap:6px;margin-top:12px}
.attach-item{display:flex;align-items:center;gap:9px;max-width:520px;padding:7px 10px;
  border:1px solid var(--line);border-radius:8px;background:#fbfcfe;
  text-decoration:none;color:inherit}
.attach-item:hover{border-color:var(--primary-line);background:var(--primary-tint)}
.attach-item .af-name{font-weight:500}
.attach-imgs{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}
.attach-imgs a{display:block;border:1px solid var(--line);border-radius:8px;overflow:hidden;line-height:0}
.attach-imgs a:hover{border-color:var(--primary)}
.attach-imgs img{display:block;width:96px;height:96px;object-fit:cover}

@media(max-width:640px){
  .rt-tool{gap:0;padding:5px 6px}
  .rt-tool button{padding:4px 6px;font-size:12px}
  .rt-editor{min-height:140px;padding:10px 12px;font-size:13.5px}
  .attach-item{max-width:100%}
  .attach-imgs img{width:76px;height:76px}
  .attach-row .af-size{display:none}
}

/* 概览统计卡里的数字入口：整块不跳，只有数字可点 */
.stat-card .stat-value .stat-link{color:inherit;text-decoration:none;border-bottom:1px dashed transparent}
.stat-card .stat-value .stat-link:hover{color:var(--primary);border-bottom-color:var(--primary)}

/* hidden 属性兜底：作者样式里的 display:grid/flex 会压掉 UA 的 [hidden]{display:none}，
   导致 el.hidden = true 看不见效果。这条放最后，保证任何元素设了 hidden 就真的不显示。 */
[hidden]{display:none!important}

/* ---------- 密集列表页（2026-10-26） ----------
   全站容器已统一 1600（见文件开头的 .wrap），这里不动宽度，只处理"列多放不下"：
   给 <body> 加 page-wide 后，单元格 nowrap、去掉 c-ell 的 230px 省略号，
   内容放不下时由 .table-wrap 横向滚动，而不是把字折成两三行或裁掉。
   目前只给采购申请列表开（12 列）。 */
body.page-wide .card{padding-left:16px;padding-right:16px}

/* ============================================================================
   新版外壳 v2：顶部一级模块 + 左侧二级菜单（2026-10-28）
   只作用于 body.v2-shell-body；旧页面继续用原来的 .topbar / .nav，不受影响。
   ============================================================================ */
:root{
  --v2-bg:#f6f7f9;
  --v2-surface:#ffffff;
  --v2-surface-2:#fcfcfb;
  --v2-text:#0b0b0b;
  --v2-muted:#52514e;
  --v2-faint:#6f6d66;
  --v2-line:#d2dae5;
  --v2-line-strong:#aebccd;
  --v2-brand:#2a78d6;
  --v2-brand-d:#1c5cab;
  --v2-radius:12px;
  --v2-shadow:0 1px 2px rgba(11,11,11,.04), 0 8px 24px rgba(11,11,11,.035);
}
body.v2-shell-body{
  background:var(--v2-bg);
  color:var(--v2-text);
  --primary:var(--v2-brand);
  --primary-d:var(--v2-brand-d);
  --primary-soft:#eaf2fd;
  --primary-line:#bcd8f2;
  --primary-glow:#bcd8f2;
  --primary-tint:#f7fbff;
}
body.app-purchase.v2-shell-body{--v2-accent:#eb6834;--v2-accent-soft:#fdf0ea;--v2-accent-strong:#c24a1a;--v2-accent-on:#fff}
body.app-dispatch.v2-shell-body{--v2-accent:#2a78d6;--v2-accent-soft:#eaf2fd;--v2-accent-strong:#1c5cab;--v2-accent-on:#fff}
body.app-quote.v2-shell-body{--v2-accent:#eda100;--v2-accent-soft:#fff6dd;--v2-accent-strong:#8a5a00;--v2-accent-on:#fff}
body.app-core.v2-shell-body{--v2-accent:#1baf7a;--v2-accent-soft:#e6f7f1;--v2-accent-strong:#0f7a55;--v2-accent-on:#fff}
body.app-home.v2-shell-body{--v2-accent:#2a78d6;--v2-accent-soft:#eaf2fd;--v2-accent-strong:#1c5cab;--v2-accent-on:#fff}
body.app-settings.v2-shell-body{--v2-accent:#64748b;--v2-accent-soft:#eef2f6;--v2-accent-strong:#475569;--v2-accent-on:#fff}

.v2-icon{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;flex:none}

/* 顶栏 */
.v2-topbar{
  position:sticky;top:0;z-index:60;
  background:rgba(255,255,255,.94);
  -webkit-backdrop-filter:blur(10px);
  backdrop-filter:blur(10px);
  border-bottom:1px solid var(--v2-line);
}
.v2-topbar-inner{
  height:60px;display:flex;align-items:center;gap:16px;
  padding:0 20px;max-width:1600px;margin:0 auto;
}
.v2-menu-btn{
  display:none;width:34px;height:34px;align-items:center;justify-content:center;
  border:1px solid var(--v2-line-strong);border-radius:9px;background:var(--v2-surface);color:var(--v2-muted);
}
.v2-menu-btn:hover{background:var(--v2-surface-2);color:var(--v2-text)}
.v2-brand{display:flex;align-items:center;gap:10px;color:var(--v2-text);text-decoration:none;white-space:nowrap;flex:none}
.v2-brand:hover{text-decoration:none}
.v2-brand-mark{
  width:32px;height:32px;border-radius:9px;display:inline-flex;align-items:center;justify-content:center;
  background:linear-gradient(145deg,var(--v2-brand),var(--v2-brand-d));
  color:#fff;font-weight:700;font-size:15px;
  box-shadow:0 2px 8px rgba(42,120,214,.28);
}
.v2-brand-text{font-weight:700;font-size:15px}
.v2-brand-text em{font-style:normal;font-weight:500;color:var(--v2-faint);font-size:12px;margin-left:6px}
.v2-modules{display:flex;align-items:center;gap:2px;min-width:0;overflow-x:auto;scrollbar-width:none}
.v2-modules::-webkit-scrollbar{display:none}
.v2-module{
  display:inline-flex;align-items:center;gap:7px;
  padding:7px 11px;border-radius:9px;color:var(--v2-muted);
  font-size:13px;font-weight:500;text-decoration:none;white-space:nowrap;
  transition:background .15s,color .15s,box-shadow .15s;
}
.v2-module .v2-icon{width:16px;height:16px;color:var(--v2-faint)}
.v2-module:hover{
  background:var(--v2-accent-soft);color:var(--v2-text);text-decoration:none;
  box-shadow:inset 0 0 0 1px var(--v2-accent);
}
.v2-module.active{background:var(--v2-accent-soft);color:var(--v2-text);font-weight:600}
.v2-module.active .v2-icon{color:var(--v2-accent)}
.v2-top-right{margin-left:auto;display:flex;align-items:center;gap:10px;flex:none}
.v2-scope{display:flex;align-items:center;gap:6px}
.v2-scope select{
  height:34px;max-width:170px;padding:0 10px;border:1px solid var(--v2-line-strong);border-radius:9px;
  background:var(--v2-surface);color:var(--v2-text);font-size:12.5px;font-family:inherit;
}
.v2-scope-tag{
  display:inline-flex;align-items:center;gap:7px;height:34px;padding:0 10px;
  border:1px solid var(--v2-line);border-radius:999px;background:var(--v2-surface-2);
  color:var(--v2-muted);font-size:12.5px;white-space:nowrap;
}
.v2-scope-dot{width:7px;height:7px;border-radius:50%;background:var(--ok);box-shadow:0 0 0 3px var(--ok-soft)}
.v2-user-menu{position:relative}
.v2-user-menu summary{
  list-style:none;display:flex;align-items:center;gap:8px;cursor:pointer;
  padding:3px 6px;border-radius:9px;
}
.v2-user-menu summary::-webkit-details-marker{display:none}
.v2-user-menu summary:hover{background:var(--v2-surface-2)}
.v2-avatar{
  width:32px;height:32px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;
  background:var(--primary-soft);color:var(--primary-d);font-weight:700;font-size:13px;
  border:1px solid var(--primary-line);flex:none;
}
.v2-user-name{font-size:13px;font-weight:600;color:var(--v2-text);white-space:nowrap}
.v2-user-pop{
  display:none;position:absolute;right:0;top:calc(100% + 8px);min-width:190px;z-index:90;
  padding:8px;background:var(--v2-surface);border:1px solid var(--v2-line);border-radius:12px;
  box-shadow:0 12px 32px rgba(11,11,11,.14);
}
.v2-user-menu[open] .v2-user-pop{display:block}
.v2-user-role{padding:6px 10px 8px;font-size:11.5px;color:var(--v2-faint);border-bottom:1px solid var(--v2-line);margin-bottom:4px}
.v2-user-pop a{display:block;padding:8px 10px;border-radius:7px;color:var(--v2-text);font-size:13px;text-decoration:none}
.v2-user-pop a:hover{background:var(--primary-soft);text-decoration:none}

/* 通知公告铃铛：项目选择与用户名之间，任意页面都在 */
.v2-bell{position:relative}
.v2-bell summary{
  list-style:none;position:relative;display:flex;align-items:center;justify-content:center;
  width:34px;height:34px;border-radius:9px;cursor:pointer;color:var(--v2-muted);
}
.v2-bell summary::-webkit-details-marker{display:none}
.v2-bell summary:hover{background:var(--v2-surface-2);color:var(--v2-text)}
.v2-bell-icon{width:19px;height:19px}
.v2-bell-badge{
  position:absolute;top:1px;right:1px;min-width:16px;height:16px;padding:0 4px;
  display:inline-flex;align-items:center;justify-content:center;
  border-radius:999px;background:var(--danger);color:#fff;font-size:10.5px;font-weight:700;
  line-height:1;box-shadow:0 0 0 2px var(--v2-surface);
}
.v2-bell-pop{
  display:none;position:absolute;right:0;top:calc(100% + 8px);width:320px;max-width:86vw;z-index:95;
  padding:8px;background:var(--v2-surface);border:1px solid var(--v2-line);border-radius:12px;
  box-shadow:0 12px 32px rgba(11,11,11,.14);
}
.v2-bell[open] .v2-bell-pop{display:block}
.v2-bell-head{
  display:flex;align-items:baseline;gap:8px;padding:4px 8px 8px;
  border-bottom:1px solid var(--v2-line);margin-bottom:6px;
}
.v2-bell-head strong{font-size:13px;color:var(--v2-text)}
.v2-bell-count{margin-left:auto;font-size:11.5px;color:var(--danger)}
.v2-bell-list{list-style:none;margin:0;padding:0;max-height:320px;overflow:auto}
.v2-bell-list li a{
  display:block;padding:7px 8px;border-radius:8px;text-decoration:none;color:var(--v2-text);
}
.v2-bell-list li a:hover{background:var(--primary-soft);text-decoration:none}
.v2-bell-title{
  display:block;font-size:13px;line-height:1.45;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.v2-bell-list li.unread .v2-bell-title{font-weight:700}
.v2-bell-list li.unread .v2-bell-title::before{
  content:"";display:inline-block;width:6px;height:6px;border-radius:50%;
  background:var(--danger);margin-right:6px;vertical-align:middle;
}
.v2-bell-meta{display:flex;align-items:center;gap:8px;margin-top:2px;font-size:11.5px;color:var(--v2-faint)}
.v2-bell-imp{color:var(--danger)}
.v2-bell-empty{margin:6px 8px;font-size:12.5px;color:var(--v2-faint)}
.v2-bell-all{
  display:block;margin-top:6px;padding:7px 8px;border-top:1px solid var(--v2-line);
  font-size:12.5px;color:var(--v2-accent);text-decoration:none;text-align:center;
}
.v2-bell-all:hover{text-decoration:underline}

/* 左侧 + 主区 */
.v2-shell{display:flex;min-height:calc(100vh - 60px)}
.v2-sidebar{
  width:224px;flex:none;z-index:40;
  position:sticky;top:60px;height:calc(100vh - 60px);
  display:flex;flex-direction:column;
  background:var(--v2-surface);border-right:1px solid var(--v2-line-strong);
}
.v2-side-head{display:flex;flex-direction:column;gap:2px;padding:18px 16px 10px}
.v2-side-kicker{font-size:10.5px;font-weight:600;color:var(--v2-faint);letter-spacing:.08em}
.v2-side-head strong{font-size:16px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.v2-side-nav{flex:1;overflow:auto;padding:4px 10px 12px}
.v2-side-item{
  position:relative;display:flex;align-items:center;gap:10px;
  min-height:37px;padding:7px 10px;margin:1px 0;border-radius:8px;
  color:var(--v2-muted);font-size:13px;white-space:nowrap;text-decoration:none;overflow:hidden;
  transition:background .12s,color .12s,box-shadow .12s;
}
.v2-side-item .v2-side-icon{width:17px;height:17px;color:var(--v2-faint)}
.v2-side-item:hover{
  background:var(--v2-accent-strong);color:var(--v2-accent-on);text-decoration:none;
  box-shadow:inset 0 0 0 1px var(--v2-accent-strong);
}
.v2-side-item:hover .v2-icon{color:var(--v2-accent-on)}
.v2-side-item.active{background:var(--v2-accent-soft);color:var(--v2-text);font-weight:600}
.v2-side-item.active::before{
  content:"";position:absolute;left:0;top:8px;bottom:8px;width:3px;border-radius:0 3px 3px 0;
  background:var(--v2-accent);
}
.v2-side-item.active .v2-icon{color:var(--v2-accent)}
.v2-side-item.active:hover::before{background:var(--v2-accent-on)}
.v2-side-foot{padding:12px 14px 16px;border-top:1px solid var(--v2-line)}
.v2-side-tip{
  display:flex;align-items:flex-start;gap:9px;padding:10px;border-radius:9px;
  background:var(--v2-accent-soft);
}
.v2-side-tip .v2-icon{width:16px;height:16px;color:var(--v2-accent-strong);margin-top:1px}
.v2-side-tip strong{display:block;font-size:12px;color:var(--v2-accent-strong);font-weight:600}
.v2-side-tip span{display:block;font-size:11px;color:var(--v2-muted);margin-top:1px}
.v2-side-version{margin-top:10px;font-size:11px;color:var(--v2-faint);text-align:center}
/* 抽屉里的一级模块（只在 ≤760px 显示，见下面媒体查询）。
   桌面端侧栏保持「当前模块 + 二级菜单」两段，不重复出现一级模块。 */
.v2-side-mods{
  display:none;flex:none;max-height:46vh;overflow:auto;
  padding:4px 10px 10px;border-bottom:1px solid var(--v2-line);
}
.v2-side-mods .v2-side-kicker{display:block;padding:8px 8px 4px}
.v2-side-mods-nav{display:flex;flex-direction:column;gap:1px}
.v2-side-mods .v2-side-item{min-height:34px;padding:5px 9px}
.v2-scrim{display:none}
.v2-main{flex:1;min-width:0;padding:24px 28px 48px}
.v2-main-inner{max-width:1500px;margin:0 auto}
.v2-page-wide .v2-main-inner{max-width:none}
.v2-footer{margin-top:32px;padding-top:14px;border-top:1px solid var(--v2-line);font-size:11.5px;color:var(--v2-faint)}
.v2-main .card{border-color:var(--v2-line);box-shadow:var(--v2-shadow)}
.v2-main .stat-grid{grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
.v2-main .table th{border-bottom-color:var(--v2-line-strong)}
.v2-main .table th,.v2-main .table td{border-bottom-color:var(--v2-line)}
.v2-main .btn.primary{background:var(--v2-brand);border-color:var(--v2-brand);color:#fff}
.v2-main .btn.primary:hover{background:var(--v2-brand-d);border-color:var(--v2-brand-d)}

@media(max-width:1500px){
  .v2-user-name{display:none}
}
@media(max-width:900px){
  .v2-main .stat-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media(max-width:1080px){
  .v2-menu-btn{display:inline-flex}
  .v2-topbar-inner{gap:10px;padding:0 12px}
  .v2-sidebar{
    position:fixed;left:0;top:60px;bottom:0;height:auto;
    transform:translateX(-100%);transition:transform .2s ease;
    box-shadow:0 12px 32px rgba(11,11,11,.18);
  }
  body.v2-side-open .v2-sidebar{transform:none}
  body.v2-side-open .v2-scrim{
    display:block;position:fixed;inset:60px 0 0;background:rgba(11,11,11,.32);z-index:35;
  }
  .v2-main{padding:20px 18px 40px}
}
@media(max-width:760px){
  .v2-brand-text{display:none}
  /* 一级模块从顶栏挪进左侧抽屉：顶栏这一行留给三横线、标记、项目选择、铃铛、头像。
     改之前这里只隐藏模块文字，图标条还是被挤成几十像素宽，等于看不见（2026-10-29）。 */
  .v2-topbar .v2-modules{display:none}
  .v2-side-mods{display:block}
  /* 上面已经有了高亮的一级模块，抽屉里再写一遍「当前模块 工作台」就重复了，省下这段高度 */
  .v2-side-head{display:none}
  .v2-scope select{max-width:130px}
  .v2-main .stat-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
}
@media(max-width:480px){
  .v2-main .stat-grid{grid-template-columns:1fr}
  .v2-main{padding:16px 12px 32px}
}
@media(prefers-reduced-motion:reduce){
  .v2-sidebar,.v2-side-item,.v2-module{transition:none!important}
}

/* ============================================================================
   v2 工作台仪表盘：KPI / 图表 / 最近单据 / 待办
   ============================================================================ */
.v2-kpi-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;margin-bottom:18px}
.v2-kpi{position:relative;padding:16px 17px 14px;border:1px solid var(--v2-line);border-radius:var(--v2-radius);background:var(--v2-surface);box-shadow:var(--v2-shadow);overflow:hidden}
.v2-kpi::after{content:"";position:absolute;left:0;right:0;top:0;height:2px;background:var(--kpi-accent,var(--v2-brand))}
.v2-kpi-info,.v2-kpi-brand{--kpi-accent:var(--v2-brand);--kpi-soft:#eaf2fd}
.v2-kpi-warn{--kpi-accent:#eda100;--kpi-soft:#fff6dd}
.v2-kpi-good{--kpi-accent:var(--ok);--kpi-soft:#e6f7f0}
.v2-kpi-top{display:flex;align-items:center;justify-content:space-between;gap:8px}
.v2-kpi-label{font-size:12px;font-weight:600;color:var(--v2-muted)}
.v2-kpi-icon{width:30px;height:30px;border-radius:9px;display:inline-flex;align-items:center;justify-content:center;background:var(--kpi-soft,var(--primary-soft));color:var(--kpi-accent,var(--v2-brand))}
.v2-kpi-icon .v2-icon{width:16px;height:16px}
.v2-kpi-value{font-size:30px;font-weight:700;line-height:1.15;margin:6px 0 4px;letter-spacing:-.02em}
.v2-kpi-foot{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:11.5px;color:var(--v2-faint)}
.v2-kpi-foot b{color:var(--v2-text);font-weight:600}
.v2-home-grid{display:grid;grid-template-columns:minmax(0,1.75fr) minmax(300px,.9fr);gap:16px;align-items:start}
.v2-home-grid > *{min-width:0}
.v2-home-stack{display:grid;gap:16px;min-width:0}
.v2-main .v2-home-grid .card{margin-bottom:0}
.v2-home-table td{padding:11px 10px}
.v2-home-table .cell-main{display:flex;flex-direction:column;gap:2px;white-space:normal;min-width:120px}
.v2-home-table .cell-main strong{font-weight:600}
.v2-home-table .cell-main span{font-size:11px;color:var(--v2-faint)}
.v2-pill{display:inline-flex;align-items:center;gap:6px;padding:3px 9px;border-radius:999px;font-size:11.5px;font-weight:600;white-space:nowrap;background:#f0f1f4;color:var(--v2-muted);box-shadow:inset 0 0 0 1px color-mix(in srgb,currentColor 18%,transparent)}
.v2-pill::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
.v2-pill-ok{background:#e6f7f0;color:#0a6b4f}
.v2-pill-warn{background:#fff6dd;color:#8a5a00}
.v2-pill-bad{background:#fdecea;color:#a32d2d}
.v2-pill-info{background:#eaf2fd;color:#1c5cab}
.v2-pill-muted{background:#f0f1f4;color:#52514e}
.v2-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:8px;padding:42px 20px;color:var(--v2-faint)}
.v2-empty-sm{padding:22px 14px}
.v2-empty-icon{width:46px;height:46px;border-radius:13px;display:flex;align-items:center;justify-content:center;background:var(--primary-soft);color:var(--primary-d);margin-bottom:2px}
.v2-empty-icon .v2-icon{width:22px;height:22px}
.v2-empty h3{margin:0;font-size:15px;color:var(--v2-text)}
.v2-empty p{margin:0;font-size:12px;max-width:360px;line-height:1.7}
.v2-chip{display:inline-flex;align-items:center;height:24px;padding:0 9px;border-radius:999px;background:var(--v2-surface-2);border:1px solid var(--v2-line);font-size:11px;color:var(--v2-muted)}
.v2-count-pill{display:inline-flex;min-width:24px;height:22px;padding:0 8px;align-items:center;justify-content:center;border-radius:999px;background:#fff6dd;color:#8a5a00;font-size:11.5px;font-weight:700}
.v2-chart{display:grid;grid-template-columns:28px 1fr;gap:8px;padding-top:6px}
.v2-chart-axis{display:flex;flex-direction:column;justify-content:space-between;height:164px;padding-bottom:22px;font-size:10px;color:var(--v2-faint);text-align:right}
.v2-chart-plot{position:relative;height:164px;margin-bottom:22px;background-image:linear-gradient(to top, var(--v2-line) 1px, transparent 1px);background-size:100% 25%;border-bottom:1px solid var(--v2-line-strong)}
.v2-chart-bars{position:absolute;inset:0;display:flex;align-items:flex-end;gap:10px;padding:0 4px}
.v2-chart-col{position:relative;flex:1;height:100%;display:flex;align-items:flex-end;justify-content:center}
.v2-chart-bar{width:100%;max-width:34px;height:var(--h);background:var(--v2-brand);border-radius:4px 4px 0 0;transition:filter .15s,transform .15s;position:relative}
.v2-chart-bar:hover{filter:brightness(1.1);transform:translateY(-1px)}
.v2-chart-bar::after{content:attr(data-tip);position:absolute;left:50%;bottom:calc(100% + 8px);transform:translateX(-50%);padding:5px 8px;border-radius:7px;background:var(--v2-text);color:var(--v2-surface);font-size:11px;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .12s;z-index:3}
.v2-chart-bar:hover::after{opacity:1}
.v2-chart-value{position:absolute;top:-19px;left:50%;transform:translateX(-50%);font-size:11px;font-weight:700;color:var(--v2-text);white-space:nowrap}
.v2-chart-x{position:absolute;bottom:-21px;left:50%;transform:translateX(-50%);font-size:10.5px;color:var(--v2-faint);white-space:nowrap}
.v2-chart-data{margin-top:10px;font-size:11.5px;color:var(--v2-muted)}
.v2-chart-data summary{cursor:pointer;color:var(--primary-d);font-weight:600}
.v2-chart-data table{width:100%;border-collapse:collapse;margin-top:8px;font-size:11.5px}
.v2-chart-data th,.v2-chart-data td{padding:6px 8px;border-bottom:1px solid var(--v2-line);text-align:left}
.v2-chart-data td:last-child{text-align:right;font-variant-numeric:tabular-nums}
.v2-todo-list{padding:4px 0}
.v2-todo-item{display:flex;align-items:flex-start;gap:10px;padding:10px 18px;color:var(--v2-text);text-decoration:none;transition:background .12s;border-bottom:1px solid var(--v2-line)}
.v2-todo-item:last-child{border-bottom:0}
.v2-todo-item:hover{background:var(--primary-soft);text-decoration:none}
.v2-todo-item:hover .v2-icon{color:var(--primary-d)}
.v2-todo-dot{width:7px;height:7px;border-radius:50%;margin-top:6px;flex:none;background:var(--v2-brand)}
.v2-todo-dot.warn{background:#eda100}
.v2-todo-dot.critical{background:var(--danger)}
.v2-todo-dot.info{background:var(--v2-brand)}
.v2-todo-main{flex:1;min-width:0}
.v2-todo-main strong{display:block;font-size:12.5px;font-weight:600;line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.v2-todo-main small{display:block;font-size:11px;color:var(--v2-faint);margin-top:2px}
.v2-todo-item>.v2-icon{width:14px;height:14px;color:var(--v2-faint);margin-top:4px;flex:none}
.v2-card-foot{display:flex;justify-content:center;padding:10px 18px 14px;border-top:1px solid var(--v2-line)}
@media(max-width:1200px){.v2-kpi-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:1100px){.v2-home-grid{grid-template-columns:1fr}}
@media(max-width:480px){.v2-kpi-grid{grid-template-columns:1fr}}

/* ============================================================================
   v2 工作台：三个业务模块各占一大行
   ============================================================================ */
.v2-mod-list{display:grid;gap:16px}
.v2-mod-row{
  position:relative;background:var(--v2-surface);border:1px solid var(--v2-line);
  border-radius:var(--v2-radius);box-shadow:var(--v2-shadow);overflow:hidden;
}
.v2-mod-row::before{content:"";position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--mod-accent)}
.v2-mod-purchase{--mod-accent:#eb6834;--mod-soft:#fdf0ea;--mod-strong:#c24a1a}
.v2-mod-dispatch{--mod-accent:#2a78d6;--mod-soft:#eaf2fd;--mod-strong:#1c5cab}
.v2-mod-quote{--mod-accent:#eda100;--mod-soft:#fff6dd;--mod-strong:#8a5a00}
.v2-mod-head{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;flex-wrap:wrap;padding:16px 18px 13px;border-bottom:1px solid var(--v2-line)}
.v2-mod-title{display:flex;align-items:flex-start;gap:12px;min-width:0}
.v2-mod-icon{width:38px;height:38px;border-radius:11px;display:inline-flex;align-items:center;justify-content:center;background:var(--mod-soft);color:var(--mod-strong);flex:none}
.v2-mod-icon .v2-icon{width:20px;height:20px}
.v2-mod-title h2{font-size:16px;line-height:1.3;margin:0}
.v2-mod-title p{margin:3px 0 0;font-size:11.5px;color:var(--v2-faint)}
.v2-mod-actions{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.v2-mod-action{color:var(--mod-strong)!important;font-weight:600;font-size:12.5px}
.v2-mod-body{padding:16px 18px}
.v2-mod-kpis{display:grid;gap:10px;align-content:start}
.v2-mod-kpis.v2-kpis-4{grid-template-columns:repeat(4,minmax(0,1fr))}
.v2-mod-kpis.v2-kpis-6{grid-template-columns:repeat(6,minmax(0,1fr))}
.v2-mod-row .v2-kpi{--kpi-accent:var(--mod-accent);--kpi-soft:var(--mod-soft)}
.v2-mod-kpis .v2-kpi{padding:12px 13px 11px}
.v2-mod-kpis .v2-kpi-value{font-size:24px;margin:4px 0 2px}
.v2-mod-kpis .v2-kpi-icon{width:26px;height:26px}
.v2-mod-kpis .v2-kpi-icon .v2-icon{width:14px;height:14px}
.v2-mod-kpis .v2-kpi-label{font-size:11.5px}
.v2-mod-kpis .v2-kpi-foot{font-size:11px}
@media(max-width:1200px){
  .v2-mod-kpis.v2-kpis-4{grid-template-columns:repeat(2,minmax(0,1fr))}
  .v2-mod-kpis.v2-kpis-6{grid-template-columns:repeat(3,minmax(0,1fr))}
}
@media(max-width:820px){
  .v2-mod-kpis.v2-kpis-4,.v2-mod-kpis.v2-kpis-6{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media(max-width:560px){
  .v2-mod-kpis.v2-kpis-4,.v2-mod-kpis.v2-kpis-6{grid-template-columns:1fr}
}
@media(max-width:760px){
  .v2-mod-head,.v2-mod-body{padding-left:14px;padding-right:14px}
  .v2-mod-title h2{font-size:15px}
  .v2-mod-actions{gap:8px}
}

/* ---------- 设备分类树（基础资料 / categories.php） ----------
   用原生 <details> 做展开折叠，不引 JS。summary 里放操作按钮时，
   按钮容器加了 onclick=stopPropagation，否则点「编辑」会把分类一起折起来。 */
.cat-tree{display:flex;flex-direction:column}
.cat-l1{border-bottom:1px solid var(--line)}
.cat-l1:last-child{border-bottom:0}
.cat-l1>summary{display:flex;align-items:center;gap:9px;padding:11px 6px;cursor:pointer;font-size:13.5px;list-style:none}
.cat-l1>summary::-webkit-details-marker{display:none}
.cat-caret{flex:0 0 auto;width:0;height:0;border-left:5px solid var(--muted);border-top:4px solid transparent;border-bottom:4px solid transparent;transition:transform .15s}
.cat-l1[open]>summary .cat-caret{transform:rotate(90deg)}
.cat-code{flex:0 0 auto;min-width:66px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:var(--muted)}
.cat-name{flex:1 1 auto;min-width:0;font-weight:600;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cat-ops{flex:0 0 auto;display:flex;align-items:center;gap:10px;font-size:12px}
.cat-children{border-left:2px solid var(--line);margin:0 0 10px 13px}
.cat-l2row{display:flex;align-items:center;gap:9px;padding:7px 6px 7px 15px;font-size:13px;border-radius:6px}
.cat-l2row:hover{background:#fafbfd}
.cat-l2row.hl{background:#fff8e1;box-shadow:inset 3px 0 0 var(--warn)}
@media(max-width:760px){
  .cat-l1>summary,.cat-l2row{flex-wrap:wrap}
  .cat-code{min-width:0}
  .cat-name{flex-basis:60%}
}

/* ---------- 资产表单的三级分类选择器（基础资料 / asset_form.php） ---------- */
.cat-picker{display:flex;gap:6px;flex-wrap:wrap}
.cat-picker select{flex:1 1 150px;min-width:0}
.cat-picker select:disabled{opacity:.55;cursor:not-allowed}
@media(max-width:760px){
  .cat-picker select{flex-basis:100%}
}

/* ---------- 资产清单：整行可点，点开弹详情（core/assets.php） ----------
   行底色用 is-active，和保存后定位用的 .hl（黄色）区分开：一个是"刚保存的就是这条"，
   一个是"我刚点了这条"。
   底色故意压深：用户色弱，浅到 #f7f9fc 那种程度的分辨不出来，
   所以三个状态的亮度要拉开，同时左侧竖条也跟着变色，不单靠色相分辨。 */
.asset-row{cursor:pointer;transition:background-color .12s}
.asset-row:hover td{background:#dde5ef}
.asset-row:hover td:first-child{box-shadow:inset 3px 0 0 #9aadc4}
.asset-row.is-active td{background:#c2d5ee}
.asset-row.is-active td:first-child{box-shadow:inset 4px 0 0 var(--primary)}
.asset-row.is-active:hover td{background:#b7cdea}
.peek-grid{display:grid;gap:10px}
.peek-row{display:grid;grid-template-columns:92px 1fr;gap:12px;font-size:13px;padding-bottom:9px;border-bottom:1px dashed var(--line)}
.peek-row:last-child{border-bottom:0;padding-bottom:0}
.peek-k{color:var(--muted)}
.peek-v{color:var(--text);word-break:break-word}

/* 资产清单的筛选条比别的页多两个下拉，三个分类框收窄一点，
   查询/重置绑成一组，换行时不会拆散。 */
.filter-bar select.cat-filter{max-width:206px}
.filter-actions{display:flex;gap:8px;flex:0 0 auto}
