

/* 明/暗两套 —— 王娟 2026-08-18:「黑色好废眼」→ **预设浅色**, 顶栏可切换,
   选择存 cookie qy_theme 由服务端渲染 (免闪一下白再变黑)。
   要加颜色请加 token, 不要在下面写死色码, 否则只有一个主题会对。 */
:root{
  --bg:#F5F7FA; --surface:#FFFFFF; --surface-2:#F1F4F8;
  --text:#141922; --text-2:#5A6472; --text-3:#98A2B0;
  --accent:#0E8FA8; --accent-2:#5B62D6;
  --accent-soft:rgba(14,143,168,.09); --accent-flash:rgba(14,143,168,.22);
  --focus:rgba(14,143,168,.18);
  --on-accent:#FFFFFF;
  --border:rgba(16,24,40,.11); --border-h:rgba(14,143,168,.45);
  --border-h2:rgba(16,24,40,.22); --border-strong:rgba(16,24,40,.16);
  --row-hover:rgba(16,24,40,.025);
  --ok:#0E9F6E; --warn:#B45309; --bad:#CE3B3B;
  --ok-bg:rgba(14,159,110,.10); --warn-bg:rgba(180,83,9,.10); --bad-bg:rgba(206,59,59,.10);
  --warn-fg:#8A5209;
  --bg-blur:rgba(245,247,250,.82);
  --shadow:0 1px 2px rgba(16,24,40,.05),0 1px 3px rgba(16,24,40,.04);
  --grad1:#22D3EE; --grad2:#818CF8; --on-grad:#06222A;
  --r:10px; --r-lg:14px; --t:160ms ease-out; --side:232px;
}
html[data-theme="dark"]{
  --bg:#0B0D12; --surface:#12151C; --surface-2:#1A1E27;
  --text:#E6E8EE; --text-2:#8B93A5; --text-3:#4B5263;
  --accent:#22D3EE; --accent-2:#818CF8;
  --accent-soft:rgba(34,211,238,.07); --accent-flash:rgba(34,211,238,.20);
  --focus:rgba(34,211,238,.15);
  --on-accent:#06222A;
  --border:rgba(255,255,255,.06); --border-h:rgba(34,211,238,.35);
  --border-h2:rgba(255,255,255,.14); --border-strong:rgba(255,255,255,.10);
  --row-hover:rgba(255,255,255,.02);
  --ok:#34D399; --warn:#FBBF24; --bad:#F87171;
  --ok-bg:rgba(52,211,153,.10); --warn-bg:rgba(251,191,36,.09); --bad-bg:rgba(248,113,113,.10);
  --warn-fg:#FDE68A;
  --bg-blur:rgba(11,13,18,.72);
  --shadow:none;
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--text);font-size:14px;line-height:1.55;
  font-family:"Inter","PingFang SC","Noto Sans SC","微软雅黑",system-ui,-apple-system,sans-serif;
  -webkit-font-smoothing:antialiased}
a{color:var(--accent);text-decoration:none} a:hover{text-decoration:underline}
svg.ic{flex:none;vertical-align:-2px}

/* ── 左侧固定导览 ───────────────────────────────────────────────── */
.side{position:fixed;top:0;left:0;bottom:0;width:var(--side);background:var(--surface);
  border-right:1px solid var(--border);display:flex;flex-direction:column;
  padding:12px 10px;gap:2px;overflow-y:auto;z-index:20;transition:width var(--t)}
.side .logo{display:flex;align-items:center;gap:9px;padding:8px 8px 14px;font-weight:600;
  font-size:14px;color:var(--text);white-space:nowrap;overflow:hidden}
.side .logo svg{color:var(--accent)}
.nv{position:relative;display:flex;align-items:center;gap:10px;padding:8px 10px;
  border-radius:var(--r);color:var(--text-2);font-size:13px;white-space:nowrap;
  overflow:hidden;transition:background var(--t),color var(--t)}
.nv:hover{background:var(--surface-2);color:var(--text);text-decoration:none}
.nv.on{color:var(--accent);background:var(--accent-soft)}
.nv.on::before{content:"";position:absolute;left:0;top:7px;bottom:7px;width:2px;
  border-radius:0 2px 2px 0;background:var(--accent)}
body.mini{--side:64px}
body.mini .nv span,body.mini .logo span{display:none}
body.mini .nv{justify-content:center;padding:9px 0}

/* ── 主区 + 顶栏 ────────────────────────────────────────────────── */
.main{margin-left:var(--side);transition:margin var(--t)}
.topbar{display:flex;align-items:center;gap:10px;padding:0 20px;height:52px;
  border-bottom:1px solid var(--border);background:var(--bg-blur);
  backdrop-filter:saturate(140%) blur(8px);position:sticky;top:0;z-index:15}
.navsp{flex:1}
.ttl{font-size:13px;font-weight:500;color:var(--text-2)}
.i-sun{display:none} html[data-theme="dark"] .i-sun{display:inline-flex}
html[data-theme="dark"] .i-moon{display:none}
.icobtn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;
  border-radius:8px;border:1px solid var(--border);background:transparent;color:var(--text-2);
  cursor:pointer;padding:0;margin:0;transition:all var(--t)}
.icobtn:hover{color:var(--accent);border-color:var(--border-h)}
/* 顶栏「回报问题」: 原生 details, 展开成一张小卡 */
details.issue{position:relative}
details.issue>summary{list-style:none;display:inline-flex;align-items:center;gap:6px;height:30px;
  padding:0 10px;border-radius:8px;border:1px solid var(--border);color:var(--text-2);
  font-size:12px;cursor:pointer;user-select:none}
details.issue>summary::-webkit-details-marker{display:none}
details.issue>summary:hover{color:var(--accent);border-color:var(--border-h)}
details.issue[open]>summary{color:var(--accent);border-color:var(--accent)}
.issueform{position:absolute;right:0;top:36px;width:min(360px,90vw);padding:12px;z-index:30;
  background:var(--surface);border:1px solid var(--border);border-radius:10px;
  box-shadow:0 8px 24px rgba(0,0,0,.12)}
.issueform textarea{width:100%;box-sizing:border-box;margin-bottom:8px}
.issueform button{width:auto;height:34px;padding:0 16px}
@media (max-width:700px){details.issue .itxt{display:none}}
.who{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text-2)}
.avatar{width:26px;height:26px;border-radius:50%;display:inline-flex;align-items:center;
  justify-content:center;font-size:12px;font-weight:600;color:var(--on-grad);
  background:linear-gradient(135deg,var(--grad1),var(--grad2))}
.roletag{font-size:11px;color:var(--text-2);border:1px solid var(--border);
  border-radius:20px;padding:1px 9px}
.logout{display:inline-flex;align-items:center;gap:5px;color:var(--text-2);font-size:13px}
.logout:hover{color:var(--accent);text-decoration:none}
body.nonav .main{margin-left:0} body.nonav .topbar{justify-content:center}

/* ── 版面 ───────────────────────────────────────────────────────── */
.wrap{max-width:1440px;margin:0 auto;padding:24px 20px 48px;
  animation:fadein 200ms ease-out}
@keyframes fadein{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
h1{font-size:24px;font-weight:600;color:var(--text);margin:0 0 4px;letter-spacing:-.01em;
  display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.sub{color:var(--text-2);font-size:12px;margin:0 0 16px}
.pill{font-size:11px;font-weight:500;color:var(--text-2);border:1px solid var(--border);
  border-radius:20px;padding:2px 9px;background:var(--surface);white-space:nowrap}
.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--r-lg);
  padding:20px;margin-bottom:16px;box-shadow:var(--shadow)}
/* 栏位分组: 区块标题 + 细分隔线, 不是一整块大卡 */
.grp{margin:0 0 22px} .grp:last-child{margin-bottom:0}
.ln{border:0;border-top:1px solid var(--border);margin:8px 0 14px}
.tt{font-size:16px;font-weight:600;color:var(--text);margin-bottom:2px;
  display:flex;align-items:center;gap:8px}
.big{font-size:17px;font-weight:600;color:var(--text)}

/* ── 表单 ───────────────────────────────────────────────────────── */
label{display:block;font-size:12px;color:var(--text-2);margin:12px 0 5px;font-weight:500}
label .hint{display:inline;margin:0 0 0 5px;color:var(--text-3)}
input,select,textarea{width:100%;height:40px;padding:0 12px;color:var(--text);
  background:var(--surface-2);border:1px solid var(--border);border-radius:var(--r);
  font-size:14px;font-family:inherit;font-variant-numeric:tabular-nums;
  transition:border-color var(--t),box-shadow var(--t)}
textarea{height:auto;padding:10px 12px;line-height:1.6;resize:vertical}
input:hover,select:hover,textarea:hover{border-color:var(--border-h2)}
input:focus,select:focus,textarea:focus{outline:0;border-color:var(--accent);
  box-shadow:0 0 0 3px var(--focus)}
input::placeholder,textarea::placeholder{color:var(--text-3)}
select{appearance:none;-webkit-appearance:none;padding-right:32px;cursor:pointer;
  background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238B93A5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 10px center}
option,optgroup{background:var(--surface-2);color:var(--text)}
input[type=file]{padding:8px 12px;height:auto}
/* 勾选类不吃上面的「文字框」尺寸 (不然排版方案的单选钮会变成 40px 白色大圆) */
input[type=radio],input[type=checkbox]{width:auto;height:auto;padding:0;margin:0;
  accent-color:var(--accent);cursor:pointer;box-shadow:none}
input[type=radio]:focus,input[type=checkbox]:focus{box-shadow:0 0 0 3px var(--focus)}
input[disabled],select[disabled]{opacity:.45;cursor:not-allowed}
/* 必填 = label 后一颗强调色小圆点 (取代红色星号) */
.req label::after{content:"";display:inline-block;width:5px;height:5px;border-radius:50%;
  background:var(--accent);vertical-align:middle;margin-left:6px}
.row{display:flex;gap:12px;flex-wrap:wrap}.row>div{flex:1;min-width:150px}
.hint{font-size:12px;color:var(--text-2);margin-top:4px}
/* 邮箱簿 (王娟 2026-09-02:「网页报价邮箱可以记忆保存吗, 或者找个地址薄储存起来」)。
   8/27 做过一版, 但是 <input list=...> 的浏览器自动补全 —— 不打字就看不到。 */
.addrbook{display:flex;gap:6px;flex-wrap:wrap;margin-top:6px}
.chip{font:inherit;font-size:12px;padding:3px 10px;border-radius:999px;cursor:pointer;
  width:auto;height:auto;  /* 王娟 2026-09-09「可以把距离调小一点吗」— 全站 button{width:100%;height:44px} 把标签撑成整行 */
  border:1px solid var(--line);background:transparent;color:var(--text-2)}
.chip:hover{border-color:var(--accent);color:var(--text)}
.chip.on{background:var(--accent);border-color:var(--accent);color:#fff}
details>summary{cursor:pointer;font-size:13px;color:var(--text-2);padding:8px 0;
  list-style:none} details>summary::-webkit-details-marker{display:none}
details>summary::before{content:"▸ ";color:var(--text-3)}
details[open]>summary::before{content:"▾ "}
details>summary:hover{color:var(--accent)}

/* ── 按钮 ───────────────────────────────────────────────────────── */
button{width:100%;height:44px;display:inline-flex;align-items:center;justify-content:center;
  gap:8px;background:var(--surface-2);color:var(--text);border:1px solid var(--border);
  border-radius:var(--r);font-size:14px;font-weight:600;font-family:inherit;
  margin-top:16px;cursor:pointer;transition:all var(--t)}
button:hover{border-color:var(--border-h);color:var(--accent)}
button[type=submit]{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
button[type=submit]:hover{filter:brightness(1.10);transform:translateY(-1px)}
button.alt{background:transparent;border-color:var(--border);color:var(--text-2)}
button.alt:hover{color:var(--text);border-color:var(--border-h2);transform:none}
a.back{display:inline-flex;align-items:center;gap:6px;margin-top:14px;color:var(--text-2);
  font-size:13px} a.back:hover{color:var(--accent);text-decoration:none}
/* 价表「审核」那一栏钉在右缘 (刘霞 2026-09-22:「显示不全了, 在哪里可以设置一下?」)。
   栏位一多, 表格横向卷动, 最右边的审核钮就被切掉, 要一路卷到底才按得到。
   注意: 用 sticky 不是 fixed -- 它仍在表格流里, 直向卷动正常, 只有横向时才黏住。 */
td.stickright, th.stickright{position:sticky;right:0;z-index:2;background:var(--card);
  box-shadow:-6px 0 8px -6px rgba(0,0,0,.18)}
th.stickright{background:var(--bg-2,var(--card))}

/* 返回钮一律置顶 (王娟 2026-09-22)。_shell 会把 a.back 全部搬进这一条, 所以这里要把
   a.back 自己的 margin-top 归零, 并做成看得见的钮 —— 以前是表单最下面一行灰字。 */
.topback{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 12px}
.topback a.back{margin-top:0;padding:6px 12px;border:1px solid var(--border);border-radius:8px;
  background:var(--card);font-weight:600}
.topback a.back:hover{border-color:var(--border-h);color:var(--accent)}

/* ── 表格 ───────────────────────────────────────────────────────── */
table{width:100%;border-collapse:collapse;font-size:13px;margin-top:10px;
  font-variant-numeric:tabular-nums}
th,td{border-bottom:1px solid var(--border);padding:9px 10px;text-align:left}
th{background:transparent;color:var(--text-2);font-weight:500;font-size:12px;
  border-bottom:1px solid var(--border-strong);white-space:nowrap}
tr:last-child td{border-bottom:0}
tbody tr:hover td,table tr:hover td{background:var(--row-hover)}
.best{background:var(--accent-soft);font-weight:600}
.best td{color:var(--text)}
code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;
  background:var(--surface-2);border:1px solid var(--border);border-radius:5px;padding:1px 5px}

/* ── 状态 / 提示 ────────────────────────────────────────────────── */
.warn{background:var(--warn-bg);border-left:2px solid var(--warn);color:var(--warn-fg);
  padding:9px 12px;border-radius:0 var(--r) var(--r) 0;font-size:13px;margin:8px 0}
.dot{display:inline-block;width:7px;height:7px;border-radius:50%;flex:none;
  vertical-align:1px;margin-right:6px;background:var(--text-3)}
.dot.is-ok{background:var(--ok)} .dot.is-warn{background:var(--warn)}
.dot.is-bad{background:var(--bad)}
.badge{display:inline-flex;align-items:center;font-size:12px;font-weight:500;
  border-radius:20px;padding:3px 11px;white-space:nowrap}
.badge.is-ok{background:var(--ok-bg);color:var(--ok)}
.badge.is-warn{background:var(--warn-bg);color:var(--warn)}
.badge.is-bad{background:var(--bad-bg);color:var(--bad)}
.badge .dot{margin-right:5px}

/* ── 首页工具卡 ─────────────────────────────────────────────────── */
.tools{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media(max-width:640px){.tools{grid-template-columns:1fr}}
/* .tool 必须是最外层 <a> —— _shell 的角色过滤用 regex 砍整个 <a>, 包了 wrapper
   会让业助看到空壳卡 (tests/test_roles.py::test_whole_card_disappears_when_card_is_the_link)。 */
.tool{position:relative;display:block;background:var(--surface);border:1px solid var(--border);
  border-radius:var(--r-lg);padding:22px;color:var(--text);transition:all var(--t);box-shadow:var(--shadow)}
.tool:hover{border-color:var(--border-h);transform:translateY(-2px);text-decoration:none}
.tool .ico{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;
  border-radius:var(--r);background:var(--surface-2);color:var(--accent);margin-bottom:14px}
.tool .tt{font-size:16px;font-weight:600;color:var(--text);margin-bottom:4px}
.tool .td{font-size:12px;color:var(--text-2);line-height:1.6}
.tool .go{position:absolute;top:22px;right:20px;color:var(--text-3);transition:all var(--t)}
.tool:hover .go{color:var(--accent);transform:translateX(2px)}
/* QR 刻意保留白底 —— 深色底扫不出来 */
.qr{display:flex;align-items:center;gap:16px;max-width:380px;margin-left:auto}
.qr img{width:96px;height:96px;background:#fff;border-radius:8px;padding:6px;flex:none}
.qr .hint{margin:0;word-break:break-all}

/* ── AI 助填卡 (全站视觉焦点) ───────────────────────────────────── */
.card.ai{position:relative;padding:1px;border:0;overflow:hidden;
  background:linear-gradient(135deg,var(--grad1),var(--grad2))}
.card.ai>.inr{background:var(--surface);border-radius:13px;padding:20px}
.card.ai .tt svg{color:var(--accent)}
.shimmer{position:absolute;top:0;left:0;right:0;height:2px;opacity:0;z-index:2;
  background:linear-gradient(90deg,transparent,var(--accent),var(--accent-2),transparent);
  background-size:50% 100%;background-repeat:no-repeat}
.aiform.busy .shimmer{opacity:1;animation:slide 1.1s linear infinite}
@keyframes slide{from{background-position:-50% 0}to{background-position:150% 0}}
.aiinput{border:1px solid var(--border);border-radius:var(--r);background:var(--surface-2);
  overflow:hidden;transition:border-color var(--t)}
.aiinput:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px var(--focus)}
.aiinput textarea{border:0;background:transparent;border-radius:0}
.aiinput textarea:focus{box-shadow:none;border:0}
.aiform.busy .aiinput textarea{animation:pulse 1.4s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.55}}
/* 拖放区: 真的 file input 藏起来, 点 label 就叫得出原生选档 (不用 JS) */
.drop{display:flex;align-items:center;gap:8px;margin:0;padding:10px 12px;cursor:pointer;
  border-top:1px solid var(--border);font-size:12px;color:var(--text-2);
  transition:all var(--t)}
.drop:hover,.drop.over{color:var(--accent);background:var(--accent-soft)}
.drop .fname{margin-left:auto;color:var(--accent);font-size:12px;max-width:45%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* 必须写 button.btn-ai 不能只写 .btn-ai —— 上面 button[type=submit]
   的权重是 (0,1,1)，.btn-ai 只有 (0,1,0)，会被盖掉变成累色底。
   (2026-08-18 截图才看出渐层一直没生效) */
button.btn-ai{background:linear-gradient(135deg,var(--grad1),var(--grad2));color:var(--on-grad);
  border:0;font-weight:600}
button.btn-ai:hover{filter:brightness(1.08);transform:translateY(-1px);color:var(--on-grad)}
button.btn-ai:disabled{opacity:.7;cursor:wait;transform:none}
.spin{display:none;width:14px;height:14px;border:2px solid rgba(6,34,42,.30);
  border-top-color:var(--on-grad);border-radius:50%;animation:spin .7s linear infinite}
.aiform.busy .spin{display:inline-block}
.aiform.busy .btn-ai svg{display:none}
@keyframes spin{to{transform:rotate(360deg)}}

/* ── 带入/AI 提取的栏位 vs 系统预设值 ───────────────────────────
   (王娟 2026-08-14:「其它信息全部不对」— 其实是没带到的栏位在显示母档预设值,
    看起来跟提取值一样, 分不出哪些要核对)。
   data-ai 属性同时是 JS 状态讯号 (_DRAFT_JS 判断能否还原草稿 / _hadAI 切型提醒),
      只能加样式, 不可换成 class。 */
input[data-ai],select[data-ai],textarea[data-ai]{
  border-left:2px solid var(--accent);background-color:var(--accent-soft);
  animation:aiflash 1.5s ease-out}
@keyframes aiflash{from{background-color:var(--accent-flash)}}
.aitag{display:inline-flex;align-items:center;gap:3px;font-size:10px;font-weight:500;
  color:var(--accent);background:var(--accent-soft);border-radius:20px;
  padding:1px 7px;margin-left:6px;cursor:help}
.aitag svg{width:10px;height:10px}
.lgd{font-size:12px;color:var(--text-2);margin:-8px 0 16px}
.lgd i{display:inline-block;width:8px;height:8px;border-radius:2px;
  vertical-align:0;margin-right:5px;background:var(--accent)}

/* 业助原文横表 (王娟 2026-09-10) —— 窄栏、可横向卷动, 不撑破版面 */
.flattbl{border-collapse:collapse;font-size:12px;white-space:nowrap}
.flattbl th,.flattbl td{border:1px solid var(--line);padding:3px 7px;text-align:left}
.flattbl th{background:var(--surface-2);font-weight:600;position:sticky;top:0}
/* 逐笔分块 (James 2026-09-10: 名称长短不一, 折行後看不出哪几行是同一笔) */
.recblk{border-left:3px solid var(--line);padding:4px 0 4px 9px;margin:5px 0;font-size:12px;
        line-height:1.55;word-break:break-word}
.recblk:nth-child(even){background:var(--surface-2)}
.recno{font-weight:600;font-size:11px;opacity:.75;margin-bottom:1px}

/* ── 询价原文对照条 (王娟 2026-08-10: 往下拉能跟原文比对, 不用另开档案) ──
   position:sticky → 卷动时钉在顶端; <details> 原生收合, 不需要 JS (CSP 挡内联 script)。 */
.signsrc .srcbox{position:static}   /* 签核表一页多笔, 不要叠在一起钉住 (2026-09-17) */
.srcbox{position:sticky;top:52px;z-index:9;background:var(--surface-2);
  border:1px solid var(--border);border-left:2px solid var(--accent-2);
  border-radius:var(--r);padding:10px 14px;margin-bottom:16px}
.srcbox summary{cursor:pointer;font-weight:500;color:var(--accent-2);font-size:12px;
  list-style:none;padding:0}
.srcbox summary::before{content:none}
.srcbox summary::-webkit-details-marker{display:none}
/* 王娟 2026-09-01:「可以把资料框的高度留窄一点吗? 我的屏幕占了一半」→ 30vh 砍到 15vh */
.srctxt{max-height:15vh;overflow:auto;white-space:pre-wrap;word-break:break-word;
  font-size:12.5px;line-height:1.6;color:var(--text-2);margin-top:10px;
  border-top:1px solid var(--border);padding-top:10px}
/* 王娟 2026-09-16 (#454):「这个报价资料占据界面90%」—— 上面那条 15vh 只套在 .srctxt,
   而逐笔分块 (.recblk) 走的是另一条路, 完全没有上限。对照条是**拿来核对的**,
   不该比要填的表单还高, 所以这里给整块内容一个统一的天花板。 */
.srcscroll{max-height:15vh;overflow:auto;margin-top:10px;
  border-top:1px solid var(--border);padding-top:6px}
/* 批量清单格子里的收合 (James 2026-09-17: AI备注 / 缺栏原因 / 长阶梯) —— 原生 <details>, 不靠 JS */
details.cellfold{margin-top:2px}
details.cellfold>summary{cursor:pointer;color:var(--accent-2);font-size:11px;list-style:none;
  white-space:nowrap}
details.cellfold[open]>summary{margin-bottom:2px}

@media(max-width:900px){
  body{--side:64px}
  .side .logo span,.nv span{display:none}
  .nv{justify-content:center;padding:9px 0}
  .wrap{padding:16px 14px 40px}
  .row{gap:10px}
  /* 顶栏在窄萤幕会挤到换行 (52px 装不下) → 只留头像与登出 icon */
  .topbar{padding:0 12px;gap:8px}
  .ttl,.roletag,.uname,.ltxt{display:none}
}
