:root {
  --bg: #f5f6f8; --card: #ffffff; --line: #e3e6ea;
  --tx: #24292f; --tx2: #6a737d;
  --blue: #185fa5; --blue-bg: #e6f1fb;
  --teal: #0f6e56; --teal-bg: #e1f5ee;
  --amber: #854f0b; --amber-bg: #faeeda;
  --red: #a32d2d; --red-bg: #fcebeb;
  --green: #3b6d11; --green-bg: #eaf3de;
  --purple: #534ab7; --purple-bg: #eeedfe;
  --pink: #993556; --pink-bg: #fbeaf0;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: "Microsoft YaHei", "PingFang SC", sans-serif; background: var(--bg); color: var(--tx); font-size: 14px; line-height: 1.6; }
#app { max-width: 980px; margin: 0 auto; padding: 16px; }

/* 顶栏 */
.topbar { display: flex; align-items: center; justify-content: space-between; background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 12px 16px; margin-bottom: 12px; }
.topbar h1 { font-size: 16px; font-weight: 500; }
.topbar .who { color: var(--tx2); font-size: 13px; display: flex; align-items: center; gap: 10px; }
.topbar .who b { color: var(--blue); font-weight: 500; }
button.link { background: none; border: none; color: var(--blue); cursor: pointer; font-size: 13px; padding: 0; }
button.link:hover { text-decoration: underline; }

/* 导航 */
.nav { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }
.nav button { border: 1px solid var(--line); background: var(--card); border-radius: 8px; padding: 7px 14px; cursor: pointer; font-size: 13px; color: var(--tx); }
.nav button.on { background: var(--blue); border-color: var(--blue); color: #fff; }

/* 卡片 */
.card { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 16px; margin-bottom: 12px; }
.card h2 { font-size: 14px; font-weight: 500; margin-bottom: 10px; }
.card h3 { font-size: 13px; font-weight: 500; margin: 8px 0 4px; }
.muted { color: var(--tx2); font-size: 12px; }

/* 表单 */
.grid2 { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 10px; }
.field label { display: block; font-size: 12px; color: var(--tx2); margin-bottom: 3px; }
.field input, .field select, .field textarea { width: 100%; border: 1px solid var(--line); border-radius: 8px; padding: 7px 10px; font-size: 13px; font-family: inherit; background: #fff; color: var(--tx); }
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: var(--blue); }
.field .err { color: var(--red); font-size: 12px; }
.actions { margin-top: 12px; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/* 按钮 */
.btn { border: none; border-radius: 8px; padding: 8px 16px; font-size: 13px; cursor: pointer; background: var(--blue); color: #fff; }
.btn:hover { opacity: .92; }
.btn.gray { background: #eceff3; color: var(--tx); }
.btn.green { background: var(--green); }
.btn.red { background: var(--red); }
.btn:disabled { opacity: .45; cursor: not-allowed; }

/* 唯一码展示 */
.code-big { font-size: 22px; font-weight: 500; letter-spacing: 1px; color: var(--amber); background: var(--amber-bg); border: 1px dashed var(--amber); border-radius: 10px; padding: 12px 16px; display: inline-block; margin: 6px 0; font-family: Consolas, monospace; }

/* 状态徽标 */
.badge { display: inline-block; font-size: 12px; border-radius: 6px; padding: 2px 8px; }
.b-submitted { background: var(--amber-bg); color: var(--amber); }
.b-l1_passed { background: var(--blue-bg); color: var(--blue); }
.b-archived { background: var(--green-bg); color: var(--green); }
.b-rejected { background: var(--red-bg); color: var(--red); }
.b-spotting { background: var(--pink-bg); color: var(--pink); }
.b-spot_ok { background: var(--green-bg); color: var(--green); }
.b-spot_bad { background: var(--red-bg); color: var(--red); }
.b-flag { background: var(--red); color: #fff; margin-left: 4px; }

/* 记录卡片 */
.rec { border: 1px solid var(--line); border-radius: 10px; padding: 12px; margin-bottom: 10px; background: #fff; }
.hash { font-family: Consolas, monospace; font-size: 12px; word-break: break-all; background: #f6f7f9; border-radius: 6px; padding: 4px 8px; margin-top: 6px; }
.deviation { color: var(--red); font-weight: 500; }
.reviewbox { margin-top: 10px; border-top: 1px dashed var(--line); padding-top: 10px; }
.reviewbox textarea { width: 100%; border: 1px solid var(--line); border-radius: 8px; padding: 8px; font-size: 13px; font-family: inherit; min-height: 56px; }
.chk { display: flex; align-items: center; gap: 6px; font-size: 13px; margin: 8px 0; }
.hist { margin-top: 8px; font-size: 12px; color: var(--tx2); }

/* 登录 */
.login-wrap { max-width: 380px; margin: 8vh auto; }
.login-wrap .card { padding: 28px; }
.login-wrap h1 { font-size: 18px; font-weight: 500; text-align: center; margin-bottom: 4px; }
.login-wrap .sub { text-align: center; color: var(--tx2); font-size: 12px; margin-bottom: 18px; }
.msg { border-radius: 8px; padding: 8px 12px; font-size: 13px; margin: 8px 0; }
.msg.err { background: var(--red-bg); color: var(--red); }
.msg.ok { background: var(--green-bg); color: var(--green); }
/* 提示（黄色）：上传已成功、但有需要人核一眼的地方（起点靠自动推算、疑似漏传一段等）。
   与 err 分开是有意的——这类情况不阻断、不重传，别让现场以为白传了。 */
.msg.warn { background: var(--amber-bg); color: var(--amber); }
/* 提示框不再靠内联 display:none 隐藏（内联优先级高于 class，会导致提示写了却看不见），
   改为「有内容才显示」：空提示自动收起，写进文本即出现。 */
.msg:empty { display: none; }

/* 表格 */
table { width: 100%; border-collapse: collapse; font-size: 12px; }
th, td { border-bottom: 1px solid var(--line); padding: 6px 8px; text-align: left; white-space: nowrap; }
th { color: var(--tx2); font-weight: 500; background: #fafbfc; }
.tabscroll { overflow-x: auto; }

.kv { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 8px; }
.kv .item { background: #fafbfc; border-radius: 8px; padding: 8px 10px; }
.kv .item .k { font-size: 12px; color: var(--tx2); }
.kv .item .v { font-size: 14px; font-weight: 500; }

/* 唯一码公示栏 */
.board .board-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; margin-top: 10px; }
.bcard { background: #fafbfc; border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; }
.bcard .bt { font-size: 13px; font-weight: 500; margin-bottom: 4px; }
.bcard .bl { font-size: 12px; color: var(--tx2); margin-top: 2px; }
.bcard .bl b { color: var(--tx); }
.bcard.dim { opacity: .85; }
.bcard .countdown { font-family: Consolas, monospace; font-size: 24px; color: var(--tx2); margin: 8px 0 4px; letter-spacing: 1px; }
.bcard .code-big { font-size: 26px; padding: 8px 12px; }

/* ---------- 移动端适配（手机浏览器 / 微信内置浏览器） ---------- */
html { -webkit-text-size-adjust: 100%; }
body { -webkit-tap-highlight-color: transparent; }
button, .btn, .nav button { touch-action: manipulation; }

@media (max-width: 640px) {
  body { font-size: 15px; }
  #app { padding: 10px 10px calc(12px + env(safe-area-inset-bottom)); }

  /* 顶栏：允许换行，退出按钮不至于挤掉 */
  .topbar { flex-wrap: wrap; gap: 6px; padding: 10px 12px; }
  .topbar .who { flex-wrap: wrap; }

  /* 导航改为可横滑的胶囊条，不占竖向空间 */
  .nav { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; padding-bottom: 4px; margin-bottom: 10px; }
  .nav button { flex: 0 0 auto; padding: 9px 14px; font-size: 14px; }

  /* 表单：单列、加大触摸区域；输入框 16px 防 iOS 聚焦自动放大 */
  .grid2 { grid-template-columns: 1fr; gap: 12px; }
  .field input, .field select, .field textarea { font-size: 16px; padding: 10px 12px; border-radius: 10px; }
  .field select[multiple] { font-size: 16px; }
  .field label { font-size: 13px; }

  /* 按钮加大 */
  .btn { padding: 12px 18px; font-size: 15px; border-radius: 10px; }
  .actions .btn { flex: 1 1 auto; min-height: 44px; }
  button.link { font-size: 14px; padding: 4px 0; }

  /* 卡片与记录 */
  .card { padding: 14px 12px; border-radius: 10px; }
  .rec { padding: 12px 10px; }
  .code-big { display: block; width: 100%; text-align: center; font-size: 28px; padding: 14px; }

  /* 表格横向滚动更顺滑，允许换行列少一些 */
  .tabscroll { -webkit-overflow-scrolling: touch; }
  th, td { padding: 8px 10px; font-size: 13px; }

  /* 验收框与勾选加大 */
  .reviewbox textarea { font-size: 16px; min-height: 72px; }
  .chk { font-size: 14px; }
  .chk input[type="checkbox"] { width: 20px; height: 20px; }

  /* 登录页 */
  .login-wrap { margin: 6vh 12px; max-width: none; }
  .login-wrap .card { padding: 22px 16px; }

  .kv { grid-template-columns: 1fr 1fr; }
  .board .board-grid { grid-template-columns: 1fr; }
  .bcard .code-big { font-size: 32px; }
}

/* 首页二维码（微信扫码打开） */
.qr-box { margin-top: 16px; padding-top: 14px; border-top: 1px dashed #d5dde6; text-align: center; }
.qr-box img { width: 150px; height: 150px; display: block; margin: 0 auto 6px; }
.qr-box .muted { font-size: 13px; }

/* 验收框标题（四、五级共用；二、三级的四段式标题在文件末尾的记录卡分层里） */
.reviewbox .rvtitle { font-weight: 500; margin-bottom: 8px; color: var(--blue, #185fa5); }

/* 一级验收录入：分组标题 / 钻孔编号前缀+序号 / 过程描述行 */
.sec { margin: 18px 0 10px; padding-left: 8px; border-left: 3px solid #185fa5; font-size: 14px; }
.grid3 { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px; }

/* 多孔录入：一个孔一张卡片，缺项只标红本孔 */
.hole-card { border: 1px solid var(--line); border-radius: 10px; padding: 12px 12px 6px; margin: 12px 0; background: #fff; }
.hole-card.bad { border-color: var(--red); background: #fffafa; box-shadow: 0 0 0 3px rgba(214, 69, 69, .06); }
.hole-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding-bottom: 8px; border-bottom: 1px dashed var(--line); margin-bottom: 10px; }
.hole-title { font-size: 14px; color: #185fa5; }
.hole-head .hole-no { font-size: 12.5px; color: var(--tx2); }
.hole-head .hole-no b { color: var(--tx); font-family: Consolas, monospace; }
.hole-head .hole-del { margin-left: auto; }
.hole-miss { display: none; }
.hole-miss.on { display: block; font-size: 12.5px; color: var(--red); background: var(--red-bg); border-radius: 6px; padding: 6px 10px; margin-bottom: 8px; }
.hole-sub { margin: 12px 0 6px; font-size: 13px; font-weight: 500; color: #185fa5; }
.holes-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 6px; }
@media (max-width: 640px) { .grid3 { grid-template-columns: 1fr; } .sec { margin: 14px 0 8px; } }

/* 二级验收：现场验收 + 视频验收 结构化表单 */
.rvgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 8px 12px; }
.rvf { display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; color: #55606c; }
.rvf select, .rvf input { font-size: 13px; }
.btn.tiny { padding: 3px 8px; font-size: 12px; align-self: flex-start; }
.l2det { margin-top: 6px; padding: 7px 9px; border-radius: 8px; background: #f2f6fa; font-size: 12.5px; color: #33404d; line-height: 1.7; }
.l2det b { color: #185fa5; font-weight: 600; }
@media (max-width: 640px) { .rvgrid { grid-template-columns: 1fr; } }

/* ===== 录像云端化：在线调看播放器 ===== */
.btn.small { padding: 5px 11px; font-size: 12px; }
.vtext2 { color: var(--tx2); font-size: 12px; }
.vok { color: var(--green); font-size: 12px; }
.vwarn { color: var(--amber); font-size: 12px; }

.vmask { position: fixed; inset: 0; background: rgba(20,24,28,.55); display: none; align-items: flex-start; justify-content: center; padding: 16px; z-index: 60; overflow: auto; }
.vmask.on { display: flex; }
.vbox { background: #fff; border-radius: 12px; width: 100%; max-width: 880px; border: 1px solid var(--line); }
.vhead { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--line); position: sticky; top: 0; background: #fff; border-radius: 12px 12px 0 0; z-index: 2; }
.vtitle { font-weight: 500; }
.vx { border: 1px solid var(--line); background: #eceff3; border-radius: 8px; padding: 5px 12px; font-size: 13px; cursor: pointer; color: var(--tx); }
.vbody { padding: 12px 14px 16px; }
.vmeta { font-size: 12px; color: var(--tx2); margin-bottom: 8px; }
.vvideo { width: 100%; background: #000; border-radius: 8px; display: block; max-height: 56vh; }

/* 整段总进度条：一个地点的全部片铺成一条，按住拖动即可跨片定位（文件不合并） */
.vtotal { margin: 8px 0 0; }
.vttrack { position: relative; height: 20px; border: 1px solid var(--line); background: #eef1f4; border-radius: 10px; cursor: pointer; touch-action: none; overflow: hidden; }
.vttrack.drag, .vttrack:hover { border-color: var(--blue); }
.vttrack.off { opacity: .55; cursor: not-allowed; }
.vtsegs { position: absolute; inset: 0; pointer-events: none; }
.vtseg { position: absolute; top: 0; bottom: 0; border-right: 1px dashed rgba(0,0,0,.16); }
.vtseg:last-child { border-right: 0; }
.vtseg.miss { background: repeating-linear-gradient(45deg, #e2e6ea 0 5px, #eef1f4 5px 10px); }
.vtseg.on { background: rgba(24,95,165,.14); }
.vtfill { position: absolute; left: 0; top: 0; bottom: 0; background: var(--blue); opacity: .28; pointer-events: none; }
.vtknob { position: absolute; top: 50%; width: 14px; height: 14px; margin: -7px 0 0 -7px; border-radius: 50%; background: #fff; border: 2px solid var(--blue); box-shadow: 0 1px 3px rgba(0,0,0,.25); pointer-events: none; }
.vttrack.drag .vtknob { transform: scale(1.2); }
.vttline { display: flex; justify-content: space-between; gap: 10px; margin-top: 3px; }
.vttime { font-size: 12px; color: var(--tx2); font-variant-numeric: tabular-nums; }
.vtnode { text-align: right; flex: 1; }
.vtnode.vdrag { color: var(--blue); }
.vpre { display: none; }

/* 跨片总轴：每片一段，孔位打点，点一下跳到该孔退钻 */
.vstrip { margin: 10px 0 0; }
.vstripslices { display: flex; gap: 2px; height: 22px; position: relative; }
.vseghead { position: absolute; top: -2px; bottom: -2px; width: 2px; background: var(--red); border-radius: 1px; pointer-events: none; }
.vseghead[hidden] { display: none; }
.vseg { flex: none; background: var(--blue-bg); border: 1px solid var(--blue); color: var(--blue); border-radius: 4px; font-size: 11px; line-height: 20px; text-align: center; cursor: pointer; overflow: hidden; white-space: nowrap; }
.vseg.off { background: #f1f3f5; border-color: var(--line); color: var(--tx2); border-style: dashed; }
.vseg.on { background: var(--blue); color: #fff; }
.vstripholes { position: relative; height: 14px; margin-top: 2px; }
.vhole { position: absolute; top: 3px; transform: translateX(-50%); width: 9px; height: 9px; padding: 0; border-radius: 50%; border: 1px solid #fff; background: var(--amber); cursor: pointer; }
.vhole.cur { background: var(--red); box-shadow: 0 0 0 2px rgba(163,45,45,.25); }
.vstriplabel { margin: 2px 0 10px; }

/* 切片列表 */
.vslices { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0; }
.vslice { border: 1px solid var(--line); background: #fff; border-radius: 8px; padding: 6px 10px; cursor: pointer; font-size: 12px; text-align: left; display: flex; flex-direction: column; gap: 1px; color: var(--tx); }
.vslice.on { border-color: var(--blue); background: var(--blue-bg); }
.vslice.off { opacity: .55; border-style: dashed; cursor: not-allowed; }
.vslice b { font-weight: 500; }
.vslice b.vsfname { display: block; max-width: 230px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 当前片的标记条 */
.vtl { position: relative; height: 42px; margin: 10px 0 4px; background: #f5f6f8; border: 1px solid var(--line); border-radius: 8px; }
.vtlhead { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--red); pointer-events: none; }
.vtlmarks { position: absolute; inset: 0; }
.vmk { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--purple); cursor: ew-resize; touch-action: none; }
.vmk i { position: absolute; top: 2px; left: -4px; width: 10px; height: 10px; border-radius: 50%; background: var(--purple); display: block; }
.vmk span { position: absolute; bottom: 1px; left: 3px; font-size: 11px; color: var(--purple); white-space: nowrap; background: #fff; padding: 0 2px; border-radius: 3px; }
.vmk.p { background: var(--amber); } .vmk.p i { background: var(--amber); } .vmk.p span { color: var(--amber); }
.vmk.a { background: var(--red); } .vmk.a i { background: var(--red); } .vmk.a span { color: var(--red); }
.vmk.drag { background: #000; }
.vtlscale { position: relative; height: 14px; margin-bottom: 8px; }
.vtlscale span { position: absolute; transform: translateX(-50%); white-space: nowrap; }

.vrow { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: 8px 0; }
.vspdrow { margin: 8px 0 0; }
.spdbtn { border: 1px solid var(--line); background: #fff; border-radius: 8px; padding: 4px 11px; font-size: 12px; cursor: pointer; color: var(--tx); }
.spdbtn.on { border-color: var(--blue); background: var(--blue-bg); color: var(--blue); font-weight: 600; }
.vcontrow { margin: 6px 0 0; }
.contbtn { border: 1px solid var(--line); background: #fff; border-radius: 8px; padding: 4px 11px; font-size: 12px; cursor: pointer; color: var(--tx); }
.contbtn.on { border-color: var(--blue); background: var(--blue-bg); color: var(--blue); font-weight: 600; }
.vordrow { margin: 6px 0 0; }
.ordtog { border: 1px solid var(--line); background: #fff; border-radius: 8px; padding: 4px 11px; font-size: 12px; cursor: pointer; color: var(--tx); }
.ordtog.on { border-color: var(--amber); background: #fdf6e8; color: var(--amber); font-weight: 600; }
.ordtog[disabled] { opacity: .5; cursor: not-allowed; }
.vcard { display: flex; flex-direction: column; gap: 3px; }
.vcard .vslice { width: 100%; }
.vordbtns { display: flex; gap: 4px; }
.ordbtn { flex: 1; border: 1px solid var(--line); background: #fff; border-radius: 6px; padding: 3px 4px; font-size: 11px; cursor: pointer; color: var(--tx2); white-space: nowrap; }
.ordbtn:not([disabled]):hover { border-color: var(--blue); color: var(--blue); }
.ordbtn[disabled] { opacity: .4; cursor: not-allowed; }
.vmarkrow { padding-top: 8px; border-top: 1px dashed var(--line); }
.mkbtn.mk-pull { background: var(--amber); }
.mkbtn.mk-drill { background: var(--blue); }
.mkbtn.mk-abn { background: var(--red); }

/* 时间节点（按填报时刻自动定位，不用手工打标记） */
.vnoderow { margin: 8px 0 0; }
.nodebtn { border: 1px solid var(--line); background: #fff; border-radius: 8px; padding: 5px 11px; font-size: 12px; cursor: pointer; color: var(--tx); }
.nodebtn:not([disabled]):hover { border-color: var(--blue); color: var(--blue); background: var(--blue-bg); }
.nodebtn[disabled] { opacity: .45; cursor: not-allowed; }
.vnodesub { margin: 0 0 4px; line-height: 1.6; }
/* 本片起点：这一段是二级验收员的核心动作，视觉上单独框出来，别淹没在按钮堆里 */
.vstartrow { padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg2, #f7f8fa); }
.vstartin { border: 1px solid var(--line); border-radius: 8px; padding: 4px 8px; font-size: 12px; color: var(--tx); background: #fff; }
.vstartin[disabled] { opacity: .5; }
.vstartsub { margin: 0 0 8px; line-height: 1.6; }
/* 「定格看首帧」那一行的样式（.vfirstrow/.vfirstimg/.vfirstimg.big/.vfirstact/.vfirsthint）
   已随该功能于 2026-10-03 一并撤除 —— 留着就是没人引用的死样式。 */

.vholes { margin-top: 10px; padding-top: 8px; border-top: 1px dashed var(--line); display: flex; flex-wrap: wrap; gap: 6px; }
.vsub { width: 100%; }
.vholebtn { border: 1px solid var(--line); background: #fff; border-radius: 8px; padding: 5px 10px; font-size: 12px; cursor: pointer; color: var(--tx); }
.vholebtn.on { border-color: var(--blue); background: var(--blue-bg); }

.vwatch { margin-top: 8px; }
.vmsg { font-size: 12px; min-height: 16px; margin-top: 6px; }
.vmsg.err { color: var(--red); }
.vmsg.ok { color: var(--green); }

/* 手机/微信内是主要场景 → 按钮要大、好点 */
@media (max-width: 640px) {
  .vmask { padding: 0; }
  .vbox { border-radius: 0; max-width: none; }
  .vhead { border-radius: 0; }
  .vvideo { max-height: 38vh; }
  .vttrack { height: 26px; }        /* 手机上总进度条加高，手指好按好拖 */
  .vtknob { width: 18px; height: 18px; margin: -9px 0 0 -9px; }
  .vslice { flex: 1 1 46%; }
  .btn.small, .mkbtn { padding: 9px 13px; font-size: 13px; }
  .spdbtn { padding: 8px 13px; font-size: 13px; }
  .contbtn { padding: 8px 13px; font-size: 13px; }
  .vcard { flex: 1 1 46%; }
  .ordbtn { padding: 7px 4px; font-size: 12px; }
  .vhole { width: 13px; height: 13px; top: 0; }
  .nodebtn { padding: 9px 13px; font-size: 13px; }
  .vstartin { flex: 1 1 150px; }
  /* 手机上首帧图必须占满整行、并抬高一点：字太小看不出时间，等于白给 */
  .vfirstimg { flex: 1 1 100%; width: 100%; height: 74px; }
  .vfirstimg.big { height: 132px; }
  .vfirstact { flex: 1 1 100%; }
}

/* 提交忙态：多孔提交期间禁用按钮并显示进度 */
.btn[disabled], .btn:disabled { opacity: .65; cursor: not-allowed; }
@media (max-width: 640px) {
  .hole-card { padding: 10px 10px 4px; }
  .hole-head { gap: 8px; }
  .hole-head .hole-del { margin-left: 0; }
  .holes-bar .btn { width: 100%; }
}

/* ===== 施工人员：左右双栏选择器（双击加入 / 双击移回） =====
   原做法是原生 multiple select：桌面上要按住 Ctrl 点、手机上几乎选不动。
   现在左边待选、右边已选，双击即可搬人；右侧顺序就是记入记录的先后顺序。 */
/* 施工人员选择器占满整行（它比旁边的输入框宽得多） */
.grid2 > .field.full { grid-column: 1 / -1; }
.opspick { display: grid; grid-template-columns: 1fr auto 1fr; gap: 8px; align-items: stretch; }
.opsbox { border: 1px solid var(--line); border-radius: 8px; overflow: hidden; background: #fff; display: flex; flex-direction: column; }
.opshead { display: flex; justify-content: space-between; gap: 6px; font-size: 12px; color: var(--tx2); background: #fafbfc; border-bottom: 1px solid var(--line); padding: 5px 9px; }
.opshead b { color: var(--blue); font-weight: 600; }
.opsfilter { width: 100%; border: none; border-bottom: 1px solid var(--line); border-radius: 0; padding: 6px 9px; font-size: 13px; font-family: inherit; background: #fff; color: var(--tx); }
.opsfilter:focus { outline: none; border-bottom-color: var(--blue); }
.opslist { height: 176px; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 4px; }
.opsitem { display: flex; align-items: center; gap: 6px; border-radius: 6px; padding: 5px 8px; font-size: 13px; cursor: pointer; user-select: none; touch-action: manipulation; }
.opsitem:hover { background: var(--blue-bg); }
.opsitem.on { background: var(--blue); color: #fff; }
.opsitem i { font-style: normal; font-size: 11.5px; color: var(--tx2); }
.opsitem.on i { color: #d8e8f8; }
.opsitem .no { min-width: 14px; font-family: Consolas, monospace; font-size: 11.5px; color: var(--tx2); }
.opsitem.on .no { color: #d8e8f8; }
.opsempty { padding: 10px 8px; text-align: center; font-size: 12px; color: var(--tx2); }
.opsmid { display: flex; flex-direction: column; justify-content: center; gap: 6px; }
.opsmid .btn { white-space: nowrap; }
.opshint { margin-top: 6px; }

@media (max-width: 640px) {
  .opspick { grid-template-columns: 1fr; }
  .opsmid { flex-direction: row; }
  .opsmid .btn { flex: 1 1 0; min-height: 40px; }
  .opsfilter { font-size: 16px; padding: 9px 10px; }
  .opslist { height: 150px; }
  .opsitem { font-size: 15px; padding: 9px 10px; }
}

/* ===== 工作台与响应式视觉规范（2026-10-01） ===== */
:root {
  --bg: #f2f5f7; --line: #dce5eb; --tx: #213547; --tx2: #647585;
  --blue: #1c5f82; --blue-bg: #eaf3f8; --teal: #167566; --teal-bg: #e9f5ef;
}
body { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif; }
button, input, select, textarea { font-family: inherit; }
button, a, input, select, textarea { -webkit-tap-highlight-color: transparent; }
button:focus-visible, a:focus-visible, summary:focus-visible, [tabindex]:focus-visible { outline: 3px solid #3496bb; outline-offset: 3px; }
[hidden] { display: none !important; }
#app { max-width: 1440px; padding: 28px 32px; }
.ui-icon { width: 20px; height: 20px; flex: 0 0 auto; vertical-align: middle; }
.brand-mark { width: 42px; height: 46px; border-radius: 12px; background: #173c55; color: #fff; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.brand-mark .ui-icon { width: 27px; height: 27px; }
.eyebrow { display: block; color: #5d788c; font-size: 12px; font-weight: 600; letter-spacing: 1.5px; margin-bottom: 8px; }
.card { padding: 24px; margin-bottom: 20px; border-radius: 14px; box-shadow: 0 3px 14px #263c4d04; }
.card h2 { font-size: 17px; font-weight: 650; margin-bottom: 14px; color: #193c53; }
.card h3 { font-weight: 600; }
.muted { line-height: 1.8; }
.grid2, .grid3 { gap: 16px; }
.field label { font-size: 13px; color: #485e70; margin-bottom: 7px; font-weight: 500; }
.field input, .field select, .field textarea, .rvf input, .rvf select { min-height: 42px; padding: 10px 12px; border: 1px solid #ccd9e2; border-radius: 8px; color: var(--tx); background: #fff; font-size: 14px; }
.field input:focus, .field select:focus, .field textarea:focus, .rvf input:focus, .rvf select:focus { outline: 0; border-color: var(--blue); box-shadow: 0 0 0 3px #1c5f8215; }
.field input[readonly] { background: #f2f6f8; color: #506b7e; }
input::placeholder, textarea::placeholder { color: #8495a3; }
input[type="checkbox"] { accent-color: var(--blue); }
.btn { min-height: 42px; padding: 10px 18px; font-weight: 600; font-size: 14px; border: 1px solid transparent; transition: background .15s; }
.btn.gray { background: #f2f6f8; border-color: #dce5eb; color: #3a566b; }
.btn:hover:not(:disabled) { opacity: 1; filter: brightness(.96); }
.btn.small, .btn.tiny { min-height: 34px; }
button.link { min-height: 36px; padding: 6px; }
.actions { gap: 10px; margin-top: 16px; }
.sec { margin: 24px 0 14px; padding-left: 10px; border-color: #248874; }
.rec { padding: 20px; border-radius: 10px; margin-top: 16px; }
.badge { padding: 4px 9px; font-size: 12px; font-weight: 500; }
.hole-card { padding: 18px; background: #fbfcfd; margin: 18px 0; }
.hole-head { border-bottom-style: solid; padding-bottom: 12px; }
.hole-title { font-size: 16px; }
.hole-sub { margin-top: 20px; }
.reviewbox { padding-top: 16px; }
.reviewbox textarea { min-height: 84px; }
.tabscroll { border: 1px solid var(--line); border-radius: 10px; }
th, td { padding: 12px 14px; font-size: 13px; }
th { color: #496376; background: #f1f6f9; font-weight: 600; }
tr:last-child td { border-bottom: 0; }
tr:hover td { background: #f8fbfd; }
.kv .item { padding: 18px; border: 1px solid var(--line); background: #f8fbfc; }
.kv .item .v { font-size: 24px; margin-top: 6px; color: #244f69; font-variant-numeric: tabular-nums; }
.msg { padding: 12px 14px; line-height: 1.7; }
.msg.info { background: var(--blue-bg); color: var(--blue); }

/* 登录页：电脑并列公示与登录；手机优先登录，公示保留独立入口。 */
#app.login-page { max-width: 1320px; padding: 36px 44px 20px; }
.login-brand { display: flex; align-items: center; gap: 14px; font-size: 18px; font-weight: 650; color: #173c55; }
.board-jump { margin-left: auto; color: var(--blue); text-decoration: none; font-size: 13px; font-weight: 500; padding: 12px 0; }
.login-layout { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 48px; align-items: start; margin-top: 40px; }
.login-intro { padding: 20px 0 30px; }
.login-intro h1 { font-size: clamp(28px, 3.1vw, 44px); line-height: 1.45; font-weight: 650; letter-spacing: -1px; color: #173c55; }
.login-intro h1 span { color: #29917c; }
.login-intro p { color: var(--tx2); font-size: 14px; margin-top: 16px; }
.login-overview .board { padding: 0; border: 0; box-shadow: none; background: transparent; }
.login-overview .board h2 { font-size: 16px; }
.login-overview .board > .muted { font-size: 12px; max-width: 600px; }
.board .board-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-top: 18px; }
.bcard { background: #fff; padding: 18px 14px; border-radius: 12px; border-top: 3px solid #409680; }
.bcard.dim { opacity: 1; border-top-color: #a6b6c3; background: #f7f9fb; }
.bcard .bt { color: #28495e; font-size: 13px; font-weight: 600; }
.bcard .code-big { display: block; border: 0; background: none; color: #173c55; padding: 8px 0; margin: 4px 0; font-size: 36px; font-weight: 650; letter-spacing: 3px; text-align: left; }
.bcard .bl { font-size: 11px; line-height: 1.85; margin-top: 6px; }
.bcard .countdown { font-size: 22px; letter-spacing: 0; min-height: 64px; display: flex; align-items: center; font-variant-numeric: tabular-nums; }
.login-note { display: flex; gap: 8px; align-items: center; color: #687f90; font-size: 12px; margin-top: 22px; }
.login-note .ui-icon { width: 17px; height: 17px; }
.login-panel { padding: 28px; box-shadow: 0 12px 40px #173c5509; border-top: 3px solid #173c55; }
.login-panel h2 { font-size: 26px; margin-bottom: 6px; }
.login-caption { color: var(--tx2); font-size: 13px; margin-bottom: 24px; }
.login-panel .field { margin-bottom: 18px; }
.login-panel .field input { min-height: 46px; }
.password-field { position: relative; }
.password-field input { padding-right: 60px; }
.password-toggle { position: absolute; right: 2px; top: 2px; bottom: 2px; min-width: 52px; border: 0; background: transparent; color: var(--blue); cursor: pointer; border-radius: 6px; }
.login-submit { width: 100%; min-height: 46px; display: flex; justify-content: center; gap: 20px; align-items: center; }
.qr-box { border-top: 1px solid var(--line); margin-top: 24px; padding-top: 16px; }
.qr-box summary { cursor: pointer; font-weight: 600; color: #4e697c; font-size: 13px; padding: 6px; }
#qrLoginBox { text-align: center; padding: 16px 0 6px; }
#qrLoginBox > svg { padding: 10px; box-sizing: content-box; border: 1px solid var(--line); }
.qr-box .qr-help { font-size: 11px; line-height: 1.9; margin-top: 6px; }
.login-footer { text-align: center; color: #718493; font-size: 11px; margin-top: 28px; padding: 16px 0; border-top: 1px solid var(--line); }

/* 应用外壳 */
#app.workspace { display: grid; grid-template-columns: 204px minmax(0, 1fr); column-gap: 28px; align-items: start; }
.topbar { grid-column: 1 / -1; padding: 0 0 22px; margin-bottom: 28px; border: 0; border-bottom: 1px solid #d5e1e8; border-radius: 0; background: transparent; gap: 24px; }
.system-brand { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
.topbar h1 { font-size: 18px; font-weight: 650; color: #173c55; }
.brand-caption { font-size: 11px; color: #688195; letter-spacing: 1px; }
.topbar .who { gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
.user-avatar { display: flex; align-items: center; justify-content: center; width: 36px; height: 36px; border: 1px solid #d5e2ea; background: #e6eff4; color: #28526c; border-radius: 50%; font-size: 14px; flex-shrink: 0; }
.user-identity { display: flex; flex-direction: column; max-width: 250px; }
.user-identity b { font-size: 13px; }
.user-identity > span { font-size: 10px; }
.account-actions { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.account-actions .link { font-size: 12px; }
.sidebar { position: sticky; top: 24px; max-height: calc(100vh - 48px); overflow: auto; }
.nav-caption { color: #7a8d9c; font-size: 11px; letter-spacing: 2px; padding: 0 14px 14px; }
.nav { display: flex; flex-direction: column; gap: 5px; margin: 0; }
.nav button { display: flex; align-items: center; gap: 12px; padding: 12px 14px; min-height: 46px; border: 1px solid transparent; border-radius: 9px; background: transparent; color: #51697b; text-align: left; font-size: 13px; }
.nav button .ui-icon { width: 18px; height: 18px; opacity: .85; }
.nav button:hover { background: #e6eef3; }
.nav button.on { background: #173c55; color: #fff; border-color: #173c55; box-shadow: 0 4px 10px #173c5512; font-weight: 600; }
.sidebar-note { display: flex; align-items: center; gap: 6px; border-top: 1px solid var(--line); color: #7a8d9c; margin-top: 28px; padding: 20px 10px; font-size: 10px; }
.sidebar-note .ui-icon { width: 14px; height: 14px; }
#mainContent { min-width: 0; }
.view-heading { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin: 0 0 24px; }
.view-heading h2 { font-size: 26px; font-weight: 650; color: #193c53; line-height: 1.35; }
.view-heading .eyebrow { font-size: 10px; margin-bottom: 7px; }
.workspace-label { display: flex; align-items: center; gap: 6px; color: #658071; font-size: 11px; background: #e8f1ec; padding: 6px 10px; border-radius: 20px; }
.workspace-label .ui-icon { width: 14px; height: 14px; }
.skip-link { position: fixed; left: 20px; top: -80px; background: #173c55; color: #fff; padding: 12px 20px; z-index: 100; border-radius: 8px; }
.skip-link:focus { top: 12px; }
.loading-state { color: var(--tx2); padding: 48px; text-align: center; }
.record-filters { display: grid; grid-template-columns: minmax(180px, 2fr) minmax(120px, 1fr) minmax(140px, 1fr) auto; gap: 12px; align-items: end; padding: 18px; border: 1px solid var(--line); border-radius: 10px; background: #f8fafb; }
.record-summary { color: var(--tx2); font-size: 12px; padding: 16px 0 0; }
.count-pill { display: inline-block; padding: 1px 8px; background: #edf3f7; font-size: 12px; border-radius: 6px; vertical-align: middle; margin-left: 6px; }
.empty-state { padding: 48px 16px; text-align: center; color: var(--tx2); }
.empty-state .ui-icon { display: block; width: 32px; height: 32px; margin: 0 auto 12px; color: #7894a6; }
.empty-state strong { color: #425e73; font-weight: 600; }
.empty-state p { font-size: 12px; margin-top: 8px; }

@media (max-width: 1120px) {
  #app { padding: 24px; }
  .login-layout { gap: 28px; grid-template-columns: minmax(0, 1fr) 330px; }
  #app.login-page { padding: 28px; }
  .board .board-grid { gap: 8px; }
  .bcard { padding: 14px 10px; }
  .record-filters { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 960px) {
  #app.workspace { grid-template-columns: minmax(0, 1fr); }
  .topbar { margin-bottom: 18px; flex-wrap: wrap; }
  .topbar .who { justify-content: flex-start; }
  .sidebar { position: static; max-height: none; overflow: visible; margin-bottom: 20px; min-width: 0; }
  .nav { flex-direction: row; flex-wrap: nowrap; overflow-x: auto; padding: 3px 3px 9px; }
  .nav button { flex: 0 0 auto; gap: 7px; padding: 10px 12px; }
  .nav-caption, .sidebar-note { display: none; }
  .view-heading { margin-bottom: 18px; }
}
@media (max-width: 760px) {
  #app.login-page { padding: 22px 18px; }
  .login-brand { gap: 10px; font-size: 14px; }
  .login-brand .brand-mark { width: 34px; height: 38px; border-radius: 10px; }
  .board-jump { font-size: 11px; white-space: nowrap; }
  .login-layout { display: flex; flex-direction: column; gap: 28px; margin-top: 24px; }
  .login-panel { order: -1; width: 100%; margin-bottom: 0; }
  .login-overview { width: 100%; }
  .login-intro { display: none; }
  .login-note { justify-content: center; font-size: 10px; }
  .login-overview .board .board-grid { grid-template-columns: 1fr; }
  .bcard { padding: 16px; }
  .bcard .bl { font-size: 12px; }
  .bcard .code-big { padding: 4px 0; font-size: 36px; }
  .bcard .countdown { min-height: 50px; }
}
@media (max-width: 640px) {
  #app { padding: 16px 12px calc(24px + env(safe-area-inset-bottom)); }
  .topbar { gap: 14px; padding-bottom: 16px; }
  .topbar h1 { font-size: 15px; }
  .brand-mark { width: 36px; height: 40px; }
  .topbar .who { gap: 8px; width: 100%; }
  .user-identity { flex: 1; max-width: none; }
  .account-actions { width: 100%; border-top: 1px solid var(--line); padding-top: 5px; justify-content: flex-end; }
  .account-actions .link { min-height: 40px; padding: 8px 12px; }
  .view-heading h2 { font-size: 23px; }
  .workspace-label { display: none; }
  .card { padding: 18px 14px; border-radius: 12px; margin-bottom: 16px; }
  .card h2 { font-size: 16px; }
  .login-panel { padding: 24px; }
  .login-panel h2 { font-size: 25px; }
  .field input, .field select, .field textarea, .rvf input, .rvf select { font-size: 16px; min-height: 46px; max-width: 100%; }
  .grid2, .grid3, .rvgrid { grid-template-columns: minmax(0, 1fr); }
  .btn, .btn.small, .btn.tiny { min-height: 44px; }
  .btn.tiny { padding: 8px 12px; }
  .rec { padding: 14px; }
  .hole-card { padding: 14px 10px; }
  .record-filters { grid-template-columns: minmax(0, 1fr); padding: 12px; }
  .board .board-grid { grid-template-columns: minmax(0, 1fr); }
  .tabscroll { max-width: 100%; }
  .opsmid .btn { min-height: 44px; }
  .password-toggle { min-width: 54px; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; transition: none !important; }
}
.upload-steps { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 4px 0 12px; color: #315b73; font-size: 13px; font-weight: 600; }
.upload-steps span { background: #edf4f8; border-radius: 6px; padding: 6px 9px; }
.upload-steps i { color: #7c94a4; font-style: normal; }
.upload-help { margin-top: 10px; }
.upload-help summary { color: var(--blue); font-size: 12px; cursor: pointer; padding: 5px 0; }
.upload-help .muted { padding: 8px 0; }

/* 上传页：超限说明与桌面端压缩助手的下载入口。
   放在「上传须知」旁边 —— 恰好是班组看到「超过上限」那一刻最需要的东西。 */
.client-box { border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; margin-top: 10px; background: #fafbfc; }
.client-box .cb-title { font-size: 13px; font-weight: 500; }
.client-box .cb-links { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
/* .btn 是给 <button> 写的，套到 <a> 上必须补 display/text-decoration，否则会出现下划线并贴在一起 */
.client-box .cb-links .btn { display: inline-flex; align-items: center; text-decoration: none; }
/* 登录页的客户端下载入口（2026-10-01）：不登录也能拿安装包。
   用虚线边框与登录表单区分开 —— 它是给"还没账号的人"看的辅助入口，不是登录流程的一步。 */
.login-client { margin-top: 14px; border-style: dashed; }
.login-client .cb-title { font-size: 12.5px; font-weight: 400; }
.up-over td { background: var(--red-bg); }

/* 质量问题异议（2026-10-01）：登记区块 / 卡片展示 / 经理逐条定夺 */
.issuebox { border: 1px dashed var(--line); border-radius: 10px; padding: 10px 12px; margin-top: 8px; background: #fffdf7; }
.issuebox textarea { width: 100%; min-height: 54px; margin-top: 6px; font-family: inherit; font-size: 13px; padding: 6px 8px; border: 1px solid var(--line); border-radius: 8px; }
.l2det.issue { background: #fff8ef; border-left: 3px solid #d85a30; padding-left: 8px; }
.issuedetail { border: 1px solid #f0997b; background: #faece7; border-radius: 10px; padding: 10px 12px; margin: 8px 0; font-size: 13px; line-height: 1.7; }
.issuedecide { border: 1px solid #f0997b; background: #faece7; border-radius: 8px; padding: 8px 10px; margin-bottom: 8px; font-size: 12px; }
.isrow { border-top: 1px solid #f5c4b3; padding: 6px 0; line-height: 1.6; }
.isrow:first-of-type { border-top: 0; }
.isopt { display: inline-flex; align-items: center; gap: 4px; margin-right: 12px; }

/* ---------- 验收队列表格（2026-10-02）----------
   一行一孔；点行尾「验收 / 审核 / 抽验」在行内展开完整的记录卡。
   展开行与它上面那行必须看起来是"同一条"：展开区去掉上边框、底色略深，
   并让被展开的那一行同时加深——两处一起做，才不会读成两条独立记录。 */
.rtable table { min-width: 760px; }
.rtable .rtid { width: 1%; color: var(--tx2); font-variant-numeric: tabular-nums; }
.rtable .rtrow > td { vertical-align: middle; }
.rtexp { border: 1px solid var(--line); background: #fff; color: var(--tx); border-radius: 8px; padding: 4px 12px; font-size: 12px; cursor: pointer; white-space: nowrap; }
.rtexp.on { background: var(--blue-bg); border-color: var(--blue); color: var(--blue); }
.rtdet[hidden] { display: none; }
.rtdet > td { background: #fafcfe; padding: 10px 12px 14px; }
.rtdet .rec { margin: 0; border-color: #e3edf4; }
/* :has 不支持时只是少一层高亮，不影响展开/收起 */
.rtrow:has(+ .rtdet:not([hidden])) > td { background: #f4f9fc; }
.qbrief { font-size: 12.5px; color: var(--tx2); margin-bottom: 10px; line-height: 1.7; }
.qbrief b { color: var(--tx); font-weight: 600; }
.qhelp { border: 1px dashed var(--line); background: #fafbfc; border-radius: 10px; padding: 10px 12px; margin-bottom: 10px; font-size: 12.5px; color: var(--tx2); line-height: 1.85; }
.qhelp b { color: var(--tx); font-weight: 600; }
.lnk { border: 0; background: none; color: var(--blue); font-size: 12.5px; cursor: pointer; padding: 0 2px; text-decoration: underline; text-underline-offset: 2px; font-family: inherit; }
.badge.b-issue { background: #faece7; color: #d85a30; margin-left: 4px; }
@media (max-width: 640px) {
  /* 井口多是手机点：展开按钮做成手指够得着的高度 */
  .rtexp { min-height: 32px; padding: 6px 14px; }
  .rtdet > td { padding: 8px; }
}

/* ==================== 记录卡信息分层（2026-10-02 改版）====================
   为什么改：卡片原来把 20 多个字段用同一套 .meta 网格平铺 —— 等权重、没标题、
   最该看的几个数被淹在中间；更糟的是卡片渲染在 <td> 里，**继承了 td 的
   white-space:nowrap**，于是「打钻：2026-10-02 09:05 ~ 2026-10-02 09:30」这种长值
   直接越过自己的格子压到隔壁字段上（现场反馈"排版很乱"就是这么来的）。
   改法：一条记录拆成六层，各司其职 ——
     ①标题条 → ②关键参数 → ③流转进度 → ④前序结论 → ⑤我的验收 → ⑥台账（折叠）
   要动手的排在前面，追溯用的（哈希、五级留痕、历史）收进台账。
   **收起的是视觉噪声，不是信息**：台账里字段一个不少，只是默认不铺开。 */

/* 根因修复：卡片在表格单元格内，必须把继承来的 nowrap 关掉，否则字段互相压字 */
.rtdet > td, .rec { white-space: normal; }

/* ① 标题条 */
.rchead { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding-bottom: 12px; border-bottom: 1px solid var(--line); }
.rchead .rch { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; min-width: 0; }
.rchead .rcid { font-size: 13px; color: #7b8b99; font-variant-numeric: tabular-nums; }
.rchead .rchole { font-size: 17px; font-weight: 650; color: #173c55; letter-spacing: .3px; }
.rchead .rchole em { font-style: normal; font-size: 12.5px; font-weight: 400; color: #7b8b99; margin-left: 10px; }
.rchead .rctag { font-size: 12.5px; color: #485e70; background: #f1f5f8; border-radius: 6px; padding: 2px 9px; }
.rchead .rcmarks { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* ② 关键参数条：小块网格，"标签小字 + 数值大字"，扫一眼就知道这孔是什么。
   列宽按"五行两排"调（唯一码/孔号/地点/施工人/日期 ｜ 打钻/退钻/孔深/里程/录像），
   正好铺满不留半排空位。 */
.rcfacts { display: grid; grid-template-columns: repeat(auto-fill, minmax(176px, 1fr)); gap: 8px; margin-top: 14px; }
.rcfacts .f { background: #f8fafb; border: 1px solid #edf2f6; border-radius: 8px; padding: 7px 11px; min-width: 0; }
.rcfacts .f > span { display: block; font-size: 11.5px; color: #7b8b99; margin-bottom: 1px; }
.rcfacts .f > b { display: block; font-size: 14px; font-weight: 600; color: #213547; word-break: break-word; }
.rcfacts .f > b.inline2 { font-size: 13px; font-weight: 500; }
.rcfacts .f.hl { background: #f1f8fb; border-color: #d3e6f0; }
.rcfacts .f.hl > b { color: #1c5f82; font-family: Consolas, Menlo, monospace; letter-spacing: .5px; }
.rcfacts .f.bad > b { color: #a32d2d; }
.rcfacts .f.ok > b { color: #167566; }

/* ③ 流转进度：六步一条线，比原来六行灰字好读，且能一眼看出卡在哪一步 */
.rcflow { display: flex; flex-wrap: wrap; margin-top: 14px; }
.rcflow .fs { flex: 1 1 150px; min-width: 140px; position: relative; padding: 0 12px 0 20px; min-height: 32px; }
.rcflow .fs::before { content: ''; position: absolute; left: 5px; top: 5px; width: 9px; height: 9px; border-radius: 50%; background: #d8e1e8; box-sizing: border-box; }
.rcflow .fs::after { content: ''; position: absolute; left: 16px; right: 2px; top: 9px; height: 2px; background: #eaeff3; }
.rcflow .fs:last-child::after { display: none; }
.rcflow .fs b { display: block; font-size: 12.5px; font-weight: 500; color: #98a2ad; line-height: 1.35; }
.rcflow .fs i { display: block; font-style: normal; font-size: 11.5px; color: #a9b4be; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rcflow .fs.done::before { background: #167566; }
.rcflow .fs.done::after { background: #c3e0d6; }
.rcflow .fs.done b { color: #167566; }
.rcflow .fs.now::before { background: #fff; border: 3px solid #1c5f82; top: 3px; left: 3px; width: 13px; height: 13px; }
.rcflow .fs.now b { color: #1c5f82; font-weight: 650; }
.rcflow .fs.now i { color: #5d788c; }
.rcflow .fs.bad::before { background: #a32d2d; }
.rcflow .fs.bad::after { background: #eec9c9; }
.rcflow .fs.bad b { color: #a32d2d; }

/* ④ 前序环节结论：复核角色真正要看的（队长/三级/四级/经理）—— 必须可见，不能收进台账 */
.rcprev { margin-top: 14px; }
.rcprev .l2det:first-child { margin-top: 0; }

/* ⑤ 我的验收：四段式，序号圆点把"要干几件事"讲清楚 */
.reviewbox { margin-top: 16px; border-top: 1px solid var(--line); padding-top: 14px; }
.reviewbox .rvtitle { font-size: 14.5px; font-weight: 650; color: #173c55; margin-bottom: 14px; }
.rvsec { margin-top: 16px; }
/* 标题后面紧跟的那一段不再加间距（:first-of-type 在这里不管用 —— .rvtitle 也是 div，
   会先占掉 first-of-type 的名额） */
.reviewbox > .rvtitle + .rvsec { margin-top: 0; }
.rvstep { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.rvstep > i { width: 20px; height: 20px; flex: none; border-radius: 50%; background: #1c5f82; color: #fff; font-style: normal; font-size: 12px; font-weight: 600; display: inline-flex; align-items: center; justify-content: center; }
.rvstep > b { font-size: 13.5px; font-weight: 650; color: #213547; }
.rvstep > span.hint { font-size: 11.5px; color: #8495a3; line-height: 1.5; }
.rvgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; align-items: start; }
/* 标签固定一行、控件另起一行并底部对齐 —— 原来 hint 内联在 label 里，
   有 hint 的字段 label 变两行、控件被推下去，几列下拉框参差不齐。 */
.rvf { display: flex; flex-direction: column; gap: 6px; font-size: 13px; color: #485e70; font-weight: 500; min-width: 0; }
.rvf > .rvfl { display: block; }
.rvf > .rvfl > i { font-style: normal; font-weight: 400; font-size: 11.5px; color: #8495a3; }
.rvf > .rvhint { font-size: 11.5px; color: #8495a3; font-weight: 400; line-height: 1.5; }
.rvf .fvrow { display: flex; gap: 6px; align-items: center; }
.rvf .fvrow > input { flex: 1 1 auto; min-width: 0; }
.rvf .fvrow > .btn { flex: none; }
.rvacts { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 16px; }
/* 调看录像一行：按钮 + 本班录像状态 + 观看进度 */
.rvwatch { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.rvwatch .vstat { font-size: 12.5px; color: #485e70; background: #f1f7fa; border: 1px solid #e0ecf2; border-radius: 7px; padding: 4px 10px; }
.rvwatch .vwarn { color: #a32d2d; font-size: 12.5px; }
.rvwatch .vok { color: #167566; font-size: 12.5px; }
/* 审核类角色的说明段（一句"你要复核什么"），与表单控件区分开 */
.rcnote { border-left: 3px solid #cfe2ee; background: #f6fafc; border-radius: 0 8px 8px 0; padding: 9px 12px; font-size: 12.5px; color: #485e70; line-height: 1.75; margin-bottom: 10px; }
.rcnote b { color: #1c5f82; font-weight: 600; }
/* 「已核实一致」勾选框做成醒目的一整块 —— 它是提交前的最后一道确认，不该是一条不起眼的小字 */
.reviewbox .chk { align-items: center; gap: 9px; font-size: 13.5px; margin: 14px 0 10px; padding: 11px 13px; background: #f2f8fb; border: 1px solid #d5e7f0; border-radius: 9px; cursor: pointer; }
.reviewbox .chk input { width: 18px; height: 18px; flex: none; }
.reviewbox .chk b { font-weight: 600; }

/* ⑥ 台账（折叠）：孔径/煤粉量/打钻过程/录像清单/哈希/完整流转/历史留痕 —— 追溯用，不占主视线 */
.rcledger { margin-top: 16px; border-top: 1px solid var(--line); padding-top: 10px; }
.rcledger > summary { cursor: pointer; font-size: 12.5px; color: #1c5f82; list-style: none; display: inline-flex; align-items: center; gap: 6px; padding: 2px 0; }
.rcledger > summary::-webkit-details-marker { display: none; }
.rcledger > summary::before { content: '▸'; font-size: 12px; color: #7b8b99; }
.rcledger[open] > summary::before { content: '▾'; }
.rcledger .lbody { margin-top: 10px; padding: 12px 14px; background: #fafcfd; border: 1px solid #eef3f7; border-radius: 10px; }
.rcledger .lsec { font-size: 11.5px; color: #8495a3; margin: 14px 0 6px; letter-spacing: .5px; }
.rcledger .lsec:first-child { margin-top: 0; }
.rcledger .lgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 6px 18px; font-size: 12.5px; color: var(--tx2); }
.rcledger .lgrid > div { display: flex; gap: 6px; min-width: 0; }
.rcledger .lgrid > div > span { flex: none; color: #8495a3; }
.rcledger .lgrid > div > b { color: var(--tx); font-weight: 500; word-break: break-word; }
.rcledger .lgrid.wide { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
.rcledger .lgrid > div > span { min-width: 5.4em; }

/* 质量问题登记：折叠块。默认收起（大多数孔没问题），一旦填了"不清晰/不符合"自动展开 */
.issuefold { margin-top: 4px; border: 1px dashed #e6d9bf; border-radius: 9px; background: #fffdf8; }
.issuefold > summary { cursor: pointer; list-style: none; font-size: 12.5px; color: #854f0b; padding: 9px 12px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.issuefold > summary::-webkit-details-marker { display: none; }
.issuefold > summary::before { content: '＋'; font-weight: 600; }
.issuefold[open] > summary::before { content: '－'; }
.issuefold > summary > span { color: #8a7a63; font-weight: 400; }
.issuefold .ifbody { padding: 0 12px 12px; }
.issuefold.need { border-color: #e08a63; background: #fff7f2; }
.issuefold.need > summary { color: #a32d2d; }
.issuefold textarea { width: 100%; border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; font-family: inherit; font-size: 13px; background: #fff; }
.issuebox { border: 0; background: none; padding: 0; margin: 0; }

/* 驳回/质量问题等"前序结论"提示条的层级：左侧色条一眼区分类型 */
.rcprev .l2det { background: #f6fafc; border-left: 3px solid #cfe2ee; border-radius: 0 8px 8px 0; padding: 9px 12px; line-height: 1.75; }
.rcprev .l2det + .l2det { margin-top: 8px; }
.rcprev .l2det.issue { background: #fff8f2; border-left-color: #e08a63; }

@media (max-width: 640px) {
  .rcfacts { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); }
  .rcflow .fs { flex: 1 1 100%; min-width: 0; padding-left: 22px; }
  .rcflow .fs::after { display: none; }
  .reviewbox .chk { font-size: 13px; }
  .rvacts .btn { flex: 1 1 auto; }
  .rvgrid { grid-template-columns: minmax(0, 1fr); }
  .rcledger .lgrid, .rcledger .lgrid.wide { grid-template-columns: minmax(0, 1fr); }
}

/* 窄屏（手机/平板竖屏）：队列表格本身要横向滚动（一行一孔的字段本来就多，塞不进 390px），
   但**展开出来的记录卡必须按"看得见的那块宽度"排版** —— 否则填一张验收表要横向拖三屏。
   做法：把滚动区设成容器，卡宽取容器的真实内宽（cqw），单元格 sticky 钉在滚动区左沿。
   比 "100vw − 固定值" 靠谱：640~900 之间页面的内边距是变的两套值，量不出一个通吃的常数。 */
.tabscroll { container-type: inline-size; }
@supports (container-type: inline-size) {
  @container (max-width: 900px) {
    /* ⚠️ 只能约束 .rec 的宽度，不能给 td 定宽：td 是 colspan 单元格，
       表格布局里 width 只是建议值，照样被别的行（一堆 nowrap 的单元格）撑到 1045px。
       所以让 td 只负责 sticky 钉住左沿、由卡片自己按容器内宽定量。 */
    .rtable .rtdet > td { position: sticky; left: 0; z-index: 2; padding: 0 0 10px; }
    .rtable .rtdet > td > .rec {
      width: calc(100cqw - 12px); max-width: calc(100cqw - 12px);
      margin: 0 6px; box-sizing: border-box;
    }
  }
}
/* 不支持容器查询的旧浏览器：退回按 100vw 定量（这套尺寸只在 ≤640 稳定，阈值也收到 640）。 */
@supports not (container-type: inline-size) {
  @media (max-width: 640px) {
    .rtable .rtdet > td { position: sticky; left: 0; z-index: 2; }
    .rtable .rtdet > td > .rec { width: calc(100vw - 64px); max-width: calc(100vw - 64px); }
  }
}
@media (max-width: 640px) {
  .topbar .brand-caption, .topbar .user-avatar { display: none; }
  .topbar .who { display: grid; grid-template-columns: minmax(0, 1fr) auto; }
  .account-actions { width: auto; border: 0; padding: 0; gap: 0; max-width: 200px; }
  .account-actions .link { padding: 8px; }
  .view-heading { display: none; }
  .sidebar { margin-bottom: 12px; }
  .upload-steps { font-size: 11px; gap: 5px; }
  /* 手机上按钮占满一行，下载入口做成大按钮（井口多是手机点） */
  .client-box .cb-links .btn { width: 100%; justify-content: center; min-height: 44px; }
  .upload-steps span { padding: 6px; }
}

/* 录像来源（上传批次）选择 —— 同一个作业地点、同一个班次里可能有两三组人同时施工，
   录像各传各的；录孔时必须选出本组那一批，否则本孔的录像清单会混进别组的片子。 */
.srcpick { display: grid; gap: 6px; margin-bottom: 6px; }
.srcitem { display: flex; align-items: center; gap: 9px; padding: 8px 11px; border: 1px solid var(--line);
  border-radius: 8px; background: var(--card); cursor: pointer; }
.srcitem.on { border-color: var(--blue); background: var(--blue-bg); }
.srcitem input { width: 16px; height: 16px; margin: 0; flex: none; }
.srcitem b { flex: none; }
.srcitem span { color: var(--tx2); font-size: 12.5px; }
@media (max-width: 640px) {
  .srcitem { flex-wrap: wrap; }        /* 窄屏上「谁 + 片数 + 起录时段」换行，不挤压压字 */
}

/* 待认领录像的文件夹名与文件指纹在手机上也允许换行。 */
.inbox-group h3, .inbox-group .chk span { min-width: 0; overflow-wrap: anywhere; white-space: normal; }
.inbox-group select { max-width: 100%; }
.inbox-group .chk { align-items: flex-start; }

/* 常用任务优先；手机上仍保留横向导航，不占用表单空间。 */
.nav-group { display: flex; flex-direction: column; gap: 4px; }
.nav-group + .nav-group { margin-top: 15px; }
.nav-group-label { padding: 6px 14px; font-size: 11px; color: var(--tx2); }
.nav-group button { width: 100%; }
.draft-bar { display: flex; gap: 12px; justify-content: space-between; align-items: center; flex-wrap: wrap; background: #f0f7fa; border: 1px solid #d9e8ee; border-radius: 8px; padding: 10px 12px; margin: 12px 0; font-size: 12px; color: #365d72; }
.opspick { grid-template-columns: 1fr 1fr; }
button.opsitem { width: 100%; border: 0; background: transparent; color: inherit; text-align: left; font-family: inherit; min-height: 40px; }
button.opsitem.on { background: var(--blue); color: #fff; }
button.opsitem:hover { background: var(--blue-bg); color: var(--tx); }
.entry-submit { position: sticky; bottom: 0; z-index: 4; background: #fff; border-top: 1px solid var(--line); padding: 12px 0; }
.queue-filters { grid-template-columns: minmax(180px, 2fr) minmax(140px, 1fr) auto; margin-top: 16px; }
.group-filters { grid-template-columns: minmax(180px, 2fr) minmax(160px, 1fr); margin-top: 16px; }
.inbox-card > summary { cursor: pointer; color: #315469; font-weight: 600; }
.inbox-card[open] > summary { margin-bottom: 12px; }
.review-draft-hint { margin-top: 8px; }
.my-video-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); gap: 12px; }
.my-video-item { border: 1px solid var(--line); border-radius: 9px; padding: 14px; min-width: 0; }
.my-video-heading { display: flex; align-items: flex-start; gap: 12px; justify-content: space-between; margin-bottom: 7px; }
.my-video-heading > b { overflow-wrap: anywhere; font-size: 13px; }
.my-video-heading > button { flex: none; min-height: 32px; }
.video-file-summary { margin-top: 7px; font-size: 12px; }
.my-video-item summary { color: var(--blue); cursor: pointer; font-size: 12px; margin-top: 10px; }
.video-file-details { margin-top: 8px; overflow-wrap: anywhere; }
.success-card { padding: 28px; }
.compact-flow { margin: 10px 0; }
.compact-flow > summary { cursor: pointer; color: var(--blue); font-size: 12px; }
.upload-confirm-summary { border-left: 3px solid var(--blue); background: var(--blue-bg); padding: 10px 12px; border-radius: 0 7px 7px 0; color: #264c65; font-size: 13px; margin-top: 10px; }
.client-box > summary { cursor: pointer; }
.client-box[open] > summary { margin-bottom: 10px; }
[hidden] { display: none !important; }
@media (max-width: 960px) {
  .nav-group { flex-direction: row; flex: 0 0 auto; }
  .nav-group + .nav-group { margin-top: 0; padding-left: 8px; border-left: 1px solid var(--line); }
  .nav-group-label { display: none; }
  .nav-group button { width: auto; }
}
@media (max-width: 640px) {
  .opspick, .queue-filters, .group-filters { grid-template-columns: minmax(0, 1fr); }
  button.opsitem { min-height: 44px; }
  .entry-submit { gap: 8px; }
  .entry-submit .btn { flex: 1; min-height: 44px; }
  .draft-bar { font-size: 12px; }
  .rtable .rtexp { min-width: 60px; min-height: 44px; }
  .entry-groups-table, .entry-groups-table tbody { display: block; width: 100%; }
  .entry-groups-table tr:first-child { display: none; }
  .entry-groups-table tr[data-entry-row] { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; padding: 14px; border: 1px solid var(--line); border-radius: 10px; margin-bottom: 12px; }
  .entry-groups-table td { display: block; padding: 0; border: 0; white-space: normal; overflow-wrap: anywhere; }
  .entry-groups-table td::before { content: attr(data-label); display: block; font-size: 11px; color: var(--tx2); margin-bottom: 3px; }
  .entry-groups-table td:nth-child(3), .entry-groups-table td:last-child { grid-column: 1 / -1; }
  .entry-groups-table td:last-child { display: flex; gap: 8px; flex-wrap: wrap; }
  .entry-groups-table td:last-child::before { display: none; }
  .entry-groups-table td:last-child .btn { flex: 1; min-height: 44px; }
  .rtable .rtrow > td:last-child, .rtable th:last-child { position: sticky; right: 0; z-index: 2; background: #fff; box-shadow: -4px 0 8px #173c5509; }
}
