.app-confirm { width: min(440px, calc(100vw - 32px)); box-sizing: border-box; max-height: calc(100dvh - 48px); overflow: auto; margin: auto; padding: 24px; border: 1px solid var(--line); border-radius: 18px; background: var(--card); color: var(--ink); box-shadow: var(--sh-2); }
.app-confirm::backdrop { background: rgba(15,23,42,.42); }
.app-confirm__header { display: flex; align-items: center; justify-content: space-between; gap: 20px; }
.app-confirm__header h2 { font-size: 19px; font-weight: 600; margin: 0; }
.app-confirm__close { flex: none; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%; font-size: 24px; color: var(--gray); }
.app-confirm__close:hover { background: var(--bg); color: var(--ink); }
.app-confirm__close:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
#appConfirmMessage { margin: 18px 0 26px; line-height: 1.75; color: var(--ink-2); overflow-wrap: anywhere; }
.app-confirm__actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 12px; }
.app-confirm__danger { background: #b91c1c; border-color: #b91c1c; box-shadow: none; }
.app-confirm__danger:hover { background: #991b1b; border-color: #991b1b; box-shadow: none; }
@media (prefers-reduced-motion: reduce) { .app-confirm .btn { transition: none; } }
.app-prompt__body { margin: 20px 0 4px; }
.app-prompt__body input { width: 100%; box-sizing: border-box; min-height: 42px; padding: 10px 14px; font-size: 15px; color: var(--ink); background: var(--bg-2); border: 1px solid var(--line); border-radius: 10px; transition: .2s var(--ease); }
.app-prompt__body input:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 18%, transparent); }
.app-prompt .app-confirm__actions { margin-top: 20px; }
/* =========================================================
   弈算 2.0 · UI 预览样式表
   设计系统：Apple 风格 · 单一 Action Blue · 发丝分隔线 · 大量留白
   字体：Noto Sans SC（中文） / Inter（拉丁与数字）
   ========================================================= */

/* ---------- 1. 设计令牌 ---------- */
:root {
  --blue: #0066cc;
  --blue-600: #0057b3;
  --blue-400: #3391e6;
  --blue-050: #eaf2ff;
  --blue-100: #d6e4ff;

  --ink: #1d1d1f;
  --ink-2: #333336;
  --gray: #7a7a7a;
  --gray-2: #9a9a9a;
  --gray-3: #c7c7cc;

  --bg: #f5f5f7;
  --card: #ffffff;
  --line: #e4e4e7;
  --line-2: #f0f0f2;

  --green: #34c759;
  --green-d: #1a7f37;
  --red: #ff3b30;
  --amber: #ffb020;
  --amber-d: #b45309;

  --r-sm: 10px;
  --r-md: 14px;
  --r-lg: 18px;
  --r-pill: 999px;

  --sh-1: 0 1px 2px rgba(0, 0, 0, .04), 0 6px 18px rgba(0, 0, 0, .05);
  --sh-2: 0 2px 6px rgba(0, 0, 0, .06), 0 18px 44px rgba(0, 0, 0, .10);
  --sh-blue: 0 8px 24px rgba(0, 102, 204, .24);

  --ease: cubic-bezier(.22, .8, .28, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-back: cubic-bezier(.34, 1.56, .64, 1);

  /* 纯系统字体栈（内网部署，不依赖任何 CDN） */
  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
          "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans SC", sans-serif;
  --font-num: "Inter", -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;

  --sb-w: 240px;
  --tb-h: 64px;
}

/* 深色模式 */
[data-theme="dark"] {
  --blue: #3b93f7;
  --blue-600: #2a7fe0;
  --blue-050: #12233a;
  --blue-100: #1b3555;
  --ink: #f2f2f4;
  --ink-2: #d8d8dd;
  --gray: #9a9aa2;
  --gray-2: #7c7c85;
  --gray-3: #3a3a41;
  --bg: #0f1115;
  --card: #171a20;
  --line: #262a32;
  --line-2: #1e222a;
  --green: #30d158;
  --green-d: #4ade80;
  --red: #ff5b52;
  --amber: #ffc247;
  --amber-d: #f0b429;
  --sh-1: 0 1px 2px rgba(0, 0, 0, .5), 0 8px 22px rgba(0, 0, 0, .45);
  --sh-2: 0 4px 12px rgba(0, 0, 0, .55), 0 24px 56px rgba(0, 0, 0, .6);
  --sh-blue: 0 10px 30px rgba(59, 147, 247, .3);
}

/* ---------- 2. 基础重置 ---------- */
*, *::before, *::after { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  /* 预留滚动条槽位，避免内容增多时页面整体向左跳动 */
  scrollbar-gutter: stable;
}

body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--ink);
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow: hidden;
  transition: background-color .45s var(--ease), color .45s var(--ease);
}

button, input, select, textarea {
  font-family: inherit;
  font-size: inherit;
  color: inherit;
}

button { border: 0; background: none; cursor: pointer; }
a { color: var(--blue); text-decoration: none; }
ul { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, h4, p { margin: 0; }

::selection { background: var(--blue); color: #fff; }

/* 细滚动条 */
.scroll { scrollbar-width: thin; scrollbar-color: var(--gray-3) transparent; }
.scroll::-webkit-scrollbar { width: 8px; height: 8px; }
.scroll::-webkit-scrollbar-thumb {
  background: var(--gray-3);
  border-radius: 99px;
  border: 2px solid transparent;
  background-clip: content-box;
}
.scroll::-webkit-scrollbar-thumb:hover { background: var(--gray-2); background-clip: content-box; }
.scroll::-webkit-scrollbar-track { background: transparent; }

/* 数字统一用 Inter，紧字距 */
.num, .kpi__value, td.num, .amount {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
}

/* ---------- 3. 全局装饰：光标光晕 / 滚动进度 / 噪点 ---------- */
.cursor-glow {
  position: fixed;
  top: 0; left: 0;
  width: 460px; height: 460px;
  margin: -230px 0 0 -230px;
  pointer-events: none;
  z-index: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(0, 102, 204, .085) 0%, rgba(0, 102, 204, 0) 68%);
  opacity: 0;
  transition: opacity .6s var(--ease);
  will-change: transform;
}
body.has-cursor .cursor-glow { opacity: 1; }

.scroll-progress {
  position: fixed;
  top: 0; left: 0;
  height: 2px;
  width: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--blue), var(--blue-400));
  z-index: 90;
  transition: transform .12s linear;
}

/* ---------- 4. 首屏加载动画 ---------- */
.loader {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 26px;
  background: var(--bg);
  transition: opacity .7s var(--ease), visibility .7s;
}
.loader.is-done { opacity: 0; visibility: hidden; }

.loader__mark {
  position: relative;
  width: 74px; height: 74px;
  display: grid;
  place-items: center;
}
.loader__ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid var(--line);
  border-top-color: var(--blue);
  animation: spin 1s linear infinite;
}
.loader__ring:nth-child(2) {
  inset: 10px;
  border-top-color: transparent;
  border-left-color: var(--blue-400);
  animation-duration: 1.4s;
  animation-direction: reverse;
}
.loader__dot {
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--blue);
  animation: breathe 1.6s var(--ease) infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes breathe {
  0%, 100% { transform: scale(.75); opacity: .65; }
  50%      { transform: scale(1.15); opacity: 1; }
}

.loader__text {
  font-size: 13px;
  letter-spacing: .32em;
  color: var(--gray);
  text-transform: uppercase;
  animation: flicker 1.8s var(--ease) infinite;
}
@keyframes flicker { 0%, 100% { opacity: .5; } 50% { opacity: 1; } }

.loader__bar {
  width: 190px; height: 3px;
  border-radius: 99px;
  background: var(--line);
  overflow: hidden;
}
.loader__bar i {
  display: block;
  height: 100%;
  width: 40%;
  border-radius: 99px;
  background: var(--blue);
  animation: slide 1.15s var(--ease-out) infinite;
}
@keyframes slide {
  0%   { transform: translateX(-110%); }
  100% { transform: translateX(310%); }
}

/* 登录 -> 应用 的卷帘过渡 */
.curtain {
  position: fixed;
  inset: 0;
  z-index: 150;
  pointer-events: none;
  background: var(--blue);
  transform: scaleY(0);
  transform-origin: 50% 100%;
}
.curtain.is-in  { animation: curtainIn .62s var(--ease) forwards; }
.curtain.is-out { animation: curtainOut .62s var(--ease) forwards; }
@keyframes curtainIn {
  0%   { transform: scaleY(0); transform-origin: 50% 100%; }
  50%  { transform: scaleY(1); transform-origin: 50% 100%; }
  51%  { transform: scaleY(1); transform-origin: 50% 0%; }
  100% { transform: scaleY(0); transform-origin: 50% 0%; }
}
@keyframes curtainOut {
  0%   { transform: scaleY(0); transform-origin: 50% 0%; }
  49%  { transform: scaleY(1); transform-origin: 50% 0%; }
  50%  { transform: scaleY(1); transform-origin: 50% 100%; }
  100% { transform: scaleY(0); transform-origin: 50% 100%; }
}

/* ---------- 5. 登录页 ---------- */
.auth {
  position: fixed;
  inset: 0;
  display: grid;
  grid-template-columns: 520px 1fr;
  z-index: 10;
  background: var(--card);
}
.auth.is-hidden { display: none; }

.auth__brand {
  position: relative;
  overflow: hidden;
  background: var(--blue) center/cover no-repeat;
  color: #fff;
  padding: 96px 60px;
  display: flex;
  flex-direction: column;
}
.auth__brand-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, rgba(0, 40, 100, .55) 0%, rgba(0, 80, 170, .25) 50%, rgba(0, 102, 204, .15) 100%);
  z-index: 1;
}

.auth__brand > *:not(.auth__brand-overlay) { position: relative; z-index: 2; }

.auth__mark {
  width: 76px; height: 76px; margin-bottom: 20px;
}
.auth__mark img {
  width: 100%; height: 100%; display: block;
  filter: drop-shadow(0 12px 28px rgba(0, 20, 60, .45));
}
.auth__logo {
  font-size: 46px;
  font-weight: 700;
  letter-spacing: -.5px;
  line-height: 1.15;
}
.auth__tagline {
  margin-top: 8px;
  font-size: 21px;
  font-weight: 600;
}
.auth__desc {
  margin-top: 18px;
  font-size: 15px;
  color: #d6e4ff;
  line-height: 1.7;
}

.auth__feats { margin-top: 96px; display: grid; gap: 16px; }
.auth__feat {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 15px;
  color: #c6dbff;
  opacity: 0;
  transform: translateX(-14px);
  animation: featIn .7s var(--ease-out) forwards;
}
.auth__feat:nth-child(1) { animation-delay: .35s; }
.auth__feat:nth-child(2) { animation-delay: .5s; }
.auth__feat:nth-child(3) { animation-delay: .65s; }
@keyframes featIn { to { opacity: 1; transform: none; } }

.auth__feat i {
  width: 22px; height: 22px;
  flex: none;
  border-radius: 50%;
  border: 1.5px solid rgba(255, 255, 255, .55);
  display: grid;
  place-items: center;
}
.auth__feat svg { width: 12px; height: 12px; stroke: #fff; fill: none; stroke-width: 2.4; }

.auth__ver {
  margin-top: auto;
  font-size: 12px;
  color: #bfd6ff;
  letter-spacing: .04em;
}

/* ---------- 5b. 登录页左栏：生产端 lg2-brand 结构 ---------- */
.auth__brand {
  padding: 58px 56px 40px;
  /* 注意：此处不可再叠 login-brand.png —— 该图本身就是生产端左栏截图，
     与下面的 lg2 DOM 文字重合会出现「两套左栏」重影。 */
  background-image: linear-gradient(135deg, #0a4a8c 0%, #0066cc 55%, #1a7fe0 100%);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

/* 「弈」字底纹水印 */
.auth__brand > .brand-watermark {
  position: absolute;
  right: -46px;
  bottom: -84px;
  z-index: 1;
  font-family: "Noto Sans SC", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
  font-size: 300px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: -8px;
  color: #fff;
  opacity: .07;
  pointer-events: none;
  user-select: none;
  animation: wmDrift 18s ease-in-out infinite alternate;
}
@keyframes wmDrift {
  from { transform: translate3d(0, 0, 0) scale(1);      opacity: .055; }
  to   { transform: translate3d(-14px, -18px, 0) scale(1.04); opacity: .085; }
}

/* 右上 / 左下 若隐若现的柔光圆 */
.auth__brand > .brand-orb {
  position: absolute;
  z-index: 1;
  border-radius: 50%;
  pointer-events: none;
  background: radial-gradient(circle at 50% 50%,
              rgba(255, 255, 255, .20) 0%,
              rgba(255, 255, 255, .10) 42%,
              rgba(255, 255, 255, 0) 72%);
  animation: orbBreathe 13s ease-in-out infinite alternate;
}
.auth__brand > .brand-orb--tr { width: 260px; height: 260px; top: -84px;    right: -66px; }
.auth__brand > .brand-orb--bl { width: 340px; height: 340px; bottom: -124px; left: -104px;
  opacity: .82; animation-duration: 17s; animation-delay: -4s; }
@keyframes orbBreathe {
  from { transform: translate3d(0, 0, 0) scale(1);         opacity: .5; }
  to   { transform: translate3d(18px, -22px, 0) scale(1.12); opacity: 1; }
}

/* lg2 内容排版（沿用生产端登录页左栏） */
.auth__brand .lg2-logo { display: flex; align-items: center; gap: 12px; }
.auth__brand .lg2-logo .mark {
  width: 48px; height: 48px; border-radius: 12px; background: transparent;
  display: inline-flex; align-items: center; justify-content: center;
  overflow: hidden;
  box-shadow: 0 6px 20px rgba(0, 40, 100, .35);
}
.auth__brand .lg2-logo .mark img { width: 100%; height: 100%; display: block; }
.auth__brand .lg2-logo .name {
  font-size: 34px; font-weight: 600; letter-spacing: 2px;
  text-shadow: 0 2px 12px rgba(15, 23, 42, .28);
}
.auth__brand .lg2-eyebrow {
  margin-top: 50px; font-size: 12px; font-weight: 600;
  letter-spacing: 2px; color: #bfdbfe; text-transform: uppercase;
}
.auth__brand .lg2-title {
  margin-top: 16px; font-size: 40px; font-weight: 800;
  line-height: 1.1; letter-spacing: 1px;
}
.auth__brand .lg2-title-sub {
  display: block; margin-top: 8px;
  font-size: 21px; font-weight: 600; letter-spacing: 3px; color: #dbeafe;
}
.auth__brand .lg2-subtitle { margin-top: 14px; font-size: 14px; color: #dbeafe; }
.auth__brand .lg2-rule {
  width: 132px; height: 2px; border: 0;
  background: rgba(147, 197, 253, .85); margin: 28px 0 30px;
}
.auth__brand .lg2-feats { display: flex; flex-direction: column; gap: 16px; }
.auth__brand .lg2-feat {
  display: flex; align-items: center; gap: 12px;
  font-size: 15px; font-weight: 500; color: #eff6ff;
  opacity: 0; transform: translateX(-14px);
  animation: featIn .7s var(--ease-out) forwards;
}
.auth__brand .lg2-feat:nth-child(1) { animation-delay: .5s; }
.auth__brand .lg2-feat:nth-child(2) { animation-delay: .65s; }
.auth__brand .lg2-feat:nth-child(3) { animation-delay: .8s; }
.auth__brand .lg2-feat i {
  width: 30px; height: 30px; flex: none; border-radius: 50%;
  background: rgba(255, 255, 255, .16); display: grid; place-items: center;
}
.auth__brand .lg2-feat svg {
  width: 16px; height: 16px; stroke: #fff; fill: none;
  stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round;
}
.auth__brand .lg2-foot { margin-top: auto; padding-top: 36px; }
.auth__brand .lg2-foot .c1 { font-size: 14px; font-weight: 600; color: #fff; }
.auth__brand .lg2-foot .c2 { margin-top: 6px; font-size: 12px; color: #bfdbfe; }

/* ---------- 5c. 登录页左栏：悬停动画 + 禁止选中（2026-09-19） ---------- */
/* 品牌展示区一律禁止选中文字（拖拽不再出现蓝色选区） */
.auth__brand { -webkit-user-select: none; user-select: none; }

/* LOGO 徽标：悬停轻浮 + 微倾 */
.auth__brand .lg2-logo .mark {
  transition: transform .45s var(--ease-out), box-shadow .45s var(--ease-out);
  cursor: default;
}
.auth__brand .lg2-logo:hover .mark {
  transform: translateY(-3px) rotate(-4deg);
  box-shadow: 0 12px 30px rgba(0, 24, 64, .38);
}
.auth__brand .lg2-logo .name { cursor: default; }

/* 特性行：玻璃亮条滑入 + 图标放大带光晕
   注意：lg2-feat 本体带 featIn 入场动画（forwards 填充会压住 :hover 的
   transform/opacity），因此悬停位移走 padding 过渡，transform 只动
   没有动画的子元素（i / svg）。 */
.auth__brand .lg2-feat {
  padding: 6px 10px;
  margin: -6px -10px;
  border-radius: 12px;
  cursor: default;
  transition: background-color .3s var(--ease-out), padding .3s var(--ease-out);
}
.auth__brand .lg2-feat:hover {
  background: rgba(255, 255, 255, .12);
  padding-left: 16px;
}
.auth__brand .lg2-feat i {
  transition: transform .35s var(--ease-back), background-color .3s var(--ease-out), box-shadow .35s var(--ease-out);
}
.auth__brand .lg2-feat:hover i {
  transform: scale(1.14);
  background: rgba(255, 255, 255, .30);
  box-shadow: 0 0 0 6px rgba(255, 255, 255, .10);
}
.auth__brand .lg2-feat svg {
  transition: transform .35s var(--ease-out);
}
.auth__brand .lg2-feat:hover svg { transform: scale(1.1); }

@media (prefers-reduced-motion: reduce) {
  .auth__brand > .brand-watermark,
  .auth__brand > .brand-orb { animation: none !important; }
  .auth__brand .lg2-logo .mark,
  .auth__brand .lg2-feat,
  .auth__brand .lg2-feat i,
  .auth__brand .lg2-feat svg { transition: none !important; }
  .reg2 { animation: none !important; }
}

/* ---------- 5d. 注册弹窗（Apple 风格重做，2026-09-19） ---------- */
/* 注册弹窗整体禁止选中文字（与登录左栏同规）；输入框例外，保可编辑。
   ⚠️ 2026-09-28：全局基线（app.css 末尾）已统一禁选并放行 input/textarea/contenteditable，
      这里的 `.reg2 .field__input { user-select: text }` 已由全局白名单覆盖，**保留无害**
      （删掉也能正常工作）；两条 `.reg2` 禁选规则同理，仅为「不依赖末尾层」的历史保险。 */
.reg2 { -webkit-user-select: none; user-select: none; }
.reg2 .field__input { -webkit-user-select: text; user-select: text; }

/* 叠加 .modal 基类（定位 / 居中 / 入场动画），仅覆盖尺寸与留白 */
.reg2 {
  width: min(430px, 100%);
  padding: 34px 34px 24px;
  border-radius: 22px;
}
.reg2__close { position: absolute; top: 14px; right: 14px; }

/* 头部：渐变徽章 + 居中标题 */
.reg2__head { text-align: center; }
.reg2__badge {
  width: 56px; height: 56px;
  margin: 0 auto;
  border-radius: 16px;
  display: grid;
  place-items: center;
  background: linear-gradient(135deg, #0a4a8c 0%, #0066cc 55%, #1a7fe0 100%);
  box-shadow: 0 10px 24px rgba(0, 102, 204, .30);
}
.reg2__badge svg {
  width: 26px; height: 26px;
  fill: none; stroke: #fff; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.reg2__title { margin-top: 14px; font-size: 22px; font-weight: 600; letter-spacing: -.2px; color: var(--ink); }
.reg2__sub { margin-top: 5px; font-size: 13.5px; color: var(--gray-2); }

/* 浮动标签字段：帮助文案常显（灰色），校验失败转红 */
.reg2 .field__hint { opacity: 1; transform: none; color: var(--gray-2); }
.reg2 .field.is-error .field__hint { color: var(--red); }

/* 浮动标签字段：帮助文案常显（灰色），校验失败转红；
   未聚焦未填写时输入框显示 placeholder 提示（与登录页同款，垂直居中） */
.reg2 .field__hint { opacity: 1; transform: none; color: var(--gray-2); }
.reg2 .field.is-error .field__hint { color: var(--red); }
.reg2 .field__input:placeholder-shown:not(:focus) {
  padding-top: 12px;
  padding-bottom: 12px;
}
/* 聚焦横线钉在输入框底端内缘（.field 容器含 hint，bottom:0 会悬空，
   改为 top 定位到 52px 输入框的底部内侧），文字下方留一点距离 */
.reg2 .field__line {
  top: 50px;
  bottom: auto;
}

/* 角色分段控件（Apple Segmented Control + 液态玻璃滑块）
   滑块是独立 absolute 元素，点击时 translateX 平移过去（弹性过渡），
   按钮本身只负责文字颜色/字重，背景一律交给滑块。
   底衬三色渐变（蓝→紫→橙）过渡，滑块移到哪一段就折射哪段颜色，
   液态玻璃的 blur/saturate 效果因此可见。 */
.reg2__seg-label { margin: 20px 0 8px; font-size: 12.5px; font-weight: 600; letter-spacing: .3px; color: var(--gray-2); }
.reg2__seg {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
  background: linear-gradient(90deg, #dbeafe 0%, #ede9fe 50%, #ffedd5 100%);
  border-radius: 12px;
  padding: 4px;
}
[data-theme="dark"] .reg2__seg {
  background: linear-gradient(90deg, #0c2a4a 0%, #241a46 50%, #46280f 100%);
}
.reg2__seg-thumb {
  position: absolute;
  top: 4px; left: 0;
  /* 宽度与横向位置由 JS 管理（placeThumb）：每边比槽位内缩 8px，
     两段式回弹的过冲量被内缩吸收，不会溢出容器边缘 */
  height: calc(100% - 8px);
  border-radius: 14px;
  background: transparent;
  backdrop-filter: blur(10px) saturate(170%);
  -webkit-backdrop-filter: blur(10px) saturate(170%);
  box-shadow: 0 1px 2px rgba(15, 23, 42, .18),
              0 4px 12px rgba(15, 23, 42, .20),
              0 10px 24px -6px rgba(15, 23, 42, .16),
              0 0 0 .5px rgba(15, 23, 42, .06),
              inset 0 1.5px 0 rgba(255, 255, 255, .95),
              inset 0 -2px 4px rgba(255, 255, 255, .38),
              inset 2px 0 4px rgba(255, 255, 255, .22),
              inset -2px 0 4px rgba(255, 255, 255, .22);
  pointer-events: none;
}
[data-theme="dark"] .reg2__seg-thumb {
  background: transparent;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .40),
              0 0 0 .5px rgba(255, 255, 255, .08),
              inset 0 1px 0 rgba(255, 255, 255, .18),
              inset 0 -1px 0 rgba(255, 255, 255, .06);
}
/* 镜面反射：斜向光带扫过（左上强高光 → 中部透明 → 右下弱回光），
   叠在折射层之上，构成「反射 + 折射」完整液态玻璃质感 */
.reg2__seg-thumb::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(115deg,
              rgba(255, 255, 255, .65) 0%,
              rgba(255, 255, 255, .24) 28%,
              rgba(255, 255, 255, .04) 46%,
              rgba(255, 255, 255, 0) 58%,
              rgba(255, 255, 255, .16) 78%,
              rgba(255, 255, 255, .30) 100%);
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .reg2__seg-thumb { transition: none !important; }
}
.reg2__seg-btn {
  position: relative;
  z-index: 1;
  height: 44px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  font-size: 14px;
  font-weight: 500;
  color: var(--gray);
  cursor: pointer;
  transition: color .22s var(--ease), transform .18s var(--ease-back);
}
.reg2__seg-btn:hover { color: var(--ink-2); }
.reg2__seg-btn:active { transform: scale(.96); }
.reg2__seg-btn.is-active {
  color: var(--ink);
  font-weight: 600;
}

/* 签名上传：虚线拖放区，选中后转实线 + 对勾 */
.reg2__upload {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 16px;
  border: 1.5px dashed var(--gray-3);
  border-radius: 12px;
  background: var(--bg);
  color: var(--gray);
  font-size: 13.5px;
  line-height: 1.5;
  cursor: pointer;
  text-align: left;
  transition: border-color .22s var(--ease), background-color .22s var(--ease), color .22s var(--ease);
}
.reg2__upload:hover { border-color: var(--blue); color: var(--blue); background: var(--blue-050); }
.reg2__upload svg {
  width: 20px; height: 20px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
.reg2__upload .reg2__upload-check { display: none; stroke: #34c759; }
.reg2__upload em { font-style: normal; font-size: 12px; color: var(--gray-2); }
.reg2__upload.is-chosen {
  border-style: solid;
  border-color: var(--blue);
  background: var(--blue-050);
  color: var(--ink);
}
.reg2__upload.is-chosen .reg2__upload-ic { display: none; }
.reg2__upload.is-chosen .reg2__upload-check { display: block; }
.reg2__upload.is-chosen em { color: var(--gray-2); }

/* 错误行 + 提交按钮 + 底部说明 */
.reg2__error { min-height: 18px; margin-top: 12px; font-size: 13px; color: var(--red); text-align: center; }
.reg2__submit[disabled] { opacity: .6; cursor: not-allowed; }
.reg2__legal { margin-top: 12px; font-size: 12px; color: var(--gray-2); text-align: center; line-height: 1.6; }

/* 右侧表单区 */
.auth__panel {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--card);
}
.auth__form {
  width: 360px;
  opacity: 0;
  transform: translateY(18px);
  animation: formIn .8s var(--ease-out) .15s forwards;
}
@keyframes formIn { to { opacity: 1; transform: none; } }

.auth__title { font-size: 34px; font-weight: 600; letter-spacing: -.4px; }
.auth__sub   { margin-top: 6px; font-size: 15px; color: var(--gray); }

/* 浮动标签输入 */
.field { position: relative; margin-top: 26px; }
.field__input {
  width: 100%;
  height: 52px;
  padding: 18px 44px 6px 16px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--bg);
  outline: none;
  font-size: 15px;
  transition: border-color .25s var(--ease), box-shadow .25s var(--ease), background-color .25s var(--ease);
}
.field__input:hover { border-color: var(--gray-3); }
.field__input:focus {
  border-color: var(--blue);
  background: var(--card);
  box-shadow: 0 0 0 4px rgba(0, 102, 204, .12);
}
.field__input::placeholder { color: var(--gray-2); opacity: 1; }
.field.is-focus .field__input::placeholder { color: transparent; }
/* Empty login prompts stay centered; focused fields reserve space for their label. */
#username.field__input:placeholder-shown:not(:focus),
#password.field__input:placeholder-shown:not(:focus) {
  padding-top: 12px;
  padding-bottom: 12px;
}

/* Edge/IE 会给 password 自动添加眼睛；项目已有自定义按钮，因此隐藏原生控件。 */
.field__input[type="password"]::-ms-reveal,
.field__input[type="password"]::-ms-clear { display: none; }
.field__label {
  position: absolute;
  left: 17px;
  top: 16px;
  font-size: 15px;
  color: var(--gray-2);
  pointer-events: none;
  transform-origin: 0 50%;
  transition: transform .22s var(--ease), color .22s var(--ease);
}
.field.is-filled .field__label,
.field__input:focus + .field__label {
  transform: translateY(-11px) scale(.76);
  color: var(--blue);
}
.field:not(.is-focus):not(.is-filled) .field__label { opacity: 0; }

.auth__register {
  display: block;
  width: 100%;
  margin: 14px 0 0;
  padding: 8px;
  color: var(--blue);
  font-size: 14px;
  background: transparent;
  border: 0;
  cursor: pointer;
}
.auth__register:hover { text-decoration: underline; }
.field__line {
  position: absolute;
  left: 16px; right: 16px;
  bottom: 0;
  height: 2px;
  background: var(--blue);
  transform: scaleX(0);
  transition: transform .32s var(--ease-out);
}
.field.is-focus .field__line { transform: scaleX(1); }

.field__eye {
  position: absolute;
  right: 12px; top: 14px;
  width: 26px; height: 26px;
  display: grid; place-items: center;
  color: var(--gray-2);
  border-radius: 8px;
  transition: color .2s, background-color .2s, transform .2s var(--ease-back);
}
.field__eye:hover { color: var(--blue); background: var(--blue-050); transform: scale(1.1); }
.field__eye:active { transform: scale(.92); }
.field__eye svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.7; }

/* 错误/成功 反馈 */
.field.is-error .field__input {
  border-color: var(--red);
  box-shadow: 0 0 0 4px rgba(255, 59, 48, .12);
  animation: shake .42s var(--ease);
}
@keyframes shake {
  10%, 90% { transform: translateX(-2px); }
  20%, 80% { transform: translateX(4px); }
  30%, 50%, 70% { transform: translateX(-7px); }
  40%, 60% { transform: translateX(7px); }
}
.field__hint {
  margin-top: 6px;
  font-size: 12px;
  color: var(--red);
  opacity: 0;
  transform: translateY(-4px);
  transition: .25s var(--ease);
}
.field.is-error .field__hint { opacity: 1; transform: none; }

.auth__row {
  margin-top: 18px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

/* 自定义勾选框 */
.check {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  cursor: pointer;
  font-size: 14px;
  color: var(--ink-2);
  user-select: none;
}
.check input { position: absolute; opacity: 0; width: 0; height: 0; }
.check__box {
  width: 18px; height: 18px;
  border: 1.5px solid var(--gray-3);
  border-radius: 5px;
  display: grid;
  place-items: center;
  transition: background-color .2s var(--ease), border-color .2s var(--ease), transform .2s var(--ease-back);
}
.check:hover .check__box { border-color: var(--blue); transform: scale(1.08); }
.check svg {
  width: 12px; height: 12px;
  fill: none; stroke: #fff; stroke-width: 2.6;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 18; stroke-dashoffset: 18;
  transition: stroke-dashoffset .3s var(--ease-out) .05s;
}
.check input:checked + .check__box { background: var(--blue); border-color: var(--blue); }
.check input:checked + .check__box svg { stroke-dashoffset: 0; }
.check input:focus-visible + .check__box { box-shadow: 0 0 0 4px rgba(0, 102, 204, .18); }

.link-btn {
  font-size: 14px;
  color: var(--blue);
  position: relative;
  transition: opacity .2s;
}
.link-btn::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -2px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform .3s var(--ease-out);
}
.link-btn:hover::after { transform: scaleX(1); }

/* ---------- 6. 按钮（胶囊 + 波纹 + 按压） ---------- */
.btn {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 44px;
  padding: 0 22px;
  border-radius: var(--r-pill);
  font-size: 15px;
  font-weight: 500;
  color: var(--ink-2);
  background: var(--card);
  border: 1px solid var(--line);
  transition: transform .18s var(--ease-back), box-shadow .28s var(--ease),
              background-color .25s var(--ease), color .25s var(--ease), border-color .25s var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.btn:hover { transform: translateY(-1.5px); box-shadow: var(--sh-1); border-color: var(--gray-3); }
.btn:active { transform: translateY(0) scale(.975); box-shadow: none; }
.btn:focus-visible { outline: 3px solid color-mix(in srgb, var(--blue) 34%, transparent); outline-offset: 3px; }

.btn--primary {
  background: var(--blue);
  color: #fff;
  border-color: transparent;
  box-shadow: var(--sh-blue);
}
.btn--primary:hover { background: var(--blue-600); box-shadow: 0 12px 30px rgba(0, 102, 204, .34); }
.btn--primary:active { background: var(--blue-600); }

/* 正向完成动作（如「打印」）：实心绿，与合格 / 已审核同色系。
   底色用绿加深档，保证白字对比度；深色模式另给一档更深的绿。 */
.btn--green {
  background: var(--green-d);
  color: #fff;
  border-color: transparent;
  box-shadow: 0 8px 24px color-mix(in srgb, var(--green-d) 26%, transparent);
}
.btn--green:hover { background: color-mix(in srgb, var(--green-d) 88%, #000); box-shadow: 0 12px 30px color-mix(in srgb, var(--green-d) 34%, transparent); }
.btn--green:active { background: color-mix(in srgb, var(--green-d) 78%, #000); box-shadow: none; }
.btn--green:focus-visible { outline-color: color-mix(in srgb, var(--green-d) 38%, transparent); }
[data-theme="dark"] .btn--green { background: #1f9d4a; box-shadow: 0 8px 24px rgba(31, 157, 74, .3); }
[data-theme="dark"] .btn--green:hover { background: #25b357; }

.btn--block { width: 100%; }
.btn--lg { height: 50px; font-size: 16px; }
.btn--sm { height: 34px; padding: 0 16px; font-size: 13px; }
.btn--ghost { background: transparent; border-color: transparent; color: var(--blue); }
.btn--ghost:hover { background: var(--blue-050); box-shadow: none; border-color: transparent; }

.btn.is-loading { color: transparent !important; pointer-events: none; }
.btn.is-loading::after {
  content: "";
  position: absolute;
  width: 17px; height: 17px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, .35);
  border-top-color: #fff;
  animation: spin .7s linear infinite;
}
.btn:not(.btn--primary).is-loading::after {
  border-color: var(--line);
  border-top-color: var(--blue);
}

/* 波纹 */
.ripple {
  position: absolute;
  border-radius: 50%;
  transform: scale(0);
  background: currentColor;
  opacity: .28;
  pointer-events: none;
  animation: rippleOut .62s var(--ease-out) forwards;
}
@keyframes rippleOut {
  to { transform: scale(2.6); opacity: 0; }
}

/* 磁吸容器 */
.magnetic { display: inline-flex; will-change: transform; transition: transform .35s var(--ease-out); }

.auth__alt {
  margin: 26px 0;
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--gray-2);
  font-size: 13px;
}
.auth__alt::before, .auth__alt::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}
.auth__foot {
  margin-top: 26px;
  text-align: center;
  font-size: 12px;
  color: var(--gray-2);
}
.auth__demo {
  margin-top: 14px;
  padding: 10px 14px;
  border-radius: var(--r-sm);
  background: var(--bg);
  border: 1px dashed var(--line);
  font-size: 12px;
  color: var(--gray);
  text-align: center;
}
.auth__demo b { color: var(--blue); font-weight: 600; }

/* ---------- 7. 应用框架：侧边栏 ---------- */
.app {
  position: fixed;
  inset: 0;
  display: grid;
  grid-template-columns: var(--sb-w) 1fr;
  opacity: 0;
  transition: opacity .5s var(--ease);
}
.app.is-visible { opacity: 1; }
.app.is-behind { display: none; }

.sidebar {
  position: relative;
  background: var(--card);
  border-right: 1px solid var(--line);
  padding: 22px 12px;
  display: flex;
  flex-direction: column;
  z-index: 20;
  transition: background-color .45s var(--ease), border-color .45s var(--ease);
}

.sidebar__brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 10px 20px;
}
.sidebar__logo {
  width: 32px; height: 32px;
  border-radius: 9px;
  background: var(--blue);
  display: grid;
  place-items: center;
  overflow: hidden;
  color: #fff;
  font-size: 15px;
  font-weight: 700;
  box-shadow: var(--sh-blue);
  transition: transform .5s var(--ease-back);
}
.sidebar__logo img { width: 100%; height: 100%; display: block; }
.sidebar__brand:hover .sidebar__logo { transform: rotate(-8deg) scale(1.08); }
.sidebar__name { font-size: 17px; font-weight: 700; letter-spacing: -.3px; }
.sidebar__sub { font-size: 11px; color: var(--gray-2); letter-spacing: .06em; }

.nav { position: relative; display: grid; gap: 2px; }
.nav__indicator {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 40px;
  border-radius: var(--r-sm);
  /* 淡蓝液态玻璃（2026-09-23）：半透明淡蓝底 + 玻璃描边 + 内高光 + 浮起阴影
     ⛔ 只用 backdrop-filter，禁止 filter:url()（历史教训：software 栅格化导致全站卡顿）。
     ⚠️ JS 只写 height / transform，本规则可安全改配色，不影响滑动逻辑。 */
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--blue-050) 94%, #fff) 0%,
    color-mix(in srgb, var(--blue-100) 74%, transparent) 54%,
    color-mix(in srgb, var(--blue-050) 90%, #fff) 100%);
  border: 1px solid color-mix(in srgb, var(--blue) 12%, transparent);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .92),
    inset 0 -1px 1px rgba(0, 102, 204, .07),
    0 6px 18px rgba(0, 102, 204, .10),
    0 1px 2px rgba(0, 102, 204, .06);
  backdrop-filter: blur(12px) saturate(175%);
  -webkit-backdrop-filter: blur(12px) saturate(175%);
  transform: translateY(0);
  transition: transform .42s var(--ease-back), height .3s var(--ease);
  overflow: hidden;
  z-index: 0;
}
/* 斜向反光带：模拟液态玻璃的折射高光 */
.nav__indicator::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(102deg,
    rgba(255, 255, 255, .62) 0%,
    rgba(255, 255, 255, .16) 28%,
    rgba(255, 255, 255, 0) 50%,
    rgba(255, 255, 255, .2) 76%,
    rgba(255, 255, 255, .46) 100%);
  pointer-events: none;
}
/* 顶缘受光细线：玻璃上沿的镜面收边 */
.nav__indicator::after {
  content: "";
  position: absolute;
  top: 0;
  left: 10%;
  right: 10%;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .95), transparent);
  pointer-events: none;
}
[data-theme="dark"] .nav__indicator {
  border-color: color-mix(in srgb, var(--blue) 26%, transparent);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .16),
    inset 0 -1px 1px rgba(0, 0, 0, .3),
    0 6px 18px rgba(0, 0, 0, .32);
}
[data-theme="dark"] .nav__indicator::before { opacity: .5; }
[data-theme="dark"] .nav__indicator::after { opacity: .35; }
.nav__item {
  position: relative;
  z-index: 1;
  height: 40px;
  padding: 0 14px;
  border-radius: var(--r-sm);
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 14px;
  color: var(--ink-2);
  transition: color .25s var(--ease), padding-left .3s var(--ease);
  width: 100%;
  text-align: left;
}
.nav__item:hover { color: var(--blue); padding-left: 18px; }
.nav__item.is-active { color: var(--blue); font-weight: 600; }
.nav__item svg {
  width: 19px; height: 19px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform .4s var(--ease-back);
}
.nav__item:hover svg { transform: scale(1.14); }
.nav__item.is-active svg { stroke-width: 1.9; }
.nav__badge {
  margin-left: auto;
  min-width: 20px; height: 20px;
  padding: 0 6px;
  border-radius: var(--r-pill);
  /* 2026-09-29：改为「未浏览提醒」红点 —— 有未浏览通知才出现，点进模块即消失 */
  background: var(--red);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  display: grid;
  place-items: center;
  box-shadow: 0 0 0 2px var(--card);
  animation: badgePop 2.6s var(--ease) infinite;
}
@keyframes badgePop {
  0%, 100% { transform: scale(1); }
  8%       { transform: scale(1.18); }
  16%      { transform: scale(1); }
}

.sidebar__foot { margin-top: auto; padding-top: 14px; border-top: 1px solid var(--line); }
.user-chip {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  border-radius: var(--r-sm);
  width: 100%;
  transition: background-color .25s var(--ease);
}
.user-chip:hover { background: var(--bg); }
.avatar {
  width: 34px; height: 34px;
  flex: none;
  border-radius: 50%;
  background: var(--blue);
  color: #fff;
  display: grid;
  place-items: center;
  font-size: 14px;
  font-weight: 600;
  box-shadow: var(--sh-blue);
}
.user-chip__name { font-size: 13px; font-weight: 600; text-align: left; }
.user-chip__role { font-size: 11px; color: var(--gray-2); }

/* ---------- 8. 顶栏 ---------- */
.main {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  /* flex 子项默认 min-height:auto 不肯收缩，会导致 .views 被内容撑高而滚不动 */
  min-height: 0;
  overflow: hidden;
  background: var(--bg);
}
.topbar {
  height: var(--tb-h);
  flex: none;
  padding: 0 24px;
  display: flex;
  align-items: center;
  gap: 16px;
  background: color-mix(in srgb, var(--card) 88%, transparent);
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  border-bottom: 1px solid transparent;
  z-index: 15;
  transition: border-color .35s var(--ease), box-shadow .35s var(--ease), background-color .45s var(--ease);
}
.topbar.is-stuck {
  border-bottom-color: var(--line);
  box-shadow: 0 1px 14px rgba(0, 0, 0, .05);
}

.topbar__title {
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -.3px;
  white-space: nowrap;
}
.topbar__title span {
  display: inline-block;
  animation: titleSwap .5s var(--ease-out);
}
@keyframes titleSwap {
  from { opacity: 0; transform: translateY(9px); filter: blur(3px); }
  to   { opacity: 1; transform: none; filter: none; }
}

/* 搜索框（聚焦展开） */
.search {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  width: 220px;
  padding: 0 14px;
  border-radius: var(--r-pill);
  background: var(--bg);
  border: 1px solid transparent;
  transition: width .4s var(--ease-out), background-color .3s var(--ease),
              border-color .3s var(--ease), box-shadow .3s var(--ease);
}
.search:focus-within {
  width: 300px;
  background: var(--card);
  border-color: var(--blue);
  box-shadow: 0 0 0 4px rgba(0, 102, 204, .12);
}
.search svg { width: 15px; height: 15px; flex: none; fill: none; stroke: var(--gray-2); stroke-width: 1.8; }
.search:focus-within svg { stroke: var(--blue); }
.search input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: none;
  outline: none;
  font-size: 13px;
}
.search input::placeholder { color: var(--gray-2); }

/* 图标按钮 */
.icon-btn {
  position: relative;
  width: 36px; height: 36px;
  flex: none;
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: var(--ink-2);
  transition: background-color .25s var(--ease), color .25s var(--ease), transform .3s var(--ease-back);
}
.icon-btn:hover { background: var(--bg); color: var(--blue); transform: rotate(8deg); }
.icon-btn:active { transform: scale(.9); }
.icon-btn svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.icon-btn--notif::after {
  content: "";
  position: absolute;
  top: 8px; right: 9px;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--red);
  box-shadow: 0 0 0 0 rgba(255, 59, 48, .5);
  animation: pulseDot 2s var(--ease) infinite;
}
@keyframes pulseDot {
  0%   { box-shadow: 0 0 0 0 rgba(255, 59, 48, .55); }
  70%  { box-shadow: 0 0 0 9px rgba(255, 59, 48, 0); }
  100% { box-shadow: 0 0 0 0 rgba(255, 59, 48, 0); }
}

/* 主题切换 */
.theme-toggle svg { transition: transform .6s var(--ease-back), opacity .3s var(--ease); }
.theme-toggle .moon { display: none; }
[data-theme="dark"] .theme-toggle .sun { display: none; }
[data-theme="dark"] .theme-toggle .moon { display: block; }

/* ---------- 9. 视图容器 ---------- */
.views {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  overflow-x: hidden;
  padding: 24px;
}
.view { display: none; }
.view.is-active { display: block; }
.view.is-active.is-entering { animation: viewIn .5s var(--ease-out); }
@keyframes viewIn {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

.section-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--gray);
  letter-spacing: .04em;
  margin-bottom: 12px;
}

/* ---------- 10. 卡片通用 ---------- */
.card {
  position: relative;
  overflow: hidden;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 20px;
  transition: transform .38s var(--ease-out), box-shadow .38s var(--ease), border-color .3s var(--ease);
}
.card--hover:hover {
  transform: translateY(-4px);
  box-shadow: var(--sh-2);
  border-color: color-mix(in srgb, var(--blue) 24%, var(--line));
}
/* 掠光扫过 */
.card--sheen::before {
  content: "";
  position: absolute;
  top: 0; left: -60%;
  width: 45%; height: 100%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .55), transparent);
  transform: skewX(-22deg);
  opacity: 0;
  pointer-events: none;
}
[data-theme="dark"] .card--sheen::before { background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .07), transparent); }
.card--sheen:hover::before { animation: sheen .85s var(--ease-out); }
@keyframes sheen {
  0%   { left: -60%; opacity: 0; }
  15%  { opacity: 1; }
  100% { left: 130%; opacity: 0; }
}

.card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
.card__title { font-size: 16px; font-weight: 600; }
.card__sub { font-size: 12px; color: var(--gray-2); margin-top: 2px; }

/* ---------- 11. KPI ---------- */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin-bottom: 16px;
}
.kpi { padding: 18px; }
.kpi__label { font-size: 13px; color: var(--gray); }
.kpi__value {
  margin-top: 6px;
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -.5px;
  line-height: 1.15;
}
.kpi__delta {
  margin-top: 12px;
  font-size: 12px;
  display: flex;
  align-items: center;
  gap: 5px;
  color: var(--green-d);
}
.kpi__delta.is-down { color: var(--red); }
.kpi__delta svg { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 2.2; }
.kpi__spark { position: absolute; right: 18px; top: 22px; width: 72px; height: 42px; }
.kpi__spark polyline {
  fill: none;
  stroke: var(--blue);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 200;
  stroke-dashoffset: 200;
}
.kpi.is-in .kpi__spark polyline { animation: draw .9s var(--ease-out) .15s forwards; }
@keyframes draw { to { stroke-dashoffset: 0; } }

/* ---------- 12. 图表 ---------- */
.grid-2 { display: grid; grid-template-columns: 1fr 380px; gap: 16px; margin-bottom: 16px; }

.chart { position: relative; height: 200px; }
.chart svg { width: 100%; height: 100%; overflow: visible; }
.chart__grid line { stroke: var(--line-2); stroke-width: 1; }
.chart__area {
  fill: var(--blue);
  opacity: 0;
  transition: opacity .8s var(--ease) .5s;
}
.chart.is-in .chart__area { opacity: .07; }
.chart__line {
  fill: none;
  stroke: var(--blue);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1400;
  stroke-dashoffset: 1400;
}
.chart.is-in .chart__line { animation: draw 1.5s var(--ease-out) forwards; }
.chart__dot {
  fill: var(--blue);
  stroke: var(--card);
  stroke-width: 3;
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(0);
  transition: transform .45s var(--ease-back);
  cursor: pointer;
}
.chart.is-in .chart__dot { transform: scale(1); }
.chart__dot:hover { transform: scale(1.7); }
.chart__xlabel { font-size: 11px; fill: var(--gray-2); }

.chart-tip {
  position: absolute;
  padding: 6px 10px;
  border-radius: 8px;
  background: var(--ink);
  color: var(--card);
  font-size: 12px;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -130%);
  transition: opacity .2s var(--ease);
  z-index: 5;
}
.chart-tip.is-show { opacity: 1; }

/* 环形图 */
.donut-wrap { display: flex; align-items: center; gap: 8px; }
.donut { width: 148px; height: 148px; flex: none; position: relative; }
.donut svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.donut circle {
  fill: none;
  stroke-width: 17;
  stroke-linecap: butt;
  transition: opacity .3s var(--ease), stroke-width .3s var(--ease);
}
.donut__seg { stroke-dasharray: 0 440; }
.donut.is-in .donut__seg { animation: donutDraw 1.1s var(--ease-out) forwards; }
.donut.is-in .donut__seg:nth-of-type(2) { animation-delay: .18s; }
.donut.is-in .donut__seg:nth-of-type(3) { animation-delay: .36s; }
@keyframes donutDraw { to { stroke-dasharray: var(--len) 440; } }
.donut.is-hover circle { opacity: .3; }
.donut circle.is-hot { opacity: 1; stroke-width: 21; }
.donut__center {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  text-align: center;
  pointer-events: none;
}
.donut__center b { display: block; font-size: 22px; font-weight: 700; font-family: "Inter", sans-serif; }
.donut__center span { font-size: 11px; color: var(--gray-2); }

.legend { display: grid; gap: 12px; flex: 1; }
.legend__item {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 13px;
  padding: 5px 8px;
  margin: -5px -8px;
  border-radius: 8px;
  cursor: default;
  transition: background-color .25s var(--ease), transform .25s var(--ease);
}
.legend__item:hover { background: var(--bg); transform: translateX(3px); }
.legend__swatch { width: 11px; height: 11px; border-radius: 3px; flex: none; transition: transform .3s var(--ease-back); }
.legend__item:hover .legend__swatch { transform: scale(1.35); }
.legend__pct { margin-left: auto; font-weight: 600; font-family: "Inter", sans-serif; }

/* 状态列表 */
.stat-list { display: grid; gap: 4px; }
.stat-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 10px;
  margin: 0 -10px;
  border-radius: 10px;
  transition: background-color .25s var(--ease);
}
.stat-row:hover { background: var(--bg); }
.stat-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; position: relative; }
.stat-dot::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 1px solid currentColor;
  opacity: 0;
  animation: ringPop 2.4s var(--ease) infinite;
}
@keyframes ringPop {
  0%   { transform: scale(.6); opacity: .7; }
  60%  { transform: scale(1.5); opacity: 0; }
  100% { opacity: 0; }
}
.stat-name { font-size: 14px; }
.stat-bar {
  flex: 1;
  height: 5px;
  border-radius: 99px;
  background: var(--line-2);
  overflow: hidden;
  margin: 0 14px;
}
.stat-bar i {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 99px;
  transition: width 1.1s var(--ease-out) .25s;
}
.stat-num {
  font-family: "Inter", sans-serif;
  font-weight: 700;
  font-size: 15px;
  min-width: 34px;
  text-align: right;
}

/* 在线用户 */
.user-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  margin: 0 -10px;
  border-radius: 10px;
  transition: background-color .25s var(--ease), transform .25s var(--ease);
}
.user-row:hover { background: var(--bg); transform: translateX(3px); }
.user-row .avatar { width: 28px; height: 28px; font-size: 12px; box-shadow: none; }
.user-row--off .avatar { background: var(--gray-3); }
.avatar-wrap { position: relative; flex: none; }
.avatar-wrap::after {
  content: "";
  position: absolute;
  right: -1px; bottom: -1px;
  width: 9px; height: 9px;
  border-radius: 50%;
  border: 2px solid var(--card);
  background: var(--green);
}
.user-row--off .avatar-wrap::after { background: var(--gray-3); }
.user-row__name { font-size: 13.5px; }
.user-row__role { font-size: 11px; color: var(--gray-2); }
.user-row__time { margin-left: auto; font-size: 11px; color: var(--gray-2); }

/* ---------- 13. 表格 ---------- */
.table-card { padding: 0; }
.table-card .card__head { padding: 18px 20px 0; margin-bottom: 12px; }
.tbl { width: 100%; border-collapse: collapse; }
.tbl th {
  text-align: left;
  font-size: 12px;
  font-weight: 400;
  color: var(--gray-2);
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.tbl td {
  padding: 13px 14px;
  border-bottom: 1px solid var(--line-2);
  font-size: 14px;
  color: var(--ink-2);
  vertical-align: middle;
}
.tbl th:first-child, .tbl td:first-child { padding-left: 20px; }
.tbl th:last-child, .tbl td:last-child { padding-right: 20px; }
.tbl tbody tr {
  position: relative;
  transition: background-color .22s var(--ease);
  cursor: pointer;
}
.tbl tbody tr::after {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--blue);
  transform: scaleY(0);
  transition: transform .28s var(--ease-out);
}
.tbl tbody tr:hover { background: var(--blue-050); }
.tbl tbody tr:hover::after { transform: scaleY(1); }
.tbl tbody tr:last-child td { border-bottom: 0; }
.tbl .mono { font-family: "Inter", sans-serif; color: var(--ink); font-weight: 500; }
.tbl .muted { color: var(--gray-2); }
.tbl .act { color: var(--blue); font-weight: 600; transition: letter-spacing .25s var(--ease); }
.tbl tbody tr:hover .act { letter-spacing: .3px; }

/* 行交错入场
   ⚠️ 默认必须可见：不能依赖 .tbl.is-in（数据异步渲染时若 is-in 缺失，
   行会永久停在 opacity:0 → 表格"发虚/空白"，正是报告列表闪烁的根因之一）。
   动画改为 from 关键帧，即使动画没跑，行也保持 opacity:1。 */
.tbl tbody tr { opacity: 1; }
.tbl.is-in tbody tr { animation: rowIn .45s var(--ease-out) both; }
@keyframes rowIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* 行展开详情 */
.detail-row > td { padding: 0 !important; border-bottom: 1px solid var(--line-2); overflow: hidden; }
.detail-box {
  max-height: 0;
  overflow: hidden;
  background: var(--bg);
  transition: max-height .5s var(--ease), padding .4s var(--ease);
  padding: 0 20px;
}
.detail-row.is-open .detail-box { max-height: 320px; padding: 18px 20px; }
.detail-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px 20px;
}
.detail-grid dt { font-size: 11.5px; color: var(--gray-2); margin-bottom: 3px; }
.detail-grid dd { margin: 0; font-size: 13.5px; color: var(--ink); }

.row-arrow {
  display: inline-block;
  transition: transform .35s var(--ease);
  color: var(--gray-3);
}
tr.is-expanded .row-arrow { transform: rotate(90deg); color: var(--blue); }

/* 跳转定位高亮：临时给目标行加 .is-flash，1.4s 后自动移除 */
@keyframes rowFlash {
  0%   { background: rgba(0, 102, 204, .18); }
  60%  { background: rgba(0, 102, 204, .18); }
  100% { background: transparent; }
}
.tbl tbody tr.is-flash,
.tbl tbody tr.is-flash:hover { animation: rowFlash 1.4s var(--ease) both; }

/* 状态徽章 */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  padding: 0 10px;
  border-radius: var(--r-pill);
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
}
.badge::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
}
.badge--pending  { color: var(--amber-d); background: color-mix(in srgb, var(--amber) 16%, transparent); }
.badge--pending::before { animation: pulseDot 1.8s var(--ease) infinite; }
.badge--progress { color: var(--blue); background: var(--blue-050); }
.badge--done     { color: var(--green-d); background: color-mix(in srgb, var(--green) 16%, transparent); }
.badge--fail     { color: var(--red); background: color-mix(in srgb, var(--red) 14%, transparent); }
.badge--gray     { color: var(--gray); background: var(--bg); }

/* ---------- 14. 提示条 / 胶囊筛选 / 页签 ---------- */
.notice {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 18px;
  border-radius: 12px;
  margin-bottom: 16px;
  background: color-mix(in srgb, var(--amber) 12%, var(--card));
  border: 1px solid color-mix(in srgb, var(--amber) 34%, transparent);
  color: var(--amber-d);
  font-size: 14px;
  animation: noticeIn .6s var(--ease-out);
}
@keyframes noticeIn { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
.notice svg { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; }
.notice b { font-weight: 600; }
.notice .link-btn { margin-left: auto; color: inherit; }

.chips { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }
.chip {
  height: 34px;
  padding: 0 16px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--card);
  font-size: 13.5px;
  color: var(--ink-2);
  position: relative;
  overflow: hidden;
  transition: color .28s var(--ease), border-color .28s var(--ease), transform .2s var(--ease-back), box-shadow .28s var(--ease);
}
.chip::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--blue);
  transform: scale(0);
  border-radius: 50%;
  transition: transform .45s var(--ease-out);
}
.chip span { position: relative; z-index: 1; }
.chip:hover { border-color: var(--blue); transform: translateY(-1.5px); }
.chip.is-active { color: #fff; border-color: var(--blue); box-shadow: var(--sh-blue); }
.chip.is-active::before { transform: scale(2.2); }

/* ---------- 15. 任务大厅卡片（3D 翻转） ---------- */
.pool-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.flip { position: relative; perspective: 1400px; height: 196px; }
.flip--folder { height: 320px; }
.flip--folder .flip__face { padding: 20px 18px 18px; }
.flip__inner {
  position: relative;
  width: 100%; height: 100%;
  transform-style: preserve-3d;
  transition: transform .75s var(--ease);
}
.flip.is-flipped .flip__inner { transform: rotateY(180deg); }
.flip__face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--card);
  padding: 18px;
  display: flex;
  flex-direction: column;
  transition: box-shadow .35s var(--ease), border-color .3s var(--ease);
  /* ⚠️ 面片是绝对定位（inset:0），自身尺寸不受内容影响；
     但内部若有横向溢出，会让浏览器在面片上生成滚动条 ⇒ 高度被压缩 ⇒ 抖动。
     这里直接裁掉横向溢出（内容靠内部 min-width:0 收缩）。 */
  overflow-x: hidden;
  min-width: 0;
}
.flip:hover .flip__face { box-shadow: var(--sh-2); border-color: color-mix(in srgb, var(--blue) 26%, var(--line)); }
.flip__back { transform: rotateY(180deg); background: var(--card); }

/* 文件夹图标 + 头部（正面） */
.flip__head { display: flex; align-items: center; gap: 14px; }
.flip__folder { width: 56px; height: 56px; flex-shrink: 0; color: var(--blue); filter: drop-shadow(0 2px 4px rgba(0,102,204,.18)); }
.flip__head-meta { min-width: 0; flex: 1; }
.flip__head-meta .pool__code { color: var(--blue); font-weight: 500; }
.flip__head-meta .pool__name { margin-top: 4px; font-size: 16px; }

/* 统计三联 */
.flip__stats { display: flex; gap: 14px; margin-top: 14px; padding: 10px 12px; background: var(--bg-2); border-radius: 10px; }
.flip__stat { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.flip__stat b { font-family: "Inter", sans-serif; font-size: 17px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.flip__stat span { font-size: 11px; color: var(--gray-2); }
.flip__bar { height: 4px; background: var(--line); border-radius: 2px; overflow: hidden; margin-top: 12px; }
.flip__bar span { display: block; height: 100%; background: linear-gradient(90deg, var(--blue), #34c759); border-radius: 2px; transition: width .6s var(--ease); }

.pool__code { font-size: 12px; color: var(--gray-2); font-family: "Inter", sans-serif; }
.pool__name { margin-top: 6px; font-size: 17px; font-weight: 600; }
.pool__meta { margin-top: 12px; display: grid; gap: 5px; font-size: 13px; color: var(--gray); }
.pool__foot { margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.pool__owner { display: flex; align-items: center; gap: 7px; font-size: 13.5px; }
.pool__owner .avatar { width: 22px; height: 22px; font-size: 11px; box-shadow: none; }
.pool__owner--in { animation: ownerIn .5s var(--ease-back) backwards; }
@keyframes ownerIn { from { opacity: 0; transform: translateX(-8px); } to { opacity: 1; transform: none; } }

/* ---------- 15b. 详情按钮（认领后才出现）+ 卡片右上角全屏按钮 ---------- */

/* 详情 ›：未认领时根本不渲染（见 renderPool 页脚）；认领成功那一刻带「弹出 + 光环扫过」入场，
   之后持续轻微呼吸 —— 要一眼看出「点这里能翻过去看样品列表」。 */
.flip__detail {
  position: relative;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 7px 16px !important;
  font-size: 13px !important; font-weight: 600;
  color: #fff !important;
  background: linear-gradient(135deg, var(--blue), #2f8ef0) !important;
  border: 0 !important;
  border-radius: var(--r-pill) !important;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3);
  overflow: hidden;
  animation: detailPop .72s var(--ease-back) backwards, detailGlow 2.6s ease-in-out 1.1s infinite;
}
.flip__detail-caret { font-size: 15px; line-height: 1; transition: transform .22s var(--ease-back); }
.flip__detail:hover { filter: saturate(1.12) brightness(1.05); }
.flip__detail:hover .flip__detail-caret { transform: translateX(4px); }
.flip__detail:active { transform: scale(.95); }
.flip__detail::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(115deg, transparent 32%, rgba(255, 255, 255, .6) 50%, transparent 68%);
  transform: translateX(-130%);
  animation: detailSheen 2.9s ease-in-out .45s infinite;
}
@keyframes detailPop {
  0%   { opacity: 0; transform: scale(.4) translateY(10px) rotate(-8deg); }
  60%  { opacity: 1; transform: scale(1.14) translateY(0) rotate(3deg); }
  100% { opacity: 1; transform: none; }
}
@keyframes detailGlow {
  0%, 100% { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3), 0 6px 16px rgba(0, 102, 204, .34), 0 0 0 0 rgba(0, 102, 204, .38); }
  55%      { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3), 0 8px 20px rgba(0, 102, 204, .38), 0 0 0 10px rgba(0, 102, 204, 0); }
}
@keyframes detailSheen {
  0%, 52%   { transform: translateX(-130%); }
  82%, 100% { transform: translateX(130%); }
}

/* 「全屏 / 返回」按钮：**必须长在背面里**（.flip__back-head 的最后一个 flex 子项）。
   ⛔ 曾经把它做成 .flip 的绝对定位兄弟节点 —— 它不参与 3D 翻转，翻开时凭空冒出来、
      收起时「啪」地消失，读起来像外挂按钮（用户报障）。
      放进背面后，它跟着面片一起转进转出，和「填写」按钮是同一种身份。
   ── 视觉取向（用户反馈「太突兀、太浮」）──
   次要工具按钮：浅蓝底 + 细蓝边 + 极轻阴影，与背面 `‹ 返回`（.btn--ghost）同一套语言；
   悬停才填成实心蓝。⛔ 不要给它蓝渐变 + 大扩散阴影，那会和「详情」这个主操作抢视觉。 */
.flip__expand {
  flex: none;
  display: inline-flex; align-items: center; gap: 6px;
  height: 30px; padding: 0 12px;
  font-family: inherit; font-size: 12px; font-weight: 600; line-height: 1;
  color: var(--blue); cursor: pointer;
  background: var(--blue-050);
  border: 1px solid color-mix(in srgb, var(--blue) 22%, var(--line));
  border-radius: var(--r-pill);
  box-shadow: 0 2px 5px rgba(0, 102, 204, .10);
  transition: transform .18s var(--ease-back), background .2s var(--ease),
              color .2s var(--ease), border-color .2s var(--ease), box-shadow .2s var(--ease);
}
.flip__expand svg { width: 13px; height: 13px; flex: none; fill: none; stroke: currentColor; stroke-width: 2.1; stroke-linecap: round; stroke-linejoin: round; }
.flip__expand:hover {
  color: #fff; background: var(--blue); border-color: var(--blue);
  box-shadow: 0 5px 12px rgba(0, 102, 204, .26);
  transform: translateY(-2px) scale(1.05);
}
.flip__expand:active {
  color: #fff; background: var(--blue-600); border-color: var(--blue-600);
  box-shadow: 0 1px 3px rgba(0, 102, 204, .24), inset 0 2px 5px rgba(9, 46, 92, .2);
  transform: translateY(0) scale(.92);
  transition-duration: .09s;
}
.flip__expand:focus-visible { outline: 3px solid rgba(0, 102, 204, .35); outline-offset: 2px; }
.flip__expand-i--back, .flip__expand-txt--back { display: none; }
.flip.is-expanded .flip__expand-i--open, .flip.is-expanded .flip__expand-txt--open { display: none; }
.flip.is-expanded .flip__expand-i--back { display: block; }
.flip.is-expanded .flip__expand-txt--back { display: inline; }

/* 全屏宿主 + 卡片本体全屏化。占位块保证网格不会因为卡片被搬走而塌陷。 */
.flip-expand-host {
  position: fixed; inset: 0; z-index: 1350;
  background: rgba(15, 23, 42, .46);
  -webkit-backdrop-filter: blur(7px); backdrop-filter: blur(7px);
  animation: fadeIn .26s var(--ease);
}
.flip-expand-ph { visibility: hidden; pointer-events: none; }
/* ⚠️ 全屏态一律 perspective: none —— 去掉透视后 rotateY(180°) 成正交投影，
   卡片是「平的」，大字列表不会因为透视畸变而挤在一起。
   阴影写在内层 face 上（.flip 上不挂 filter：filter 会建立新渲染上下文，3D 面片行为易变）。 */
.flip.is-expanded {
  position: absolute; inset: 20px; height: auto; width: auto;
  perspective: none;
}
.flip.is-expanded .flip__face {
  border-radius: 22px; padding: 26px 28px 24px;
  border-color: color-mix(in srgb, var(--blue) 22%, var(--line));
  box-shadow: 0 26px 64px rgba(15, 23, 42, .32);
}
.flip.is-expanded .flip__list { gap: 9px; }
.flip.is-expanded .flip__row { padding: 13px 16px; }
.flip.is-expanded .flip__row-name { font-size: 16.5px; }
.flip.is-expanded .flip__row-qty { font-size: 12.5px; }
.flip.is-expanded .flip__row-sub { font-size: 12.5px; }
.flip.is-expanded .flip__row-fill { padding: 7px 16px !important; font-size: 13px !important; }
.flip.is-expanded .flip__folder { width: 64px; height: 64px; }
.flip.is-expanded .flip__back-title { font-size: 14px; }
/* 全屏里空间大，退出按钮可以大一号（但仍是同一套浅蓝原生质感） */
.flip.is-expanded .flip__expand { height: 34px; padding: 0 15px; font-size: 13.5px; gap: 8px; }
.flip.is-expanded .flip__expand svg { width: 15px; height: 15px; }
html.is-card-expanded { overflow: hidden; }

/* ⚠️ 收起时的「翻回正面」必须用**显式动画**，不能只靠「移除 is-flipped 触发隐式 transition」：
   收起流程要把卡片搬回网格、又要在同一帧改写外层 .flip 的 transform，浏览器会把这一串样式变更
   合并成一次重算 —— 隐式过渡拿不到「前一个计算值」，结果只剩缩小、看不到翻转（用户报障）。
   animation + fill both 强制从 rotateY(180deg) 播到 0，与前面的计算值无关。 */
/* ⚠️ 串行：delay 必须 = 外层缩小的时长（.42s），两个动画**不要同时跑**。
   同时跑时前半段「又缩又转」，卡片在斜着的状态下变形，观感很怪（用户明确否决）。
   delay 期间靠 fill-mode: both 保持 rotateY(180deg) → 背面稳稳缩到位，然后才翻回正面。 */
.flip.is-unflipping .flip__inner { animation: flipBackFace .44s cubic-bezier(.4, 0, .2, 1) .42s both; }
@keyframes flipBackFace {
  from { transform: rotateY(180deg); }
  to   { transform: rotateY(0deg); }
}

/* 列表行右侧「删除这条原始记录」小图标（需 record_delete 权限才渲染） */
.flip__row-del {
  flex: none;
  display: grid; place-items: center;
  width: 26px; height: 26px;
  padding: 0; cursor: pointer;
  color: var(--gray-2);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  transition: color .18s var(--ease), background .18s var(--ease),
              border-color .18s var(--ease), transform .16s var(--ease-back);
}
.flip__row-del svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.flip__row-del:hover { color: var(--red); background: color-mix(in srgb, var(--red) 10%, transparent); border-color: color-mix(in srgb, var(--red) 32%, transparent); transform: scale(1.08); }
.flip__row-del:active { transform: scale(.9); }
.flip__row-del:focus-visible { outline: 3px solid color-mix(in srgb, var(--red) 32%, transparent); outline-offset: 2px; }
.flip.is-expanded .flip__row-del { width: 32px; height: 32px; }
.flip.is-expanded .flip__row-del svg { width: 18px; height: 18px; }

@media (prefers-reduced-motion: reduce) {
  .flip__detail, .flip__detail::after, .pool__owner--in { animation: none; }
  .flip.is-unflipping .flip__inner { animation: none; }
  .flip__expand, .flip__row-del { transition: none; }
  .flip__expand:hover, .flip__expand:active, .flip__row-del:hover, .flip__row-del:active { transform: none; }
}

/* ---------- 报告文件夹（按委托单位归档） ---------- */
.report-folder-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 16px; }
.report-folder-card { min-height: 190px; padding: 20px; color: var(--ink); text-align: left; cursor: pointer; background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--r-lg); transition: transform .2s var(--ease), box-shadow .2s var(--ease), border-color .2s var(--ease); }
.report-folder-card:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--blue) 38%, var(--line)); box-shadow: var(--sh-2); }
.report-folder-icon { width: 52px; height: 52px; color: var(--blue); filter: drop-shadow(0 3px 5px rgba(0,102,204,.2)); }
.report-folder-name { min-height: 44px; margin-top: 14px; font-size: 15px; font-weight: 600; line-height: 1.45; word-break: break-word; }
.report-folder-meta { margin-top: 8px; color: var(--gray-2); font-size: 12px; }
.report-folder-status { display: flex; gap: 8px; margin-top: 12px; font-size: 12px; color: var(--gray); }
.report-folder-toolbar { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; padding: 10px 12px; background: var(--bg-2); border-radius: 10px; }
.report-folder-back { padding: 6px 12px; color: #fff; cursor: pointer; background: var(--blue); border: 0; border-radius: 7px; }
.report-folder-title { min-width: 0; font-size: 15px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.report-file-list { display: grid; gap: 8px; }
.report-file-row { display: flex; align-items: center; gap: 12px; padding: 13px 14px; cursor: pointer; background: var(--bg-2); border: 1px solid var(--line); border-radius: 10px; transition: background .2s var(--ease), border-color .2s var(--ease); }
.report-file-row:hover { background: color-mix(in srgb, var(--blue) 6%, var(--card)); border-color: color-mix(in srgb, var(--blue) 26%, var(--line)); }
.report-file-main { min-width: 0; flex: 1; }
.report-file-no { font-family: "Inter", sans-serif; font-size: 13px; font-weight: 600; }
.report-file-sub { margin-top: 4px; color: var(--gray-2); font-size: 12px; }
.report-folder-empty { padding: 42px 0; color: var(--gray-2); text-align: center; }
/* 2026-09-18：`.report-folder-empty__hint` 随「不合格报告」筛选页签一并删除
   （那个空态说明只服务于该筛选，现无任何调用点） */

/* ===== 报告审阅全屏工作区 =====
   交互定性（用户 2026-09-18）：**全屏查看 = 打开新页面** → 退出走左上角「返回」；
   叉号只属于真正的弹窗（app-confirm / 流转单弹窗 / .modal）。三者不再混用。
   尺寸整体收一档（用户：「界面整体无需做得过大」）。 */
.report-fullscreen { position: fixed; inset: 0; z-index: 1300; display: flex; flex-direction: column; background: #f1f5f9; }
.report-fullscreen__bar {
  position: sticky; top: 0; z-index: 2;
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center; gap: 12px;
  min-height: 52px; padding: 8px 18px;
  background: rgba(248,250,252,.95);
  border-bottom: 1px solid var(--line);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
}
.report-fullscreen__title { grid-column: 2; min-width: 0; display: grid; gap: 1px; text-align: center; }
.report-fullscreen__title strong { font-size: 14.5px; }
.report-fullscreen__title > span { color: var(--gray); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.report-fullscreen__left-tools { grid-column: 1; display: flex; align-items: center; justify-self: start; gap: 8px; min-width: 0; }
/* 左上角「返回」——全屏页面的唯一退出入口 */
.report-fullscreen__back {
  grid-column: auto; justify-self: auto;
  display: inline-flex; align-items: center; gap: 6px;
  height: 34px; padding: 0 15px 0 11px;
  font-family: inherit; font-size: 14px; font-weight: 600; line-height: 1;
  color: var(--blue); cursor: pointer;
  background: var(--blue-050);
  border: 1px solid color-mix(in srgb, var(--blue) 24%, var(--line));
  border-radius: var(--r-pill);
  transition: color .2s var(--ease), background .2s var(--ease), border-color .2s var(--ease),
              box-shadow .2s var(--ease), transform .18s var(--ease-back);
}
.report-fullscreen__back svg { width: 17px; height: 17px; flex: none; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; transition: transform .22s var(--ease-back); }
.report-fullscreen__back:hover { color: #fff; background: var(--blue); border-color: var(--blue); box-shadow: 0 6px 14px rgba(0, 102, 204, .28); transform: translateY(-1px); }
.report-fullscreen__back:hover svg { transform: translateX(-3px); }
.report-fullscreen__back:active { transform: scale(.95); box-shadow: 0 2px 6px rgba(0, 102, 204, .24); }
.report-fullscreen__back:focus-visible { outline: 3px solid rgba(0, 102, 204, .34); outline-offset: 2px; }
.report-preview-mode {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 34px; padding: 0 12px; font: inherit; font-size: 13px; font-weight: 600;
  color: var(--ink-2); background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-pill); cursor: pointer;
  transition: color .18s var(--ease), background .18s var(--ease), border-color .18s var(--ease), transform .18s var(--ease-back);
}
.report-preview-mode:hover { color: var(--blue); border-color: color-mix(in srgb, var(--blue) 44%, var(--line)); transform: translateY(-1px); }
.report-preview-mode[aria-pressed="true"] { color: var(--blue); background: var(--blue-050); border-color: color-mix(in srgb, var(--blue) 40%, var(--line)); }
.report-preview-mode:focus-visible { outline: 3px solid color-mix(in srgb, var(--blue) 34%, transparent); outline-offset: 2px; }
.report-preview-mode:disabled { opacity: .65; cursor: wait; transform: none; }

.report-fullscreen__content { display: grid; grid-template-columns: minmax(0, 1fr) 300px; flex: 1; min-height: 0; }
.report-fullscreen__preview { min-width: 0; padding: 14px; overflow: auto; }
.report-fullscreen__preview iframe { display: block; width: 100%; height: 100%; min-height: 520px; background: #fff; border: 1px solid var(--line); border-radius: 10px; box-shadow: var(--sh-1); }
.report-fullscreen__actions { padding: 16px; overflow-y: auto; background: #fff; border-left: 1px solid var(--line); }
.report-fullscreen__actions h3 { margin: 0 0 12px; font-family: "Inter", sans-serif; font-size: 14px; }
.report-fullscreen__meta { display: grid; gap: 7px; margin-bottom: 12px; color: var(--gray); font-size: 12.5px; }
.report-fullscreen__meta div { display: flex; justify-content: space-between; gap: 10px; }
.report-fullscreen__meta b { color: var(--ink); font-weight: 500; text-align: right; }

/* 封面日期：只留一个「日历」，不再是白底输入框 */
.report-actions__field { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 12px 0 4px; }
.report-actions__field-label { color: var(--gray); font-size: 12.5px; }
.report-date-input {
  box-sizing: border-box; width: auto; max-width: 160px; min-height: 34px;
  padding: 5px 10px; margin: 0;
  font-family: inherit; font-size: 13px; text-align: center;
  color: var(--ink); cursor: pointer;
  background: var(--blue-050);
  border: 1px solid color-mix(in srgb, var(--blue) 26%, var(--line));
  border-radius: 9px;
  color-scheme: light;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease), transform .18s var(--ease-back);
}
.report-date-input:hover { border-color: var(--blue); box-shadow: 0 3px 9px rgba(0, 102, 204, .16); transform: translateY(-1px); }
.report-date-input:active { transform: scale(.97); }
.report-date-input:focus-visible { outline: 3px solid rgba(0, 102, 204, .3); outline-offset: 2px; }
.report-date-input::-webkit-calendar-picker-indicator { cursor: pointer; opacity: .75; }
.report-date-input::-webkit-calendar-picker-indicator:hover { opacity: 1; }

/* ── 右侧操作按钮 ──
   ⚠️ 根因（用户报「一致性检查 / 删除报告 / 驳回 被做成大号输入框」）：
      旧规则 `.report-fullscreen__actions input, ... button:not(.report-fullscreen__close)`
      把 actions 里**所有** button 都套上了 input 的样式 —— width:100% + text-align:left
      + 浅灰底 + 方角 → 三个按钮肉眼就是一排白输入框。
      现拆开：input 走上面的日历样式，button 走 .report-btn 自己的按钮语言（尺寸合适、文字居中、带颜色）。 */
.report-btn {
  box-sizing: border-box;
  /* position + overflow 是点击波纹的硬前提：.ripple 是绝对定位子元素，
     父级缺 position:relative 会跑到别的定位祖先上去，缺 overflow:hidden 会溢出按钮外。 */
  position: relative;
  overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  width: 100%; min-height: 34px; padding: 7px 14px; margin: 5px 0;
  font-family: inherit; font-size: 13px; font-weight: 500; line-height: 1.2;
  text-align: center;
  color: var(--ink-2); cursor: pointer;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 9px;
  transition: color .2s var(--ease), background .2s var(--ease), border-color .2s var(--ease),
              box-shadow .2s var(--ease), transform .16s var(--ease-back);
}
/* ⚠️ 必须显式压掉：.report-btn 的 display:inline-flex 会盖掉 UA 的 [hidden]{display:none}，
   否则「保存封面日期」按钮永远显示 */
.report-btn[hidden] { display: none !important; }
.report-btn:hover { transform: translateY(-1.5px); box-shadow: 0 6px 14px color-mix(in srgb, var(--ink) 12%, transparent); }
.report-btn:active { transform: translateY(0) scale(.97); box-shadow: inset 0 2px 5px rgba(15, 23, 42, .14); }
.report-btn:focus-visible { outline: 3px solid color-mix(in srgb, var(--blue) 32%, transparent); outline-offset: 2px; }
.report-btn--check { color: var(--blue); background: var(--blue-050); border-color: color-mix(in srgb, var(--blue) 26%, var(--line)); }
.report-btn--check:hover { color: #fff; background: var(--blue); border-color: var(--blue); box-shadow: 0 7px 16px rgba(0, 102, 204, .28); }
.report-btn--save { color: var(--blue); background: var(--blue-050); border-color: color-mix(in srgb, var(--blue) 40%, transparent); font-weight: 600; }
.report-btn--save:hover { color: #fff; background: var(--blue); border-color: var(--blue); box-shadow: 0 7px 16px rgba(0, 102, 204, .28); }
.report-btn--danger, .report-btn--reject { color: #b42318; background: color-mix(in srgb, var(--red) 6%, var(--card)); border-color: color-mix(in srgb, var(--red) 32%, var(--line)); }
.report-btn--danger:hover, .report-btn--reject:hover { color: #fff; background: var(--red); border-color: var(--red); box-shadow: 0 7px 16px color-mix(in srgb, var(--red) 30%, transparent); }
.report-fullscreen__decision { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 12px; }
.report-fullscreen__decision .report-btn { min-width: 0; padding-inline: 8px; }

/* 「通过并签发」= 绿色实心按钮（颜色是用户 2026-09-18 定的）。
   ⛔ 这里**只允许** hover / active / 点击波纹三类反馈。
      曾经做过一版「塌缩成方块 → 转圈 → 描出对勾 → 光环扩散」的苹果支付式演出，
      用户试过后明确否决（嫌花哨，且当时附带 720ms 最短转圈 + 820ms 延迟关窗，体感拖慢）。
      要再加任何变形/多段动画之前，先问。 */
.report-btn--approve {
  color: #fff;
  background: linear-gradient(135deg, #34c759, #28a745);
  border-color: #28a745;
  font-weight: 600;
  box-shadow: 0 4px 14px rgba(40, 167, 69, .28);
}
.report-btn--approve:hover {
  background: linear-gradient(135deg, #3ad463, #2fbd52);
  border-color: #2fbd52;
  box-shadow: 0 10px 24px rgba(40, 167, 69, .38);
  transform: translateY(-2px);
}
.report-btn--approve:active { transform: translateY(0) scale(.97); box-shadow: inset 0 2px 6px rgba(14, 84, 33, .3); }
/* 请求在途时按钮被 disabled（文案换成「签发中…」）—— 不再做变形演出 */
.report-btn:disabled { cursor: not-allowed; opacity: .72; }
.report-btn:disabled:hover, .report-btn:disabled:active { transform: none; box-shadow: none; }
/* 「审核人签字」（2026-09-29，需求三）：蓝色描边（非实心）——
   与「通过并签发」（绿实心）/「驳回」（红）刻意区分：它只落一个签字位，不改变报告状态。
   已签字后转绿描边锁定态，与流转单的 is-signed 同一种视觉语言。 */
.report-btn--review {
  color: var(--blue);
  background: color-mix(in srgb, var(--blue) 8%, var(--card));
  border: 1px solid color-mix(in srgb, var(--blue) 40%, var(--line));
  font-weight: 600;
}
.report-btn--review:hover:not(:disabled) {
  background: color-mix(in srgb, var(--blue) 14%, var(--card));
  border-color: var(--blue);
  box-shadow: 0 10px 24px rgba(0, 102, 204, .18);
  transform: translateY(-2px);
}
.report-btn--review.is-signed {
  color: #1a7f37;
  background: color-mix(in srgb, #34c759 12%, var(--card));
  border-color: color-mix(in srgb, #34c759 42%, var(--line));
}
.report-btn--review.is-signed:disabled { cursor: default; opacity: 1; }
/* 「申请修改报告」（2026-09-24）：**无签发权限者**在报告预览里的唯一动作入口。
   中性蓝 —— 与「通过并签发」（绿）/「驳回」（红）刻意区分，避免被误读成审核动作。
   按钮下方 hint 说明本次走哪条变更分支（3 个自然日内重出 / 逾期加 -XG）。 */
.report-change { display: grid; gap: 8px; margin-top: 12px; }
.report-change__hint { margin: 0; font-size: 12px; line-height: 1.55; color: var(--gray); }
.report-btn--apply { color: var(--blue); background: var(--blue-050); border-color: color-mix(in srgb, var(--blue) 26%, var(--line)); }
.report-btn--apply:hover { color: #fff; background: var(--blue); border-color: var(--blue); box-shadow: 0 7px 16px rgba(0, 102, 204, .28); }
.report-btn--apply:active { transform: translateY(0) scale(.97); }
@media (prefers-reduced-motion: reduce) {
  .report-btn, .report-fullscreen__back, .report-date-input { transition: none; }
  .report-btn:hover, .report-btn:active, .report-fullscreen__back:hover, .report-fullscreen__back:active,
  .report-fullscreen__back:hover svg, .report-date-input:hover, .report-date-input:active { transform: none; }
}
/* ---------- 报告一致性检查结果面板 ----------
   2026-09-18：旧版是「绿框 / 红框 + 逐条差异」，新版重构时退化成一行纯文字，
   而且 .is-checking 从来没有样式（核对中毫无反馈）→ 用户「感觉不像真查了」。这里补全。 */
.report-check-result { margin: 10px 0; color: var(--gray); font-size: 13px; line-height: 1.5; }
.report-check-result:empty { display: none; margin: 0; }
.report-check-result.is-pass { color: var(--green-d); font-weight: 500; }
.report-check-result.is-fail { color: var(--red); font-weight: 500; }
.report-check-card {
  display: flex; gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--card);
  font-weight: 400;
  animation: checkCardIn .34s var(--ease-out);
}
@keyframes checkCardIn { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: none; } }
.report-check-card__icon { width: 18px; height: 18px; flex: none; margin-top: 1px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.report-check-card__body { display: grid; gap: 3px; min-width: 0; }
.report-check-card__body strong { font-size: 13px; font-weight: 600; }
.report-check-card__body span { font-size: 12.5px; color: var(--gray); }
.report-check-card__row { display: block; margin-top: 5px; padding: 5px 9px; font-size: 12.5px; color: var(--ink-2); background: color-mix(in srgb, var(--bg) 72%, transparent); border-radius: 7px; }
.report-check-card__row b { color: var(--ink); font-weight: 600; }
.report-check-card__row i { font-style: normal; }
.report-check-card__row .is-bad { color: var(--red); }
.report-check-card__row .is-good { color: var(--green-d); }
/* 仅提示、不阻断签发的一档（规格型号/检测依据/温湿度等允许为空的字段） */
.report-check-card__row--warn { color: var(--amber-d); background: color-mix(in srgb, var(--amber) 10%, transparent); }
.report-check-card__row--warn b { color: var(--amber-d); }
.report-check-card--pass { color: var(--green-d); background: color-mix(in srgb, var(--green) 8%, var(--card)); border-color: color-mix(in srgb, var(--green) 34%, transparent); }
.report-check-card--fail { color: var(--red); background: color-mix(in srgb, var(--red) 6%, var(--card)); border-color: color-mix(in srgb, var(--red) 32%, transparent); }
.report-check-card--checking { color: var(--blue); background: color-mix(in srgb, var(--blue) 6%, var(--card)); border-color: color-mix(in srgb, var(--blue) 30%, transparent); }
.report-check-card__spin {
  flex: none; width: 16px; height: 16px; margin-top: 1px;
  border: 2px solid color-mix(in srgb, var(--blue) 26%, transparent);
  border-top-color: var(--blue);
  border-radius: 50%;
  animation: checkSpin .7s linear infinite;
}
@keyframes checkSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .report-check-card { animation: none; }
  .report-check-card__spin { animation-duration: 1.6s; }
}
/* 「保存封面日期」只在日期被改动后才出现（JS 控制 hidden）。
   外观已由 .report-btn--save 承担，这里不再用 !important 覆盖 —— 否则会把 hover 态一起钉死。 */
.report-actions__dirty { font-weight: 600; }
@media (max-width: 900px) { .report-fullscreen__content { grid-template-columns: 1fr; overflow: auto; } .report-fullscreen__preview { min-height: 62vh; } .report-fullscreen__actions { border-top: 1px solid var(--line); border-left: 0; } .report-fullscreen__bar span { display: none; } }

.flip__back .pool__name { font-size: 15px; }
.spec-list { margin-top: 10px; display: grid; gap: 7px; }
.spec-list div { display: flex; justify-content: space-between; font-size: 12.5px; }
.spec-list span { color: var(--gray-2); }
.spec-list b { font-weight: 500; font-family: "Inter", sans-serif; }

/* 背面：原始记录列表（可滚动） */
/* ⚠️ min-width:0 —— flex 子项默认 min-width:auto，会被 nowrap 内容撑破；
   它是横向溢出的常见源头（见 .flip__list 振动说明）。 */
.flip__back-head { display: flex; align-items: center; gap: 10px; padding-bottom: 10px; border-bottom: 1px solid var(--line); flex-shrink: 0; min-width: 0; }
.flip__back-head .btn--ghost {
  flex: none;
  min-width: 78px;
  padding-inline: 14px;
  color: var(--blue);
  background: var(--blue-050);
  border-color: color-mix(in srgb, var(--blue) 22%, var(--line));
  box-shadow: 0 4px 12px rgba(0, 102, 204, .12);
  font-weight: 600;
}
.flip__back-head .btn--ghost:hover {
  color: #fff;
  background: var(--blue);
  border-color: var(--blue);
  box-shadow: 0 8px 18px rgba(0, 102, 204, .26);
  transform: translateX(-2px) translateY(-1px);
}
.flip__back-head .btn--ghost:active { transform: translateX(0) scale(.96); }
.flip__back-title { flex: 1; font-size: 13px; color: var(--gray); font-family: "Inter", sans-serif; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* ⚠️⚠️ overflow-x 必须显式 hidden —— 否则会出现「高频振动」：
   行内容宽度临界超出 ⇒ 冒出横向滚动条 ⇒ 挤掉底部垂直空间 ⇒ .flip__list 高度变化
   ⇒ 布局重算、可用宽度微变 ⇒ 滚动条消失 ⇒ 再溢出……Chromium 下形成
   scrollbar oscillation（每秒数十次重排，肉眼即"卡牌整个在抖"）。
   正确做法：禁止横向滚动，让内容靠 .flip__row-main{min-width:0} + 省略号自行收缩。 */
.flip__list { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; margin: 8px 0; display: flex; flex-direction: column; gap: 6px; -webkit-overflow-scrolling: touch; }
.flip__list::-webkit-scrollbar { width: 6px; }
.flip__list::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--gray-2) 40%, transparent); border-radius: 3px; }
.flip__list::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--gray-2) 60%, transparent); }
.flip__row {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: 10px;
  background: var(--bg-2); cursor: pointer;
  transition: background .2s var(--ease), transform .2s var(--ease);
  border: 1px solid transparent;
  /* ⚠️ min-width:0 + max-width:100% —— 防止行内 nowrap 文本把容器撑宽、
     进而触发 .flip__list 横向滚动条（见上方振动说明）。 */
  min-width: 0; max-width: 100%; box-sizing: border-box;
}
/* ⚠️ .flip__row:hover 的 translateX(2px) 会让行右缘多出 2px。
   配合 overflow-x:hidden 后不会再催生滚动条，但为稳妥改用 padding 抖动，
   避免任何越界（2px 溢出在窄卡片里足以触发重排）。 */
.flip__row:hover { background: color-mix(in srgb, var(--blue) 8%, var(--card)); border-color: color-mix(in srgb, var(--blue) 22%, var(--line)); transform: none; }
.flip__row-main { flex: 1; min-width: 0; overflow: hidden; }
/* ⚠️ 这一对类被「任务大厅（原始记录）」和「报告审核页」共用：
   大厅 = 大字样品名称 / 小字样品编号；报告审核页小字位是报告编号（也是对的）。
   所以字号字重只能取两者的交集需求 —— 报告审核页的编号行本来也偏小，一起放大没问题。
   用户 2026-09-20：名称要更大更黑。12.5px/500 → 14.5px/700。 */
.flip__row-name { font-size: 14.5px; color: var(--ink); font-weight: 700; font-family: "Inter", sans-serif; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 数量跟在产品名后面（不是编号后面），所以是 name 的行内子元素：
   比名称小一档、比编号深一点，用蓝色点缀做视觉锚，不抢名称。 */
.flip__row-qty { display: inline-block; margin-left: 6px; font-size: 11.5px; font-weight: 600; color: var(--blue); vertical-align: 1px; }
.flip__row-sub { font-size: 11px; color: var(--gray-2); margin-top: 2px; }
/* 「填写」按钮：用户反馈「太平了、没阴影」。
   根因：它继承的 .btn--primary 阴影是 --sh-blue = `0 8px 24px / .24` —— 大模糊 + 低透明度，
   落在 28px 高的小胶囊上只会变成一圈灰气，读不出「厚度」。
   小按钮要的是**小而实**的双层阴影（近处紧贴 + 远处托起），悬停再抬一档。
   ⚠️ :hover / :active 必须写成 .flip__row-fill 同级选择器，否则被 .btn--primary:hover（0,2,0）压掉。 */
.flip__row-fill {
  padding: 5px 12px !important; font-size: 12px !important; min-height: 28px; flex-shrink: 0;
  box-shadow: 0 2px 5px rgba(0, 102, 204, .30), 0 7px 14px -4px rgba(0, 102, 204, .26);
}
.flip__row-fill:hover {
  box-shadow: 0 4px 10px rgba(0, 102, 204, .34), 0 12px 22px -6px rgba(0, 102, 204, .30);
}
.flip__row-fill:active {
  box-shadow: 0 1px 3px rgba(0, 102, 204, .26), inset 0 2px 6px rgba(9, 46, 92, .22);
}
/* 文件夹背面底部：**一键打印**（2026-09-20 需求 2 起，打印的唯一入口）。
   两种状态由 `.is-ready` 切换：
     ① 默认（未全审批）→ 灰色 / 扁平 / 无阴影 / 不可点，带「待审批 N」小字说明原因
     ② 全部已审批     → 绿色 / 带阴影 / 凸起立体
   ⚠️ 「灰色扁平」不能只靠 :disabled 的 opacity —— 浏览器默认 disabled 样式
      会连字体颜色一起吃掉，跟设计稿不一致，所以显式写全。 */
.flip__foot { flex-shrink: 0; display: flex; justify-content: flex-end; padding-top: 8px; border-top: 1px solid var(--line-2); }
.flip__foot .btn { font-size: 12px; }
.flip__print {
  gap: 6px;
  height: 32px;
  padding: 0 14px;
  background: var(--bg-2);
  color: var(--gray-2);
  border: 1px solid var(--line);
  box-shadow: none;
  cursor: not-allowed;
  font-weight: 500;
}
.flip__print svg {
  width: 14px; height: 14px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round;
}
.flip__print:hover, .flip__print:active { transform: none; box-shadow: none; background: var(--bg-2); }
/* 「待审批 N」：不是错误，只是解释为什么不能点，所以用中性灰、字号更小 */
.flip__print-note {
  margin-left: 2px; padding: 1px 6px; border-radius: var(--r-pill);
  font-size: 10.5px; font-weight: 600;
  color: var(--gray-2);
  background: color-mix(in srgb, var(--gray-2) 12%, transparent);
}
/* 就绪态：绿实心 + 双层实阴影（近处紧贴 + 远处托起），与 .btn--green 同色系 */
.flip__print.is-ready {
  background: var(--green-d);
  color: #fff;
  border-color: transparent;
  cursor: pointer;
  font-weight: 600;
  box-shadow: 0 2px 5px rgba(26, 127, 55, .32), 0 8px 16px -4px rgba(26, 127, 55, .30);
}
.flip__print.is-ready:hover {
  background: color-mix(in srgb, var(--green-d) 88%, #000);
  box-shadow: 0 4px 10px rgba(26, 127, 55, .36), 0 13px 24px -6px rgba(26, 127, 55, .34);
  transform: translateY(-1.5px);
}
.flip__print.is-ready:active {
  background: color-mix(in srgb, var(--green-d) 78%, #000);
  box-shadow: 0 1px 3px rgba(26, 127, 55, .28), inset 0 2px 6px rgba(9, 46, 92, .22);
  transform: translateY(0) scale(.975);
}
.flip__print.is-ready:focus-visible { outline: 3px solid color-mix(in srgb, var(--green-d) 38%, transparent); outline-offset: 2px; }
[data-theme="dark"] .flip__print.is-ready { background: #1f9d4a; box-shadow: 0 2px 5px rgba(31, 157, 74, .38), 0 8px 16px -4px rgba(31, 157, 74, .34); }
[data-theme="dark"] .flip__print.is-ready:hover { background: #25b357; }
/* 加载中（一键打印批量出图中）：沿用 .btn.is-loading 的转圈，但底色要保持可读 */
.flip__print.is-loading { color: transparent !important; pointer-events: none; }
.flip__print.is-loading .flip__print-note { visibility: hidden; }

/* 「重新生成」在工具栏里的位置（需求 1）：贴在右上角全屏按钮**左侧**，
   比全屏按钮弱一档（灰字），但不能太小 —— 它是唯一的补出报告入口。 */
.flip__regen {
  flex: none;
  gap: 5px;
  height: 30px;
  padding: 0 10px;
  font-size: 12px;
  color: var(--gray);
  background: transparent;
  border-color: transparent;
}
.flip__regen svg {
  width: 13px; height: 13px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.flip__regen:hover { color: var(--blue); background: var(--blue-050); box-shadow: none; }
.flip__regen[disabled] { opacity: .5; cursor: wait; }

/* ---------- 报告只读阅读器（防泄漏，2026-09-20） ----------
   服务端把 PDF 渲染成 PNG，前端只显示位图；PDF 源不进 DOM。
   整块禁用选中 / 右键 / 拖拽，视觉上保持「纸」的质感。 */
.report-reader {
  width: 100%; height: 100%;
  overflow-y: auto;
  background: color-mix(in srgb, var(--ink) 7%, var(--bg));
  padding: 18px 0 26px;
  /* 只读壳：不选中、不拖拽、不弹出长按菜单（移动端） */
  -webkit-user-select: none; -moz-user-select: none; user-select: none;
  -webkit-touch-callout: none;
  -webkit-user-drag: none;
  outline: none;
}
/* T03（2026-09-23）：审核预览改为 iframe 直出 PDF —— 让 PDF 填满预览区（去内边距）。 */
.report-reader:has(.report-reader__frame) { padding: 0; overflow: hidden; }
.report-reader__frame { display: block; width: 100%; height: 100%; border: 0; background: #fff; }
.report-reader.is-dual { box-sizing: border-box; padding: 14px; overflow: auto; }
.report-spread { min-height: 100%; display: flex; flex-direction: column; gap: 12px; }
.report-spread__toolbar {
  position: sticky; top: 0; z-index: 1; display: grid; grid-template-columns: auto 1fr auto;
  align-items: center; gap: 12px; width: fit-content; max-width: 100%; margin: 0 auto;
  padding: 6px; color: var(--ink-2); background: color-mix(in srgb, var(--card) 94%, transparent);
  border: 1px solid var(--line); border-radius: var(--r-pill); box-shadow: var(--sh-1);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
}
.report-spread__toolbar button {
  min-height: 30px; padding: 4px 11px; color: var(--blue); font: inherit; font-size: 12px;
  background: var(--blue-050); border: 1px solid color-mix(in srgb, var(--blue) 24%, var(--line));
  border-radius: var(--r-pill); cursor: pointer;
}
.report-spread__toolbar button:disabled { color: var(--gray-2); background: var(--bg); border-color: var(--line); cursor: default; opacity: .7; }
.report-spread__toolbar button:focus-visible { outline: 3px solid color-mix(in srgb, var(--blue) 34%, transparent); outline-offset: 2px; }
.report-spread__range { min-width: 150px; text-align: center; font-size: 12px; white-space: nowrap; }
.report-spread__pages { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; gap: 14px; }
.report-spread__pages.is-single { grid-template-columns: minmax(0, 1fr); }
.report-spread__pages.is-single .report-spread__page { width: 100%; max-width: 860px; justify-self: center; }
.report-spread__page {
  position: relative; min-width: 0; min-height: 200px; margin: 0; overflow: hidden;
  background: #fff; border: 1px solid var(--line); border-radius: 4px;
  box-shadow: 0 1px 2px rgba(0,0,0,.1), 0 10px 28px -8px rgba(0,0,0,.22);
}
.report-spread__page img { display: block; width: 100%; height: auto; pointer-events: none; }
.report-spread__page img.is-failed { display: none; }
.report-spread__page figcaption {
  position: absolute; right: 8px; bottom: 6px; padding: 1px 7px; color: var(--gray-2);
  font: 10.5px "Inter", sans-serif; background: color-mix(in srgb, var(--bg) 82%, transparent);
  border-radius: var(--r-pill); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
.report-spread__page-error { display: block; padding: 50px 12px; color: #b91c1c; text-align: center; font-size: 13px; line-height: 1.6; }
.report-spread__page-error[hidden] { display: none; }
[data-theme="dark"] .report-spread__toolbar { background: color-mix(in srgb, var(--card) 94%, transparent); }
[data-theme="dark"] .report-spread__page { box-shadow: 0 1px 2px rgba(0,0,0,.5), 0 10px 28px -8px rgba(0,0,0,.7); }
@media (max-width: 900px) {
  .report-fullscreen__left-tools { gap: 5px; }
  .report-fullscreen__bar { padding-inline: 10px; gap: 6px; }
  .report-preview-mode { padding-inline: 8px; font-size: 12px; }
  .report-spread__pages { grid-template-columns: minmax(0, 1fr); justify-content: center; }
  .report-spread__range { min-width: 112px; }
}
@media (prefers-reduced-motion: reduce) {
  .report-preview-mode { transition: none; }
  .report-preview-mode:hover { transform: none; }
}
/* T04（2026-09-23）：委托单详情（查看态）工具栏的「导出 / 打印委托单 PDF」入口 */
.order-export-pdf {
  margin-left: 10px; padding: 6px 13px; border-radius: 999px;
  border: 1px solid var(--line, #e5e7eb); background: var(--bg, #fff); color: inherit;
  font-size: 12.5px; cursor: pointer; line-height: 1.4; white-space: nowrap;
}
.order-export-pdf:hover { border-color: #2563eb; color: #2563eb; }
.report-reader__stage { display: flex; flex-direction: column; align-items: center; gap: 14px; }
.report-reader__page {
  position: relative;
  margin: 0;
  width: min(100%, 860px);
  background: #fff;
  border-radius: 4px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .10), 0 10px 28px -8px rgba(0, 0, 0, .22);
  overflow: hidden;
}
.report-reader__page img {
  display: block; width: 100%; height: 100%; object-fit: contain;
  pointer-events: none;            /* 图片自身不接收事件，右键/拖拽全部落到外壳上 */
  opacity: 1; transition: opacity .25s var(--ease);
}
.report-reader__page img.is-loading { opacity: 0; }
.report-reader__page img.is-failed { opacity: .25; }
.report-reader__page figcaption {
  position: absolute; right: 8px; bottom: 6px;
  padding: 1px 7px; border-radius: var(--r-pill);
  font-size: 10.5px; font-family: "Inter", sans-serif;
  color: var(--gray-2);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(4px);
}
.report-reader__loading, .report-reader__error {
  margin: 40px auto; font-size: 13px; color: var(--gray-2); text-align: center;
}
.report-reader__error { color: #b91c1c; max-width: 78%; line-height: 1.7; }
[data-theme="dark"] .report-reader { background: color-mix(in srgb, #000 22%, var(--bg)); }
[data-theme="dark"] .report-reader__page { box-shadow: 0 1px 2px rgba(0,0,0,.5), 0 10px 28px -8px rgba(0,0,0,.7); }
@media (prefers-reduced-motion: reduce) {
  .flip__print, .flip__regen { transition: none; }
  .flip__print.is-ready:hover { transform: none; }
}

/* ---------- 报告类型（合格 / 不合格）标注 ---------- */
.flip__row.report-kind--nonconforming { background: color-mix(in srgb, var(--red) 5%, var(--bg-2)); border-left: 3px solid var(--red); }
.flip__row.report-kind--nonconforming:hover { background: color-mix(in srgb, var(--red) 10%, var(--card)); border-color: color-mix(in srgb, var(--red) 30%, var(--line)); }
.flip__row.report-kind--qualified { border-left: 3px solid color-mix(in srgb, var(--green) 55%, transparent); }

/* ---------- 报告行操作按钮（2026-09-24，用户要求）----------
   打印是**主操作** → 明显更大更醒目；「导出 Word」是次要/近乎隐藏功能
   → 收到一个纯 SVG 图标按钮（无文字标签，靠 title 提示）。
   ⚠️ 选择器统一带 `.flip__row` 前缀提高权重，避免被前面的 .btn--sm / .btn 规则盖掉。 */
.flip__row .report-print-btn {
  height: 42px; padding: 0 28px; flex-shrink: 0;
  font-size: 15px; font-weight: 600;
  box-shadow: 0 3px 8px color-mix(in srgb, var(--green-d) 30%, transparent),
              0 10px 22px -6px color-mix(in srgb, var(--green-d) 26%, transparent);
}
.flip__row .report-print-btn:hover {
  box-shadow: 0 5px 14px color-mix(in srgb, var(--green-d) 34%, transparent),
              0 14px 28px -8px color-mix(in srgb, var(--green-d) 30%, transparent);
}
.flip__row .report-docx-btn {
  width: 32px; height: 32px; padding: 0; flex-shrink: 0;
  color: var(--gray-2); background: transparent; border-color: transparent;
}
.flip__row .report-docx-btn:hover {
  color: var(--blue); background: var(--blue-050);
  border-color: color-mix(in srgb, var(--blue) 26%, transparent);
}
.flip__row .report-docx-btn svg {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
/* 编号 + 类型标签同一行：先看编号（402-02）再看类型（不合格报告） */
.flip__row-name { display: flex; align-items: center; gap: 6px; }
.flip__row-no { font-family: "Inter", sans-serif; font-variant-numeric: tabular-nums; }
.flip__row.report-kind--nonconforming .flip__row-no { color: #b91c1c; font-weight: 600; }
.report-kind__tag {
  flex-shrink: 0; padding: 2px 7px; border-radius: var(--r-pill);
  /* ⚠️ 2026-09-28 修正（二稿）：合格 / 不合格 **都加粗到 600**。
     一稿我把不合格从 600 降到 500「向合格看齐」—— 这是**理解反了**：
     用户本意是「把合格也变成不合格那样」，而且明确说「细的不好看，还是加粗吧」。
     ⇒ 基准 = 600，两个标签同字号同字重，只剩配色差异。 */
  font-size: 10.5px; font-weight: 600; line-height: 1.55; white-space: nowrap;
}
.report-kind__tag--qualified { color: var(--green-d); background: color-mix(in srgb, var(--green) 16%, transparent); }
.report-kind__tag--nonconforming { color: #b91c1c; background: color-mix(in srgb, var(--red) 15%, transparent); }
/* ⚠️ 2026-09-28 二稿：字重**统一由基类给 600**，两个修饰类都不再声明 font-weight。
   一稿曾把 nonconforming 的 600 删掉改成向 500 看齐 → 理解反了用户意图
   （用户本意：让「合格」变成「不合格」那样的粗体，且「细的不好看」）。 */
/* ⚠️ 2026-09-28：原本这里给「不合格」单独加了 `font-weight: 600`，
   结果合格(500) 与 不合格(600) 两个字重不一致，同屏并排时一眼看出粗细不同。
   用户反馈要统一 ⇒ 字重交回基类 `.report-kind__tag`（500），本行只保留配色差异。
   语义区分靠**颜色 + 底色**已足够，不需要再叠字重。 */
.flip__stat--warn b { color: #b91c1c; }
.report-fullscreen__bar span.report-kind--nonconforming { color: #b91c1c; font-weight: 500; }
/* 2026-09-18：`.chip--nonconforming.is-active` 已删 —— 「不合格报告」筛选页签不存在了
   （合格与不合格同处一个报告文件夹）；下面的行样式与标签样式**仍然在用**，不要删。 */

.claim-btn.is-claimed {
  background: color-mix(in srgb, var(--green) 14%, transparent);
  color: var(--green-d);
  border-color: transparent;
  box-shadow: none;
}
.claim-btn .tick { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2.6; }

/* 粒子（认领成功） */
.particle {
  position: fixed;
  width: 7px; height: 7px;
  border-radius: 2px;
  pointer-events: none;
  z-index: 120;
  animation: particleFly .9s var(--ease-out) forwards;
}
@keyframes particleFly {
  0%   { transform: translate(0, 0) rotate(0) scale(1); opacity: 1; }
  100% { transform: translate(var(--dx), var(--dy)) rotate(var(--rot)) scale(0); opacity: 0; }
}

/* ---------- 16. 骨架屏 ---------- */
.skeleton {
  background: linear-gradient(90deg, var(--line-2) 25%, var(--line) 37%, var(--line-2) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease-in-out infinite;
  border-radius: 6px;
}
@keyframes shimmer {
  0%   { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}
.sk-line { height: 12px; margin-bottom: 10px; }
.sk-card { height: 196px; border-radius: var(--r-lg); }

/* ---------- 17. 模态框 ---------- */
.modal-host {
  position: fixed;
  inset: 0;
  z-index: 130;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.modal-host.is-open { display: flex; }
.modal__mask {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, .38);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  animation: fadeIn .32s var(--ease);
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

.modal {
  position: relative;
  width: 560px;
  max-width: 100%;
  max-height: 86vh;
  overflow: auto;
  background: var(--card);
  border-radius: 20px;
  box-shadow: var(--sh-2);
  padding: 24px;
  animation: modalIn .48s var(--ease-back);
}
@keyframes modalIn {
  from { opacity: 0; transform: translateY(26px) scale(.94); filter: blur(6px); }
  to   { opacity: 1; transform: none; filter: none; }
}
.modal__close {
  position: absolute;
  top: 16px; right: 16px;
  width: 30px; height: 30px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: var(--gray-2);
  transition: .25s var(--ease);
}
.modal__close:hover { background: var(--bg); color: var(--ink); }
.modal__close svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; }
.modal__title { font-size: 19px; font-weight: 600; }
.modal__sub { font-size: 13px; color: var(--gray-2); margin-top: 3px; }
.modal__body { margin-top: 18px; }
.modal__foot { margin-top: 22px; display: flex; justify-content: flex-end; gap: 10px; }

/* 客户资料弹窗：新建与编辑共用同一套稳定、可扫描的表单。 */
.customer-modal {
  width: min(720px, 100%);
  padding: 0;
  overflow: hidden;
}
.customer-modal__header {
  padding: 26px 30px 20px;
  border-bottom: 1px solid var(--line);
}
.customer-modal__body { max-height: min(72vh, 720px); overflow-y: auto; }
.customer-form { padding: 24px 30px 0; }
.customer-form__intro {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  margin-bottom: 22px;
  color: var(--ink);
  background: var(--blue-050);
  border-radius: var(--r-md);
}
.customer-form__icon {
  display: grid;
  flex: 0 0 38px;
  width: 38px;
  height: 38px;
  place-items: center;
  color: var(--blue);
  background: var(--card);
  border-radius: 12px;
}
.customer-form__icon svg { display: block; width: 21px; height: 21px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.customer-form__intro > div > strong,
.customer-form__intro > div > span { display: block; }
.customer-form__intro strong { font-size: 14px; font-weight: 600; }
.customer-form__intro span { margin-top: 2px; color: var(--gray); font-size: 12px; }
.customer-form__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 20px; }
.customer-form__field { display: block; min-width: 0; }
.customer-form__field--wide { grid-column: 1 / -1; }
.customer-form__label { display: block; margin-bottom: 7px; color: var(--ink-2); font-size: 13px; font-weight: 600; }
.customer-form__label em { margin-left: 3px; color: var(--red); font-style: normal; }
.customer-form__field input {
  width: 100%;
  height: 44px;
  padding: 0 13px;
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  outline: none;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease), background-color .2s var(--ease);
}
.customer-form__field input::placeholder { color: var(--gray-2); }
.customer-form__field input:hover { border-color: var(--gray-3); }
.customer-form__field input:focus { border-color: var(--blue); box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 16%, transparent); }
.customer-form__field input[readonly] { color: var(--gray); cursor: not-allowed; background: var(--bg); }
.customer-form__field input.is-error { border-color: var(--red); box-shadow: 0 0 0 3px color-mix(in srgb, var(--red) 14%, transparent); }
.customer-form__field small { display: block; margin-top: 5px; color: var(--gray); font-size: 11px; }
.customer-form__type { padding: 0; margin: 22px 0 0; border: 0; }
.customer-form__type legend { margin-bottom: 9px; color: var(--ink-2); font-size: 13px; font-weight: 600; }
.customer-form__chips { display: flex; flex-wrap: wrap; gap: 9px; }
.customer-form__chips input { position: absolute; opacity: 0; pointer-events: none; }
.customer-form__chips span { display: block; min-height: 38px; padding: 8px 16px; color: var(--gray); cursor: pointer; border: 1px solid var(--line); border-radius: var(--r-pill); transition: .2s var(--ease); }
.customer-form__chips input:checked + span { color: #fff; background: var(--blue); border-color: var(--blue); box-shadow: var(--sh-blue); }
.customer-form__chips input:focus-visible + span { outline: 3px solid color-mix(in srgb, var(--blue) 28%, transparent); outline-offset: 2px; }
.customer-chip { position: relative; display: inline-flex; align-items: center; perspective: 900px; }
.customer-chip--locked { cursor: default; }
.customer-form__chips .customer-chip__flip { position: relative; display: grid; padding: 0; border: 0; background: none; border-radius: 0; transform-style: preserve-3d; transition: transform .42s cubic-bezier(.34, 1.56, .64, 1); }
.customer-chip.is-armed .customer-chip__flip { transform: rotateY(180deg); }
.customer-form__chips input:checked ~ .customer-chip__flip { color: inherit; background: none; border-color: transparent; box-shadow: none; }
.customer-form__chips .customer-chip__face { grid-area: 1 / 1; display: flex; align-items: center; justify-content: center; min-height: 38px; padding: 8px 16px; border: 1px solid var(--line); border-radius: var(--r-pill); white-space: nowrap; -webkit-backface-visibility: hidden; backface-visibility: hidden; transition: border-color .2s var(--ease), background .2s var(--ease); }
.customer-form__chips .customer-chip__face--front { color: var(--gray); background: var(--card); cursor: pointer; }
.customer-chip:hover .customer-chip__face--front { border-color: color-mix(in srgb, var(--blue) 42%, transparent); }
.customer-chip input:checked ~ .customer-chip__flip .customer-chip__face--front { color: #fff; background: var(--blue); border-color: var(--blue); box-shadow: var(--sh-blue); }
.customer-form__chips .customer-chip__face--back { color: #fff; background: var(--red); border-color: var(--red); cursor: pointer; transform: rotateY(180deg); box-shadow: 0 4px 14px color-mix(in srgb, var(--red) 30%, transparent); }
.customer-chip__face--back svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.customer-chip__add {
  min-height: 38px; padding: 8px 14px;
  color: var(--blue); background: transparent;
  border: 1px dashed color-mix(in srgb, var(--blue) 45%, transparent);
  border-radius: var(--r-pill); cursor: pointer;
  transition: .2s var(--ease);
}
.customer-chip__add:hover { background: color-mix(in srgb, var(--blue) 8%, transparent); border-color: var(--blue); }
.customer-form__foot {
  position: sticky;
  bottom: 0;
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 20px 0 24px;
  margin-top: 26px;
  background: var(--card);
  border-top: 1px solid var(--line);
}
@media (max-width: 640px) {
  .customer-modal__header { padding: 22px 22px 17px; }
  .customer-form { padding: 20px 22px 0; }
  .customer-form__grid { grid-template-columns: 1fr; }
  .customer-form__field--wide { grid-column: auto; }
  .customer-form__foot { padding-bottom: 20px; }
}

.kv { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px 20px; }
.kv__k { font-size: 11.5px; color: var(--gray-2); }
.kv__v { font-size: 14px; margin-top: 2px; }
.kv__v.mono { font-family: "Inter", sans-serif; }

.result-list { margin-top: 16px; border-top: 1px solid var(--line); padding-top: 14px; }
.result-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  font-size: 13.5px;
  border-bottom: 1px dashed var(--line-2);
  opacity: 0;
  transform: translateX(-8px);
  animation: featIn .45s var(--ease-out) forwards;
}
.result-item:last-child { border-bottom: 0; }
.result-item .ok { color: var(--green-d); }
.result-item .no { color: var(--red); }
.result-item svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2.4; }
.result-item b { margin-left: auto; font-family: "Inter", sans-serif; font-weight: 500; }

/* ---------- 18. Toast ---------- */
/* 2026-09-18：顶部偏移改成「顶栏之下」—— 原来 top:20px 正好压在右上角
   搜索框 / 通知铃 / 主题切换 / 退出这一排上，用户报「弹窗挡住按钮」。 */
.toast-host {
  position: fixed;
  top: calc(var(--tb-h, 64px) + 16px); right: 22px;
  z-index: 1500;
  display: grid;
  gap: 10px;
  justify-items: end;
  width: min(390px, calc(100vw - 32px));
  pointer-events: none;
}
.toast {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
  min-height: 64px;
  padding: 14px 18px 14px 20px;
  overflow: hidden;
  border-radius: 14px;
  background: var(--card);
  border: 1px solid var(--line);
  box-shadow: 0 18px 46px rgba(15,23,42,.24), inset 0 1px 0 rgba(255,255,255,.72);
  font-size: 14px;
  font-weight: 620;
  line-height: 1.5;
  pointer-events: auto;
  animation: toastIn .45s var(--ease-back);
}
.toast::before { content:""; position:absolute; inset:0 auto 0 0; width:4px; background:var(--green); }
.toast--info::before { background:var(--blue); }
.toast--warn::before { background:var(--amber); }
.toast>span:last-child { white-space:pre-line; }
.toast.is-out { animation: toastOut .35s var(--ease) forwards; }
@keyframes toastIn  { from { opacity: 0; transform: translateX(40px) scale(.94); } to { opacity: 1; transform: none; } }
@keyframes toastOut { to { opacity: 0; transform: translateX(40px) scale(.94); } }
.toast__icon {
  width: 22px; height: 22px;
  flex: none;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: color-mix(in srgb, var(--green) 18%, transparent);
  color: var(--green-d);
}
.toast__icon svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2.8; }
.toast--info .toast__icon { background: var(--blue-050); color: var(--blue); }
.toast--warn .toast__icon { background: color-mix(in srgb, var(--amber) 20%, transparent); color: var(--amber-d); }

/* ---------- 19. 滚动渐显 / 视差 ---------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .7s var(--ease-out), transform .7s var(--ease-out);
  transition-delay: var(--d, 0ms);
}
[data-reveal].is-in { opacity: 1; transform: none; }

[data-parallax] { will-change: transform; }

/* ---------- 20. 日志时间线 ---------- */
.timeline { position: relative; padding: 4px 0 4px 26px; }
.timeline::before {
  content: "";
  position: absolute;
  left: 6px; top: 6px; bottom: 6px;
  width: 1px;
  background: var(--line);
}
/* 非列表状态（空 / 失败 / 加载）时收起左侧竖线，避免「一根线配一段文字」的怪异感 */
.timeline.is-flat { padding-left: 0; }
.timeline.is-flat::before { display: none; }

/* 日期分隔（今天 / 昨天 / 月-日） */
.tl-day {
  position: relative;
  margin: 4px 0 2px;
  font-size: 12px;
  font-weight: 600;
  color: var(--gray);
}
.tl-day:first-child { margin-top: 0; }
.tl-day > span {
  display: inline-block;
  padding: 3px 10px;
  border-radius: var(--r-pill);
  background: var(--line-2);
}

.tl-item { position: relative; padding: 10px 0; }
.tl-item::before {
  content: "";
  position: absolute;
  left: -24px; top: 16px;
  width: 11px; height: 11px;
  border-radius: 50%;
  background: var(--card);
  border: 2px solid var(--blue);
  transition: transform .3s var(--ease-back), background-color .3s var(--ease);
}
/* 圆点颜色按动作类型区分：删除/拒绝=红、账号与权限=蓝、业务数据=绿、其它=灰 */
.tl-item[data-tone="danger"]::before { border-color: var(--red); }
.tl-item[data-tone="ok"]::before { border-color: var(--green); }
.tl-item[data-tone="other"]::before { border-color: var(--gray-3); }
.tl-item:hover::before { transform: scale(1.35); background: var(--blue); }
.tl-item[data-tone="danger"]:hover::before { background: var(--red); }
.tl-item[data-tone="ok"]:hover::before { background: var(--green); }
.tl-item[data-tone="other"]:hover::before { background: var(--gray-3); }

.tl-item__head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.tl-item__time { flex: none; font-size: 11.5px; color: var(--gray-2); font-family: var(--font-num); }
.tl-item__who { font-size: 12.5px; font-weight: 600; color: var(--ink); }
.tl-item__act { font-size: 13px; color: var(--ink-2); }
.tl-item__ip { margin-left: auto; font-size: 11.5px; color: var(--gray-3); font-family: var(--font-num); }
.tl-item__detail {
  margin-top: 3px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--gray);
  word-break: break-word;
}
.tl-item__text { font-size: 13.5px; margin-top: 2px; }
.tl-item__text b { font-weight: 600; }

/* 载入动画：用纯 CSS keyframes，**不能**用 .data-reveal ——
   那套由 IntersectionObserver 驱动，只在 activate() 时对当时已存在的元素生效；
   日志是异步晚到的，新节点永远拿不到 .is-in，会停在 opacity:0（这正是「什么都看不到」的根因）。 */
@keyframes tlIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.tl-day, .tl-item {
  animation: tlIn .42s var(--ease-out) both;
  animation-delay: var(--d, 0ms);
}

/* 时间线内的空 / 失败 / 加载 */
.tl-state { padding: 34px 16px; text-align: center; }
.tl-skel { padding: 10px 0; }
.tl-skel .adm-skel { height: 12px; margin-bottom: 7px; }
.tl-skel .adm-skel:last-child { width: 52%; margin-bottom: 0; }

@media (max-width: 720px) {
  .tl-item__ip { margin-left: 0; width: 100%; }
  .adm-stats { grid-template-columns: minmax(0, 1fr); }
  .adm-stat + .adm-stat { border-left: 0; border-top: 1px solid var(--line-2); }
}

/* ---------- 21. 客户卡片 ---------- */
.cust-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }

/* 客户管理 —— 顶部工具条（搜索 + 新建） */
.cust-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
  padding: 16px 20px;
  background: var(--card);
  border: 1px solid var(--line-2);
  border-radius: var(--r, 16px);
}
.cust-bar__tools { display: flex; align-items: center; gap: 10px; }
.cust-search {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding: 0 14px;
  border-radius: 999px;
  background: var(--bg);
  border: 1px solid var(--line-2);
  transition: border-color .2s var(--ease), background .2s var(--ease), box-shadow .2s var(--ease);
}
.cust-search:focus-within {
  background: #fff;
  border-color: var(--blue);
  box-shadow: 0 0 0 4px rgba(0, 102, 204, .12);
}
.cust-search svg {
  width: 15px; height: 15px; flex: none;
  fill: none; stroke: var(--gray-2); stroke-width: 1.8; stroke-linecap: round;
}
.cust-search input {
  width: 190px; height: 100%;
  border: 0; outline: none; background: transparent;
  font-size: 13.5px; color: var(--ink);
  font-family: inherit;
}
.cust-search input::placeholder { color: var(--gray-2); }

/* 弹窗内的分组小标题 */
.seg-label {
  margin: 20px 0 10px;
  font-size: 12.5px; font-weight: 600; color: var(--gray-2);
  letter-spacing: .04em;
}

/* 空状态 */
.empty {
  grid-column: 1 / -1;
  padding: 48px 0;
  text-align: center;
  font-size: 14px;
  color: var(--gray-2);
}
.cust__logo {
  width: 42px; height: 42px;
  border-radius: 12px;
  display: grid;
  place-items: center;
  background: var(--blue-050);
  color: var(--blue);
  font-size: 17px;
  font-weight: 700;
  transition: transform .5s var(--ease-back), background-color .3s var(--ease), color .3s var(--ease);
}
.card--hover:hover .cust__logo { transform: rotate(-10deg) scale(1.1); background: var(--blue); color: #fff; }
.cust__name { font-size: 16px; font-weight: 600; margin-top: 12px; }
.cust__meta { margin-top: 8px; display: grid; gap: 4px; font-size: 13px; color: var(--gray); }
.cust__nums { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line-2); display: flex; gap: 18px; }
.cust__num b { display: block; font-family: "Inter", sans-serif; font-size: 20px; font-weight: 700; }
.cust__num span { font-size: 11.5px; color: var(--gray-2); }
.cust-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
}
.cust-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 36px;
  padding: 7px 13px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--card);
  color: var(--ink-2);
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
  transition: color .18s var(--ease), background-color .18s var(--ease), border-color .18s var(--ease), box-shadow .18s var(--ease), transform .18s var(--ease);
}
.cust-action:hover {
  color: var(--blue);
  border-color: color-mix(in srgb, var(--blue) 32%, var(--line));
  background: var(--blue-050);
  box-shadow: 0 5px 14px rgba(0, 102, 204, .12);
  transform: translateY(-1px);
}
.cust-action:active { box-shadow: none; transform: translateY(0) scale(.97); }
.cust-action:focus-visible { outline: 3px solid color-mix(in srgb, var(--blue) 24%, transparent); outline-offset: 2px; }
.cust-action--primary { color: #fff; border-color: var(--blue); background: var(--blue); box-shadow: 0 4px 12px rgba(0, 102, 204, .2); }
.cust-action--primary:hover { color: #fff; border-color: var(--blue-600); background: var(--blue-600); }
.cust-action--danger { color: #c9342c; border-color: color-mix(in srgb, var(--red) 26%, var(--line)); background: color-mix(in srgb, var(--red) 6%, var(--card)); }
.cust-action--danger:hover { color: #a9251f; border-color: color-mix(in srgb, var(--red) 42%, var(--line)); background: color-mix(in srgb, var(--red) 11%, var(--card)); box-shadow: 0 5px 14px rgba(201, 52, 44, .1); }

/* ---------- 22. 响应式 ---------- */
@media (max-width: 1180px) {
  .kpi-grid { grid-template-columns: repeat(2, 1fr); }
  .grid-2 { grid-template-columns: 1fr; }
  .pool-grid, .cust-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 900px) {
  .auth { grid-template-columns: 1fr; }
  .auth__brand { display: none; }
  .app { grid-template-columns: 76px 1fr; }
  .sidebar { padding: 18px 8px; align-items: center; }
  .sidebar__name, .sidebar__sub, .nav__item span, .user-chip__meta { display: none; }
  .nav__item { justify-content: center; padding: 0; }
  .nav__item:hover { padding-left: 0; }
  .detail-grid { grid-template-columns: repeat(2, 1fr); }
  .pool-grid, .cust-grid { grid-template-columns: 1fr; }
}

/* 减少动效偏好 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* =========================================================================
   16. 账户与权限（一级页面）
   -------------------------------------------------------------------------
   设计取向：Operate（后台管理）。目标是把「扫读—定位—操作」的路径压到最短，
   所以：表格优先、单一右侧面板承载配置、不用大卡片堆叠、不做无意义悬停动效。
   视觉沿用既有 Apple 风格令牌（--blue / --line / --r-* 系列 / --sh-* 系列 / --ease），
   深色模式不需要额外覆盖——所有颜色都走变量。
   响应式两档：
     ≤1180px：右侧面板改到下方（改单列）
     ≤ 780px：表格由「横排多列」改为「每行一张紧凑卡」，避免横向滚动
   ========================================================================= */

/* ---------- 页面头 ---------- */
.adm-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
}
.adm-head__text { min-width: 0; }
.adm-title {
  margin: 0;
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--ink);
}
.adm-desc {
  margin: 6px 0 0;
  max-width: 64ch;
  font-size: 13px;
  line-height: 1.6;
  color: var(--gray);
}
/* 自动刷新指示：静态圆点，不做任何动画 ——
   界面每秒都在轮询，悬停动画/旋转圈都属于无谓重绘，会把「不闪」的努力抵消掉。 */
.adm-live { flex: none; display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--gray); }
.adm-live > i { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--green); }
/* 连续轮询失败时变色（只在状态变化时写 DOM，不随每拍重绘） */
.adm-live[data-state="error"] { color: var(--amber-d); }
.adm-live[data-state="error"] > i { background: var(--amber); }

/* ---------- 顶部状态概览（一条细边框长条，不是三张卡片） ---------- */
.adm-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-bottom: 18px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--card);
  overflow: hidden;
}
.adm-stat { display: flex; flex-direction: column; gap: 4px; padding: 12px 16px; }
.adm-stat + .adm-stat { border-left: 1px solid var(--line-2); }
.adm-stat__label { font-size: 12.5px; color: var(--gray); }
.adm-stat__value {
  font-family: var(--font-num);
  font-size: 22px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--ink);
}
/* 只有真的有待办才上色，0 时保持中性，避免不必要的紧张感 */
.adm-stat__value[data-hot="1"] { color: var(--amber-d); }

/* ---------- 页签（分段控件，无位移动效） ---------- */
.acc-tabs {
  position: relative;
  display: inline-grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0;
  padding: 3px;
  margin-bottom: 14px;
  border-radius: var(--r-pill);
  background: var(--line-2);
}
.acc-tab-slider {
  position: absolute;
  top: 3px;
  bottom: 3px;
  left: 3px;
  width: calc(50% - 3px);
  border-radius: var(--r-pill);
  background: var(--card);
  box-shadow: 0 1px 2px rgba(15,23,42,.08), 0 7px 18px rgba(15,23,42,.08);
  transform: translateX(0);
  transition: transform .42s cubic-bezier(.16,1,.3,1), background-color .2s var(--ease), box-shadow .3s var(--ease);
  pointer-events: none;
}
.acc-tabs[data-active="grants"] .acc-tab-slider { transform: translateX(100%); }
[data-theme="dark"] .acc-tab-slider { background: var(--line); box-shadow: 0 1px 1px rgba(255,255,255,.04), 0 8px 22px rgba(0,0,0,.24); }
.acc-tab {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 18px;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--gray);
  font: inherit;
  font-size: 13.5px;
  font-weight: 500;
  cursor: pointer;
  transition: color .2s var(--ease), background-color .2s var(--ease);
}
.acc-tab:hover { color: var(--ink); }
.acc-tab.is-active { background: transparent; color: var(--ink); box-shadow: none; }
/* 深色下 --card(#171a20) 比轨道 --line-2(#1e222a) 更暗，激活项会变成「凹坑」；
   换用 --line(#262a32) 让它比轨道更亮，「凸起」的语义才与浅色一致。 */
[data-theme="dark"] .acc-tab.is-active { background: transparent; }
.acc-tab:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.acc-tab__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--amber) 22%, transparent);
  color: var(--amber-d);
  font-size: 11.5px;
  font-style: normal;
  font-weight: 600;
}

/* ---------- 主体布局：左列表 + 右详情 ---------- */
.acc-shell { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; align-items: start; }
/* 面板宽度取 300px：再宽会把并排时的可用表格宽度压到 731px 以下（实测会裁掉操作列） */
.acc-shell.has-panel { grid-template-columns: minmax(0, 1fr) 300px; }
.acc-main { min-width: 0; }
.acc-pane[hidden] { display: none; }

/* ---------- 工具栏 ---------- */
.adm-toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.adm-search {
  flex: 1 1 240px;
  min-width: 190px;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--card);
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.adm-search:focus-within { border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-050); }
.adm-search svg { width: 16px; height: 16px; flex: none; fill: none; stroke: var(--gray-2); stroke-width: 1.8; }
.adm-search input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  font: inherit;
  font-size: 13.5px;
  color: var(--ink);
}
.adm-search input::-webkit-search-cancel-button { cursor: pointer; }
.adm-filterbox { position: relative; flex: none; }
.adm-filter {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding: 0 10px 0 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--card);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}
.adm-filter:focus-within { border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-050); }
.adm-filter__label { font-size: 13px; color: var(--gray); }
.adm-filter__value { min-width: 38px; text-align: left; font-size: 13.5px; font-weight: 550; }
.adm-filter__chevron { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.8; transition: transform .28s var(--ease); }
.adm-filter[aria-expanded="true"] .adm-filter__chevron { transform: rotate(180deg); }
.adm-select-menu {
  position: absolute; z-index: 40; top: calc(100% + 8px); right: 0; min-width: 154px;
  padding: 6px; border: 1px solid color-mix(in srgb, var(--blue) 18%, var(--line)); border-radius: 12px;
  background: color-mix(in srgb, var(--card) 94%, transparent); box-shadow: 0 18px 44px rgba(15,23,42,.16), 0 2px 8px rgba(15,23,42,.08);
  backdrop-filter: blur(18px) saturate(1.2); transform-origin: top right;
}
.adm-select-menu[hidden] { display: none; }
.adm-select-menu button {
  position: relative; display: flex; align-items: center; width: 100%; min-height: 38px; padding: 0 34px 0 12px;
  border: 0; border-radius: 8px; background: transparent; color: var(--ink); font: inherit; font-size: 13.5px; text-align: left; cursor: pointer;
  transition: background-color .16s var(--ease), color .16s var(--ease), transform .2s var(--acc-motion-ease);
}
.adm-select-menu button:hover, .adm-select-menu button:focus-visible { outline: 0; background: var(--blue-050); color: var(--blue-600); transform: translateX(2px); }
.adm-select-menu button[aria-selected="true"] { background: var(--blue-050); color: var(--blue-600); font-weight: 600; }
.adm-select-menu button[aria-selected="true"]::after { content: ""; position: absolute; right: 13px; width: 7px; height: 4px; border-left: 1.8px solid currentColor; border-bottom: 1.8px solid currentColor; transform: rotate(-45deg) translateY(-1px); }
[data-theme="dark"] .adm-select-menu { background: color-mix(in srgb, var(--card) 92%, transparent); box-shadow: 0 20px 50px rgba(0,0,0,.38); }
.adm-count { margin-left: auto; font-size: 12.5px; color: var(--gray-2); }

/* ---------- 表格容器 ---------- */
.acc-tablewrap {
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--card);
  overflow-x: auto;   /* 兜底：极端窄宽度下宁可出横向滚动，也不要静默裁掉整列 */
  overflow-y: hidden;
}
.acc-table { width: 100%; }
/* 比 .tbl 默认的 14px 更紧：后台表格列多，收紧内边距换取「详情面板并排时也不裁切」 */
.acc-table th, .acc-table td { padding-left: 10px; padding-right: 10px; white-space: nowrap; }
.acc-table th:first-child, .acc-table td:first-child { padding-left: 14px; }
.acc-table th:last-child, .acc-table td:last-child { padding-right: 14px; }
.acc-table__ops { text-align: right; }
.acc-rs { display: inline-flex; align-items: center; gap: 8px; }
.acc-table tbody tr.is-self td:first-child::after {
  content: "（本人）";
  margin-left: 6px;
  font-size: 11.5px;
  color: var(--gray-2);
}
.acc-role { color: var(--gray); }
.acc-who { display: flex; flex-direction: column; gap: 2px; }
.acc-who__name { color: var(--ink); }
.acc-ops { display: inline-flex; gap: 6px; justify-content: flex-end; flex-wrap: nowrap; }
.acc-sig { max-width: 72px; max-height: 28px; display: block; }
.acc-sig--none { color: var(--gray-2); }

/* 危险操作：红色但克制（细边 + 文字红），不做实心大红块 */
.btn--danger {
  color: var(--red);
  border-color: color-mix(in srgb, var(--red) 34%, var(--line));
  background: transparent;
}
.btn--danger:hover:not([disabled]) { background: color-mix(in srgb, var(--red) 8%, transparent); }

/* ---------- 表格内的骨架 / 空 / 错 ---------- */
.acc-rowstate td { padding: 34px 16px; text-align: center; color: var(--gray); white-space: normal; }
.adm-skel-row td { padding: 14px 16px; }
.adm-skel {
  height: 12px;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--line-2) 25%, var(--line) 37%, var(--line-2) 63%);
  background-size: 400% 100%;
  animation: accShimmer 1.4s var(--ease) infinite;
}
@keyframes accShimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }
.adm-empty__title { font-size: 14px; color: var(--ink-2); }
.adm-empty__hint { margin-top: 6px; font-size: 12.5px; color: var(--gray-2); }
.adm-error { color: var(--red); }
.adm-error__hint { margin-top: 6px; font-size: 12.5px; color: var(--gray); }

/* ---------- 编辑审批页 ---------- */
.adm-note {
  margin: 0 0 12px;
  padding: 10px 14px;
  border-radius: var(--r-sm);
  background: var(--blue-050);
  border: 1px solid var(--blue-100);
  color: var(--blue-600);
  font-size: 12.5px;
  line-height: 1.6;
}

/* ---------- 右侧详情面板 ---------- */
.acc-panel {
  position: sticky;
  top: 0;
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - var(--tb-h, 64px) - 44px);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--card);
  box-shadow: var(--sh-1);
}
.acc-panel[hidden] { display: none; }
.acc-panel__head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line-2);
}
.acc-panel__title {
  flex: 1;
  min-width: 0;
  margin: 0;
  overflow: hidden;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.acc-panel__body { padding: 14px; overflow: auto; }
.acc-panel__foot {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: flex-end;
  padding: 12px 14px;
  border-top: 1px solid var(--line-2);
}
.acc-panel__foot[hidden] { display: none; }
.acc-panel__meta { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.acc-panel__row { display: flex; gap: 10px; font-size: 13px; }
.acc-panel__row dt { flex: none; width: 68px; color: var(--gray); }
.acc-panel__row dd { margin: 0; min-width: 0; color: var(--ink); word-break: break-all; }

/* 权限分组列表 */
.acc-permgroup + .acc-permgroup { margin-top: 14px; }
.acc-permgroup__title {
  margin: 0 0 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--gray);
}
.acc-perm {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--r-sm);
  cursor: pointer;
}
.acc-perm:hover { background: var(--line-2); }
.acc-perm input {
  flex: none;
  width: 16px;
  height: 16px;
  margin: 2px 0 0;
  accent-color: var(--blue);
  cursor: pointer;
}
.acc-perm input:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.acc-perm__text { min-width: 0; }
.acc-perm__name { font-size: 13.5px; color: var(--ink); }
.acc-perm__desc { margin-top: 2px; font-size: 12px; line-height: 1.5; color: var(--gray); }
.acc-panel__hint { margin: 12px 0 0; font-size: 12px; line-height: 1.6; color: var(--gray-2); }

/* ---------- 响应式（阈值由实测几何反推，不是拍的） ----------
   实测：成员表 6 列 nowrap 的固有宽度约 731px（已在 1920/1440/1280/1100/1000/420 逐一量过）。
     · 并排（面板在右、宽 300px）需要 731 + 300 + 间距 16 + 侧边栏 240 + 内边距 ≈ 1330px
       → 取 1380px 为界；再低就会把「操作」列裁掉。
     · 单列（面板在下）需要 731 + 侧边栏 240 + 内边距 ≈ 1046px
       → 低于 1080px 就改成一列一张卡，避免横向滚动。
   实测结论：1920 / 1440 / 1280 / 1100 / 1000 / 420 六档均无溢出、无横向滚动。
   -------------------------------------------------------------------- */
@media (max-width: 1379px) {
  .acc-shell.has-panel { grid-template-columns: minmax(0, 1fr); }
  .acc-panel { position: static; }
}
@media (max-width: 1080px) {
  .adm-head { flex-direction: column; align-items: stretch; }
  .adm-live { align-self: flex-start; }
  .acc-tablewrap { border: 0; background: transparent; }
  .acc-table thead { display: none; }
  .acc-table tbody tr {
    display: block;
    margin-bottom: 10px;
    padding: 12px 14px;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--card);
  }
  .acc-table tbody tr:last-child { margin-bottom: 0; }
  .acc-table td {
    display: grid;
    grid-template-columns: 84px minmax(0, 1fr);
    gap: 10px;
    padding: 3px 0;
    border: 0;
    white-space: normal;
  }
  .acc-table td::before {
    content: attr(data-th);
    font-size: 12.5px;
    color: var(--gray);
  }
  .acc-table td:empty { display: none; }
  .acc-table__ops, .acc-ops { justify-content: flex-start; text-align: left; }
  .acc-rowstate td { display: block; padding: 28px 12px; }
  .acc-rowstate td::before { content: none; }
  .adm-skel-row td { display: block; padding: 10px 0; }
  .adm-skel-row td::before { content: none; }
}
@media (max-width: 560px) {
  .adm-stats { grid-template-columns: minmax(0, 1fr); }
  .adm-stat + .adm-stat { border-left: 0; border-top: 1px solid var(--line-2); }
  .acc-tab { padding: 0 14px; }
  .adm-count { margin-left: 0; width: 100%; }
}

/* =========================================================================
   账户与权限 · 动效层
   主线是“控制台被数据唤醒”：进入页面分层展开，真实数据变化才触发反馈。
   所有空间运动仅使用 transform / opacity / filter / clip-path，不参与布局计算。
   ========================================================================= */
.view[data-view="accounts"] { --acc-motion-ease: cubic-bezier(.16, 1, .3, 1); }
.view[data-view="accounts"].is-active .adm-head {
  animation: accPageReveal .62s var(--acc-motion-ease) both;
}
.view[data-view="accounts"].is-active .adm-stats {
  animation: accPageReveal .66s var(--acc-motion-ease) .07s both, accSurfaceGlow .9s var(--acc-motion-ease) .12s both;
}
.view[data-view="accounts"].is-active .acc-tabs {
  animation: accPageReveal .58s var(--acc-motion-ease) .13s both;
}
.view[data-view="accounts"].is-active .acc-shell {
  animation: accPageReveal .66s var(--acc-motion-ease) .18s both;
}
@keyframes accPageReveal {
  from { opacity: 0; transform: translateY(16px); filter: blur(5px); }
  to { opacity: 1; transform: translateY(0); filter: blur(0); }
}
@keyframes accSurfaceGlow {
  0% { box-shadow: 0 0 0 rgba(0,102,204,0); }
  48% { box-shadow: 0 12px 34px rgba(0,102,204,.13); }
  100% { box-shadow: var(--sh-1); }
}

/* 在线状态：低频呼吸只作用于 7px 圆点，避免整块区域持续重绘。 */
.adm-live > i { position: relative; animation: accLivePulse 2.6s ease-in-out infinite; }
.adm-live > i::after {
  content: ""; position: absolute; inset: -4px; border: 1px solid currentColor;
  border-radius: 50%; opacity: 0; animation: accLiveRing 2.6s var(--acc-motion-ease) infinite;
}
@keyframes accLivePulse { 0%,100% { transform: scale(.92); opacity: .72; } 50% { transform: scale(1.12); opacity: 1; } }
@keyframes accLiveRing { 0% { transform: scale(.55); opacity: .55; } 55%,100% { transform: scale(1.35); opacity: 0; } }

/* 概览条：保持一个整体表面，只在交互时显出轻微深度和蓝色能量线。 */
.adm-stats { position: relative; box-shadow: var(--sh-1); transition: transform .3s var(--acc-motion-ease), box-shadow .3s var(--ease), border-color .3s var(--ease); }
.adm-stats::after {
  content: ""; position: absolute; inset: auto 0 0; height: 2px; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--blue), transparent);
  transform: scaleX(.12); opacity: 0; transition: transform .55s var(--acc-motion-ease), opacity .3s var(--ease);
}
.adm-stats:hover { transform: translateY(-2px); border-color: color-mix(in srgb, var(--blue) 22%, var(--line)); box-shadow: 0 10px 30px rgba(0,0,0,.09); }
.adm-stats:hover::after { transform: scaleX(.88); opacity: .55; }
.adm-stat { position: relative; transition: background-color .22s var(--ease); }
.adm-stat:hover { background: color-mix(in srgb, var(--blue-050) 52%, transparent); }
.adm-stat__value { transform-origin: left center; }

/* 页签：激活面像液态滑片般长出，文字始终清晰且可打断。 */
.acc-tab { isolation: isolate; overflow: hidden; transition: color .2s var(--ease), transform .2s var(--acc-motion-ease), box-shadow .25s var(--ease); }
.acc-tab:hover { transform: translateY(-1px); }
.acc-tab:active { transform: translateY(0) scale(.97); }
.acc-tab.is-active { background: transparent; box-shadow: none; }
[data-theme="dark"] .acc-tab.is-active { background: transparent; }
.acc-tab__count { transition: transform .28s var(--acc-motion-ease), box-shadow .28s var(--ease); }
.acc-tab:hover .acc-tab__count { transform: scale(1.08); box-shadow: 0 3px 10px color-mix(in srgb, var(--amber) 28%, transparent); }

/* 输入与筛选反馈。 */
.adm-search, .adm-filter { transition: transform .24s var(--acc-motion-ease), border-color .2s var(--ease), box-shadow .24s var(--ease), background-color .2s var(--ease); }
.adm-search:hover, .adm-filter:hover { transform: translateY(-1px); border-color: color-mix(in srgb, var(--blue) 26%, var(--line)); }
.adm-search:focus-within, .adm-filter:focus-within { transform: translateY(-2px); }
.adm-search svg { transition: transform .35s var(--acc-motion-ease), stroke .2s var(--ease); }
.adm-search:focus-within svg { transform: rotate(-9deg) scale(1.08); stroke: var(--blue); }
.adm-select-menu.is-opening { animation: accSelectOpen .3s var(--acc-motion-ease) both; }
@keyframes accSelectOpen { from { opacity: 0; transform: translateY(-7px) scale(.96); filter: blur(3px); } to { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); } }

/* 表格：整面保持稳定，行只在悬停时出现方向感与轻量高光。 */
.acc-tablewrap { position: relative; transition: border-color .3s var(--ease), box-shadow .3s var(--ease); }
.acc-tablewrap:hover { border-color: color-mix(in srgb, var(--blue) 18%, var(--line)); box-shadow: 0 9px 28px rgba(0,0,0,.06); }
.acc-table tbody tr { transition: background-color .22s var(--ease), transform .24s var(--acc-motion-ease), box-shadow .24s var(--ease); }
.acc-table tbody tr:not(.acc-rowstate):not(.adm-skel-row):not(.acc-detail-row):hover { transform: translateX(3px); box-shadow: inset 3px 0 0 color-mix(in srgb, var(--blue) 70%, transparent); }
.acc-table tbody tr:not(.acc-rowstate):not(.adm-skel-row):not(.acc-detail-row):active { transform: translateX(1px) scale(.998); }
.acc-sig { transition: transform .3s var(--acc-motion-ease), filter .3s var(--ease); transform-origin: left center; }
.acc-table tr:hover .acc-sig { transform: scale(1.08); filter: contrast(1.06); }

/* Uiverse 组件只取“反馈清晰”的原则：按钮高光掠过、按下收紧，不复制外部样式。 */
.view[data-view="accounts"] .btn { position: relative; overflow: hidden; transition: transform .18s var(--acc-motion-ease), box-shadow .24s var(--ease), color .2s var(--ease), background-color .2s var(--ease), border-color .2s var(--ease); }
.view[data-view="accounts"] .btn::after {
  content: ""; position: absolute; top: -70%; bottom: -70%; left: -38%; width: 24%; pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.55), transparent); transform: translateX(0) skewX(-18deg); opacity: 0;
}
.view[data-view="accounts"] .btn:hover:not([disabled]) { transform: translateY(-2px); box-shadow: 0 7px 18px rgba(0,102,204,.14); }
.view[data-view="accounts"] .btn:hover:not([disabled])::after { animation: accButtonSheen .68s var(--acc-motion-ease); }
.view[data-view="accounts"] .btn:active:not([disabled]) { transform: translateY(0) scale(.95); box-shadow: none; }
@keyframes accButtonSheen { 0% { transform: translateX(0) skewX(-18deg); opacity: 0; } 24% { opacity: .75; } 100% { transform: translateX(650%) skewX(-18deg); opacity: 0; } }

/* 详情工作台与权限选择。布局先切换，面板自身由 WAAPI 完成可中断入场。 */
.acc-shell { transition: grid-template-columns .42s var(--acc-motion-ease); }
.acc-main { transform-origin: left top; transition: filter .42s var(--acc-motion-ease); }
.acc-shell.has-panel .acc-main { filter: saturate(.9); }
.acc-shell.has-panel .acc-tablewrap { box-shadow: inset -18px 0 28px -30px color-mix(in srgb, var(--blue) 45%, transparent); }
.acc-panel { transform-origin: right top; overflow: hidden; }
.acc-panel__head { position: relative; }
.acc-panel__head::after { content: ""; position: absolute; right: 14px; bottom: -1px; left: 14px; height: 1px; background: linear-gradient(90deg, transparent, var(--blue), transparent); opacity: .35; }
.acc-panel__close { transition: background-color .2s var(--ease), color .2s var(--ease); }
.acc-panel__row { transition: transform .22s var(--acc-motion-ease), background-color .2s var(--ease); border-radius: 7px; }
.acc-panel__row:hover { transform: translateX(3px); background: var(--line-2); }
.acc-perm { position: relative; overflow: hidden; transition: transform .22s var(--acc-motion-ease), background-color .2s var(--ease), box-shadow .24s var(--ease); }
.acc-perm:hover { transform: translateX(3px); }
.acc-perm:has(input:checked) { background: color-mix(in srgb, var(--blue-050) 76%, transparent); box-shadow: inset 2px 0 0 var(--blue); }
.acc-perm input { transition: transform .24s var(--acc-motion-ease), filter .2s var(--ease); }
.acc-perm input:checked { transform: scale(1.08); filter: drop-shadow(0 2px 4px color-mix(in srgb, var(--blue) 30%, transparent)); }

/* 移动端卡片不横移，避免贴边视觉抖动。 */
@media (max-width: 1080px) {
  .acc-table tbody tr:not(.acc-rowstate):not(.adm-skel-row):not(.acc-detail-row):hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0,0,0,.08); }
}

/* 减少动态效果：保留颜色与焦点反馈，移除位移、模糊和循环。 */
@media (prefers-reduced-motion: reduce) {
  .view[data-view="accounts"].is-active .adm-head,
  .view[data-view="accounts"].is-active .adm-stats,
  .view[data-view="accounts"].is-active .acc-tabs,
  .view[data-view="accounts"].is-active .acc-shell,
  .adm-live > i, .adm-live > i::after,
  .view[data-view="accounts"] .btn:hover::after, .adm-select-menu.is-opening { animation: none !important; }
  .view[data-view="accounts"] *, .view[data-view="accounts"] *::before, .view[data-view="accounts"] *::after {
    scroll-behavior: auto !important; transition-duration: .01ms !important;
  }
  .adm-stats:hover, .acc-tab:hover, .adm-search:hover, .adm-filter:hover,
  .acc-table tbody tr:hover, .view[data-view="accounts"] .btn:hover,
  .acc-panel__close:hover, .acc-panel__row:hover, .acc-perm:hover { transform: none !important; }
  .acc-tab-slider { transition-duration: .01ms !important; }
}

/* 账户详情保持在当前可视区内；标题与操作区固定，中段独立滚动。 */
.acc-panel {
  height: clamp(420px, calc(100dvh - 190px), 640px);
  max-height: calc(100dvh - 190px);
  min-height: 0;
}
.acc-panel__head,
.acc-panel__foot { flex: none; }
.acc-panel__body {
  flex: 1;
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-color: color-mix(in srgb, var(--gray) 42%, transparent) transparent;
  scrollbar-width: thin;
}
.acc-panel__body::-webkit-scrollbar { width: 8px; }
.acc-panel__body::-webkit-scrollbar-track { background: transparent; }
.acc-panel__body::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--gray) 36%, transparent);
  border: 2px solid transparent;
  border-radius: 999px;
  background-clip: padding-box;
}
.acc-panel__body::-webkit-scrollbar-thumb:hover { background-color: color-mix(in srgb, var(--gray) 58%, transparent); }
.acc-panel__meta { gap: 6px; margin-bottom: 12px; }
.acc-panel__row { line-height: 1.35; }
.acc-permgroup + .acc-permgroup { margin-top: 10px; }
.acc-permgroup__title { margin-bottom: 4px; }
.acc-perm {
  min-height: 32px;
  padding: 6px 8px;
  align-items: center;
}
.acc-perm input { margin-top: 0; }
.acc-perm__desc { line-height: 1.35; }
@media (max-width: 1379px) {
  .acc-panel {
    height: clamp(420px, calc(100dvh - 190px), 640px);
    max-height: calc(100dvh - 190px);
  }
}
@media (max-height: 680px) {
  .acc-panel {
    height: calc(100dvh - 150px);
    max-height: calc(100dvh - 150px);
  }
  .acc-panel__head, .acc-panel__foot { padding-block: 9px; }
  .acc-panel__body { padding-block: 10px; }
}

/* 委托单操作：将文字链接收束为可识别、可聚焦的紧凑按钮组。 */
.order-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; min-width: 330px; }
.order-action {
  display: inline-flex; align-items: center; gap: 5px; min-height: 32px; padding: 6px 9px;
  color: var(--ink-2); font: inherit; font-size: 12px; white-space: nowrap; cursor: pointer;
  background: color-mix(in srgb, var(--card) 90%, var(--blue-050)); border: 1px solid var(--line); border-radius: 9px;
  box-shadow: 0 1px 1px rgba(15,23,42,.03);
  transition: color .2s var(--ease), background-color .2s var(--ease), border-color .2s var(--ease), transform .2s cubic-bezier(.2,.8,.2,1), box-shadow .2s var(--ease);
}
.order-action svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.order-action:hover { color: var(--blue); border-color: color-mix(in srgb, var(--blue) 34%, var(--line)); background: var(--blue-050); box-shadow: 0 5px 14px rgba(0,102,204,.12); transform: translateY(-2px); }
.order-action:active { transform: translateY(0) scale(.96); box-shadow: none; }
.order-action:focus-visible { outline: 3px solid color-mix(in srgb, var(--blue) 24%, transparent); outline-offset: 2px; }
.order-action--flow { color: #6953c7; background: color-mix(in srgb, #7659dc 8%, var(--card)); border-color: color-mix(in srgb, #7659dc 22%, var(--line)); }
.order-action--flow:hover { color: #6246c7; background: color-mix(in srgb, #7659dc 13%, var(--card)); border-color: color-mix(in srgb, #7659dc 42%, var(--line)); box-shadow: 0 5px 14px rgba(102,74,196,.14); }
.order-action--danger { color: var(--gray); }
.order-action--danger:hover { color: #c23b34; background: color-mix(in srgb, #d54840 8%, var(--card)); border-color: color-mix(in srgb, #d54840 30%, var(--line)); box-shadow: 0 5px 14px rgba(197,55,48,.1); }

/* 流转单 PDF 工作台。 */
/* 2026-09-18：流转单从「全屏界面」改为「居中弹窗」。
   全屏界面配右上角叉不符合交互逻辑（全屏该用「返回」，弹窗才用叉）。
   外层 .transfer-fullscreen 降级为遮罩层，卡片实体是 .transfer-modal__card。 */
.transfer-fullscreen { position: fixed; inset: 0; z-index: 1320; display: grid; place-items: center; padding: 28px; background: rgba(15,23,42,.44); animation: transferVeilIn .22s var(--ease) both; }
.transfer-modal__card { display: flex; flex-direction: column; width: min(1200px, 100%); height: min(780px, 100%); overflow: hidden; color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 20px; box-shadow: var(--sh-2); animation: transferEnter .32s cubic-bezier(.2,.8,.2,1) both; }
@keyframes transferVeilIn { from { opacity: 0; } to { opacity: 1; } }
.transfer-fullscreen__bar { display: flex; align-items: center; justify-content: space-between; min-height: 68px; padding: 0 26px; background: color-mix(in srgb, var(--card) 92%, transparent); border-bottom: 1px solid var(--line); backdrop-filter: blur(18px); }
.transfer-fullscreen__bar > div { display: grid; gap: 3px; }
.transfer-fullscreen__bar span, .transfer-eyebrow { color: var(--blue); font-size: 11px; font-weight: 650; letter-spacing: .12em; text-transform: uppercase; }
.transfer-fullscreen__bar strong { font-size: 16px; }
.transfer-fullscreen__close { display: grid; place-items: center; width: 36px; height: 36px; padding: 0; color: var(--gray); cursor: pointer; background: var(--bg-2); border: 1px solid var(--line); border-radius: 50%; transition: color .2s, background-color .2s, border-color .2s; }
.transfer-fullscreen__close svg { display: block; width: 20px; height: 20px; overflow: visible; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; transform-box: view-box; transform-origin: 50% 50%; transition: transform .28s cubic-bezier(.16,1,.3,1); }
.transfer-fullscreen__close:hover { color: var(--ink); background: var(--card); border-color: color-mix(in srgb, var(--blue) 24%, var(--line)); }
.transfer-fullscreen__close:hover svg { transform: rotate(90deg); }
.transfer-fullscreen__close:active svg { transform: rotate(90deg) scale(.88); }
.transfer-fullscreen__content { display: grid; grid-template-columns: minmax(0, 1fr) 350px; flex: 1; min-height: 0; }
.transfer-fullscreen__preview { min-width: 0; padding: 20px; background: color-mix(in srgb, var(--bg-2) 80%, var(--blue-050)); }
/* 弹窗高度由卡片封顶（780px），所以 iframe 的下限要跟着放低：
   原来 680px 是给「全屏界面」用的，改成弹窗后会把卡片撑破导致 PDF 下沿被裁。 */
.transfer-fullscreen__preview iframe { display: block; width: 100%; height: 100%; min-height: 420px; background: #fff; border: 1px solid var(--line); border-radius: 14px; box-shadow: 0 18px 50px rgba(15,23,42,.12); }
.transfer-fullscreen__actions { padding: 30px 24px; overflow-y: auto; background: var(--card); border-left: 1px solid var(--line); }
.transfer-fullscreen__actions h3 { margin: 10px 0 8px; font-size: 23px; letter-spacing: -.03em; }
.transfer-fullscreen__actions > p { margin: 0 0 24px; color: var(--gray); font-size: 13px; line-height: 1.65; }
.transfer-sign-stack { display: grid; gap: 10px; }
/* 流转单签字进度（2026-09-30）：签齐 3/3 时转绿，并提示下一步去点「生成原始记录」 */
.transfer-sign-progress { margin: 0 0 12px; padding: 8px 12px; color: var(--gray); font-size: 12px; font-weight: 600; letter-spacing: .01em; background: var(--bg); border: 1px solid var(--line); border-radius: 10px; }
.transfer-sign-progress.is-done { color: var(--green); background: color-mix(in srgb, var(--green) 8%, var(--bg)); border-color: color-mix(in srgb, var(--green) 30%, var(--line)); }
[data-theme="dark"] .transfer-sign-progress { background: #10151d; }
[data-theme="dark"] .transfer-sign-progress.is-done { background: color-mix(in srgb, var(--green) 14%, #10151d); }
.transfer-sign-btn { display: grid; grid-template-columns: 34px 1fr; gap: 1px 11px; width: 100%; padding: 14px; color: var(--ink); text-align: left; cursor: pointer; background: var(--bg); border: 1px solid var(--line); border-radius: 12px; transition: transform .22s cubic-bezier(.2,.8,.2,1), border-color .2s, box-shadow .22s, background-color .2s; }
.transfer-sign-btn > span { grid-row: 1 / 3; display: grid; place-items: center; width: 34px; height: 34px; color: var(--blue); font-size: 11px; font-weight: 700; background: var(--blue-050); border-radius: 9px; }
.transfer-sign-btn b { color: var(--ink); font-size: 13px; font-weight: 650; }
.transfer-sign-btn small { color: var(--gray); font-size: 11px; }
/* 三个签字位沿用旧版的绿/青/紫身份色，但只染角标，正文一律深色。
   旧版是「彩色渐变底 + 白字」，搬到新界面的白色侧栏上会白字看不见底，
   所以这里把颜色收进角标，既保住三种角色的辨识度，又不牺牲可读性。 */
.transfer-sign-btn[data-transfer-sign="acceptor"] > span { color: #1a7f37; background: color-mix(in srgb, #34c759 18%, transparent); }
.transfer-sign-btn[data-transfer-sign="receiver"] > span { color: #0e7490; background: color-mix(in srgb, #06b6d4 18%, transparent); }
.transfer-sign-btn[data-transfer-sign="claimer"] > span { color: #6d28d9; background: color-mix(in srgb, #8b5cf6 18%, transparent); }
.transfer-sign-btn:hover:not(:disabled) { border-color: color-mix(in srgb, var(--blue) 38%, var(--line)); background: color-mix(in srgb, var(--blue-050) 60%, var(--card)); box-shadow: 0 9px 22px rgba(0,102,204,.11); transform: translateX(-4px); }
.transfer-sign-btn:disabled { cursor: wait; opacity: .58; }
/* 已签字：落锁态。禁用的同时保持可读（不要 inherit 上面的半透明），角标转绿。 */
.transfer-sign-btn.is-signed:disabled { cursor: default; opacity: 1; background: color-mix(in srgb, var(--green) 9%, var(--bg)); border-color: color-mix(in srgb, var(--green) 34%, var(--line)); }
/* 用 [data-transfer-sign] 把权重抬到与上面三条角色色相同，靠「写在后面」取胜 */
.transfer-sign-btn.is-signed[data-transfer-sign] > span { color: #1a7f37; background: color-mix(in srgb, #34c759 20%, transparent); }
.transfer-sign-message { min-height: 42px; padding: 12px 2px; color: var(--gray); font-size: 12px; line-height: 1.5; }
/* 流转单日期（2026-09-29，需求二）：签订后出现在该签字位按钮下方，一对一绑定。
   签字动作触发回填当天日期；之后可手动改动覆盖（改动即落库）。 */
.transfer-sign-slot { display: grid; gap: 8px; }
.transfer-sign-date { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 10px; padding: 9px 12px 9px 14px; background: color-mix(in srgb, var(--green) 7%, var(--bg)); border: 1px solid color-mix(in srgb, var(--green) 26%, var(--line)); border-radius: 10px; }
.transfer-sign-date[hidden] { display: none; }
.transfer-sign-date label { color: var(--gray); font-size: 11px; font-weight: 600; white-space: nowrap; }
.transfer-sign-date .transfer-date-input { width: 100%; min-height: 32px; padding: 4px 9px; color: var(--ink); font-family: inherit; font-size: 12px; background: var(--card); border: 1px solid var(--line); border-radius: 8px; }
.transfer-sign-date .transfer-date-input:focus { border-color: var(--blue); outline: none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 16%, transparent); }
.transfer-sign-date .transfer-date-input:disabled { cursor: wait; opacity: .6; }
[data-theme="dark"] .transfer-sign-date { background: color-mix(in srgb, var(--green) 12%, #10151d); }
.transfer-download-btn { display: flex; align-items: center; justify-content: center; min-height: 42px; color: #fff; font-size: 13px; font-weight: 650; text-decoration: none; background: var(--blue); border-radius: 11px; box-shadow: 0 9px 20px rgba(0,102,204,.2); transition: transform .2s cubic-bezier(.2,.8,.2,1), box-shadow .2s; }
.transfer-download-btn:hover { color: #fff; box-shadow: 0 13px 28px rgba(0,102,204,.28); transform: translateY(-2px); }
@keyframes transferEnter { from { opacity: 0; transform: scale(.985); } to { opacity: 1; transform: scale(1); } }
[data-theme="dark"] .order-action { background: color-mix(in srgb, var(--card) 88%, white 2%); }
[data-theme="dark"] .transfer-fullscreen__preview { background: #0c1017; }
[data-theme="dark"] .transfer-fullscreen__preview iframe { border-color: #2d3644; box-shadow: 0 20px 60px rgba(0,0,0,.38); }
@media (max-width: 900px) {
  .order-actions { min-width: 0; }
  .order-action span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .order-action { padding: 8px; }
  /* 窄屏时弹窗铺满可视区（仍是弹窗语义：遮罩 + 圆角卡片，不用全屏那套） */
  .transfer-fullscreen { padding: 12px; }
  .transfer-modal__card { height: 100%; border-radius: 16px; }
  .transfer-fullscreen__content { grid-template-columns: 1fr; overflow-y: auto; }
  .transfer-fullscreen__preview { min-height: 62vh; }
  .transfer-fullscreen__actions { border-top: 1px solid var(--line); border-left: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .transfer-fullscreen, .transfer-modal__card { animation: none; }
  .order-action, .transfer-fullscreen__close, .transfer-fullscreen__close svg, .transfer-sign-btn, .transfer-download-btn { transition-duration: .01ms !important; }
  .order-action:hover, .transfer-fullscreen__close:hover svg, .transfer-fullscreen__close:active svg, .transfer-sign-btn:hover, .transfer-download-btn:hover { transform: none; }
}

/* PDF 预览缩放条（2026-09-29）：报告审核 / 流转单 / 委托单三处工作台共用同一份 DOM。
   记忆值存偏好 pdf_zoom，DOM 与绑定见 app.js 的 pdfZoomBarHtml / bindPdfZoomBar。 */
.pdf-zoom { display: flex; align-items: center; gap: 10px; margin: 0 0 14px; }
.pdf-zoom[hidden] { display: none; }
.pdf-zoom__label { flex: none; color: var(--gray); font-size: 11px; font-weight: 650; letter-spacing: .06em; }
.pdf-zoom__group { display: inline-flex; align-items: center; gap: 2px; padding: 3px; background: var(--bg); border: 1px solid var(--line); border-radius: 10px; }
.pdf-zoom__btn { display: grid; place-items: center; width: 28px; height: 28px; padding: 0; color: var(--gray); cursor: pointer; background: transparent; border: 0; border-radius: 7px; transition: color .18s, background-color .18s, transform .18s cubic-bezier(.16,1,.3,1); }
.pdf-zoom__btn svg { display: block; width: 15px; height: 15px; overflow: visible; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.pdf-zoom__btn:hover:not(:disabled) { color: var(--blue); background: color-mix(in srgb, var(--blue) 10%, var(--card)); }
.pdf-zoom__btn:active:not(:disabled) { transform: scale(.9); }
.pdf-zoom__btn:disabled { cursor: default; opacity: .32; }
.pdf-zoom__value { display: grid; place-items: center; min-width: 58px; height: 28px; padding: 0 6px; color: var(--ink); font-family: "Inter", "Noto Sans SC", sans-serif; font-size: 12px; font-weight: 650; font-variant-numeric: tabular-nums; cursor: pointer; background: var(--card); border: 0; border-radius: 7px; box-shadow: 0 1px 2px rgba(15,23,42,.07); transition: color .18s, background-color .18s; }
.pdf-zoom__value:hover { color: var(--blue); background: color-mix(in srgb, var(--blue) 7%, var(--card)); }
[data-theme="dark"] .pdf-zoom__group { background: color-mix(in srgb, #000 26%, var(--bg)); }
[data-theme="dark"] .pdf-zoom__value { background: color-mix(in srgb, #fff 8%, var(--card)); box-shadow: none; }
@media (prefers-reduced-motion: reduce) {
  .pdf-zoom__btn, .pdf-zoom__value { transition: none; }
  .pdf-zoom__btn:active:not(:disabled) { transform: none; }
}

/* 关闭控件统一使用 SVG 几何中心旋转，按钮容器本身保持不动。 */
.app-confirm__close,.report-fullscreen__close { display:grid; place-items:center; padding:0; }
.app-confirm__close svg,.modal__close svg,.report-fullscreen__close svg,.acc-panel__close svg,.order-form-close svg { display:block; overflow:visible; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; transform-box:view-box; transform-origin:50% 50%; transition:transform .28s cubic-bezier(.16,1,.3,1); }
.app-confirm__close svg { width:17px; height:17px; }
.report-fullscreen__close svg { width:18px; height:18px; }
.modal__close:hover,.acc-panel__close:hover { transform:none; }
.app-confirm__close:hover svg,.modal__close:hover svg,.report-fullscreen__close:hover svg,.acc-panel__close:hover svg,.order-form-close:hover svg { transform:rotate(90deg); }
@media (prefers-reduced-motion:reduce) { .app-confirm__close svg,.modal__close svg,.report-fullscreen__close svg,.acc-panel__close svg,.order-form-close svg { transition:none; } .app-confirm__close:hover svg,.modal__close:hover svg,.report-fullscreen__close:hover svg,.acc-panel__close:hover svg,.order-form-close:hover svg { transform:none; } }
/* 委托方客户联想：配色克制，动效用于状态反馈 */
.customer-suggestion-menu{overflow:hidden;animation:customerMenuIn .24s cubic-bezier(.16,1,.3,1) both}
.customer-suggestion{width:100%;border:0;background:#fff;color:#172033;padding:11px 14px;text-align:left;display:flex;justify-content:space-between;gap:14px;cursor:pointer;transition:background .18s ease,transform .18s cubic-bezier(.16,1,.3,1)}
.customer-suggestion:hover,.customer-suggestion:focus-visible{background:#eef5ff;transform:translateX(3px);outline:none}.customer-suggestion strong{font-size:14px}.customer-suggestion span{font-size:12px;color:#59677d;white-space:nowrap}
[data-theme="dark"] .customer-suggestion-menu { background:#1b2029; color:#dce5f2; }
[data-theme="dark"] .customer-suggestion { background:#1b2029; color:#dce5f2; }
[data-theme="dark"] .customer-suggestion span { color:#a9b8cb; }
[data-theme="dark"] .customer-suggestion:hover,
[data-theme="dark"] .customer-suggestion:focus-visible { background:#202e43; color:#8dc1ff; }
[data-theme="dark"] .customer-suggestion:focus-visible { outline:2px solid #8dc1ff; outline-offset:-2px; }
.customer-field-filled{animation:customerFieldFill .58s cubic-bezier(.16,1,.3,1)}
.customer-confirm-dialog{width:min(480px,calc(100vw - 32px));border:0;border-radius:16px;padding:0;color:#172033;box-shadow:0 22px 70px rgba(25,40,70,.24);animation:customerDialogIn .32s cubic-bezier(.16,1,.3,1) both}.customer-confirm-dialog::backdrop{background:rgba(24,35,52,.46);backdrop-filter:blur(5px)}
.customer-confirm-dialog__head{padding:24px 24px 12px}.customer-confirm-dialog__head h2{margin:0 0 7px;font-size:19px}.customer-confirm-dialog__head p{margin:0;color:#59677d;font-size:13px}.customer-confirm-dialog__name{margin:4px 24px 16px;padding:15px;border-radius:12px;background:#f1f5fa;font-size:18px;font-weight:650;word-break:break-all}
.customer-confirm-dialog__similar{padding:0 24px 16px;display:flex;flex-wrap:wrap;gap:8px}.customer-confirm-dialog__similar>span{width:100%;font-size:12px;color:#59677d}.customer-confirm-dialog__similar button{border:1px solid #bfd1e8;background:#fff;color:#22517f;border-radius:9px;padding:7px 10px;cursor:pointer;transition:transform .18s,background .18s}.customer-confirm-dialog__similar button:hover{transform:translateY(-2px);background:#eef5ff}.customer-confirm-dialog__actions{padding:16px 24px 24px;display:flex;justify-content:flex-end;gap:10px}
@keyframes customerMenuIn{from{opacity:.35;transform:translateY(-7px);clip-path:inset(0 0 100% 0 round 12px);filter:blur(3px)}to{opacity:1;transform:none;clip-path:inset(0 round 12px);filter:none}}
@keyframes customerFieldFill{0%{background:#dfeeff;box-shadow:0 0 0 3px rgba(64,122,190,.18)}100%{background:inherit;box-shadow:none}}
@keyframes customerDialogIn{from{opacity:.2;transform:translateY(18px) scale(.97);filter:blur(5px)}to{opacity:1;transform:none;filter:none}}
@media (prefers-reduced-motion: reduce){.customer-suggestion-menu,.customer-field-filled,.customer-confirm-dialog{animation:none}.customer-suggestion,.customer-confirm-dialog__similar button{transition:none}}

/* 通知中心：真实入口的液态玻璃开关与交互卡片。 */
.notification-modal { width:min(720px,94vw)!important; padding:26px!important; overflow:hidden!important; background:color-mix(in srgb,var(--card) 76%,transparent)!important; border:1px solid color-mix(in srgb,#fff 58%,var(--line))!important; box-shadow:0 30px 90px rgba(15,23,42,.28),inset 0 1px 0 rgba(255,255,255,.62)!important; backdrop-filter:blur(30px) saturate(1.35); -webkit-backdrop-filter:blur(30px) saturate(1.35); }
.notification-modal::before { content:""; position:absolute; inset:0; z-index:-1; pointer-events:none; border-radius:inherit; background:linear-gradient(135deg,rgba(255,255,255,.38),transparent 36%,color-mix(in srgb,var(--blue) 8%,transparent)); }
.notification-modal>.modal__title { padding:0 46px 20px 0; font-size:22px; letter-spacing:-.025em; border-bottom:1px solid color-mix(in srgb,var(--line) 74%,transparent); }
.notification-modal>.modal__body { margin-top:18px; }
.notif-center { display:grid; gap:20px; }
.notif-center__inbox { display:grid; gap:8px; max-height:150px; overflow:auto; }
.notif-center__note { display:flex; align-items:flex-start; gap:10px; padding:10px 12px; color:var(--ink-2); background:color-mix(in srgb,var(--card) 54%,transparent); border-radius:10px; }
.notif-center__note>span { width:7px; height:7px; margin-top:6px; flex:none; background:var(--blue); border-radius:50%; }
.notif-center__note p { margin:0; font-size:12px; line-height:1.5; }
.notif-center__empty { display:flex; align-items:center; gap:10px; min-height:42px; color:var(--gray); font-size:12px; }
.notif-center__empty svg { width:18px; height:18px; fill:none; stroke:currentColor; stroke-width:1.7; stroke-linecap:round; }
.notif-center__settings { padding:12px; background:color-mix(in srgb,var(--bg-2) 58%,transparent); border:1px solid color-mix(in srgb,#fff 48%,var(--line)); border-radius:16px; box-shadow:inset 0 1px 0 color-mix(in srgb,#fff 58%,transparent); backdrop-filter:blur(18px) saturate(1.2); }
.notif-center__heading { display:flex; align-items:flex-start; justify-content:space-between; gap:18px; padding:5px 5px 13px; }
.notif-center__heading h3 { margin:0 0 4px; color:var(--ink); font-size:16px; }
.notif-center__heading p { margin:0; color:var(--gray); font-size:12px; }
.notif-center__heading>span { padding:5px 9px; color:var(--blue); font-size:10px; font-weight:700; background:var(--blue-050); border-radius:999px; }
.notif-pref-list { display:grid; gap:9px; }
.notif-pref { position:relative; isolation:isolate; display:grid; grid-template-columns:42px minmax(0,1fr) auto; align-items:center; gap:14px; min-height:78px; padding:12px 14px; overflow:hidden; cursor:pointer; background:color-mix(in srgb,var(--card) 62%,transparent); border:1px solid color-mix(in srgb,#fff 60%,var(--line)); border-radius:14px; box-shadow:0 8px 24px rgba(15,23,42,.07),inset 0 1px 0 rgba(255,255,255,.58); backdrop-filter:blur(18px) saturate(1.25); transition:transform .3s cubic-bezier(.16,1,.3,1),background-color .2s,border-color .2s,box-shadow .24s; }
.notif-pref::after { content:""; position:absolute; z-index:-1; top:-90%; left:-30%; width:32%; height:280%; pointer-events:none; background:linear-gradient(90deg,transparent,rgba(255,255,255,.62),transparent); opacity:0; transform:rotate(12deg); }
.notif-pref:hover { transform:translateY(-2px) scale(1.006); border-color:color-mix(in srgb,var(--blue) 28%,var(--line)); box-shadow:0 13px 30px rgba(15,23,42,.11),inset 0 1px 0 rgba(255,255,255,.72); }
.notif-pref:hover::after { opacity:.7; transform:translateX(410%) rotate(12deg); transition:transform .72s cubic-bezier(.16,1,.3,1),opacity .2s; }
.notif-pref:active { transform:scale(.99); }
.notif-pref.is-on { background:color-mix(in srgb,var(--blue-050) 72%,var(--card)); border-color:color-mix(in srgb,var(--blue) 30%,var(--line)); }
.notif-pref__icon { display:grid; place-items:center; width:42px; height:42px; color:var(--gray); background:color-mix(in srgb,var(--bg-2) 72%,transparent); border-radius:11px; transition:transform .3s cubic-bezier(.16,1,.3,1),color .2s,background-color .2s; }
.notif-pref__icon svg { width:21px; height:21px; fill:none; stroke:currentColor; stroke-width:1.75; stroke-linecap:round; stroke-linejoin:round; }
.notif-pref.is-on .notif-pref__icon { color:var(--blue); background:color-mix(in srgb,var(--blue) 13%,var(--card)); transform:scale(1.04); }
.notif-pref__copy { display:grid; gap:3px; min-width:0; }
.notif-pref__copy strong { color:var(--ink); font-size:13px; font-weight:650; }
.notif-pref__copy small { overflow:hidden; color:var(--gray); font-size:11px; line-height:1.45; text-overflow:ellipsis; white-space:nowrap; }
.notif-pref__copy em { color:var(--gray-2); font-size:10px; font-style:normal; font-weight:650; }
.notif-pref.is-on .notif-pref__copy em { color:var(--blue); }
.notif-glass-switch { position:relative; width:52px; height:31px; flex:none; }
.notif-glass-switch input { position:absolute; width:1px; height:1px; opacity:0; }
.notif-glass-switch>span { position:absolute; inset:0; overflow:hidden; background:color-mix(in srgb,var(--gray) 38%,transparent); border:1px solid rgba(255,255,255,.5); border-radius:999px; box-shadow:inset 0 2px 5px rgba(15,23,42,.16),inset 0 1px 0 rgba(255,255,255,.46); transition:background .32s cubic-bezier(.16,1,.3,1),box-shadow .28s,border-color .28s; }
.notif-glass-switch>span::before { content:""; position:absolute; top:2px; left:2px; width:25px; height:25px; box-sizing:border-box; background:linear-gradient(145deg,#fff,rgba(241,245,249,.88)); border:1px solid rgba(255,255,255,.92); border-radius:50%; box-shadow:0 3px 8px rgba(15,23,42,.28),inset 0 1px 0 #fff; transition:transform .42s cubic-bezier(.16,1,.3,1),width .18s ease; }
.notif-glass-switch input:checked+span { background:linear-gradient(135deg,#60a5fa,var(--blue)); border-color:rgba(147,197,253,.78); box-shadow:inset 0 2px 5px rgba(30,64,175,.25),0 5px 15px rgba(37,99,235,.22); }
.notif-glass-switch input:checked+span::before { transform:translateX(21px); }
.notif-glass-switch:active>span::before { width:28px; }
.notif-glass-switch:active input:checked+span::before { transform:translateX(18px); }
.notif-glass-switch input:focus-visible+span { outline:3px solid color-mix(in srgb,var(--blue) 28%,transparent); outline-offset:3px; }
.notif-center__footer { display:flex; align-items:center; justify-content:space-between; gap:14px; padding:15px 5px 3px; }
.notif-center__footer>span { color:var(--gray); font-size:11px; }
#saveNotif { display:inline-flex; align-items:center; justify-content:center; gap:7px; min-width:126px; min-height:40px; color:#fff; font-size:13px; font-weight:650; cursor:pointer; background:var(--blue); border:0; border-radius:10px; box-shadow:0 6px 16px rgba(0,102,204,.22); transition:transform .22s cubic-bezier(.16,1,.3,1),box-shadow .22s,background-color .2s; }
#saveNotif svg { width:17px; height:17px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; transition:transform .3s cubic-bezier(.16,1,.3,1); }
#saveNotif:hover { transform:translateY(-2px); box-shadow:0 9px 22px rgba(0,102,204,.28); }
#saveNotif:active { transform:scale(.96); box-shadow:none; }
#saveNotif.has-changes svg { transform:scale(1.16); }
#saveNotif.is-saving svg { animation:notifSavePulse .78s ease-in-out infinite alternate; }
#saveNotif:disabled { opacity:.66; cursor:wait; }
@keyframes notifSavePulse { to { transform:scale(1.2); } }
[data-theme="dark"] .notification-modal { background:rgba(22,27,35,.76)!important; border-color:rgba(148,163,184,.17)!important; box-shadow:0 34px 96px rgba(0,0,0,.58),inset 0 1px 0 rgba(255,255,255,.07)!important; }
[data-theme="dark"] .notification-modal::before { background:linear-gradient(135deg,rgba(255,255,255,.07),transparent 40%,rgba(59,130,246,.07)); }
[data-theme="dark"] .notif-center__settings { background:rgba(30,37,47,.48); border-color:rgba(148,163,184,.13); }
[data-theme="dark"] .notif-pref { background:rgba(37,45,56,.5); border-color:rgba(148,163,184,.13); box-shadow:0 10px 28px rgba(0,0,0,.2),inset 0 1px 0 rgba(255,255,255,.05); }
[data-theme="dark"] .notif-pref:hover { background:rgba(45,56,70,.72); border-color:rgba(96,165,250,.34); }
[data-theme="dark"] .notif-pref.is-on { background:linear-gradient(135deg,rgba(38,57,84,.82),rgba(32,39,49,.66)); border-color:rgba(96,165,250,.34); }
@media (max-width:640px) { .notification-modal { padding:20px 14px!important; } .notif-pref { grid-template-columns:38px minmax(0,1fr) auto; gap:10px; padding:11px 10px; } .notif-pref__copy small { white-space:normal; } .notif-center__footer { align-items:stretch; flex-direction:column; } #saveNotif { width:100%; } }
@media (prefers-reduced-motion:reduce) { .notif-pref,#saveNotif,.notif-glass-switch>span,.notif-glass-switch>span::before { transition:none!important; } .notif-pref:hover,#saveNotif:hover { transform:none; } .notif-pref:hover::after { display:none; } #saveNotif.is-saving svg { animation:none; } }

/* 个人中心：签名与账户安全共用的液态玻璃工作台。 */
.profile-modal { width:min(840px,94vw)!important; padding:26px!important; overflow:hidden!important; background:color-mix(in srgb,var(--card) 76%,transparent)!important; border:1px solid color-mix(in srgb,#fff 58%,var(--line))!important; box-shadow:0 30px 90px rgba(15,23,42,.28),inset 0 1px 0 rgba(255,255,255,.62)!important; backdrop-filter:blur(30px) saturate(1.35); -webkit-backdrop-filter:blur(30px) saturate(1.35); }
.profile-modal::before { content:""; position:absolute; inset:0; z-index:-1; pointer-events:none; border-radius:inherit; background:linear-gradient(135deg,rgba(255,255,255,.4),transparent 38%,color-mix(in srgb,var(--blue) 8%,transparent)); }
.profile-modal>.modal__title { padding:0 46px 18px 0; font-size:22px; letter-spacing:-.025em; }
/* 2026-09-29：个人中心内容（签名 + 密码 + 界面效果 + 通知设置 4 个开关）总高必然超过
   视口，而本弹窗为了裁圆角用了 overflow:hidden!important ⇒ 把 liveModal 内联的
   overflow:auto 吃掉了 ⇒ 滚不动、底部内容被截断（用户报障「通知设置显示不全」）。
   解法：外层继续 hidden（负责圆角与 ::before 装饰裁剪），滚动交给 .modal__body。 */
.profile-modal { display:flex; flex-direction:column; }
.profile-modal>.modal__body {
  flex:1 1 auto; min-height:0;                 /* 关键：允许被压缩，否则 flex 子项会撑破容器 */
  max-height:calc(90vh - 120px);               /* 兜底：flex 未生效时也不越出视口 */
  overflow-y:auto; overscroll-behavior:contain;/* 滚到底不再带动背后页面 */
  padding-right:4px;                           /* 给滚动条让位，别压住卡片阴影 */
  scrollbar-width:thin;
}
.profile-center { display:grid; gap:16px; }
.profile-hero { display:flex; align-items:center; gap:13px; padding:14px 16px; background:color-mix(in srgb,var(--blue-050) 54%,transparent); border:1px solid color-mix(in srgb,var(--blue) 16%,var(--line)); border-radius:14px; }
.profile-avatar { display:grid; place-items:center; width:46px; height:46px; flex:none; color:#fff; font-size:18px; font-weight:700; background:var(--blue); border-radius:13px; box-shadow:0 8px 20px color-mix(in srgb,var(--blue) 28%,transparent),inset 0 1px 0 rgba(255,255,255,.38); }
.profile-hero>div { display:grid; gap:2px; min-width:0; }
.profile-hero strong { color:var(--ink); font-size:15px; }
.profile-hero div span { color:var(--gray); font-size:11px; }
.profile-hero em { margin-left:auto; padding:6px 10px; color:var(--blue); font-size:11px; font-style:normal; font-weight:650; background:color-mix(in srgb,var(--card) 68%,transparent); border:1px solid color-mix(in srgb,var(--blue) 16%,var(--line)); border-radius:999px; }
.profile-grid { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:14px; }
.profile-section { position:relative; overflow:hidden; padding:16px; background:color-mix(in srgb,var(--card) 62%,transparent); border:1px solid color-mix(in srgb,#fff 58%,var(--line)); border-radius:15px; box-shadow:0 10px 28px rgba(15,23,42,.08),inset 0 1px 0 rgba(255,255,255,.6); backdrop-filter:blur(18px) saturate(1.22); }
.profile-section::after { content:""; position:absolute; top:-60%; right:-24%; width:52%; height:120%; pointer-events:none; background:radial-gradient(circle,rgba(96,165,250,.12),transparent 68%); }
.profile-section__head { position:relative; z-index:1; display:flex; align-items:center; gap:11px; margin-bottom:14px; }
.profile-section__icon { display:grid; place-items:center; width:38px; height:38px; flex:none; color:var(--blue); background:var(--blue-050); border-radius:10px; }
.profile-section__icon svg { width:19px; height:19px; fill:none; stroke:currentColor; stroke-width:1.75; stroke-linecap:round; stroke-linejoin:round; }
.profile-section__head h3 { margin:0 0 3px; color:var(--ink); font-size:14px; }
.profile-section__head p { margin:0; color:var(--gray); font-size:10px; }
.profile-signature__preview { position:relative; z-index:1; display:grid; place-items:center; min-height:112px; padding:12px; overflow:hidden; background:color-mix(in srgb,var(--bg-2) 70%,transparent); border:1px dashed color-mix(in srgb,var(--gray) 36%,var(--line)); border-radius:12px; transition:border-color .25s,background-color .25s,transform .3s cubic-bezier(.16,1,.3,1); }
.profile-signature__preview.has-new-file { background:color-mix(in srgb,var(--blue-050) 68%,transparent); border-color:color-mix(in srgb,var(--blue) 44%,var(--line)); transform:scale(1.01); }
.profile-signature__preview img { display:block; max-width:100%; max-height:82px; object-fit:contain; filter:contrast(1.04); }
.profile-signature__preview>span { color:var(--gray); font-size:11px; }
.profile-file-row { position:relative; z-index:1; display:flex; align-items:center; gap:10px; margin-top:11px; }
.profile-file-picker { display:inline-flex; align-items:center; gap:7px; min-height:36px; padding:0 11px; flex:none; color:var(--ink-2); font-size:11px; font-weight:650; cursor:pointer; background:color-mix(in srgb,var(--card) 70%,transparent); border:1px solid var(--line); border-radius:9px; transition:transform .22s cubic-bezier(.16,1,.3,1),border-color .2s,color .2s,background-color .2s; }
.profile-file-picker:hover { color:var(--blue); background:var(--blue-050); border-color:color-mix(in srgb,var(--blue) 32%,var(--line)); transform:translateY(-1px); }
.profile-file-picker input { position:absolute; width:1px; height:1px; opacity:0; }
.profile-file-picker svg { width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
#profileFileName { min-width:0; overflow:hidden; color:var(--gray); font-size:10px; text-overflow:ellipsis; white-space:nowrap; }
.profile-field { position:relative; z-index:1; display:grid; gap:5px; margin-bottom:11px; }
.profile-field>span { color:var(--gray); font-size:10px; font-weight:600; }
.profile-field>div { display:flex; align-items:center; gap:8px; min-height:40px; padding:0 11px; background:color-mix(in srgb,var(--card) 64%,transparent); border:1px solid var(--line); border-radius:10px; transition:border-color .2s,box-shadow .22s,transform .22s cubic-bezier(.16,1,.3,1); }
.profile-field>div:focus-within { border-color:var(--blue); box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent); transform:translateY(-1px); }
.profile-field svg { width:16px; height:16px; flex:none; fill:none; stroke:var(--gray); stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round; }
.profile-field input { width:100%; min-width:0; padding:0; color:var(--ink); font:inherit; font-size:12px; background:transparent; border:0; outline:0; }
.profile-field input::placeholder { color:var(--gray-2); }
.profile-primary-btn { position:relative; z-index:1; display:inline-flex; align-items:center; justify-content:center; gap:7px; width:100%; min-height:40px; margin-top:12px; color:#fff; font-size:12px; font-weight:650; cursor:pointer; background:var(--blue); border:0; border-radius:10px; box-shadow:0 6px 16px rgba(0,102,204,.22); transition:transform .22s cubic-bezier(.16,1,.3,1),box-shadow .22s,background-color .2s,opacity .2s; }
.profile-primary-btn svg { width:17px; height:17px; fill:none; stroke:currentColor; stroke-width:1.9; stroke-linecap:round; stroke-linejoin:round; }
.profile-primary-btn:hover:not(:disabled) { transform:translateY(-2px); box-shadow:0 9px 22px rgba(0,102,204,.28); }
.profile-primary-btn:active:not(:disabled) { transform:scale(.97); box-shadow:none; }
.profile-primary-btn:disabled { opacity:.5; cursor:not-allowed; box-shadow:none; }
.profile-primary-btn.is-saving svg { animation:profileButtonPulse .78s ease-in-out infinite alternate; }
@keyframes profileButtonPulse { to { transform:scale(1.2); } }
[data-theme="dark"] .profile-modal { background:rgba(22,27,35,.76)!important; border-color:rgba(148,163,184,.17)!important; box-shadow:0 34px 96px rgba(0,0,0,.58),inset 0 1px 0 rgba(255,255,255,.07)!important; }
[data-theme="dark"] .profile-modal::before { background:linear-gradient(135deg,rgba(255,255,255,.07),transparent 42%,rgba(59,130,246,.07)); }
[data-theme="dark"] .profile-hero { background:rgba(38,57,84,.54); border-color:rgba(96,165,250,.24); }
[data-theme="dark"] .profile-section { background:rgba(37,45,56,.5); border-color:rgba(148,163,184,.13); box-shadow:0 10px 28px rgba(0,0,0,.2),inset 0 1px 0 rgba(255,255,255,.05); }
[data-theme="dark"] .profile-signature__preview,[data-theme="dark"] .profile-field>div,[data-theme="dark"] .profile-file-picker { background:rgba(28,34,43,.62); }
@media (max-width:720px) { .profile-modal { padding:20px 14px!important; } .profile-grid { grid-template-columns:1fr; } .profile-hero em { display:none; } }
@media (prefers-reduced-motion:reduce) { .profile-signature__preview,.profile-file-picker,.profile-field>div,.profile-primary-btn { transition:none; } .profile-file-picker:hover,.profile-field>div:focus-within,.profile-primary-btn:hover { transform:none; } .profile-primary-btn.is-saving svg { animation:none; } }

/* 所有普通提示与业务待办共用右上角通知栈，按出现顺序向下排列。 */
.business-notif-stack { position:fixed; top:calc(var(--tb-h,64px) + 16px); right:22px; z-index:1500; display:grid; justify-items:end; gap:10px; width:min(390px,calc(100vw - 32px)); pointer-events:none; }
.business-notif { position:relative; display:grid; grid-template-columns:38px minmax(0,1fr) 28px; align-items:center; gap:11px; width:100%; min-height:70px; box-sizing:border-box; padding:12px 12px 12px 14px; overflow:hidden; color:var(--ink); cursor:pointer; pointer-events:auto; background:color-mix(in srgb,var(--card) 86%,transparent); border:1px solid color-mix(in srgb,#fff 58%,var(--line)); border-radius:14px; box-shadow:0 16px 42px rgba(15,23,42,.2),inset 0 1px 0 rgba(255,255,255,.64); backdrop-filter:blur(22px) saturate(1.3); -webkit-backdrop-filter:blur(22px) saturate(1.3); animation:businessNotifIn .42s cubic-bezier(.16,1,.3,1) both; transition:transform .22s cubic-bezier(.16,1,.3,1),box-shadow .22s; }
.business-notif:hover { transform:translateX(-3px); box-shadow:0 20px 48px rgba(15,23,42,.24),inset 0 1px 0 rgba(255,255,255,.72); }
.business-notif.is-leaving { animation:businessNotifOut .32s ease-in both; }
.business-notif::before { content:""; position:absolute; inset:0 auto 0 0; width:3px; background:var(--blue); }
.business-notif[data-type="edit_request"]::before,.business-notif[data-type="register"]::before { background:#f59e0b; }
.business-notif[data-type="pending_report"]::before { background:#10b981; }
.business-notif__icon { display:grid; place-items:center; width:38px; height:38px; color:var(--blue); background:var(--blue-050); border-radius:10px; }
.business-notif[data-type="edit_request"] .business-notif__icon,.business-notif[data-type="register"] .business-notif__icon { color:#d97706; background:rgba(245,158,11,.12); }
.business-notif[data-type="pending_report"] .business-notif__icon { color:#059669; background:rgba(16,185,129,.12); }
.business-notif__icon svg { width:19px; height:19px; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
.business-notif__copy { display:grid; gap:3px; min-width:0; }
.business-notif__copy strong { overflow:hidden; color:var(--ink); font-size:13px; font-weight:650; line-height:1.4; text-overflow:ellipsis; white-space:nowrap; }
.business-notif__copy small { overflow:hidden; color:var(--gray); font-size:11px; line-height:1.4; text-overflow:ellipsis; white-space:nowrap; }
.business-notif__close { display:grid; place-items:center; width:28px; height:28px; padding:0; color:var(--gray); cursor:pointer; background:transparent; border:0; border-radius:8px; }
.business-notif__close:hover { color:var(--ink); background:color-mix(in srgb,var(--gray) 12%,transparent); }
.business-notif__close svg { width:15px; height:15px; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; transform-box:view-box; transform-origin:center; transition:transform .25s cubic-bezier(.16,1,.3,1); }
.business-notif__close:hover svg { transform:rotate(90deg); }
.business-notif>i { position:absolute; right:0; bottom:0; left:0; height:2px; background:color-mix(in srgb,var(--blue) 58%,transparent); transform-origin:left center; animation:businessNotifProgress 5.2s linear both; }
.business-notif[data-type="edit_request"]>i,.business-notif[data-type="register"]>i { background:rgba(245,158,11,.58); }
.business-notif[data-type="pending_report"]>i { background:rgba(16,185,129,.58); }
.icon-btn--notif:not(.has-business-notifs)::after { display:none; }
@keyframes businessNotifIn { from { opacity:0; transform:translateX(calc(100% + 28px)) scale(.96); filter:blur(4px); } to { opacity:1; transform:none; filter:none; } }
@keyframes businessNotifOut { to { opacity:0; transform:translateX(calc(100% + 28px)) scale(.96); filter:blur(3px); } }
@keyframes businessNotifProgress { to { transform:scaleX(0); } }
[data-theme="dark"] .business-notif { background:rgba(27,33,42,.86); border-color:rgba(148,163,184,.18); box-shadow:0 18px 48px rgba(0,0,0,.42),inset 0 1px 0 rgba(255,255,255,.07); }
@media (max-width:640px) { .toast-host,.business-notif-stack { top:calc(var(--tb-h,64px) + 8px); right:12px; width:calc(100vw - 24px); } }
@media (prefers-reduced-motion:reduce) { .business-notif,.business-notif.is-leaving,.business-notif>i { animation:none; } .business-notif:hover,.business-notif__close:hover svg { transform:none; } }

/* ---------- 首次登录欢迎动画遮罩（2026-09-19 三版） ---------- */
/* 入场两段式（模仿登录卷帘，看得见的「盖上来」）：
   ①纯蓝层 scaleY(0→1) 从下往上涨满（0.45s）
   ②iframe 画面淡入（1.2s，等蓝层盖满再显，内容不变形）
   出场：动画页内收笔消失后，整层慢速渐隐 */
.hello-welcome {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: #2e3f9e;
  transform-origin: 50% 100%;
  transform: scaleY(0);
  animation: helloRise .45s cubic-bezier(.16, 1, .3, 1) forwards;
  opacity: 1;
  /* ⚠️ 渐隐必须用 linear（不用 ease-out）：
     ease-out 开头极快，0.2s 就透明大半 → 用户很早就看清背景，
     而入场动画那时才开始，永远显得「晚了」。linear 让透明度均匀下降，
     与同时在 T+0 开播的数据动画形成重叠。 */
  transition: opacity 1.4s linear;
}
@keyframes helloRise { to { transform: scaleY(1); } }
.hello-welcome.is-leaving { opacity: 0; pointer-events: none; }
.hello-welcome__frame {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  opacity: 0;
  /* ②画面淡入：0.35s → **1.2s**（2026-09-20）。
     用户要求「画面淡入加长」——指**内容本身显形**这段（不是整层遮罩的渐隐）。
     ⚠️ 起始仍是 .45s（卷帘盖满那一刻）；但淡入变长后会**越过** 0.48s 的起笔点，
     即「画面还在显影、H 已经开始写」——这是有意保留的重叠感，不是 bug。
     若想让它彻底先显完再动笔，把 apple-hello.html 的 DELAY 从 480 提到 1700 左右。 */
  animation: helloFrameIn 1.2s ease .45s forwards;
}
@keyframes helloFrameIn { to { opacity: 1; } }

/* ---------- 报告审核全屏 · 暗色主题适配（2026-09-19） ----------
   该界面其余颜色全部走设计令牌（--card/--line/--ink…）会自动跟随主题，
   只有这几处写死了亮色；iframe 保持白底 —— 里面是 PDF 报告纸面。 */
[data-theme="dark"] .report-fullscreen { background: var(--bg); }
[data-theme="dark"] .report-fullscreen__bar { background: rgba(23, 26, 32, .92); }
[data-theme="dark"] .report-fullscreen__actions { background: var(--card); }


/* ---------- 个人中心「界面效果」开关（2026-09-23）---------- */
.pref-list { display: flex; flex-direction: column; gap: 10px; }
.pref-toggle { display: flex; align-items: flex-start; gap: 12px; cursor: pointer; user-select: none; }
.pref-toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.pref-toggle__ui { position: relative; flex: none; width: 42px; height: 24px; margin-top: 1px; border-radius: 999px; background: var(--line); box-shadow: inset 0 1px 2px rgba(30,75,120,.10); transition: background .24s var(--ease); }
.pref-toggle__ui i { position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; border-radius: 50%; background: var(--card); box-shadow: 0 1px 3px rgba(0,0,0,.18); transition: transform .24s var(--ease); }
.pref-toggle input:checked + .pref-toggle__ui { background: var(--blue); }
.pref-toggle input:checked + .pref-toggle__ui i { transform: translateX(18px); }
.pref-toggle input:focus-visible + .pref-toggle__ui { outline: 2px solid var(--blue); outline-offset: 2px; }
.pref-toggle__text strong { display: block; font-size: 13.5px; font-weight: 600; }
.pref-toggle__text em { display: block; margin-top: 3px; color: var(--gray); font-size: 11.5px; font-style: normal; }

/* ---------- 导出 Word 预览层（2026-09-23）----------
   「导出 Word」不再直接下载：先在本层用 docx-preview 渲染 .docx 让用户确认排版，
   再点「打印 / 导出 Word」下载，由用户在自己的 Word 里打印。
   ⚠️ 页面本体由 assets/vendor/docx-preview.min.js 生成（其自带样式写在容器内部），
      本段只接管舞台底色、缩放与纸张阴影；靠**更高特异性**覆盖，禁用 !important。 */
.wp__bar-actions { grid-column: 3; justify-self: end; display: flex; align-items: center; gap: 12px; min-width: 0; }
.wp__tip { color: var(--gray); font-size: 11.5px; white-space: nowrap; }
.wp__stage { position: relative; flex: 1; min-height: 0; overflow: auto; padding: 24px; background: var(--stage, #e9eef5); }
.wp__hint { display: flex; align-items: center; justify-content: center; gap: 10px; min-height: 40vh; color: var(--gray); font-size: 13px; }
.wp__spin { flex: none; width: 16px; height: 16px; border: 2px solid var(--line); border-top-color: var(--blue); border-radius: 50%; animation: wpSpin .8s linear infinite; }
@keyframes wpSpin { to { transform: rotate(360deg); } }
.wp__paper .docx-wrapper { background: transparent; padding: 0; }
.wp__paper .docx-wrapper > section.docx { zoom: var(--wp-zoom, 1); margin: 0 auto 20px; box-shadow: 0 6px 22px rgba(20, 45, 80, .14); }
[data-theme="dark"] .wp__stage { background: color-mix(in srgb, #000 26%, var(--bg)); }
[data-theme="dark"] .wp__paper .docx-wrapper > section.docx { box-shadow: 0 6px 22px rgba(0, 0, 0, .46); }

.wp__note { max-width: 760px; margin: 0 auto 24px; color: var(--gray); font-size: 11.5px; line-height: 1.7; text-align: center; }

@media (max-width: 900px) {
  .wp__tip { display: none; }
  .wp__stage { padding: 12px; }
  .wp__paper .docx-wrapper > section.docx { zoom: var(--wp-zoom, 1); }
}

/* ---------- 账户与权限：行内展开详情（2026-09-24 改造）----------
   取代原右侧 300px 侧栏：点「详情」在**被点那一行的下方**整行展开，
   不占横向空间、不遮挡表格；细粒度权限再长也只是把页面撑高。
   （原侧栏的 .acc-panel__meta / .acc-panel__row 是独立类选择器，直接复用。） */
.acc-detail-cell { padding: 0; }
.acc-detail {
  margin: 4px 0 12px;
  padding: 14px 16px 12px;
  text-align: left;
  background: var(--card);
  border: 1px solid var(--line);
  border-left: 3px solid color-mix(in srgb, var(--blue) 55%, transparent);
  border-radius: 12px;
  box-shadow: 0 6px 20px rgba(20, 45, 80, .06);
}
.acc-detail__head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.acc-detail__name { font-size: 14px; color: var(--ink); }
.acc-detail__close { flex: none; }
.acc-detail__foot {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-top: 14px; padding-top: 12px;
  border-top: 1px dashed var(--line);
}
.acc-detail__foot[hidden] { display: none; }
.acc-detail-row.is-opening { animation: accDetailIn .34s var(--acc-motion-ease, ease) both; }
@keyframes accDetailIn {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: none; }
}
/* 展开态：所在行左侧留一道蓝标，明确「这一行的详情正开着」 */
.acc-table tbody tr.is-detail-open {
  background: color-mix(in srgb, var(--blue) 7%, transparent);
  box-shadow: inset 3px 0 0 var(--blue);
}
/* 暗色模式：浅色投影在深底上会发灰，换一档更深的 */
[data-theme="dark"] .acc-detail { box-shadow: 0 6px 20px rgba(0, 0, 0, .42); }

@media (max-width: 1080px) {
  /* 1080 以下表格已卡片化（tr → block 带边框内边距）→ 展开行要还原成全宽块，
     否则会被卡片样式挤成"又一张卡里的小卡"。 */
  .acc-table tbody tr.acc-detail-row { display: block; margin: 0 0 10px; padding: 0; border: 0; background: transparent; }
  .acc-table tbody tr.acc-detail-row > td.acc-detail-cell { display: block; width: auto; padding: 0; }
  .acc-table tbody tr.acc-detail-row > td.acc-detail-cell::before { content: none; }
}

/* ---------- 后端看门狗：重连横幅（2026-09-28）----------
   ⚠️ 追加在文件最末尾（本项目铁律：新增样式不插队，避免通配/同名类权重串扰）。
   用途：探活连续失败达阈值后，告诉用户「后端断了，正在救」，而不是静默卡死。
   视觉：顶部居中的浮层胶囊，不进文档流（position:fixed），不挤压任何布局。 */
.ys-net {
  position: fixed;
  top: 14px;
  left: 50%;
  z-index: 2400;               /* 高于 .auth(10) 与 toast-host，低于系统级确认框 */
  transform: translate(-50%, -140%);
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: min(560px, calc(100vw - 32px));
  padding: 11px 18px 11px 15px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  box-shadow: var(--sh-2);
  color: var(--ink);
  opacity: 0;
  pointer-events: none;
  transition: opacity .26s var(--ease), transform .34s var(--ease-out);
}
.ys-net.is-on { opacity: 1; transform: translate(-50%, 0); }

.ys-net__spinner {
  flex: none;
  width: 15px;
  height: 15px;
  border: 2px solid var(--line);
  border-top-color: var(--amber);
  border-radius: 50%;
  animation: ysNetSpin .8s linear infinite;
}
@keyframes ysNetSpin { to { transform: rotate(360deg); } }

.ys-net__body { min-width: 0; display: flex; flex-direction: column; line-height: 1.35; }
.ys-net__title { font-size: 13px; font-weight: 600; }
.ys-net__detail { font-size: 11.5px; color: var(--gray); }

/* 重连格子：一格 = 一次机会，走完即踢出；已用的格子变灰留痕 */
.ys-net__slots { flex: none; display: flex; gap: 4px; }
.ys-net__slot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--amber);
  transition: background .2s var(--ease);
}
/* ⚠️ 「格子」与「已用格子」是同权重选择器（各一个类），
   谁写在后面谁赢。这条必须紧跟在 .ys-net__slot 之后，
   否则上面那条 background 会把灰底覆盖掉（2026-09-28 无头实测踩过）。 */
.ys-net__slot.is-lost { background: var(--line); }

[data-theme="dark"] .ys-net { box-shadow: 0 10px 30px rgba(0, 0, 0, .62); }

@media (prefers-reduced-motion: reduce) {
  .ys-net { transition: opacity .12s linear; }
  .ys-net__spinner { animation: none; }
}

/* =========================================================
   重要提醒模态弹窗 .app-notice（2026-09-28 新增）
   ⚠️ 与 .app-confirm 的差别只在「外观语气」与「只有确认一个出口」：
      外壳复用 .app-confirm（宽度 / 圆角 / backdrop / 阴影 / 动效一致），
      这里只加：警示图标头、标题居中、主按钮放大加宽。
   ⚠️ 本块必须留在文件**最末尾**（项目铁律：新增 CSS 排到所有既有规则之后），
      且**不使用 !important**。
   ========================================================= */
.app-notice {
  width: min(480px, calc(100vw - 32px));
  text-align: center;
  padding: 30px 28px 26px;
}
.app-notice::backdrop {
  background: rgba(15, 23, 42, .52);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}
.app-notice__icon {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  margin: 0 auto;
  border-radius: 50%;
  color: var(--amber-d);
  background: color-mix(in srgb, var(--amber) 22%, transparent);
  box-shadow: 0 0 0 8px color-mix(in srgb, var(--amber) 9%, transparent);
}
.app-notice__icon svg {
  width: 30px;
  height: 30px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.1;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.app-notice__title {
  margin: 20px 0 0;
  font-size: 20px;
  font-weight: 640;
  color: var(--ink);
}
.app-notice__message {
  margin: 14px 0 0;
  font-size: 15.5px;
  line-height: 1.85;
  color: var(--ink-2);
  overflow-wrap: anywhere;
}
/* 行内换行符（后端文案里的 \n）在 <p> 里默认被折叠，这里显式保留 */
.app-notice__message { white-space: pre-line; }
/* ⚠️ 2026-09-28 用户要求：弹窗内文字**一律不可选中**（禁止拖选高亮 / 复制）。
   覆盖全弹窗（图标 / 标题 / 正文 / 按钮文案）。 */
.app-notice {
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
.app-notice .app-confirm__actions {
  margin-top: 26px;
  justify-content: center;
}
/* 主按钮：比常规 .btn 更大更高（56px 高 / 拉满宽度 / 字重 600），
   确保用户一定看到并愿意点。 */
.app-notice__ok {
  width: 100%;
  height: 54px;
  font-size: 16.5px;
  font-weight: 620;
  letter-spacing: .02em;
  border-radius: 14px;
  /* ⚠️ 过渡时长 150–300ms 区间（用户要求）：悬停用 220ms，按压回弹用 180ms */
  transition: transform .18s var(--ease-back), box-shadow .22s var(--ease),
              background-color .22s var(--ease);
}
.app-notice__ok:hover {
  transform: translateY(-2px) scale(1.012);
  box-shadow: 0 14px 34px rgba(0, 102, 204, .38);
}
.app-notice__ok:active {
  transform: translateY(0) scale(.972);
  box-shadow: 0 4px 12px rgba(0, 102, 204, .26);
  transition-duration: .12s;
}

/* 弹窗入场：轻微上浮 + 淡入，风格与站内其它弹窗一致 */
@media (prefers-reduced-motion: no-preference) {
  .app-notice[open] { animation: appNoticeIn .26s var(--ease-out); }
  .app-notice[open] .app-notice__icon { animation: appNoticePop .42s var(--ease-back) .04s both; }
}
@keyframes appNoticeIn {
  from { opacity: 0; transform: translateY(14px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
@keyframes appNoticePop {
  from { opacity: 0; transform: scale(.5); }
  to   { opacity: 1; transform: none; }
}

/* 小屏 / 移动端：贴边、缩小内边距与按钮高度，保证内容完整可读不溢出 */
@media (max-width: 640px) {
  .app-notice {
    width: calc(100vw - 24px);
    max-height: calc(100dvh - 32px);
    padding: 24px 20px 20px;
  }
  .app-notice__icon { width: 48px; height: 48px; }
  .app-notice__icon svg { width: 24px; height: 24px; }
  .app-notice__title { font-size: 18px; margin-top: 16px; }
  .app-notice__message { font-size: 14.5px; line-height: 1.8; }
  .app-notice__ok { height: 50px; font-size: 16px; }
}

@media (prefers-reduced-motion: reduce) {
  .app-notice[open],
  .app-notice[open] .app-notice__icon { animation: none; }
  .app-notice__ok:hover { transform: none; }
}

/* =========================================================
   全局文字可选性基线（2026-09-28 用户要求）
   ─────────────────────────────────────────────────────────
   策略：**白名单反转** —— 全局默认禁止选中，仅对「用户可输入/可编辑」
        的元素放行。比逐个元素打补丁彻底，天然无遗漏。
   ⚠️ 三条硬约束（用户明确要求）：
      ① 展示性文字一律禁选（弹窗内容 / 标题 / 标签 / 按钮文案 / 菜单项 /
         提示信息 / 表格表头 / 静态说明文本）；
      ② 用户输入或编辑的内容**必须**可选中（输入框 / 文本域 / contenteditable /
         用户填写后回显的内容）；
      ③ 禁选**不得**影响滚动、拖拽、点击、focus 等交互
         —— `user-select` 只控制文本选区，与 pointer-events 无关，天然满足。
   ⚠️ 本块必须留在 app.css **最末尾**（项目铁律），且**不使用强制覆盖关键字**。
      —— 靠「同属性 + 更靠后」压过前面零星规则；`*` 通配符权重为 0，
         任何具体选择器（.foo）都能覆盖它，因此放行规则无需加力。
   ⚠️ ⚠️ 通配符权重坑（项目铁律）：`*` 权重 0，**会**被 `body`/`.app` 这类
      单类选择器盖掉。故这里必须用 `html, body, *` 三件套同时命中，
      否则站点根节点的可继承值仍是 `auto`，全站禁选会莫名其妙失效。
   ========================================================= */
html,
body,
*:not(input):not(textarea):not(select):not([contenteditable="true"]):not([contenteditable=""]) {
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* ⚠️⚠️ 必须**紧跟在全局禁选之后**再放行 contenteditable 的**后代**。
   原因（2026-09-28 无头实测踩过）：Chrome 里 `user-select:none` 的祖先会
   **截断**后代选区 —— 仅给 contenteditable 元素自身写 text **不够**，
   其内部子节点（富文本 editor 里的 span/b 等）仍算 `none`，
   导致实验区规格型号单元格无法拖选。
   ⚠️ 权重：`[contenteditable="true"] *` = 1（属性）+ 0（*），
      而上面的全局规则 = 0（:not 内均为元素选择器）→ 本规则权重更高，
      即使写在前面也能赢；但为可读性仍放在禁选规则紧邻处。
   ⚠️ 这条**必须**留在本块内（全局层），不要挪到前文 —— 否则又被
      「末尾的新增 CSS」盖掉。 */
[contenteditable="true"],
[contenteditable=""],
[contenteditable="plaintext-only"],
[contenteditable="true"] *,
[contenteditable=""] *,
[contenteditable="plaintext-only"] * {
  -webkit-user-select: text;
  -moz-user-select: text;
  user-select: text;
}

/* ---------- 白名单：用户可输入 / 可编辑的内容恢复可选中 ---------- */
input,
textarea,
select,
[contenteditable="true"],
[contenteditable=""],
[contenteditable="plaintext-only"] {
  -webkit-user-select: text;
  -moz-user-select: text;
  user-select: text;
}

/* 日期/时间/数字等原生控件的内部文本同样放行（避免点日期时无法拖选年月） */
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="month"],
input[type="week"],
input[type="number"],
input[type="search"],
input[type="email"],
input[type="tel"],
input[type="url"],
input[type="password"],
input[type="text"] {
  -webkit-user-select: text;
  -moz-user-select: text;
  user-select: text;
}

/* ⚠️ 例外：勾选框 / 单选框 / 按钮 / 文件选择器的**点击**不受影响，
   但其可见内容也不是「可复制文本」，故不放进白名单（保持默认禁选）。 */

/* 可编辑区域内部的**子节点**要显式放行 ——
   ⚠️ `user-select: text` 在 Chrome 上对「已禁选的祖先 → 放行的子级」这条链
   支持不稳定（选区会被祖先的 none 截断），所以对 contenteditable 的后代
   追加一条，确保富文本编辑区能正常拖选（如实验区规格型号单元格）。 */
[contenteditable="true"] *,
[contenteditable=""] * {
  -webkit-user-select: text;
  -moz-user-select: text;
  user-select: text;
}

/* PDF 预览壳 / 报告只读壳本来就是位图或 iframe，保持禁选（前面已有规则，这里只补 select） */
.report-reader,
.report-reader * {
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
}

@media print {
  /* 打印时不需要选区控制，恢复默认，避免某些打印引擎对 user-select 处理异常 */
  html, body, *,
  input, textarea, select, [contenteditable] {
    -webkit-user-select: auto;
    user-select: auto;
  }
}

/* ==========================================================================
   黄色「详情」按钮（2026-09-28 用户要求）
   --------------------------------------------------------------------------
   用户诉求：报告审核页的「详情」按钮与任务大厅的「详情」按钮做成一致样式、
   颜色为黄色，提高辨识度与点击引导（原样式太不显眼）。
   ⚠️ 颜色取 app.css 既有变量 --amber (#ffb020) / --amber-d (#b45309)，
      不新增色值；⚠️ 遵守项目铁律：追加到文件末尾、不使用强制覆盖优先级。
   与 .flip__detail（任务大厅）保持同一套视觉语言：胶囊形 + 渐变 + 内高光。
   ========================================================================== */
.btn--amber {
  position: relative;
  display: inline-flex; align-items: center; gap: 5px;
  font-weight: 600;
  color: #4a2c00;
  background: linear-gradient(135deg, var(--amber), #f5a11c);
  border: 0;
  border-radius: var(--r-pill);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .42), 0 2px 8px color-mix(in srgb, var(--amber) 34%, transparent);
  overflow: hidden;
  transition: filter .2s var(--ease-out), transform .16s var(--ease-out);
}
.btn--amber:hover:not([disabled]) {
  filter: saturate(1.1) brightness(1.04);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45), 0 5px 16px color-mix(in srgb, var(--amber) 44%, transparent);
}
.btn--amber:active:not([disabled]) { transform: scale(.96); }
.btn--amber[disabled] { opacity: .5; cursor: not-allowed; }
/* 任务大厅的「详情」原本是蓝色胶囊，这里统一换成同款黄色，与报告审核一致 */
.flip__detail {
  color: #4a2c00;
  background: linear-gradient(135deg, var(--amber), #f5a11c);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .42), 0 2px 8px color-mix(in srgb, var(--amber) 34%, transparent);
}
.flip__detail-caret { color: #4a2c00; }

/* ==========================================================================
   报告寄出 · 3 天（72 小时）倒计时进度条（2026-09-28 用户要求）
   --------------------------------------------------------------------------
   用户诉求：
     ① 「报告寄出中 / 已寄出」的绿色任务条改成 3 天倒计时进度条，随时间推进缩短；
     ② 页面下方「截止到 X 年 X 月 X 日」保持不变，**另找位置**显示剩余时间；
     ③ 不显示「时:分」，改为 **百分比 + 剩余小时数**（如「已用 12% · 剩 63 小时」）；
     ④ 精度到分钟；**只计算屏幕上可见的卡片**；
     ⑤ ⚠️ 滚动回到视野时按**当前时间**重算，绝不用离开时的缓存值
        —— 否则会出现「一滚到它就突然少一截」的跳变。
   ⚠️ 进度条按**分钟**推进（用户选定方案 B），配合 `transition: transform` 平滑过渡。
   ⚠️ 遵守项目铁律：追加到文件末尾、不使用强制覆盖优先级。
   ========================================================================== */
.dispatch-countdown__meta { align-items: center; }
/* 百分比：等宽数字，避免数字变化引起宽度抖动 */
.dispatch-countdown__pct {
  font: 650 12px/1 var(--font-num);
  color: var(--green-d);
  font-variant-numeric: tabular-nums;
}
/* 剩余小时：次要信息，弱化配色 */
.dispatch-countdown__left {
  font: 600 11px/1 var(--font-num);
  color: var(--gray);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* ⚠️ 进度条本体：transform 由 JS 按分钟写入，transition 让「跳格」看起来是平滑推进 */
.dispatch-countdown__fill {
  transition: transform .5s var(--ease-out);
  will-change: transform;
}
/* ⚠️ 2026-09-28 用户要求：去掉进度条上的「N%」叠加层——
   剩余百分比只在左上角「剩余 N%」展示一处。原 `.dispatch-countdown__bar-pct`
   的定位/字色/字距/深色主题规则整组删除（节点已从 DOM 移除，留着是死代码）。
   注意 `.dispatch-countdown__track { position: relative }` 保留，fill 的
   ::after 覆盖层仍以它为定位上下文。 */
.dispatch-countdown__track { position: relative; }
/* 窗口结束（归档）时进度条灰化，语义与「已归档」一致 */
.dispatch-item--archived .dispatch-countdown__fill { background: var(--gray); }

/* 倒计时容器加宽：原 136px 放不下「剩余 12% / 剩 63 小时」两段文字会挤成两行 */
.dispatch-countdown { width: 158px; }
/* meta 里 strong 承载百分比，配色沿用 green-d 与右侧剩余小时区分层级 */
.dispatch-countdown__meta strong { font: 700 11.5px/1 var(--font-num); color: var(--green-d); font-variant-numeric: tabular-nums; }
.dispatch-countdown__meta span { color: var(--gray); font: 600 11px/1 var(--font-num); }

/* ==========================================================================
   ⚠️ 2026-09-28 文案与配色修正（用户第二轮反馈）
   --------------------------------------------------------------------------
   用户要求：
     ① 左上角去掉「已用」字样 → 改为展示**剩余百分比**（「剩余 71%」），**黑色**字体；
     ② 其后跟**绿色**的「剩 N 小时」；
     ③ 截止日期补具体时刻，精确到**分**（无秒精度，不显示秒）→「2026年9月30日 23:59」；
     ④ 绿色进度条加**循环播放**的动效，让用户看出「在持续变化、没有卡住」；
     ⑤ 整体布局 / 位置 / 配色不变（黑文本 + 绿文字 + 绿进度条）。

   ⚠️ 配色必须在这里**重新声明**：`dispatch.css` 的
      `.dispatch-countdown__meta strong{color:var(--ink)}` 与 `span{color:var(--green-d)}`
      已把语义定死为「strong=黑、span=绿」。
      而 app.css 4316 行又写了 `strong{color:var(--green-d)}` / `span{color:var(--gray)}`
      —— 那是上一轮「已用% / 剩N小时」配色**反了**的历史遗留（当时忘了加载序是
      dispatch.css → app.css，app.css 后置会覆盖）。本轮按用户要求**摆正**。
   ⚠️ 遵守项目铁律：追加到文件末尾、不使用强制覆盖优先级。
   ========================================================================== */
/* 左上角「剩余 N%」：黑色（--ink），等宽数字防抖动 */
.dispatch-countdown__meta strong { color: var(--ink); font-variant-numeric: tabular-nums; }
/* 右侧「剩 N 小时」：绿色（--green-d），语义色与进度条同源 */
.dispatch-countdown__meta span { color: var(--green-d); font: 650 12px/1 var(--font-num); font-variant-numeric: tabular-nums; }
/* 「剩余 71%」比「已用 29%」字数少，158px 富余 → 收回窄一点，避免右侧留白过大 */
.dispatch-countdown { width: 150px; }
/* 截止行带上时刻后变长（「截止 2026年9月30日 23:59」），放宽截断阈值保持单行 */
.dispatch-countdown small { font-size: 10px; letter-spacing: -.1px; }
/* 深色主题：绿色提亮一档，黑字转浅色（否则 --ink 在深底上不可读） */
[data-theme=dark] .dispatch-countdown__meta span { color: var(--green); }

/* ---- 绿色进度条：循环播放的流光动效（让用户感知「在走、没卡住」）----
   手法：在填充条上叠一层 **斜向流动条纹**（45° 渐变 + background-position 循环位移），
        外加整条**呼吸脉冲**（透明度微变）。两者都是纯 CSS、无限循环、无 JS 开销。
   ⚠️ 条纹盖在绿色底上，用半透明白保证「仍是绿色进度条」的观感不变。
   ⚠️ 动效挂在 ::after 上，**不碰 fill 的 transform**
      （fill 的 transform 由 JS 按分钟写入，transition .5s 平滑推进；两者互不干扰）。
   ⚠️ 铁律：不使用 !important；追加到文件末尾。 */
@keyframes dispatch-bar-flow {
  /* ⚠️ 2026-09-28 用户反馈：条纹视觉上应**向左**流动（原为向右，观感别扭）。
     反向只需把终点取负，周期仍为 32px → 依旧无缝循环。 */
  from { background-position: 0 0; }
  to   { background-position: -32px 0; }   /* 恰好一个周期（反向）→ 无缝循环 */
}
@keyframes dispatch-bar-pulse {
  0%, 100% { opacity: .34; }
  50%      { opacity: .72; }
}
.dispatch-countdown__fill { position: relative; overflow: hidden; }
.dispatch-countdown__fill::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: linear-gradient(115deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, .55) 38%,
    rgba(255, 255, 255, .55) 52%,
    rgba(255, 255, 255, 0) 90%);
  background-size: 32px 100%;
  background-repeat: repeat-x;
  animation: dispatch-bar-flow 1.6s linear infinite,
             dispatch-bar-pulse 2.4s ease-in-out infinite;
  pointer-events: none;
}
/* 归档（窗口结束）态：灰化时**停掉动效** —— 已结束的窗口不该再显示「在走」 */
.dispatch-item--archived .dispatch-countdown__fill::after { animation: none; opacity: 0; }
/* 尊重系统的「减弱动态效果」偏好：保留静态绿条，不加动画 */
@media (prefers-reduced-motion: reduce) {
  .dispatch-countdown__fill::after { animation: none; opacity: .3; }
}

/* ==========================================================================
   报告行 · 合格/不合格 标签防裁切（2026-09-28 用户反馈）
   --------------------------------------------------------------------------
   事故：窄卡片 / 缩放下，.flip__row-name 内的 .report-kind__tag 被
        .flip__row-main 的 overflow:hidden **硬裁**，只剩「合格」两字的一半。
   修法：
     ① JS 已把标签移出 .flip__row-name，改为 .flip__row-main 的同级 flex 项；
     ② 标签本体加 flex:none + 不可收缩，保证「宁挤别人不挤自己」——它是语义标签，
        被裁就完全失去意义；
     ③ 给可压缩的文本项（.flip__row-no / .flip__row-sub）加 min-width:0 与
        ellipsis，让**先牺牲长文本**而不是牺牲标签；
     ④ 文案从「合格报告」缩到「合格」，4 字→2 字，进一步降低挤占。
   ⚠️ 遵守项目铁律：追加到文件末尾，不使用强制覆盖优先级。
   ========================================================================== */
.flip__row-name { overflow: hidden; }
/* 编号：可压缩 + 省略号（它是长文本，优先让它让位） */
.flip__row-no {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.flip__row-sub {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 标签：绝不压缩、绝不换行 —— 被裁等于语义丢失 */
.report-kind__tag {
  flex: 0 0 auto;
  min-width: max-content;
}
/* 状态徽章同理：短标签，宁可挤长文本 */
.flip__row > .badge { flex: 0 0 auto; }

/* 统一省略号兜底：受 ellipsis-guard.js 管理的元素至少要能裁出省略号 */
[data-ellipsis] {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ⚠️⚠️ 根因修正（2026-09-28 实测）：.flip__row-no 是 <span>（inline 元素），
   inline 元素的 clientWidth/scrollWidth **不可靠** —— overflow / text-overflow /
   min-width 对 inline 也不生效。这会导致 JS 溢出检测**误判**：
   实测出现「编号被压成一个 …」（二分把它一路截到最短）与
   「容器变宽后无法还原」两类错误。
   ⇒ 必须显式给 display 才能成为可测量的块级盒。选 inline-block 而非 block：
     保留原有「与徽章同行排列」的视觉，不改变 .flip__row-name 的 flex 布局行为。 */
.flip__row-no { display: inline-block; max-width: 100%; vertical-align: bottom; }
/* 同一道理：.flip__row-sub 原本是 <div>（块级）无碍，但显式声明避免将来改标签踩坑 */
.flip__row-sub { display: block; max-width: 100%; }
/* 受管元素通用兜底：JS 只对「可测量盒」做溢出判定 */
[data-ellipsis] { display: inline-block; max-width: 100%; box-sizing: border-box; }
/* ⚠️ 例外：本身就带 flex / grid 语义的受管元素不能被改成 inline-block，
   否则会破坏其父容器的布局（如徽章在 flex 行内需要按 flex 项参与分配）。 */
.report-kind__tag[data-ellipsis],
.badge[data-ellipsis] { display: inline-block; }
.flip__row > .badge[data-ellipsis] { display: inline-flex; }
/* ⚠️⚠️ 2026-09-28 根因修正③：`.pool__code` **必须回到 block**，不能进上面的
   「inline-block 例外名单」。
   事故现象：任务大厅卡片上「委托单 · HBGT-WT-SJZ-2026-06-1005」与客户名
   「英伟达」挤在同一行紧贴着，看着像编号后面粘了三个字。
   成因：`.pool__code` 与 `.pool__name` 是 `.flip__head-meta` 里的两个兄弟
   `<div>`，本来就是**上下两行**。
   把 inline-block 施加到 `.pool__code` 后，它由块级盒变成行内盒 →
   紧跟其后的 `.pool__name` 不再被挤到下一行，而是**流到它右边**。
   （`.pool__name` 自身没有 display 声明，被兜底规则设成 inline-block，
    所以它也不会独占一行 —— 两者一起变成了行内并排。）
   修法：把 `.pool__code` 从例外名单里**移除**，让兜底规则的 inline-block 不生效，
   恢复 <div> 的默认块级行为 → 两行自然回位。
   注意：块级盒同样满足 JS 溢出检测所需的「可测量」前提，所以移除后
   **溢出守护功能不受影响**（block 的 clientWidth 同样是确定值）。 */
.flip__head-meta .pool__code { display: block; max-width: 100%; }

/* ==========================================================================
   ⚠️⚠️ 根因修正 ②（2026-09-28 几何实测）
   --------------------------------------------------------------------------
   实测（250px 窄行）：
     .flip__row            = 250px
     .flip__row-main       = **4px**   ← 编号被压到只剩 4px，等同不可读
     .flip__row-no         clientW=4  scrollW=236
   成因：行是 flex，右侧「合格 + 已审核 + 打印按钮」都是 flex:none 固定宽，
   而 .flip__row-main{flex:1;min-width:0} 会被一路压到 0 —— min-width:0 本意是
   「允许收缩以便 ellipsis 生效」，但在**同级固定宽项太多**时它会收缩过头，
   把主标识（报告编号）彻底挤没，反而让次要标签完好，主次颠倒。

   修法：给主区一个**最小可读宽度下限**，宁可让整行换行，也不把编号压没。
       用 min-width: clamp(...) 保证不同字号下都留得住至少 8 个字符的宽度。
   ⚠️ 不引入横向滚动：配合 .flip__row 的 flex-wrap 让溢出的按钮换到第二行。
   ========================================================================== */
.flip__row-main {
  /* 编号是主标识，必须优先保住；8ch ≈ 能看清「2026-09-」这一级信息 */
  min-width: 8ch;
}
/* 主区被压缩到下限后，右侧固定宽项放不下 → 允许换行（不产生横向滚动条） */
.flip__row { flex-wrap: wrap; row-gap: 8px; }
/* 换行后按钮独占一行时右对齐，视觉上仍像「行尾操作」 */
.flip__row > .report-print-btn,
.flip__row > .report-docx-btn,
.flip__row > .report-approve-btn { margin-left: auto; }
/* ⚠️ 窄行下标签/徽章与按钮同排时不被拉伸 */
.flip__row > .report-kind__tag,
.flip__row > .badge { align-self: center; }

/* ==========================================================================
   液态玻璃 · 双屏预览分页器（2026-09-28）
   --------------------------------------------------------------------------
   目标（用户原话）：「上一页下一页，包括下边这个做成液态玻璃的效果。
   包括但不限于文字的扭曲和边缘的色散，还有玻璃边缘的高光。」

   四层结构（自下而上），全部用**不占位**的伪元素/覆盖层实现，
   不改动分页器自身的布局与尺寸（原 grid/padding/圆角一律保留）：

     ① backdrop-filter：真实折射模糊 + saturate 提色，让背后 PDF 透出来
     ② ::before  玻璃体本体：斜向高光渐变 + 内阴影（上缘亮、下缘暗）
     ③ ::after   specular 高光弧：一条贴边的弧光 + 柔和光晕
     ④ 文字层：轻微色散（chromatic aberration）+ 逐层模糊的「液体」描边

   ⚠️⚠️ 「文字扭曲」的实现边界（诚实说明）：
     CSS 的 `filter: blur()` 是**各向同性**的，无法做真正的**方向性透视折射**
     （像真实玻璃那样把文字按法线方向推开）。SVG 的 `<feDisplacementMap>`
     需要内联滤镜且对**实时 backdrop 内容**无效。
     因此这里采用**业界通行的近似法**：三层同字重影 + 递减模糊，
     视觉上等价于「透过厚度不均的玻璃看字」，且零依赖、零 JS、不牺牲可读性。
     真实位移映射若要做，需 WebGL/Canvas 抓帧，代价远超收益（本页是内网 PDF 预览）。

   ⚠️ 铁律遵守：不使用 !important；追加到文件末尾；不新增依赖；不引入 emoji。
   ⚠️ 深色主题另给一套参数（浅色玻璃在深底上会「发灰」，必须单独调）。
   ========================================================================== */

/* ---------- ① 玻璃基座 ---------- */
.report-spread__toolbar {
  position: sticky;
  /* 常规定位上下文之外再叠一层隔离，确保 backdrop-filter 只吃自身背后的内容 */
  isolation: isolate;
  background:
    /* ⚠️ 2026-09-28 用户第二次反馈（「外壳下边有一条灰色纸槽，看不出来」）
     问题不在透明度，而在**模糊半径**：30px 把两页之间 14px 的窄槽直接糊平。
     ⇒ 外壳填充再砍半（.10→.05），模糊 30px→10px，饱和度/亮度同时降档。
     ⚠️ 仍然不是 0：保留极轻的白色底，避免「没有体积的一团光」。
     玻璃的「存在感」改由 ::before 的贴边光影承担（强度已同步加强）。 */
    linear-gradient(
      108deg,
      rgba(255, 255, 255, .02) 0%,
      rgba(255, 255, 255, 0) 26%,
      rgba(255, 255, 255, .015) 48%,
      rgba(255, 255, 255, 0) 72%,
      rgba(255, 255, 255, .02) 100%
    );
  border: 1px solid rgba(255, 255, 255, .55);
  /* ⚠️⚠️ 2026-09-28 三稿（用户第三次要求「还是不够透」）—— 找到真凶了：
     前几稿一直在降「填充 alpha」，但真正让外壳看起来发白的是这两条**通栏 inset 白边**：
       inset 0  1px 0 rgba(255,255,255,.95)   ← 上缘一条 95% 不透明白杠
       inset 0 -1px 0 rgba(255,255,255,.38)   ← 下缘一条 38% 白杠
     它们横跨整个宽度、不渐变，在 62px 高的胶囊上等于给玻璃**镶了两条白漆**，
     把背后的纸槽竖线硬生生截断 —— 这才是「看着不透」的主因，跟填充 alpha 关系很小。
     ⇒ 本稿：**删掉这两条通栏白边**，只留 `inset 0 0 0 1px .14` 的一圈细描边。
     同时把填充再压一档（.05→.02 / .02→0 / .04→.015），blur 10px→5px，
     saturate/brightness 从 150%/1.02 收到 115%/1.00（别再给背景提亮加白）。
     实测对照见 tmp/_glass_opacity_ab.html（A=旧 / B=本稿 / C=极限），A 明显是一块白板。 */
  box-shadow:
    /* 外侧：一点贴地阴影 + 大范围柔光，避免玻璃「浮不起来」 */
    0 1px 1px rgba(0, 0, 0, .04),
    0 10px 30px -10px rgba(16, 24, 40, .18),
    /* 内侧：只保留一圈极细内描边（定义轮廓），**不再有通栏上下白边** */
    inset 0 0 0 1px rgba(255, 255, 255, .14);
  /* ⚠️ 外壳变透后，背后的 PDF 正文会更清晰 → 页码文字需要更强的背景虚化兜底，
     否则「第 1–2 页 / 共 4 页」会跟背后的字叠在一起看不清。
     ⚠️⚠️ 2026-09-28：从 30px **回落到 10px** —— 30px 会把两页之间 14px 的纸槽
     完全糊平（用户反馈「灰槽看不见」）。本稿再降到 5px：槽的边界更锐利，
     且 5px 已足以把正文糊成「能辨认字形但读不清」的灰块，可读性兜底仍在。 */
  -webkit-backdrop-filter: blur(5px) saturate(115%) brightness(1.00);
  backdrop-filter: blur(5px) saturate(115%) brightness(1.00);
  overflow: hidden;            /* 让高光弧不越出圆角 */
  transition: box-shadow .28s var(--ease-out), background .28s var(--ease-out);
}

/* ---------- ② 玻璃厚度层：斜向高光带 ---------- */
.report-spread__toolbar::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;                 /* 压在内容下、背景上 */
  border-radius: inherit;
  pointer-events: none;
  /* ⚠️ 2026-09-28：外壳填充压到 .05 后，玻璃的「边界」**只能靠边缘光影定义**：
     ① 一条贴边的 1px 内描边（否则完全透明 = 看不出这块玻璃的轮廓）
     ② 上沿 5px 内渐隐的柔和高光、下沿 5px 内渐隐的蓝灰厚边
        —— 手法直接照搬 #orderBottomBar::before（order.css:678-684），
        并以「外壳填充减半」为代价把强度提上去（.55→.78 / .16→.30）
     ③ 再叠原本的斜向高光带，保持左上光源的一致性 */
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .30);
  background:
    /* 贴边厚度：**加强**——外壳填充压到 .05 后，玻璃的轮廓全靠在贴边 5px 内完成
       （直接照搬 #orderBottomBar::before 的思路：底色近全透，边缘光影成形） */
    linear-gradient(to bottom, rgba(255, 255, 255, .78) 0 1px, rgba(255, 255, 255, .18) 2px, rgba(255, 255, 255, 0) 5px),
    linear-gradient(to top, rgba(114, 149, 191, .30) 0 1px, rgba(114, 149, 191, .10) 2px, rgba(114, 149, 191, 0) 5px),
    /* 一道斜穿整个玻璃的宽高光（模拟光源在左上） */
    linear-gradient(112deg,
      rgba(255, 255, 255, .38) 0%,
      rgba(255, 255, 255, .07) 18%,
      rgba(255, 255, 255, 0) 34%,
      rgba(255, 255, 255, 0) 62%,
      rgba(255, 255, 255, .18) 82%,
      rgba(255, 255, 255, .34) 100%),
    /* 底部的冷色折射反光 */
    linear-gradient(to top, rgba(120, 170, 255, .10), rgba(120, 170, 255, 0) 46%);
}

/* ---------- ③ specular 边缘高光弧 ---------- */
.report-spread__toolbar::after {
  content: '';
  position: absolute;
  top: 0; left: 8px; right: 8px; height: 1.5px;
  z-index: 2;
  pointer-events: none;
  border-radius: inherit;
  background: linear-gradient(90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, .95) 14%,
    rgba(255, 255, 255, .55) 46%,
    rgba(255, 255, 255, .92) 78%,
    rgba(255, 255, 255, 0) 100%);
  filter: blur(.2px);
  opacity: .95;
}

/* ---------- ④ 「液体」文字：色散 + 逐层模糊描边 ---------- */
.report-spread__range {
  position: relative;
  color: var(--ink);
  font-weight: 600;
  letter-spacing: .2px;
  /* 轻微色散：左右各偏一像素的红/青，透明到几乎只留边缘 —— 非常克制 */
  text-shadow:
    -.5px 0 0 rgba(255, 90, 90, .26),
    .5px 0 0 rgba(70, 190, 255, .26),
    0 1px 0 rgba(255, 255, 255, .7);
}
/* 逐层模糊的「厚度」副本：三层不同模糊半径叠加 = 液体玻璃的透视感 */
.report-spread__range::before,
.report-spread__range::after {
  content: attr(data-range);
  position: absolute;
  left: 0; top: 0;
  width: 100%;
  z-index: -1;
  color: currentColor;
  pointer-events: none;
  white-space: nowrap;
  text-align: center;
}
.report-spread__range::before { filter: blur(1.1px); opacity: .34; transform: translateY(.6px); }
.report-spread__range::after  { filter: blur(2.4px); opacity: .18; transform: translateY(1.4px) scale(1.012); }

/* ---------- ⑤ 玻璃里的按钮：半透明「水滴」 ---------- */
.report-spread__toolbar button {
  position: relative;
  isolation: isolate;
  background: linear-gradient(148deg,
    rgba(255, 255, 255, .78) 0%,
    rgba(234, 242, 255, .62) 52%,
    rgba(255, 255, 255, .70) 100%);
  border: 1px solid rgba(255, 255, 255, .82);
  box-shadow:
    0 1px 2px rgba(16, 24, 40, .07),
    inset 0 1px 0 rgba(255, 255, 255, .95),
    inset 0 -1px 1px rgba(120, 150, 200, .16);
  -webkit-backdrop-filter: blur(6px) saturate(170%);
  backdrop-filter: blur(6px) saturate(170%);
  transition: transform .18s var(--ease-out), box-shadow .24s var(--ease-out),
              background .24s var(--ease-out);
}
/* ⚠️⚠️ 2026-09-28 修正（用户第二次反馈「外壳下边那条灰色槽看不见」）
   --------------------------------------------------------------------------
   现场（截图）：双屏预览时左右各是一张白纸，两纸之间有一条**灰色纸槽**
   （.report-spread__pages 的 14px gap，露出页面底色）。
   期望：这条槽要能**透过玻璃看见**，成为「玻璃真的贴在纸面上」的证据。

   为什么之前看不见：
     ① `backdrop-filter: blur(30px)` —— 30px 的模糊半径把 14px 的窄槽直接糊成一团灰，
        与两侧白纸混在一起，边界消失。**这是主因。**
     ② 外壳自身的 `.10` 白色渐变把底下的对比度压低，灰槽更淡。
   修法（保持「完全透明」的结论不变，只改「怎么透」）：
     · 模糊半径 30px → **10px**：仍然足以柔化背后的正文文字（可读性不受影响），
       但 14px 的灰槽宽度已大于模糊核，**边界得以保留**。
     · 饱和度 185% → **150%**、亮度 1.06 → **1.02**：减少对背后内容的「提亮+加白」，
       灰槽的灰阶不会被抬成白。
     · 外壳填充的 `.10/.05/.09/.04/.10` → **`.05/.02/.04/.02/.05`**（再砍一半）：
       每多一分白色填充，槽就少一分对比。**仍然不是 0**，保留极轻的「玻璃有厚度」。
     · 下面 ::before 的**上/下贴边光影加强**，改由边缘高光承担玻璃的「存在感」——
       这正是委托单底栏 #orderBottomBar 的思路（底色近全透 + 边缘光影成形）。 */
/* 按钮上缘也来一道贴边的高光弧，与外壳呼应 */
.report-spread__toolbar button::before {
  content: '';
  position: absolute;
  top: 1px; left: 20%; right: 20%; height: 1px;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(90deg,
    rgba(255, 255, 255, 0), rgba(255, 255, 255, .98) 50%, rgba(255, 255, 255, 0));
  z-index: 2;
}
.report-spread__toolbar button:hover:not(:disabled) {
  transform: translateY(-1px);
  background: linear-gradient(148deg,
    rgba(255, 255, 255, .92) 0%,
    rgba(214, 228, 255, .74) 52%,
    rgba(255, 255, 255, .86) 100%);
  box-shadow:
    0 3px 8px rgba(16, 24, 40, .12),
    0 8px 20px -8px rgba(0, 102, 204, .30),
    inset 0 1px 0 rgba(255, 255, 255, 1),
    inset 0 -1px 1px rgba(120, 150, 200, .20);
}
.report-spread__toolbar button:active:not(:disabled) {
  transform: translateY(0) scale(.985);
  transition-duration: .06s;
}
/* 禁用态：「毛玻璃但薄」，不能抢视觉——仍保留玻璃质感，只降对比 */
.report-spread__toolbar button:disabled {
  color: var(--gray-2);
  background: linear-gradient(148deg,
    rgba(255, 255, 255, .42) 0%,
    rgba(245, 245, 247, .34) 100%);
  border-color: rgba(255, 255, 255, .55);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .6);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  opacity: .62;
}
.report-spread__toolbar button:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--blue) 34%, transparent);
  outline-offset: 2px;
}

/* ---------- ⑥ 深色主题：改用「烟熏玻璃」参数 ---------- */
[data-theme="dark"] .report-spread__toolbar {
  background:
    /* ⚠️ 2026-09-28：与浅色同因（模糊半径糊平了 14px 纸槽）→ 填充同样砍半到
       `.06/.03/.05/.03/.06`，让背后的纸槽边界透得出来。
       深色下边缘光影比浅色更关键，故 ::before 的强度单独提档。 */
    linear-gradient(108deg,
      rgba(16, 18, 26, .03) 0%,
      rgba(16, 18, 26, .01) 26%,
      rgba(16, 18, 26, .025) 48%,
      rgba(16, 18, 26, .01) 72%,
      rgba(16, 18, 26, .03) 100%);
  border-color: rgba(255, 255, 255, .20);
  box-shadow:
    0 1px 1px rgba(0, 0, 0, .35),
    0 12px 34px -10px rgba(0, 0, 0, .55),
    /* ⚠️ 同浅色：删掉「inset 0 1px 0 / inset 0 -1px 0」两条通栏白边，
       只留一圈细描边（否则深色玻璃上会出现一条刺眼的白杠）。 */
    inset 0 0 0 1px rgba(255, 255, 255, .04);
}
[data-theme="dark"] .report-spread__toolbar::before {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .22);
  background:
    /* 2026-09-28：深色下填充砍半后，贴边光影同步提档（.16→.30 / .16→.28） */
    linear-gradient(to bottom, rgba(255, 255, 255, .30) 0 1px, rgba(255, 255, 255, .07) 2px, rgba(255, 255, 255, 0) 5px),
    linear-gradient(to top, rgba(90, 130, 190, .28) 0 1px, rgba(90, 130, 190, .09) 2px, rgba(90, 130, 190, 0) 5px),
    linear-gradient(112deg,
      rgba(255, 255, 255, .10) 0%,
      rgba(255, 255, 255, .02) 18%,
      rgba(255, 255, 255, 0) 34%,
      rgba(255, 255, 255, 0) 62%,
      rgba(255, 255, 255, .05) 82%,
      rgba(255, 255, 255, .09) 100%),
    linear-gradient(to top, rgba(90, 140, 255, .10), rgba(90, 140, 255, 0) 46%);
}
[data-theme="dark"] .report-spread__toolbar::after { opacity: .5; }
[data-theme="dark"] .report-spread__range {
  text-shadow:
    -.5px 0 0 rgba(255, 120, 120, .22),
    .5px 0 0 rgba(90, 200, 255, .22);
}
[data-theme="dark"] .report-spread__toolbar button {
  background: linear-gradient(148deg,
    rgba(255, 255, 255, .14) 0%,
    rgba(90, 120, 180, .16) 52%,
    rgba(255, 255, 255, .10) 100%);
  border-color: rgba(255, 255, 255, .16);
  box-shadow:
    0 1px 2px rgba(0, 0, 0, .35),
    inset 0 1px 0 rgba(255, 255, 255, .16);
}
[data-theme="dark"] .report-spread__toolbar button:hover:not(:disabled) {
  background: linear-gradient(148deg,
    rgba(255, 255, 255, .22) 0%,
    rgba(90, 130, 200, .26) 52%,
    rgba(255, 255, 255, .16) 100%);
  box-shadow:
    0 3px 10px rgba(0, 0, 0, .45),
    0 8px 22px -8px rgba(59, 147, 247, .35),
    inset 0 1px 0 rgba(255, 255, 255, .24);
}
[data-theme="dark"] .report-spread__toolbar button:disabled {
  background: linear-gradient(148deg,
    rgba(255, 255, 255, .06) 0%,
    rgba(255, 255, 255, .03) 100%);
  border-color: rgba(255, 255, 255, .08);
}

/* ---------- ⑦ 无障碍回退 ---------- */
/* ① 浏览器不支持 backdrop-filter：玻璃会「只剩半透明白」→ 退回实色卡片，
      否则在花哨的 PDF 背景上文字可能不可读（这是功能性回退，不是装饰）。 */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .report-spread__toolbar {
    background: var(--card);
    border-color: var(--line);
  }
  [data-theme="dark"] .report-spread__toolbar { background: var(--card); border-color: var(--line); }
  .report-spread__toolbar button { background: var(--blue-050); border-color: color-mix(in srgb, var(--blue) 24%, var(--line)); }
}
/* ② 系统「减弱动态效果」：去掉位移/缩放，仅保留静态玻璃外观 */
@media (prefers-reduced-motion: reduce) {
  .report-spread__toolbar { transition: none; }
  .report-spread__toolbar button:hover:not(:disabled),
  .report-spread__toolbar button:active:not(:disabled) { transform: none; }
  .report-spread__toolbar button { transition: none; }
}
/* ③ 高对比度偏好：色散重影会降低可读性，直接关掉 */
@media (prefers-contrast: more) {
  .report-spread__range { text-shadow: none; }
  .report-spread__range::before,
  .report-spread__range::after { display: none; }
  .report-spread__toolbar { background: var(--card); }
}
/* ④ 打印：玻璃效果毫无意义且会白底变灰，直接还原 */
@media print {
  .report-spread__toolbar {
    background: #fff; box-shadow: none; border-color: #ddd;
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  .report-spread__toolbar::before,
  .report-spread__toolbar::after { display: none; }
  .report-spread__range { text-shadow: none; }
  .report-spread__range::before,
  .report-spread__range::after { display: none; }
}

/* ==========================================================================
   Astra 倒计时条（紫色）· 2026-09-28 落地到开发集
   --------------------------------------------------------------------------
   需求来源（用户第三轮反馈后定稿）+「使用这个效果，先放到我的开发集中，但是
   颜色使用紫色」：

     ① 渐变形态 = **V 形**：左端深 → 中段亮斑 → 右端**再变深**。
        不是单调「左深右浅」（那一版被用户否掉，绿色版更是「右边完全没回深」）。
        依据：逐帧亮度曲线 —— 左端 0.346 → 峰值在 39% 处 1.000 → 右端 0.002。
     ② 中间那块亮斑**不是静止的**，它在左右滑动（实测亮度重心总行程 ≈108px，
        约占条宽 26%，方向偏左）。
     ③ 粒子必须**位置不规则 + 速度各自独立**。原实现是「一整层 background-image
        + 单条 keyframes 平移 background-position」= 刚体平移，粒子等距且相对静止，
        用户明确指出「全部都是规则的」。
        实测：x 间距 CV=0.879（等距应 <0.15）、同帧速度极差平均 6.61 px/帧。
     ④ 颜色 = **紫色**（落地时的显式指定；绿色语义版留在预览页备查）。

   ⚠️ 三条实现约束（踩过的坑，别改回去）：
     1) **不得碰 fill 的 transform**：进度由 JS 按分钟写入
        `style="transform:scaleX(p)"`（app.js renderDispatch + _dispatchPaintCountdown）。
        CSS 只做「皮肤」，任何 transform/width 声明都会与 JS 打架。
     2) **::after 已被老条纹层占用**（见上方 4371 行 dispatch-bar-flow / dispatch-bar-pulse）。
        本段用 ::before 承载「V 形底色 + 移动亮斑」，两层的 background 不冲突；
        老条纹层保留原样叠加（它负责「流动感」，本层负责「形态 + 亮斑」）。
     3) **粒子必须逐颗独立元素**（span.dispatch-countdown__dust > i）：
        每颗自带 --x/--y/--s/--o/--dur/--dist/--delay，速度 = --dist/--dur（双重随机）。
        ⛔ 禁止写成「一层 background-image + 一条 keyframes 平移」的刚体模式。
        容器由 JS 播种（app.js `_seedAstraDust`），CSS 只描述样式。

   ⚠️ 铁律遵守：追加到文件末尾；不使用 !important；注释内不出现「星号紧跟斜杠」。
   ========================================================================== */

/* ---- ① + ② V 形底色：两端深、中段亮（静态），其上叠会移动的亮斑 ---- */
/* 底色用**更宽**的渐变（跨整个填充宽度铺满），色标呈 V 形分布。
   紫色阶取自项目既有蓝紫体系（#2249c5 → #947afb）并向紫偏移，
   两端压到深紫、中段提到亮紫，形成用户描述的「深→亮→深」。 */
.dispatch-countdown__fill {
  background-image: linear-gradient(90deg,
    #3b1d8f 0%, #4a24a8 10%, #6234c6 22%, #7d4ae0 33%,
    #9b6bf2 44%, #a97cf8 50%, #9b6bf2 56%,
    #7d4ae0 67%, #6234c6 78%, #4a24a8 90%, #3b1d8f 100%);
  background-size: 100% 100%;
  background-repeat: no-repeat;
}

/* ---- ② 移动的亮斑：柔和白色高光带，在条内左右滑动 ---- */
.dispatch-countdown__fill::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background-image: radial-gradient(60% 150% at 50% 50%,
    rgba(255, 255, 255, .34) 0%,
    rgba(255, 255, 255, .16) 38%,
    rgba(255, 255, 255, 0) 72%);
  background-size: 70% 100%;
  background-repeat: no-repeat;
  animation: dispatch-astra-spot 4.2s ease-in-out infinite alternate;
}
/* 亮斑滑动：**用 background-position 平移**（不是换色、不是改 animation-direction）。
   行程 12% → 88%，与实测「重心来回滑动、总行程约 26% 条宽」同量级。
   ⚠️ alternate：8 秒视频只够看一趟半，真实运动是否严格周期无法判定；
      当前取「来回摆动」，若需单向循环改 animation-direction 即可。 */
@keyframes dispatch-astra-spot {
  0%   { background-position: 12% 0; }
  100% { background-position: 88% 0; }
}

/* ---- ③ 粒子层：逐颗独立，位置不规则 + 速度各自不同 ---- */
.dispatch-countdown__dust {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  overflow: hidden;
  border-radius: inherit;
  /* ⚠️ 本容器**自身不得**有任何 background-position 动画 —— 那正是刚体平移的特征。 */
}
/* 每颗粒子：位置/大小/亮度/时长/位移/相位全部来自各自的自定义属性 */
.dispatch-countdown__dust i {
  position: absolute;
  top: var(--y, 50%);
  left: var(--x, 50%);
  width: var(--s, 2px);
  height: var(--s, 2px);
  border-radius: 50%;
  background: radial-gradient(circle,
    rgba(255, 255, 255, var(--o, .9)) 0%,
    rgba(255, 255, 255, 0) 72%);
  transform: translate(0, -50%);
  animation: dispatch-astra-dust var(--dur, 1.6s) linear var(--delay, 0s) infinite;
  will-change: transform;
}
/* ⚠️ 位移量取自**每颗自己的 --dist**，不是共用常量 → 速度 = --dist / --dur，
   两条随机相乘，必然各不相同（这正是「相对静止」的反面）。 */
@keyframes dispatch-astra-dust {
  from { transform: translate(0, -50%); }
  to   { transform: translate(calc(-1 * var(--dist, 240px)), -50%); }
}

/* ---- ⑤ 归档（窗口结束）：灰化时停掉全部动效与亮斑 ---- */
.dispatch-item--archived .dispatch-countdown__fill {
  background-image: none;
  background: var(--gray);
}
.dispatch-item--archived .dispatch-countdown__fill::before { animation: none; opacity: 0; }
.dispatch-item--archived .dispatch-countdown__dust { display: none; }

/* ---- ⑥ 深色主题：深底上把两端再压暗一档、亮斑略提亮，保持 V 形对比 ---- */
[data-theme=dark] .dispatch-countdown__fill {
  background-image: linear-gradient(90deg,
    #2c1470 0%, #39208a 10%, #4e28ab 22%, #663bc9 33%,
    #8b5ae8 44%, #9a6bf2 50%, #8b5ae8 56%,
    #663bc9 67%, #4e28ab 78%, #39208a 90%, #2c1470 100%);
}
[data-theme=dark] .dispatch-countdown__fill::before {
  background-image: radial-gradient(60% 150% at 50% 50%,
    rgba(255, 255, 255, .26) 0%,
    rgba(255, 255, 255, .12) 38%,
    rgba(255, 255, 255, 0) 72%);
}

/* ---- ⑦ 尊重系统「减弱动态效果」：保留静态 V 形条，亮斑与粒子全停 ---- */
@media (prefers-reduced-motion: reduce) {
  .dispatch-countdown__fill::before {
    animation: none;
    background-position: 50% 0;
  }
  .dispatch-countdown__dust { display: none; }
}


/* ============================================================
   样品台账（2026-09-29 新增一级功能页）
   列宽比例严格照录 Word 备案模板 HBGT-JL-39-01-2020-1/0：
   2.9 / 10.5 / 4.9 / 12.2 / 8.0 / 7.8 / 12.5 / 8.3 / 11.9 / 10.7 / 10.3 (%)
   ============================================================ */
.ledger-card { padding: 0; overflow: hidden; }
.ledger-scroll { width: 100%; overflow-x: auto; overscroll-behavior-x: contain; }
.ledger-tbl { min-width: 1180px; table-layout: fixed; }
.ledger-tbl th, .ledger-tbl td {
  text-align: center;
  padding: 10px 6px;
  font-size: 12.5px;
  word-break: break-all;
}
.ledger-tbl th { white-space: normal; line-height: 1.45; }
.ledger-tbl td { font-size: 12.5px; color: var(--ink-2); }
.ledger-tbl tbody tr::after { display: none; }

/* 11 列列宽（%）：与备案模板逐列对齐 */
.lg-c-no   { width: 2.9%; }

/* ⚠️ 序号列必须横向单行（2026-09-29 用户要求「不要换行」）：
   列宽仅 2.9%，而上面 .ledger-tbl td 设了 word-break: break-all，
   两/三位数（如 12、128）会被拆成「1 / 2」上下两行。
   故对首列单独关掉断词 + 禁止换行，并压缩左右内边距腾出宽度。 */
.ledger-tbl th.lg-c-no,
.ledger-tbl td:first-child {
  word-break: keep-all;
  overflow-wrap: normal;
  white-space: nowrap;
  padding-left: 2px;
  padding-right: 2px;
  font-variant-numeric: tabular-nums;
}
.lg-c-name { width: 10.5%; }
.lg-c-qty  { width: 4.9%; }
.lg-c-code { width: 12.2%; }
.lg-c-time { width: 8.0%; }
.lg-c-time + .lg-c-sign { width: 12.5%; }
.lg-c-sign { width: 8.3%; }
.lg-c-sign:last-child { width: 10.3%; }

/* 签字列：签名图 or 空白手签栏 */
.ledger-sign {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 26px; width: 100%;
}
.ledger-sign img {
  max-height: 26px; max-width: 100%;
  object-fit: contain;
  mix-blend-mode: multiply;
}
.dark .ledger-sign img { mix-blend-mode: normal; filter: invert(1) hue-rotate(180deg); }
.ledger-dash { color: var(--gray-3); }

/* 搜索框 */
.ledger-search {
  height: 34px; width: 230px;
  padding: 0 12px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink);
  font-size: 13px;
  font-family: inherit;
  outline: none;
  transition: border-color .22s var(--ease), box-shadow .22s var(--ease);
}
.ledger-search:focus {
  border-color: var(--blue);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 18%, transparent);
}
