:root{
  --blue:#1a50be; --blue-d:#12398a; --bg:#f4f6fb; --line:#e3e8f0;
  --text:#1f2733; --muted:#8a94a6; --ok:#00a05a; --warn:#e08a00; --err:#d93636;
}
*{box-sizing:border-box}
body{margin:0;font-family:"Microsoft YaHei","PingFang SC",system-ui,sans-serif;
  background:var(--bg);color:var(--text);font-size:14px;line-height:1.6}
code{font-family:Consolas,Monaco,monospace;background:#eef2f9;padding:1px 6px;border-radius:4px;font-size:12px}

/* ---------- 登录页 ---------- */
.login-page{display:flex;align-items:center;justify-content:center;min-height:100vh;
  background:linear-gradient(135deg,#1a50be,#12398a)}
.login-card{background:#fff;border-radius:14px;padding:38px 40px;width:380px;
  box-shadow:0 18px 50px rgba(0,0,0,.25)}
.brand{text-align:center;margin-bottom:26px}
.logo{width:62px;height:62px;line-height:62px;margin:0 auto 12px;border-radius:14px;
  background:var(--blue);color:#fff;font-weight:700;font-size:19px;letter-spacing:1px}
.brand h1{font-size:19px;margin:0 0 4px}
.brand .sub{color:var(--muted);font-size:12.5px;margin:0}
.login-card label{display:block;margin:14px 0 6px;font-size:13px;color:#48536a}
.login-card input{width:100%;padding:11px 13px;border:1px solid #ccd6e4;border-radius:8px;
  font-size:14px;outline:none;transition:.15s}
.login-card input:focus{border-color:var(--blue);box-shadow:0 0 0 3px rgba(26,80,190,.12)}
/* v2.0.40：密码框容器 + 显示/隐藏眼睛按钮（登录页 & 改密弹窗通用） */
.pwd-wrap{position:relative;display:block}
.pwd-wrap input{padding-right:42px}          /* 右侧留出按钮位置，避免文字压到图标 */
.pwd-eye{position:absolute;right:6px;top:50%;transform:translateY(-50%);
  display:flex;align-items:center;justify-content:center;
  width:30px;height:30px;padding:0;border:0;border-radius:7px;
  background:transparent;color:#8a94a6;cursor:pointer;line-height:0;
  transition:color .15s, background .15s}
.pwd-eye:hover{color:#1c7ed6;background:#eef4fd}
.pwd-eye:active{transform:translateY(-50%) scale(.94)}
.pwd-eye.on{color:#1c7ed6}                   /* 明文状态：图标高亮，提醒密码可见 */
.pwd-eye svg{display:block}

/* 改密弹窗里的密码框同样适配（.modal-field 下的 input 宽度 100%） */
.modal-field .pwd-wrap input{width:100%}
.tip{color:var(--muted);font-size:12px;text-align:center;margin-top:20px;line-height:1.7}

/* ---------- 按钮 ---------- */
.btn{display:inline-block;border:none;border-radius:8px;padding:10px 18px;font-size:14px;
  cursor:pointer;background:#e8eefb;color:var(--blue-d);text-decoration:none;transition:.15s}
.btn:hover{filter:brightness(.96)}
.btn.primary{background:var(--blue);color:#fff}
.btn.block{width:100%;margin-top:22px;padding:12px}
.btn.tiny{padding:4px 10px;font-size:12px;border-radius:6px}
.btn.ok{background:#d9f5e6;color:#0a7a45}
.btn.danger{background:#fde3e3;color:#b32020}
.btn:disabled{opacity:.6;cursor:not-allowed}

/* ---------- 顶栏 ---------- */
.topbar{background:#fff;border-bottom:1px solid var(--line);padding:0 22px;height:56px;
  display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:10}
.topbar-left,.topbar-right{display:flex;align-items:center;gap:12px}
.logo-sm{background:var(--blue);color:#fff;width:34px;height:34px;line-height:34px;
  text-align:center;border-radius:8px;font-size:12px;font-weight:700}
.title{font-weight:600;font-size:15px}
.ver{color:var(--muted);font-size:12px}
.user{color:#48536a;font-size:13px}
.link{color:var(--blue);text-decoration:none;font-size:13px}
.link:hover{text-decoration:underline}
/* v2.1.15：单证追溯 —— 「曾被引擎改写」文件警示标签 */
.tag-warn{display:inline-block;margin-left:6px;padding:1px 6px;border-radius:3px;
  background:#fdecea;color:#c00000;border:1px solid #f5c6c0;
  font-size:11px;font-weight:700;vertical-align:middle;white-space:nowrap;cursor:help}

/* ---------- 容器 / 卡片 ---------- */
.container{max-width:1180px;margin:22px auto;padding:0 18px}
.card{background:#fff;border:1px solid var(--line);border-radius:12px;padding:20px 22px;
  margin-bottom:18px;box-shadow:0 1px 3px rgba(20,40,90,.04)}
.card h2{font-size:15.5px;margin:0 0 16px;padding-left:10px;border-left:4px solid var(--blue)}
.card h3{font-size:14px;margin:16px 0 8px}

/* ---------- 表单 ---------- */
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:18px}
.field label{display:block;margin-bottom:7px;font-size:13px;color:#48536a;font-weight:600}
.field input[type=file]{width:100%;padding:10px;border:1px dashed #bfcde0;border-radius:8px;background:#fafcff}
.actions{margin-top:16px;display:flex;align-items:center;gap:14px}
.hint{color:var(--muted);font-size:12.5px}
.inline-form{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.inline-form input{padding:9px 12px;border:1px solid #ccd6e4;border-radius:8px;font-size:13.5px}
.inline-form input[name=username],.inline-form input[name=org_name]{width:170px}
.inline-form input[name=password],.inline-form input[name=remark]{width:180px}
.inline-form input[name=valid_days]{width:90px}

/* ---------- 表格 ---------- */
.table{width:100%;border-collapse:collapse;font-size:13.5px}
.table th{background:#f2f6fd;color:#3d4a61;text-align:left;padding:10px 12px;
  font-weight:600;border-bottom:1px solid var(--line);white-space:nowrap}
.table td{padding:10px 12px;border-bottom:1px solid #f0f3f8;vertical-align:middle}
/* v1.8.57：任务「状态」列——列头与内容一律水平+垂直居中，徽标与文字居中 */
.table th.c-center,.table td.c-center{text-align:center}
.table td.c-center .pill{display:inline-block;vertical-align:middle;line-height:1.5;
  padding:2px 10px;text-align:center;margin:0 auto}
/* v1.8.58：任务表所有列头与内容一律水平+垂直居中 */
.table.center-all th,.table.center-all td{text-align:center;vertical-align:middle}
.table.center-all td .pill{margin:0 auto}
.table.center-all code{display:inline-block}
/* v2.0.96：指定列「强制单行、不换行」——
   问题：全平台任务总览第 1 页/第 2 页的技能（及结果文件、操作）文字换行不一致。
   原因：表格为 auto 布局，列宽由【本页最长内容】决定；不同页最长内容不同 → 同一技能名
         在一页放得下（单行）、另一页放不下（折两行），视觉不统一。
   处理：对技能 / 结果文件 / 操作 三列内容强制 white-space:nowrap，宽度由内容撑开；
         若整表超宽，由外层 .table-wrap(overflow-x:auto) 横向滚动，不再挤压文字换行。 */
.table td.c-nowrap,.table th.c-nowrap{white-space:nowrap}
/* v2.0.97：提交时间列【日期 / 时间 分两行】显示（br 换行），两行紧贴不额外撑高行 */
.table td .dt-d{display:inline-block;line-height:1.35}
.table td .dt-t{display:inline-block;line-height:1.35;color:var(--muted);font-size:12.5px}
/* v2.1.01：下载确认弹窗里的文件名（长文件名自动折行，不撑破弹窗） */
.modal-box .dl-file{background:#f6f8fb;border:1px solid #e2eaf4;border-radius:8px;
  padding:10px 12px;font-size:13.5px;color:#22384f;word-break:break-all;line-height:1.5}
.table tr:hover td{background:#fafcff}
.table.small{font-size:13px}
.table.small td,.table.small th{padding:7px 10px}
.row-off td{background:#fbfbfc;color:#9aa4b4}
.center{text-align:center}
.muted{color:var(--muted)}
.ops{display:flex;gap:6px;flex-wrap:wrap}
.ops form{display:inline}
/* v2.0.76：任务表操作列纵向排列（校验状态 / 打包下载 / 查看日志 / 前往技能，一行一个、垂直居中） */
.ops-v{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px}
.ops-v .pill{margin:0}
/* v2.0.89：操作列按钮【文字绝不换行】—— 原因：技能为「9610商品合规校验（product）」时，
   操作列的「打包下载 / 单证追溯 / 查看日志」被 104px 限宽 + 表格挤压，出现「打包下\n载」之类的断行。
   处理：按钮改按内容自适应（去 max-width），文字 white-space:nowrap，宽度由内容撑开；
   列本身靠表格布局吸收，不再硬挤按钮。 */
.ops-v .btn{width:auto;max-width:none;white-space:nowrap;text-align:center;box-sizing:border-box}
/* v2.0.91：技能页「本技能历史任务」操作列【2 行 2 列】网格（用户指定）
   第 1 行：校验状态 / 打包下载   第 2 行：单证追溯 / 查看日志
   两格等宽、居中、列与列对齐；按钮文字统一 nowrap，宽度自适应不折断。 */
.ops-grid{display:grid;grid-template-columns:auto auto;gap:5px 8px;
  justify-content:center;align-items:center;justify-items:stretch}
.ops-grid .pill{margin:0;white-space:nowrap}
.ops-grid .btn{width:100%;max-width:none;white-space:nowrap;text-align:center;box-sizing:border-box}

/* ---------- 徽标 ---------- */
.pill{display:inline-block;padding:2px 10px;border-radius:20px;font-size:12px;
  line-height:1.5;background:#eef2f9;color:#4a5568;text-align:center;vertical-align:middle}
.pill.active,.pill.done{background:#d9f5e6;color:#0a7a45}
.pill.disabled,.pill.failed{background:#fde3e3;color:#b32020}
.pill.running{background:#fff4d6;color:#9a6a00}
.pill.pending{background:#eef2f9;color:#5a6478}
/* v2.0.74：任务列表「校验状态」徽标（9610match / 9610validate） */
.pill.ok-v{background:#d9f5e6;color:#0a7a45;font-weight:600;white-space:nowrap}
.pill.bad-v{background:#fde3e3;color:#b32020;font-weight:600;white-space:nowrap}
.pill.none-v{background:#eef2f9;color:#5a6478;font-weight:500;white-space:nowrap}
.badge{background:#eef2f9;color:var(--blue-d);padding:3px 11px;border-radius:20px;font-size:12.5px}
.badge.warn{background:#fff4d6;color:#9a6a00}
.tag{display:inline-block;background:#eef2f9;color:#4a5568;padding:1px 8px;border-radius:5px;font-size:11.5px;margin-right:4px}
.tag.validate{background:#e6f0ff;color:#1a50be}
.warn-text{color:var(--warn);font-weight:600}

/* ---------- 日志 ---------- */
.log{background:#0f1729;color:#c8e1ff;padding:14px;border-radius:9px;font-size:12.5px;
  max-height:400px;overflow:auto;font-family:Consolas,Monaco,monospace;white-space:pre-wrap;
  margin:0;line-height:1.55}

/* ---------- 提示条 ---------- */
.alert{padding:11px 15px;border-radius:8px;margin-bottom:14px;font-size:13.5px}
.alert.error{background:#fdeaea;color:#b32020;border:1px solid #f6c9c9}
.alert.ok{background:#e8f8ef;color:#0a7a45;border:1px solid #c2ebd5}

/* ---------- 键值行 ---------- */
.kv{display:grid;grid-template-columns:130px 1fr;gap:8px 14px;font-size:13.5px;margin-bottom:14px}
.kv span{color:var(--muted)}

@media(max-width:820px){
  .grid2{grid-template-columns:1fr}
  .topbar{height:auto;padding:10px;flex-direction:column;gap:8px}
}

/* ---------- 知识库范围 ---------- */
.disabled-box{background:#fff8f8;border:1px solid #f6d5d5;border-radius:9px;padding:12px 14px;margin-bottom:14px}
.chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:9px}
.chip{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:16px;font-size:12.5px}
.chip.dir{background:#fdeaea;color:#b32020}
.chip.file{background:#fff2e0;color:#9a6a00}
.chip-x{border:none;background:rgba(0,0,0,.08);color:inherit;border-radius:50%;
  width:17px;height:17px;line-height:15px;font-size:13px;cursor:pointer;padding:0}
.chip-x:hover{background:rgba(0,0,0,.18)}
select{padding:9px 12px;border:1px solid #ccd6e4;border-radius:8px;font-size:13.5px;background:#fff}

/* ---------- 技能菜单 ---------- */
.skill-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(330px,1fr));gap:14px;margin-top:12px}
.skill-card{display:flex;align-items:flex-start;gap:13px;padding:16px 18px;border:1px solid #e2e8f0;
  border-radius:12px;background:#fff;text-decoration:none;color:inherit;transition:.15s;position:relative}
.skill-card:hover{border-color:#5b8def;box-shadow:0 4px 16px rgba(91,141,239,.14);transform:translateY(-1px)}
.skill-icon{font-size:27px;line-height:1;flex-shrink:0}
.skill-body{flex:1;min-width:0}
.skill-name{font-size:15px;font-weight:600;margin-bottom:5px;color:#1a2b45}
.skill-desc{font-size:12.5px;color:#66788f;line-height:1.55;margin-bottom:8px}
.skill-io{display:flex;flex-direction:column;gap:3px;font-size:11.5px;color:#8d9bb0}
.io-in,.io-out{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.skill-go{font-size:12px;color:#5b8def;font-weight:600;align-self:center;flex-shrink:0}
.req{color:#e05252}

/* ---------- 技能授权 ---------- */
.radio-row{display:flex;gap:26px;flex-wrap:wrap;padding:11px 14px;background:#f6f9fe;border-radius:9px;font-size:13.5px}
.radio-row label{display:flex;align-items:center;gap:7px;cursor:pointer}

/* v1.8.55：顶部右侧 web 版本徽标（企业端也显示） */
.badge.ver-badge{background:#f1f3f5;color:#868e96;border:1px solid #dee2e6;font-weight:600}

/* v2.0.47：「怎么用这个技能」与「← 返回列表」并排一行；返回列表带背景色 */
.usage-card summary{display:flex;align-items:center;gap:10px}
.usage-card summary .usage-title{flex:1;min-width:0}
.back-list-btn{flex:none;display:inline-flex;align-items:center;gap:4px;
  background:#eef4fb;color:#1a4d8f;border:1px solid #cfe0f5;border-radius:7px;
  padding:5px 12px;font-size:12.5px;font-weight:600;text-decoration:none;
  white-space:nowrap;transition:background .15s,border-color .15s,box-shadow .15s}
.back-list-btn:hover{background:#e0ebfa;border-color:#a9c8ec;
  box-shadow:0 1px 4px rgba(26,80,190,.12)}
.back-list-btn:active{background:#d3e2f7}
@media(max-width:640px){
  .usage-card summary{flex-wrap:wrap}
  .usage-card summary .usage-title{flex:1 0 100%}
  .back-list-btn{margin-left:13px}
}

/* v2.0.49：协管员建号时「账号类型」纯文本展示（终端账号固定，灰色不可点）
   v2.0.50：盒模型完全复刻 `.create-form .cf-table select`，保证与下拉框同高同宽，
            排版与各框体尺寸绝对不变（height 38px / padding 9px 12px / border 1px /
            font-size 13.5px / line-height 20px / border-radius 8px / 宽度随 select 一致） */
.create-form .cf-table .role-fixed{
  display:block;height:38px;line-height:20px;box-sizing:border-box;
  padding:9px 12px;border:1px solid #e0e5ec;border-radius:8px;
  font-size:13.5px;font-family:inherit;color:#8a94a6;
  background:#f2f4f7;cursor:default;user-select:none;white-space:nowrap;
}

/* v2.0.53：协管员新建账号时「账号类型」select 禁用灰显（与行2 同款） */
.create-form .cf-table tr:nth-child(1) td.cf-span4 select.cf-disabled{
  background:#f2f4f7 !important;color:#9aa6b5 !important;
  border-color:#e0e5ec !important;cursor:not-allowed !important;
  opacity:1;background-image:none !important;
}

/* v2.0.105：下载确认框（dlMask）层级提升 —— 修复「在追溯详情弹窗内点下载，
   确认框被详情弹窗盖住」的问题。
   根因：dlMask 与 traceMask/logMask 都用 .modal-mask（z-index:100），属同一层；
        而 dlMask 在 DOM 中【排在前面】，同层同 z-index 时后出现的遮罩压住它。
   做法：把确认框抬到最高层（9999），保证无论在哪个弹窗上触发都在最上层。 */
.modal-mask#dlMask{z-index:9999}
