/* ============================================================
   飞行审批 · 智能检测（#apvr-panel）
   —— 三段叙事，各管各的语义：
      ① 边缘 .apvs-frame：一圈冷光弧绕行 + 四角取景框 + 内侧呼吸辉光。
         常驻：进详情亮起、退回列表撤下。
      ② 扫描 .apvs-stage：自上而下一道光缝（白芯 + 上下两撇色散边
         + 头顶竖纹读痕 + 身下一片镜头光），划过的地方逐行点亮，
         读作「这份申报被逐行读取」。
      ③ 研判 .apvs-ai：扫描走完，一块被雾气蒙住的结果区自上而下解开——
         雾面（backdrop-filter）向上退、退到哪儿、哪一块才开始出结论，
         风险 → 气象 → 冲突依次落定，最后把结论写进底部受理意见。
   —— 色只用「冷白 → 雾蓝 → 钢蓝」一支（钢蓝 #8FB0CC 就是面板本色），
      通过用面板自己的 #7EC9A6，提示用 #E0A968，不另立一套色。
      检测态不靠撞色成立，靠明度：深玻璃上一道近白的光走过去，
      本身就够狠；再叠高饱和紫/洋红，读起来是游戏 HUD，不是审批系统。
   —— 全部 pointer-events: none；本层只在 detail + smart + mine 三条件
      同时成立时存在，开关关闭 / 退回列表即整层撤下，原交互零改动
   ============================================================ */

/* 角度变量：@property 让 conic-gradient 的起点可被动画驱动。
   不支持时退回静态：光弧停在一个角度上，仍是可读的一道边光 */
@property --apvs-a {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

/* 压暗带的分界位置：0% 整块压暗、100% 整块还原。
   与光缝共用同一组 lead / scan，所以两者严格同步向下退 */
@property --apvs-dy {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 0%;
}

/* ============================================================
   ① 边缘：冷光弧 + 取景框
   ============================================================ */
.apvs-frame {
  position: absolute; inset: 0; z-index: 4;
  border-radius: inherit; overflow: hidden;
  pointer-events: none;
  opacity: 0;
  transition: opacity 420ms ease;
}
.apvs-frame.is-on { opacity: 1; }
/* 扫描完的常驻态：收一档，别跟正文抢注意力 */
.apvs-frame.is-steady { opacity: 0.9; }

/* 内侧通电辉光：光弧之外的第二层，让整块面板像被点亮了一圈。
   幅度压得很轻——它是「有余温」，不是「在闪」 */
.apvs-aura {
  position: absolute; inset: 0; border-radius: inherit;
  box-shadow:
    inset 0 0 38px rgba(120, 168, 208, 0.20),
    inset 0 0 1px rgba(214, 232, 246, 0.52);
  animation: apvsBreath 3.8s ease-in-out infinite;
}
@keyframes apvsBreath {
  0%, 100% { opacity: 0.68; }
  50%      { opacity: 1; }
}

/* 光弧本体：conic 渐变铺满整块，双 mask 裁成 2px 的边框环。
   一明一暗两道——明的一支在 0deg（纯白芯带冷尾），次亮的一支在 210deg 附近。
   两层：.apvs-bloom 是同一支渐变的模糊版，负责「溢出边框的光晕」；
   .apvs-ring 保持锐利，负责那条看得清的 2px 亮线。
   只有一层锐线时，边光在深色玻璃上太薄；只有一层光晕时，又说不出是「光在走」。

   —— 周期由脚本写进 --apvs-orbit，值就是扫描总长（lead + scan）。
      光弧与光缝同一刻起步、同一刻收尾，绕完正好一圈：
      它不再是「背景里一圈自己在转的边」，而是「跟着这次扫描一起跑的一束光」。
      原来写死 8.6s，一圈比扫描长出两倍多，3.3s 里只走 138°，
      看着就像一圈静态描边——灵动感是被周期拖没的。
   —— 亮段与暗段的落差要拉够：亮段接近纯白，暗段压到 0.04。
      光在边框上「走」不靠色相变化，靠这一段明暗差在环上滑动 */
.apvs-ring, .apvs-bloom {
  position: absolute; inset: 0; border-radius: inherit; padding: 2.5px;
  background: conic-gradient(from var(--apvs-a, 0deg),
    rgba(255, 255, 255, 1) 0deg,
    rgba(234, 246, 255, 0.98) 7deg,
    rgba(198, 224, 244, 0.74) 18deg,
    rgba(162, 200, 232, 0.34) 34deg,
    rgba(150, 190, 230, 0.11) 56deg,
    rgba(150, 190, 230, 0.05) 88deg,
    rgba(150, 190, 230, 0.04) 176deg,
    rgba(178, 210, 238, 0.09) 196deg,
    rgba(200, 226, 244, 0.34) 208deg,
    rgba(172, 208, 236, 0.50) 216deg,
    rgba(160, 198, 232, 0.22) 230deg,
    rgba(150, 190, 230, 0.07) 252deg,
    rgba(150, 190, 230, 0.04) 310deg,
    rgba(150, 190, 230, 0.05) 360deg);
  -webkit-mask-image: linear-gradient(#000 0 0), linear-gradient(#000 0 0);
  -webkit-mask-clip: content-box, border-box;
  -webkit-mask-composite: xor;
  mask-image: linear-gradient(#000 0 0), linear-gradient(#000 0 0);
  mask-clip: content-box, border-box;
  mask-composite: exclude;
  animation: apvsOrbit var(--apvs-orbit, 3680ms) linear infinite;
}
/* 光晕不再提饱和：saturate 会把旁边那点冷蓝一路推到发青，
   而这支色系的全部力气在明度上，不在彩度上。
   模糊半径收到 6px、不透明度提到 0.9——光晕要贴着锐线，才读成「同一束光的溢出」 */
.apvs-bloom { filter: blur(6px) saturate(0.92); opacity: 0.9; }
@keyframes apvsOrbit {
  from { --apvs-a: 0deg; }
  to   { --apvs-a: 360deg; }
}

/* 四角取景框：15px 的 L 形细线，向内 8px。
   它的作用是「这是一块被系统框住的区域」，比再加一圈边框轻，也不抢光弧 */
.apvs-corners { position: absolute; inset: 8px; }
.apvs-corners i {
  position: absolute; width: 15px; height: 15px;
  border: 1px solid rgba(206, 228, 246, 0.40);
  filter: drop-shadow(0 0 4px rgba(140, 182, 218, 0.6));
}
.apvs-corners i:nth-child(1) { left: 0; top: 0; border-right: 0; border-bottom: 0; border-radius: 2px 0 0 0; }
.apvs-corners i:nth-child(2) { right: 0; top: 0; border-left: 0; border-bottom: 0; border-radius: 0 2px 0 0; }
.apvs-corners i:nth-child(3) { right: 0; bottom: 0; border-left: 0; border-top: 0; border-radius: 0 0 2px 0; }
.apvs-corners i:nth-child(4) { left: 0; bottom: 0; border-right: 0; border-top: 0; border-radius: 0 0 0 2px; }

/* ============================================================
   ② 扫描舞台
   —— top / height / 三个时长都由脚本写进 CSS 变量：
      舞台只覆盖「抬头 + 正文」这一块，也就是这条申请的申报信息本体
   ============================================================ */
.apvs-stage {
  position: absolute; left: 0; right: 0; top: 0; height: 0;
  z-index: 4; pointer-events: none; overflow: hidden;
  opacity: 0;
  transition: opacity 320ms ease;
}
.apvs-stage.is-on { opacity: 1; }

/* 压暗带：扫描期间把还没读到的那一半压下去，白线才有对比。
   —— 关键在于它不能整块压暗。整块压暗 + 一条亮线，读起来是
      「一块暗底上有条白杠在动」，光缝和白杠是两层东西；
      压暗带跟着光缝一起往下退，读到的才是「光走过的地方被读亮了、
      还没走到的地方还暗着」——这才是「自上而下」。
   —— 分界位置由 --apvs-dy 驱动，与 .apvs-beam 同 lead、同 scan、同为 linear：
      两者是一条时间轴上的两个表现，不是两个各自跑的动画。
      分界处留 56px 的过渡，是给光缝自己的身体（色散边 + 前溢）留位置，
      硬切会在白线下面切出一道直边。 */
.apvs-dim {
  position: absolute; inset: 0; opacity: 0;
  background:
    radial-gradient(130% 80% at 50% 34%, rgba(8, 13, 20, 0.07) 0%, rgba(4, 7, 11, 0.33) 100%);
  -webkit-mask-image: linear-gradient(180deg,
    rgba(0, 0, 0, 0) 0,
    rgba(0, 0, 0, 0) var(--apvs-dy, 0%),
    #000 calc(var(--apvs-dy, 0%) + 56px),
    #000 100%);
  mask-image: linear-gradient(180deg,
    rgba(0, 0, 0, 0) 0,
    rgba(0, 0, 0, 0) var(--apvs-dy, 0%),
    #000 calc(var(--apvs-dy, 0%) + 56px),
    #000 100%);
}
.apvs-stage.is-scan .apvs-dim {
  /* 两条动画分工：一条管整体进出（明度），一条管分界位置（几何）。
     拆开是因为它们时长不同——进出要跟着整段扫描收，分界只跟光缝走 */
  animation:
    apvsDimIn var(--apvs-total, 3680ms) linear both,
    apvsDimSweep var(--apvs-scan, 3300ms) linear var(--apvs-lead, 380ms) both;
}
@keyframes apvsDimIn {
  0%   { opacity: 0; }
  6%   { opacity: 1; }
  92%  { opacity: 1; }
  100% { opacity: 0; }
}
@keyframes apvsDimSweep {
  from { --apvs-dy: 0%; }
  to   { --apvs-dy: 100%; }
}

/* 点位矩阵：比方格网更像「被数字化采样」，也不会在字下面结成一层格栅 */
.apvs-dots {
  position: absolute; inset: 0; opacity: 0;
  mix-blend-mode: screen;
  background-image:
    radial-gradient(rgba(178, 208, 232, 0.16) 0.9px, rgba(0, 0, 0, 0) 1px);
  background-size: 22px 22px;
  -webkit-mask-image: radial-gradient(150% 96% at 50% 26%, #000 28%, rgba(0, 0, 0, 0) 100%);
  mask-image: radial-gradient(150% 96% at 50% 26%, #000 28%, rgba(0, 0, 0, 0) 100%);
}
.apvs-stage.is-scan .apvs-dots {
  animation: apvsDots var(--apvs-total, 4200ms) linear both;
}
@keyframes apvsDots {
  0%   { opacity: 0; background-position: 0 0; }
  10%  { opacity: 0.85; }
  68%  { opacity: 0.5; }
  100% { opacity: 0; background-position: 0 102px; }
}

/* 光缝本体：零高容器，靠 translateY 整段下移；--apvs-h 由脚本量出的舞台高度写入 */
.apvs-beam {
  position: absolute; left: 0; right: 0; top: 0; height: 0;
  will-change: transform;
}
.apvs-stage.is-scan .apvs-beam {
  /* 匀速：光缝是「扫描」，不是「弹入」。匀速也让「划到哪一行、哪一行才亮」
     这条时间轴能与脚本里的逐行计时严格对齐（缓动会把两者错开一截） */
  animation: apvsDrop var(--apvs-scan, 3300ms) linear var(--apvs-lead, 380ms) both;
}
@keyframes apvsDrop {
  from { transform: translateY(0); }
  to   { transform: translateY(var(--apvs-h, 0px)); }
}

/* 镜头光：缝上方一团宽而极淡的椭圆，读作「光从玻璃上扫过」，
   不是「面板上糊了一块白」。它负责体积，白线负责形 */
.apvs-lens {
  position: absolute; left: -8%; right: -8%; bottom: 0; height: 250px;
  mix-blend-mode: screen;
  background: radial-gradient(58% 66% at 50% 100%,
    rgba(226, 240, 252, 0.30) 0%,
    rgba(156, 198, 234, 0.15) 42%,
    rgba(140, 180, 220, 0.05) 62%,
    rgba(90, 140, 190, 0) 76%);
}

/* 竖纹读痕：缝上方 24px 的一排 1px 短竖线，横向慢速流动。
   它把「正在解析数据」这件事说得比任何一段文字都直接 */
.apvs-ticks {
  position: absolute; left: 0; right: 0; bottom: 1px; height: 16px;
  mix-blend-mode: screen; opacity: 0;
  background-image: repeating-linear-gradient(90deg,
    rgba(228, 240, 250, 0.80) 0 1px, rgba(0, 0, 0, 0) 1px 7px);
  -webkit-mask-image: radial-gradient(112% 132% at 50% 100%, rgba(0, 0, 0, 0.95) 26%, rgba(0, 0, 0, 0) 82%);
  mask-image: radial-gradient(112% 132% at 50% 100%, rgba(0, 0, 0, 0.95) 26%, rgba(0, 0, 0, 0) 82%);
  animation: apvsTicks 0.9s linear infinite;
}
.apvs-stage.is-scan .apvs-ticks { opacity: 0.4; }
@keyframes apvsTicks {
  from { background-position: 0 0; }
  to   { background-position: 14px 0; }
}

/* 白芯：1.5px，两端收掉、中段提纯白——不是均匀的一条白杠。
   光晕最外那一圈也从粉换成冷蓝：白线周围该是寒光，不是霓虹 */
.apvs-core {
  position: absolute; left: 0; right: 0; top: -1px; height: 2px;
  mix-blend-mode: screen;
  background: linear-gradient(90deg,
    rgba(150, 190, 230, 0) 0%,
    rgba(206, 228, 246, 0.72) 5%,
    #FFFFFF 20%,
    #FFFFFF 80%,
    rgba(214, 234, 250, 0.72) 95%,
    rgba(150, 190, 230, 0) 100%);
  box-shadow:
    0 0 2px rgba(255, 255, 255, 0.95),
    0 0 10px rgba(234, 245, 255, 0.98),
    0 0 30px rgba(140, 186, 230, 0.85),
    0 0 62px rgba(120, 168, 215, 0.34);
}
/* 色散两撇：白线上下各一条 1px，一条偏冷白、一条偏钢蓝。
   这是「棱镜」的全部机关——宽度只有 1px，但一眼就把白线从「一条白杠」
   变成「一束光」；再宽就假，就变成霓虹灯管。
   —— 上下两支都留在同族里（冷白 / 雾蓝），不再一紫一洋红地唱反调 */
.apvs-fr {
  position: absolute; left: 0; right: 0;
  mix-blend-mode: screen; pointer-events: none;
  filter: blur(3px);
}
/* 上方：近白色的雾带，越靠近白线越亮；
   下方：偏钢蓝的雾带。两条 2px 的纯色线在这个尺寸上根本看不出来——
   色散要靠「雾」才成立：白线位于中间，上下各有一层颜色，才读成一束光 */
.apvs-fr.is-a {
  top: -22px; height: 21px;
  background: linear-gradient(180deg,
    rgba(150, 190, 230, 0) 0%,
    rgba(172, 206, 236, 0.40) 44%,
    rgba(214, 234, 250, 0.82) 100%);
}
.apvs-fr.is-b {
  top: 2px; height: 12px;
  background: linear-gradient(180deg,
    rgba(198, 224, 244, 0.66) 0%,
    rgba(126, 170, 210, 0.26) 44%,
    rgba(90, 140, 190, 0) 100%);
}
/* 前溢：缝下方一小段被照亮，光才有「正在推进」的体积；再往下就收干净，
   否则整块正文会被泡在一层白雾里 */
.apvs-under {
  position: absolute; left: 0; right: 0; top: 1px; height: 30px;
  mix-blend-mode: screen;
  background: linear-gradient(180deg,
    rgba(214, 234, 250, 0.16) 0%,
    rgba(150, 190, 230, 0) 100%);
}
/* 两端的小光斑：线走到面板边不硬切，收成两个点光 */
.apvs-glint {
  position: absolute; top: 0; width: 38px; height: 38px; margin-top: -19px;
  mix-blend-mode: screen;
  background: radial-gradient(closest-side,
    rgba(246, 252, 255, 0.92) 0%, rgba(156, 198, 234, 0.32) 42%, rgba(150, 190, 230, 0) 72%);
}
.apvs-glint.is-l { left: -14px; }
.apvs-glint.is-r { right: -14px; }

/* 起手蓄势：线先在顶端自中线抽出（lead 那一段），抽满即开始下落 */
.apvs-stage.is-scan .apvs-core {
  animation: apvsCoreIn var(--apvs-lead, 380ms) cubic-bezier(0.2, 0.8, 0.3, 1) both;
}
@keyframes apvsCoreIn {
  0%   { opacity: 0; transform: scaleX(0.14); }
  55%  { opacity: 1; }
  100% { opacity: 1; transform: scaleX(1); }
}

/* —— 逐行点亮：光缝经过某一行时，这一行从底下浮起一层冷光，760ms 退掉 ——
   按行而不是按分区：按分区亮，一屏只亮四次，读起来像「换了四块背景」；
   按行亮，才像光真的在一行一行读过去。
   —— 亮度靠「蓝的明度」给，不靠加彩度：0.10 的紫在暗底上已经偏艳，
      这里是 0.09 的雾蓝，只会读成「这一行被照亮了」 */
.apvs-lit { animation: apvsRow 760ms cubic-bezier(0.25, 0.7, 0.3, 1) both; }
@keyframes apvsRow {
  0%   { box-shadow: inset 0 0 0 40px rgba(150, 190, 230, 0); }
  20%  { box-shadow: inset 0 0 0 40px rgba(160, 198, 232, 0.09); }
  100% { box-shadow: inset 0 0 0 40px rgba(150, 190, 230, 0); }
}
/* 抬头卡自带一道 insets 高光，动画起终帧必须把它原样带上，
   否则一入一出会把卡片顶部那道 0.045 的白线吃掉 */
.apvr-dhero.apvs-lit { animation-name: apvsRowHero; }
@keyframes apvsRowHero {
  0%   { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.045); }
  20%  { box-shadow: inset 0 0 0 1px rgba(172, 206, 236, 0.20),
                     inset 0 0 60px rgba(120, 168, 208, 0.14),
                     inset 0 1px 0 rgba(255, 255, 255, 0.045); }
  100% { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.045); }
}
.apvs-lit .apvr-dh > i { animation: apvsTick 760ms ease both; }
@keyframes apvsTick {
  0%   { box-shadow: 0 0 7px rgba(111, 163, 208, 0.55); }
  22%  { box-shadow: 0 0 14px rgba(234, 246, 255, 1), 0 0 28px rgba(140, 182, 218, 0.75); }
  100% { box-shadow: 0 0 7px rgba(111, 163, 208, 0.55); }
}

/* ============================================================
   ③ 研判结果：一块按内容定高的浮层，压在模糊过的正文之上
   ============================================================
   这一层不再「替换」正文，也不再折叠任何分区：
     · 正文（审批进度 / 申报信息 / 航空器 / 操控员）全部留在原位，
       只被一层高斯模糊推远——它是背景，不是被删掉的旧内容；
     · 结果是一块浮起来的玻璃卡，高度由内容自己决定，
       垂直居中于滚动视口，上下露出的正是那层模糊的正文。
   —— 为什么不再撑满：结论只有 470 来 px，拉成一整屏就得靠 flex-grow
      把空白摊给三块读数，块与块之间的松紧全靠凑——读起来是
      「表格被拉长了」，不是「这一屏就是结论」。按内容定高、居中悬浮，
      视觉重量才落回结论本身，下方那层模糊自然补上「下面还有东西」。
   —— 为什么不再折叠分区：折叠会让航空器、操控员整体上移，一次点击里
      同时发生「模糊 + 上移 + 结果入场」三件事，视线没有落点；
      现在只发生一件事——正文退到玻璃后面，结果浮起来。
   —— 模糊加在 #apvr-content 自己身上（filter），不是盖一层 backdrop-filter：
      后者连同面板背后的地图一起糊掉，整块面板都变成磨砂玻璃；
      前者只糊正文，地图、面板边缘、抬头保持清晰。
   ============================================================ */
#apvr-panel.is-ai-veiled .apvr-content {
  /* 结果态背景是静止的：身后有文字在滚，模糊层一动，眼睛就会跟着往边缘跑 */
  overflow: hidden;
  /* 亮度和模糊都要留一线：糊到全黑，背景就成了一块空板，
     读不出「底下还有一条申请」——那点模糊的字影正是景深本身 */
  filter: blur(8px) saturate(0.62) brightness(0.72);
}
/* 过渡写在常态规则上，加类与撤类两个方向才有得插值 */
#apvr-panel .apvr-content { transition: filter 520ms ease; }
/* 正文已经不能滚（上面那条 overflow: hidden），滚动指示条还亮着就是在骗人 */
#apvr-panel.is-ai-veiled .apvr-scroll { opacity: 0; }

/* 浮层容器：铺满滚动视口，卡片在其中垂直居中。
   pointer-events: none —— 它是一层，不是一堵墙，底下正文不归它管。
   —— 四边必须留出这段内边距：不留，卡片就顶到视口四边，读起来还是
      「这一块换成了结果」，模糊的正文只剩四条缝。留出这一圈，卡片才是浮着的 */
.apvs-layer {
  position: absolute; z-index: 5;
  display: flex; align-items: center; justify-content: center;
  padding: 12px 8px;
  box-sizing: border-box;
  pointer-events: none;
  opacity: 0;
  transition: opacity 360ms ease;
}
.apvs-layer.is-on { opacity: 1; }

/* 结果卡：一块真正浮起来的玻璃。
   —— 材质必须和面板同一支墨：面板是 rgba(13,18,26,.62) + 左上角一层极淡紫光，
      卡片原来自己调了一版「蓝灰渐变」（27,35,46 → 12,17,24），
      比面板更亮也更蓝，放在一起就是「面板里嵌了另一块屏」。
      现在沿用面板同一个色值、只把不透明度提到 0.86——同一块玻璃，厚了一层。
   —— 再加一层 backdrop-filter：身后已经是模糊的字，再糊一次把笔画压平成
      一片调子，卡片上的字才立得住；不加，模糊的字影会从卡片底下透上来抢读。
   —— 投影要重、要偏下：浮起来的那点错觉全靠它，描边只负责把边缘说清楚 */
.apvs-ai {
  position: relative;
  width: 100%; max-height: 100%; box-sizing: border-box;
  display: flex; flex-direction: column;
  padding: 12px;
  border-radius: 12px;
  pointer-events: auto;
  overflow: hidden auto;
  scrollbar-width: none; -ms-overflow-style: none;
  -webkit-backdrop-filter: blur(16px) saturate(1.04);
  backdrop-filter: blur(16px) saturate(1.04);
  background:
    radial-gradient(118% 56% at 0% 0%, rgba(184, 158, 255, 0.075) 0%, rgba(184, 158, 255, 0) 64%),
    rgba(13, 18, 26, 0.86);
  box-shadow:
    0 36px 74px -20px rgba(0, 0, 0, 0.72),
    inset 0 1px 0 rgba(255, 255, 255, 0.06);
  /* 自下而上浮起：24px 的位移刚好够读成「升上来」，再多就成了弹窗 */
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 460ms ease, transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
}
.apvs-ai::-webkit-scrollbar { width: 0; height: 0; display: none; }
.apvs-ai.is-on { opacity: 1; transform: none; }

/* 抬头：沿用 .apvr-dh 的骨架（与「申报信息」等分区同一字号），
   右端只留一枚收起键——结论出来后这里不再报读数，读数在下面的判定卡里 */
.apvs-ai-hd { height: 22px; margin-bottom: 8px; }
.apvs-ai-hd > i {
  background: linear-gradient(180deg, #DCEAF6 0%, #8FB0CC 100%);
  box-shadow: 0 0 9px rgba(140, 178, 212, 0.75);
}
.apvs-ai-hd > span { color: #F0F6FB; font-size: 12.5px; letter-spacing: 1.5px; }
.apvs-ai-hd > b {
  display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 500;
  letter-spacing: 0.4px; color: rgba(178, 204, 228, 0.72);
  transition: color 300ms ease, opacity 260ms ease;
}
.apvs-ai-hd > b::before {
  content: ""; width: 4px; height: 4px; border-radius: 50%;
  background: currentColor; box-shadow: 0 0 7px currentColor;
}
.apvs-ai-hd > b.is-ok   { color: #7EC9A6; }
.apvs-ai-hd > b.is-warn { color: #E0A968; }
/* 结论已出：这行字连同那枚小圆点一起收掉 */
.apvs-ai-hd > b.is-off { opacity: 0; }
.apvs-ai.is-done .apvs-ai-hd > b::before { animation: none; opacity: 1; }
.apvs-ai:not(.is-done) .apvs-ai-hd > b::before { animation: apvsPulse 1.6s ease-in-out infinite; }

/* 收起键：抬头右端一枚 22px 的图标按钮。
   —— 图标走项目统一的绘制规范：24 网格、stroke-width 2、圆头圆角、currentColor，
      与面板右上那枚折叠开关是同一族；方向朝上，两处箭头都在说「收起来」。
   —— 不写成「收起 + 箭头」的文字胶囊：这一行左侧已经有一句「智能决策结果」，
      右边再来一个词就是两个标签并排，按钮反而没有按钮的样子。
      宽度靠方形键身和一道实描边撑住，跟面板头的圆形按钮同一档分量 */
.apvs-collapse {
  flex-shrink: 0; width: 22px; height: 22px; margin-left: 8px; padding: 0;
  display: none; align-items: center; justify-content: center;
  border: 0; border-radius: 6px;
  background: rgba(140, 178, 212, 0.10);
  box-shadow: inset 0 0 0 1px rgba(152, 192, 226, 0.30);
  color: rgba(206, 226, 242, 0.86); cursor: pointer;
  transition: background 200ms ease, box-shadow 200ms ease, color 200ms ease, transform 200ms ease;
}
.apvs-collapse svg { width: 15px; height: 15px; display: block; }
.apvs-ai.is-done .apvs-collapse { display: inline-flex; animation: apvsFadeIn 320ms ease both; }
.apvs-collapse:hover {
  color: #FFFFFF;
  background: rgba(150, 190, 224, 0.22);
  box-shadow: inset 0 0 0 1px rgba(178, 210, 240, 0.56), 0 0 16px rgba(140, 182, 218, 0.45);
}
.apvs-collapse:active { transform: translateY(0.5px); }
.apvs-collapse:focus-visible { outline: 1px solid rgba(196, 228, 255, 0.8); outline-offset: 1px; }
@keyframes apvsFadeIn { from { opacity: 0; } to { opacity: 1; } }

/* —— 综合判定：一条占满宽度的结论带 ——
   原来这一块是全系统最艳的地方：紫色对角渐变 + 洋红角光 + 紫色外发光。
   但那三样东西说的都是「我很高科技」，没有一样在说「这条计划能不能放行」。
   现在只用中性冷灰玻璃 + 一道极弱的冷光，配左侧那条状态色竖线——
   结论的分量交给 17px 的粗字和那条竖线，不交给背景 */
.apvs-hero {
  position: relative; flex-shrink: 0;
  display: grid; grid-template-columns: 1fr; align-items: end;
  gap: 3px 10px; padding: 12px 12px 13px;
  border-radius: 9px;
  background:
    radial-gradient(130% 120% at 0% 0%, rgba(150, 190, 230, 0.075) 0%, rgba(150, 190, 230, 0) 62%),
    rgba(255, 255, 255, 0.045);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    inset 0 0 0 1px rgba(150, 186, 220, 0.18),
    0 10px 26px rgba(0, 0, 0, 0.22);
  margin-bottom: 5px;
}
.apvs-hero::before {
  content: ""; position: absolute; left: 0; top: 11px; bottom: 11px; width: 2px;
  border-radius: 0 2px 2px 0;
  background: linear-gradient(180deg,
    rgba(123, 240, 194, 0.95) 0%, rgba(123, 240, 194, 0.06) 100%);
  box-shadow: 0 0 12px rgba(126, 201, 166, 0.55);
  transition: background 400ms ease, box-shadow 400ms ease;
}
.apvs-ai[data-st="warn"] .apvs-hero::before {
  background: linear-gradient(180deg,
    rgba(224, 169, 104, 0.95) 0%, rgba(224, 169, 104, 0.06) 100%);
  box-shadow: 0 0 12px rgba(224, 169, 104, 0.55);
}
.apvs-ai[data-st="fail"] .apvs-hero::before {
  background: linear-gradient(180deg,
    rgba(223, 106, 74, 0.95) 0%, rgba(223, 106, 74, 0.06) 100%);
  box-shadow: 0 0 12px rgba(223, 106, 74, 0.55);
}
/* 需协调：琥珀，与警告同一支。
   它比「通过」重（要人动手），比「不予放行」轻（不是驳回）——
   硬要给它第五支颜色，就成了另一套色系，四档之间反而比不出来 */
.apvs-ai[data-st="hold"] .apvs-hero::before {
  background: linear-gradient(180deg,
    rgba(224, 169, 104, 0.95) 0%, rgba(224, 169, 104, 0.06) 100%);
  box-shadow: 0 0 12px rgba(224, 169, 104, 0.55);
}
/* 检测中：判定带左沿先按中性走。
   这一段写的是「分析中」，绿色是「过了」、红色是「没过」，
   出结论之前先把颜色放出去，等于把答案提前写在封面上 */
.apvs-ai[data-st="run"] .apvs-hero::before {
  background: linear-gradient(180deg,
    rgba(176, 202, 226, 0.55) 0%, rgba(176, 202, 226, 0.04) 100%);
  box-shadow: 0 0 10px rgba(150, 190, 226, 0.28);
}
.apvs-hero-l { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
/* 标签从「综合判定」变成「综合判定结果」，字数多了一个；
   原来 9.5px / 字距 2.4 是按 4 个字排的，加到 5 个字会拖成一条松散的小横线，
   于是收一档字距、抬半档字号，让它读起来仍是一个整块的小标题 */
.apvs-hero-k {
  font-size: 10px; letter-spacing: 1.6px; text-transform: uppercase;
  color: rgba(176, 200, 224, 0.66);
}
/* 结论字：白 → 淡钢蓝的极浅渐变。字本身够大够重，不需要发光来撑；
   原来那层 10px 的紫 drop-shadow 只让人以为这是一句可以滑动的标语 */
.apvs-verdict {
  font-size: 19px; font-weight: 700; letter-spacing: 1.5px; line-height: 1;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  background: linear-gradient(180deg, #FFFFFF 0%, #EDF4FB 46%, #C4D8E9 100%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
  color: #EDF4FB;
  filter: drop-shadow(0 1px 10px rgba(140, 185, 230, 0.26));
  transition: opacity 260ms ease;
}
.apvs-ai[data-st="warn"] .apvs-verdict {
  background: linear-gradient(180deg, #FFF3E2 0%, #FFD3A0 44%, #FFA845 100%);
  -webkit-background-clip: text; background-clip: text;
  filter: drop-shadow(0 0 10px rgba(224, 169, 104, 0.45));
}
/* 通过：绿。取系统里那支「通过」绿（#7EC9A6 一族），上端抬亮两档——
   19px 粗字压在深底上，#7EC9A6 原色会发灰，读起来像「淡了」而不是「过了」 */
.apvs-ai[data-st="ok"] .apvs-verdict {
  background: linear-gradient(180deg, #EAFCF3 0%, #9FE6C6 44%, #5EC79A 100%);
  -webkit-background-clip: text; background-clip: text;
  filter: drop-shadow(0 0 10px rgba(126, 201, 166, 0.42));
}
/* 不予放行：朱红。与冲突清单、图上锚点同一支红——
   三处说的是同一个结论，不该出现三种红 */
.apvs-ai[data-st="fail"] .apvs-verdict {
  background: linear-gradient(180deg, #FFEDE6 0%, #FFAD95 44%, #EC6C4E 100%);
  -webkit-background-clip: text; background-clip: text;
  filter: drop-shadow(0 0 10px rgba(223, 106, 74, 0.45));
}
/* 需协调：琥珀。这句 19px 的话就是审批人要读的那一行，
   它如果是绿的，下面三块写什么都白搭——「需协调」四个字压不住一支绿 */
.apvs-ai[data-st="hold"] .apvs-verdict {
  background: linear-gradient(180deg, #FFF6EA 0%, #FFD9AC 44%, #F0A85C 100%);
  -webkit-background-clip: text; background-clip: text;
  filter: drop-shadow(0 0 10px rgba(224, 169, 104, 0.42));
}

/* 三段读数条：一块走完填一段。
   —— 原来是 紫 → 靛 → 洋红 的彩虹，三条并排就是一段 RGB 灯带，
      面板里再没有第二处这么亮的东西，所以怎么看怎么跳。
      现在收成单色的「浅钢蓝 → 冷白」：它要说的是「这一段满了」，
      不是「我在发光」 */
.apvs-meter {
  grid-column: 1 / -1;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px;
  margin-top: 10px;
}
.apvs-meter > i {
  position: relative; height: 2px; border-radius: 2px;
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
}
.apvs-meter > i::after {
  content: ""; position: absolute; inset: 0; border-radius: 2px;
  background: linear-gradient(90deg, #3F9E79 0%, #6FD3A6 55%, #C4F3DC 100%);
  box-shadow: 0 0 10px rgba(126, 201, 166, 0.45);
  transform: scaleX(0); transform-origin: left center;
  transition: transform 560ms cubic-bezier(0.22, 1, 0.36, 1);
}
.apvs-meter > i.is-on::after { transform: scaleX(1); }
.apvs-meter > i.is-warn::after {
  background: linear-gradient(90deg, #C08A4A 0%, #E0A968 55%, #FFD3A0 100%);
  box-shadow: 0 0 10px rgba(224, 169, 104, 0.5);
}

/* —— 三块读数 ——
   三块按内容自然排，不再靠 grow 去分摊空白：卡片高度就是内容高度，
   多出来的空间留在卡片上下（也就是那层模糊的正文），而不是摊进块里。
   块与块之间的松紧由 gap 一处决定，三块读起来是同一个节奏
   —— 每块加一层极淡的底与一道描边：三块是三次判定，不是一张长表的三段。
      只靠一条 1px 的分隔线，扫下来是「一列数据」；给了框，
      才是「三段结论」，01/02/03 的编号也才站得住 */
.apvs-steps { display: flex; flex-direction: column; gap: 6px; }
.apvs-blk {
  --blk-x: 12px;                          /* 左右内边距：栏线的两端也吃这个值 */
  position: relative; overflow: hidden;   /* 雾要被这一块裁住 */
  padding: 10px var(--blk-x) 12px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.022);
  box-shadow: inset 0 0 0 1px rgba(150, 186, 220, 0.15);
}
/* 雾只盖内容、不盖块头：块头上的「检测中」正是此刻要说的话 */
.apvs-blk > .apvs-veil { top: 46px; }

/* 标题栏：编号 + 名字在左、状态胶囊在右，两者原来几乎贴在卡片描边上，
   一左一右顶着边框，读起来像被挤出去的。现在左右各留 14px，
   再给栏底一道贯穿的线——三块是三次判定，每块得先有一条自己的「栏」 */
.apvs-b-hd {
  position: relative; display: flex; align-items: center; gap: 8px;
  height: 20px; margin-bottom: 8px; padding-bottom: 8px;
}
.apvs-b-hd::before {
  content: ""; position: absolute; bottom: 0; height: 1px;
  left: calc(var(--blk-x) * -1); right: calc(var(--blk-x) * -1);
  background: linear-gradient(90deg,
    rgba(158, 196, 230, 0.30) 0%,
    rgba(158, 196, 230, 0.13) 52%,
    rgba(158, 196, 230, 0.04) 100%);
}
/* 序号：01/02/03。三块是「先风险、再气象、后冲突」的三步，
   给编号比给三个一样的菱形图标更说得清顺序 */
.apvs-idx {
  font-family: var(--font-mono); font-size: 9.5px; font-style: normal;
  font-weight: 500; letter-spacing: 0.6px;
  color: rgba(150, 182, 212, 0.6);
  transition: color 400ms ease;
}
.apvs-blk.is-done .apvs-idx { color: rgba(150, 182, 212, 0.4); }
.apvs-blk.is-done[data-st="ok"] .apvs-idx   { color: rgba(123, 240, 194, 0.6); }
.apvs-blk.is-done[data-st="warn"] .apvs-idx { color: rgba(224, 169, 104, 0.75); }
.apvs-b-hd > span {
  font-size: 12px; font-weight: 600; letter-spacing: 1.3px;
  color: #E6EEF6; white-space: nowrap;
}
/* 运行中：块头下缘扫一道 1px 亮线，说明这一块正在被读 */
.apvs-b-hd::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg,
    rgba(160, 198, 232, 0) 0%, rgba(212, 232, 248, 0.95) 50%, rgba(160, 198, 232, 0) 100%);
  opacity: 0; transform: scaleX(0.08);
}
.apvs-blk.is-live .apvs-b-hd::after {
  animation: apvsHeadSweep 900ms cubic-bezier(0.3, 0.7, 0.3, 1) both;
}
@keyframes apvsHeadSweep {
  0%   { opacity: 0; transform: scaleX(0.06); }
  18%  { opacity: 1; }
  100% { opacity: 0; transform: scaleX(1); }
}

/* 状态胶囊：检测中 / 通过 / 存在风险。三档只换色，不换尺寸 */
.apvs-chip {
  margin-left: auto; flex-shrink: 0;
  display: inline-flex; align-items: center; gap: 4px;
  height: 18px; padding: 0 7px; border-radius: 4px;
  font-size: 10px; font-style: normal; font-weight: 600; letter-spacing: 0.7px;
  transition: color 300ms ease, background 300ms ease, box-shadow 300ms ease;
}
.apvs-chip > i { width: 4px; height: 4px; border-radius: 50%; background: currentColor; opacity: 0.9; }
.apvs-blk[data-st="run"] .apvs-chip {
  color: rgba(198, 220, 238, 0.95);
  background: rgba(140, 178, 212, 0.12);
  box-shadow: inset 0 0 0 1px rgba(140, 178, 212, 0.3);
}
.apvs-blk[data-st="run"] .apvs-chip > i { animation: apvsPulse 1.6s ease-in-out infinite; }
@keyframes apvsPulse {
  0%, 100% { opacity: 0.25; box-shadow: 0 0 0 rgba(190, 214, 236, 0); }
  50%      { opacity: 1;    box-shadow: 0 0 8px currentColor; }
}
.apvs-blk[data-st="ok"] .apvs-chip {
  color: #7EC9A6;
  background: rgba(126, 201, 166, 0.11);
  box-shadow: inset 0 0 0 1px rgba(126, 201, 166, 0.36);
}
.apvs-blk[data-st="warn"] .apvs-chip {
  color: #E0A968;
  background: rgba(224, 169, 104, 0.11);
  box-shadow: inset 0 0 0 1px rgba(224, 169, 104, 0.38);
}

/* 雾：backdrop-filter 把下面这层内容糊掉，上缘一道亮缝是「解开的边缘」 */
.apvs-veil {
  position: absolute; left: -2px; right: -2px; top: 0; bottom: -2px; z-index: 2;
  -webkit-backdrop-filter: blur(10px) saturate(0.55) brightness(0.86);
  backdrop-filter: blur(10px) saturate(0.55) brightness(0.86);
  background: linear-gradient(180deg,
    rgba(16, 22, 30, 0.56) 0%,
    rgba(9, 13, 19, 0.42) 100%);
  transform: translateY(0);
  transition: transform 640ms cubic-bezier(0.42, 0.02, 0.22, 1);
  pointer-events: none;
}
.apvs-veil::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px;
  background: linear-gradient(90deg,
    rgba(160, 198, 232, 0) 0%, rgba(226, 242, 252, 0.95) 22%,
    #FFFFFF 50%, rgba(226, 242, 252, 0.95) 78%, rgba(160, 198, 232, 0) 100%);
  box-shadow: 0 0 12px rgba(150, 190, 230, 0.7);
}
.apvs-veil::after {
  content: ""; position: absolute; left: 0; right: 0; top: 1px; height: 22px;
  background: linear-gradient(180deg,
    rgba(200, 224, 244, 0.16) 0%, rgba(140, 178, 212, 0) 100%);
}
.apvs-blk.is-live .apvs-veil { transform: translateY(101%); }
.apvs-blk.is-done .apvs-veil { display: none; }

/* —— 风险项：三列小格，一枚一项 ——
   图标与名字整组居中：这些格子是「六项都过了」的六个刻度，
   左对齐时右边空一截，读起来像六条没写完的条目 */
.apvs-risks { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px 7px; }
.apvs-item {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  height: 26px; padding: 0 7px; border-radius: 5px;
  background: rgba(255, 255, 255, 0.024);
  box-shadow: inset 0 0 0 1px rgba(150, 186, 220, 0.09);
  font-size: 11.5px; letter-spacing: 0.3px; color: rgba(198, 212, 228, 0.44);
  transition: color 320ms ease, background 320ms ease, box-shadow 320ms ease;
  /* 初始留三成多的「幽灵」：雾才糊得住东西。全隐了，雾底就是一块空板 */
  opacity: 0.4; transform: translateY(3px);
}
.apvs-item.is-on {
  opacity: 1; transform: none;
  color: #E8EFF6;
  background: rgba(255, 255, 255, 0.045);
  box-shadow: inset 0 0 0 1px rgba(150, 186, 220, 0.18);
  transition: color 320ms ease, background 320ms ease, box-shadow 320ms ease,
              opacity 320ms ease 240ms, transform 320ms ease 240ms;
}
.apvs-item > span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* 出事的那几格：底板与字一起转琥珀，但只转一档。
   六格里三格同时报警，整块就会被读成「一片红」；这里要的是
   「这三项没过」，不是「整块烧起来了」——差一档，读法完全不同 */
.apvs-item[data-st="warn"] {
  color: #EFD9BF;
  background: rgba(224, 169, 104, 0.065);
  box-shadow: inset 0 0 0 1px rgba(224, 169, 104, 0.22);
}
.apvs-item[data-st="warn"].is-on { color: #F6E2CA; }

/* 状态图标：勾 / 叹号都是画出来的（stroke-dashoffset），不是贴两枚现成图标 */
.apvs-si {
  width: 13px; height: 13px; flex-shrink: 0; overflow: visible;
  fill: none; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round;
}
.apvs-si .g-ok { stroke: #6FB795; }
.apvs-si .g-no { stroke: #DFA45F; }
.apvs-blk [data-st="ok"] .g-no,
.apvs-item[data-st="ok"] .g-no,
.apvs-item[data-st="warn"] .g-ok { display: none; }
.apvs-si path, .apvs-si circle {
  stroke-dasharray: 42; stroke-dashoffset: 42;
  transition: stroke-dashoffset 380ms cubic-bezier(0.3, 0.7, 0.3, 1) 120ms;
}
.apvs-item.is-on .apvs-si path, .apvs-item.is-on .apvs-si circle { stroke-dashoffset: 0; }
.apvs-item.is-on .apvs-si path { transition-delay: 260ms; }
.apvs-item .apvs-si { opacity: 0.30; transition: opacity 300ms ease; }
.apvs-item.is-on .apvs-si { opacity: 1; }

/* —— 气象：一行一个时段，左边时段、右边四枚读数 ——
   原来只有三条发丝线分隔，跟上面那六枚有底的格子在视觉上不是同一套语言，
   读起来像「一张附注表」。现在每行也给自己一块底，字号提一档：
   这一段的信息密度和风险格是同级的，字不该比它小 */
.apvs-wx { display: flex; flex-direction: column; gap: 5px; }
/* 列宽：时段 / 胶囊 / 降水 / 温度 / 风。
   —— 风占得比另外两枚宽，它是唯一一个「两件事」的读数（角度 / 速度），
      按 1fr 平分时「120°/4m/s」会顶到格线外面；
      时段那列窄一档就够了：09:00 只有五个等宽字符 */
.apvs-wx-row {
  display: grid; grid-template-columns: 40px auto 1fr 1fr 1.34fr;
  align-items: center; gap: 6px; height: 30px;
  padding: 0 9px; border-radius: 5px;
  background: rgba(255, 255, 255, 0.026);
  box-shadow: inset 0 0 0 1px rgba(150, 186, 220, 0.09);
  opacity: 0.32; transform: translateY(3px);
  transition: opacity 340ms ease, transform 340ms ease;
}
.apvs-wx-row.is-on { opacity: 1; transform: none; }

.apvs-wx-t {
  font-family: var(--font-mono); font-size: 12.5px; letter-spacing: 0.2px;
  color: rgba(190, 208, 226, 0.7);
}
/* 胶囊：原来它是个 grid 子项，会被默认的 stretch 拉成整列宽（60px），
   而里面「圆点 + 适飞」只有 30px——字就一路贴在左边，右边空出 23px。
   现在胶囊按自己的内容定宽（justify-self: start），内部居中，
   左右 padding 对称，于是字真正落在胶囊正中 */
.apvs-wx-st {
  justify-self: start; justify-content: center;
  display: inline-flex; align-items: center; gap: 5px;
  height: 21px; padding: 0 8px; border-radius: 4px;
  font-size: 11.5px; letter-spacing: 0.5px;
  color: #7EC9A6;
  background: rgba(126, 201, 166, 0.10);
  box-shadow: inset 0 0 0 1px rgba(126, 201, 166, 0.26);
  opacity: 0.45; transition: opacity 360ms ease;
}
.apvs-wx-row.is-on .apvs-wx-st { opacity: 1; }
.apvs-wx-st > i {
  width: 3px; height: 3px; border-radius: 50%; background: currentColor;
  box-shadow: 0 0 6px rgba(126, 201, 166, 0.95);
}
.apvs-wx-m { display: flex; align-items: baseline; gap: 4px; min-width: 0; white-space: nowrap; }
.apvs-wx-m > em {
  font-style: normal; font-size: 11.5px; letter-spacing: 0.2px;
  color: rgba(178, 198, 218, 0.6);
}
.apvs-wx-m > b {
  font-family: var(--font-mono); font-weight: 500; font-size: 13.5px; letter-spacing: 0;
  color: rgba(206, 222, 238, 0.58); font-variant-numeric: tabular-nums;
  transition: color 420ms ease;
}
.apvs-wx-m > b > i { font-style: normal; opacity: 0.32; margin: 0 -0.5px; }
.apvs-wx-row.is-on .apvs-wx-m > b { color: #E6EEF6; }

/* —— 气象报告：跟在「气象评估」标题后面的那枚入口 ——
   三行读数是「此刻适不宜飞」，报告是「为什么」。报告不进读数表，
   也不另起一行按钮——它是这一块的附件，就贴在标题后面：
   文件页图标 + 四个字，点字即开。常态暗一档，指上去才亮、才起下划线，
   与受理意见里「详见《安全飞行告知书》」同一个语气。
   —— 检测还没跑完（未 .is-done）时它不可见也不可点：
      这一块还没有结论，先把报告递出去，顺序就反了 */
.apvs-report {
  display: inline-flex; align-items: center; gap: 4px;
  margin-left: 2px; padding: 0 1px;
  border: 0; background: none; cursor: pointer;
  font-family: inherit; font-size: 11px; font-weight: 400;
  letter-spacing: 0.5px; line-height: 1;
  color: rgba(150, 190, 226, 0.62);
  transition: color 180ms ease, opacity 300ms ease;
}
.apvs-report svg { width: 11px; height: 11px; flex: none; opacity: 0.85; }
.apvs-report > span {
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 2.5px;
  transition: text-decoration-color 180ms ease;
}
.apvs-report:hover { color: rgba(207, 228, 245, 0.95); }
.apvs-report:hover > span { text-decoration-color: rgba(178, 202, 226, 0.45); }
.apvs-report:focus-visible {
  outline: 0; border-radius: 3px;
  color: rgba(207, 228, 245, 0.95);
  box-shadow: 0 0 0 2px rgba(110, 165, 220, 0.24);
}
.apvs-blk:not(.is-done) .apvs-report { opacity: 0; pointer-events: none; }

/* —— 冲突：没有冲突时不留一张空表，留一枚「零」——
   六列空表头在 460px 里只会糊成一片小字，读不出信息，只读到「这儿有张表」 */
.apvs-conf-zero { display: flex; align-items: center; justify-content: center; gap: 13px; padding: 0; }
.apvs-zero-ring {
  position: relative; width: 38px; height: 38px; flex-shrink: 0;
  display: grid; place-items: center; border-radius: 50%;
  background: radial-gradient(circle at 50% 50%, rgba(126, 201, 166, 0.18) 0%, rgba(126, 201, 166, 0) 72%);
  box-shadow: inset 0 0 0 1px rgba(126, 201, 166, 0.30);
}
.apvs-zero-ring::before {
  content: ""; position: absolute; inset: -4px; border-radius: 50%;
  border: 1px dashed rgba(126, 201, 166, 0.26);
  animation: apvsSpin 9s linear infinite;
}
.apvs-zero-ring svg {
  width: 17px; height: 17px; fill: none; stroke: #7EC9A6; stroke-width: 1.4;
  stroke-linecap: round; stroke-linejoin: round;
  filter: drop-shadow(0 0 6px rgba(126, 201, 166, 0.6));
}
.apvs-zero-n {
  font-family: var(--font-mono); font-size: 17px; font-weight: 500; line-height: 1;
  color: #7EC9A6; text-shadow: 0 0 16px rgba(126, 201, 166, 0.75);
  font-variant-numeric: tabular-nums; font-feature-settings: "zero" 0;
}
.apvs-zero-t { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; min-width: 0; }
.apvs-zero-t > b { font-size: 13px; font-weight: 600; letter-spacing: 0.8px; color: #E6EFF7; }
.apvs-zero-t > em {
  font-style: normal; font-size: 11px; letter-spacing: 0.3px;
  color: rgba(176, 196, 216, 0.55);
}
.apvs-conf-zero {
  opacity: 0; transform: translateY(4px);
  transition: opacity 400ms ease, transform 400ms ease;
}
.apvs-conf-zero.is-on { opacity: 1; transform: none; }
@keyframes apvsSpin { to { transform: rotate(360deg); } }

/* —— 冲突清单：一行一处，行首序号与地图圆牌同号 ——
   —— 为什么不做成表格：冲突只有 1~3 条，每条是「航段 + 什么事 + 怎么办」
      一句话，做成三列表格会把 460px 切成 100/120/200 三段，最长的那句
      反而最窄。行式排法让处置建议拿满宽度，一句一行读得完。
   —— 序号是这一块与地图之间唯一的连接件：图上看到「2」，回来找第 2 行。
      底板刻意做得比风险格窄一点（只给左侧一条发丝线 + 极淡的底），
      因为这下面是「说明」，不是又一层状态 */
.apvs-conf { display: flex; flex-direction: column; gap: 6px; }
/* 一行一处，且这一行是可以点的：点下去相机飞到图上那一段。
   —— 光有 hover 不够，要给出「按得下去」的确定感：底色抬一档、
      左沿那条线由 0.42 提到 0.72 */
.apvs-conf-row {
  display: grid; grid-template-columns: 14px 1fr; gap: 9px;
  padding: 7px 10px 8px; border-radius: 5px;
  cursor: pointer;
  background: rgba(224, 169, 104, 0.045);
  box-shadow: inset 2px 0 0 rgba(224, 169, 104, 0.42),
              inset 0 0 0 1px rgba(224, 169, 104, 0.10);
  opacity: 0; transform: translateY(3px);
  transition: opacity 340ms ease, transform 340ms ease,
              background 180ms ease, box-shadow 180ms ease;
}
.apvs-conf-row.is-on { opacity: 1; transform: none; }
.apvs-conf-row:hover {
  background: rgba(224, 169, 104, 0.085);
  box-shadow: inset 2px 0 0 rgba(224, 169, 104, 0.72),
              inset 0 0 0 1px rgba(224, 169, 104, 0.20);
}
/* 选中 = 图上现在停在这一处。不是「删除」也不是「已处理」，
   所以只把左沿加粗一档、不留任何勾选或高亮整块的样式 */
.apvs-conf-row.is-active {
  background: rgba(224, 169, 104, 0.10);
  box-shadow: inset 3px 0 0 rgba(224, 169, 104, 0.9),
              inset 0 0 0 1px rgba(224, 169, 104, 0.24);
}
/* 行首三角：与地图锚点同一枚符号。改用图标而不是序号——
   01~06 的航点角标已经占住了「数字」这套语言，
   冲突再编号，两套数字在地图上会互相冒充 */
.apvs-hi {
  width: 13px; height: 13px; margin-top: 2px;
  fill: none; stroke: currentColor; stroke-width: 1.15;
  stroke-linejoin: round; stroke-linecap: round;
  color: #E9B57C;
  transition: color 180ms ease, filter 180ms ease;
}
.apvs-conf-row:hover .apvs-hi,
.apvs-conf-row.is-active .apvs-hi { filter: drop-shadow(0 0 5px rgba(224, 169, 104, 0.45)); }
/* —— 一行两段：上一段是「哪一段、什么事」，下一段是「撞到谁、怎么办」——
   拆两段是因为它们答的是两个问题。合成一句时，标题已经说过的
   「特殊空域区域重叠」会在正文里再说一遍，三行叠起来就是六遍；
   时间窗也从句子里拿出来推到第一行右端——它是这一行的属性，
   不是那句话的成分，留在句子里会把一句 8 秒能读完的话撑成两行 */
.apvs-conf-t { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.apvs-conf-h { display: flex; align-items: baseline; gap: 7px; min-width: 0; }
/* 航段号：等宽小片。与地图上短标签 / 告示牌里那枚完全同一种处理——
   同一枚标识，在三种尺寸上不该长成三个样 */
.apvs-conf-h > em {
  flex-shrink: 0;
  font-family: var(--font-mono); font-style: normal; font-weight: 500;
  font-size: 10px; letter-spacing: 0.2px; line-height: 1.5;
  padding: 0 5px; border-radius: 2.5px;
  color: #E9B57C; background: rgba(224, 169, 104, 0.13);
  box-shadow: inset 0 0 0 1px rgba(224, 169, 104, 0.34);
}
/* 标题：这一行里只有它该「说出来」。字距给一点，
   让它与下面那句读起来是两层，而不是一句话折成了两行 */
.apvs-conf-k {
  flex: 0 1 auto; min-width: 0;
  font-size: 11.5px; font-weight: 600; letter-spacing: 0.3px;
  color: #F2E4D3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 时间窗：等宽、弱一档、贴右。
   —— 它不是所有人都要看的东西：核时段的人在同一列里一眼扫得到，
      不核的人也不必在读标题时先绕过一串日期 */
.apvs-conf-w {
  margin-left: auto; flex-shrink: 0; padding-left: 8px;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0;
  color: rgba(224, 169, 104, 0.62); font-variant-numeric: tabular-nums;
}
/* 正文：撞到谁（亮）+ 怎么处置（压一档）。
   事实与建议在同一个句子里，但不该是同一个灰度 */
.apvs-conf-d {
  font-size: 11px; line-height: 1.5; letter-spacing: 0.2px;
  color: rgba(198, 210, 224, 0.62);
}
.apvs-conf-d > em { font-style: normal; color: rgba(230, 236, 243, 0.86); }

/* —— 等级：冲突（朱红）/ 提示（琥珀）
   —— 颜色只上在「行首图标 + 左沿 + 航段号片」，正文不上色。
      图上的锚点是朱红，面板这一枚也必须是朱红，两边才像同一个东西；
      正文染红只会让三行说明读起来像三处警报 */
.apvs-conf-row[data-lvl="fail"] {
  background: rgba(223, 106, 74, 0.05);
  box-shadow: inset 2px 0 0 rgba(223, 106, 74, 0.5),
              inset 0 0 0 1px rgba(223, 106, 74, 0.12);
}
.apvs-conf-row[data-lvl="fail"]:hover {
  background: rgba(223, 106, 74, 0.09);
  box-shadow: inset 2px 0 0 rgba(223, 106, 74, 0.78),
              inset 0 0 0 1px rgba(223, 106, 74, 0.22);
}
.apvs-conf-row[data-lvl="fail"].is-active {
  background: rgba(223, 106, 74, 0.11);
  box-shadow: inset 3px 0 0 rgba(223, 106, 74, 0.92),
              inset 0 0 0 1px rgba(223, 106, 74, 0.26);
}
.apvs-conf-row[data-lvl="fail"] .apvs-hi { color: #FFC9B4; }
.apvs-conf-row[data-lvl="fail"]:hover .apvs-hi,
.apvs-conf-row[data-lvl="fail"].is-active .apvs-hi {
  filter: drop-shadow(0 0 5px rgba(223, 106, 74, 0.5));
}
.apvs-conf-row[data-lvl="fail"] .apvs-conf-h > em {
  color: #FFC9B4; background: rgba(223, 106, 74, 0.14);
  box-shadow: inset 0 0 0 1px rgba(223, 106, 74, 0.36);
}

/* —— 批内关联：同一块里回答的另一个来源 ——
   —— 上面那份清单答的是「这条航线会不会切进限制面」，
      这一段答的是「同一批里会不会跟别人撞车」。两件事都没有撞到设施，
      但一件是对地、一件是对人，混进一张清单就会互相冒充。
   —— 为什么不给序号、不给圆牌、不可点：另一条申请此刻不在这张图上，
      点下去没有落点。清单里每一行的圆牌编号是它与地图的连接件，
      这里没有那根线，就不该长成清单里的样子。
   —— 底色比清单再淡一档（清单是「出事了」，这里是「须知会」），
      但保留同一支琥珀与同一道左侧竖线，读起来仍是同一块的第 03 项 */
.apvs-cx {
  margin-top: 9px;
  padding: 8px 10px 9px;
  border-radius: 6px;
  background: rgba(224, 169, 104, 0.032);
  box-shadow: inset 2px 0 0 rgba(224, 169, 104, 0.38),
              inset 0 0 0 1px rgba(224, 169, 104, 0.09);
  opacity: 0; transform: translateY(3px);
  transition: opacity 340ms ease, transform 340ms ease;
}
.apvs-cx.is-on { opacity: 1; transform: none; }
.apvs-cx-h {
  display: flex; align-items: center; gap: 6px;
  font-size: 10.5px; line-height: 1.5; letter-spacing: 0.35px;
  color: rgba(228, 184, 128, 0.9);
}
.apvs-cx-i {
  flex-shrink: 0; width: 12px; height: 12px;
  display: inline-flex; align-items: center; justify-content: center;
}
.apvs-cx-i > svg {
  width: 12px; height: 12px;
  fill: none; stroke: currentColor;
  stroke-width: 1.15; stroke-linecap: round;
}
.apvs-cx-h > span { font-weight: 500; }
.apvs-cx-h > em {
  margin-left: auto; font-style: normal;
  font-size: 10px; letter-spacing: 0;
  color: rgba(206, 172, 130, 0.6);
}
/* 一行一条计划：名称占满、读数靠右。
   名称可能很长（「南岸区南山植物园林业病虫害监测飞行计划」），
   截断而不换行——这两段是读数，换行会让「重叠 180 分钟」掉到下一行去 */
.apvs-cx-row {
  display: flex; align-items: baseline; gap: 8px;
  margin-top: 7px;
  font-size: 12px; line-height: 1.55;
}
.apvs-cx-row > b {
  flex: 1; min-width: 0;
  font-weight: 500; letter-spacing: 0.2px;
  color: #EAF2FA;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.apvs-cx-m {
  flex-shrink: 0; white-space: nowrap;
  /* 与左侧名称同为 12px：它们是同一行里的两件事，
     差半号读起来就像主副标题，可这里并没有主副 */
  font-size: 12px; color: rgba(224, 178, 120, 0.85);
}
.apvs-cx-m > i {
  font-style: normal; font-weight: 600;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  color: #F4CE9C;
}
.apvs-cx-m > em {
  font-style: normal; margin-left: 6px;
  font-family: var(--font-mono); font-size: 11px;
  color: rgba(200, 170, 132, 0.62);
  font-variant-numeric: tabular-nums;
}
/* 有批内关联时，「限制面 0 处」压成一行灰字：
   同一句话在别处是一枚 60px 的圆环，这里只需要一行 */
.apvs-cx-lite {
  padding: 3px 0 0 2px;
  font-size: 10.5px; line-height: 1.5; letter-spacing: 0.2px;
  color: rgba(150, 180, 205, 0.6);
}


/* ============================================================
   ④ 收回态：一条钉在「受理意见」上方的结果条
   —— 之前这里是一枚挂在输入框框沿上的小签（圆点 + 名称 + 展开箭头）。
      它能说清「这儿有个结果」，但说不清「结论是什么」「还能再做什么」；
      而且它的底边死死压在框沿上、只比输入框高出 28px，读起来像
      在「受理意见」标题行里塞了一张外来的标签。
   —— 现在是一条 36px 的通栏条，横跨与结果卡完全相同的宽度：
        · 左簇 = 名称 + 判定 + 重新检测（判定点开看明细）；
        · 右端 = 一枚展开键，与卡片右上那枚收起键同款。
      它不再「挂」在框上，而是浮在正文底部、操作位上方的那条空档里，
      像正文走到尽头时留下的一行结论摘要。
   —— 它是展开态那张卡压成一行，所以「同一套」不是形容，是硬要求：
        · 底：与 .apvs-ai 同一块底（同色相、同那层紫调冷光、同 blur），
          只把不透明度从 .86 放到 .80——比卡片轻一档，但仍压得住
          底下的正文：透是要的，读得出字就不是透了；
        · 左沿：与 .apvs-hero::before 同一条 2px 状态竖线（同色、同光晕、
          同起止位置），三档状态各一支；
        · 名称：与 .apvs-ai-hd > span 同字号同字距（12.5px / 1.5），
          标题在卡片里长什么样，在这里就长什么样；
        · 判定：沿用 .apvs-verdict 的配色——通过近白、其余琥珀，
          字重 700，不另立一种绿，也不单开一档红；
        · 展开键：直接照 .apvs-collapse 的规格（22×22、圆角 6、
          常驻底 .10 + 内描边 .30、图标 15px、hover 提亮到 .22 + 外发光）。
          收起键在卡片右上长什么样，展开键在这条上就长什么样；
          重新检测不带框，靠文字说自己是什么。
   —— 结果条是常驻的，不能像卡片那样整块发光——它要说的是
      「结论在这儿，随时能看」，不是「这里正在报警」。
   ============================================================ */
.apvr-d { position: relative; }

/* 结果条的两个尺寸只在 CSS 里写一次，脚本按名读取：
   —— --apvr-pill-gap：条子下缘离「受理意见」那条分区线多远。脚本定位用它，
      档案展开时算可用高也用它，两处同源才不会一个 10、一个 12；
   —— --apvr-pill-h：条子的实际高度，随 1K / 2K 换档。脚本不量元素
      （量到的可能正处在入场缩放的那一帧），直接读这个数 */
#apvr-panel { --apvr-pill-gap: 10px; --apvr-pill-h: 36px; }

.apvs-pill {
  position: absolute; top: 0; left: 0; z-index: 6;
  display: flex; align-items: center;
  height: 36px; padding: 0 10px 0 12px;
  box-sizing: border-box;
  border-radius: 9px;
  -webkit-backdrop-filter: blur(16px) saturate(1.04);
  backdrop-filter: blur(16px) saturate(1.04);
  background:
    radial-gradient(118% 56% at 0% 0%, rgba(184, 158, 255, 0.07) 0%, rgba(184, 158, 255, 0) 64%),
    rgba(13, 18, 26, 0.80);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 18px 36px -18px rgba(0, 0, 0, 0.85);
  font-family: inherit;
  color: #E4EDF5;
}
/* 左沿那道竖线：与 .apvs-hero::before 是同一支颜色、同一段光晕、同一处起止
   —— 收起之后「这条结论是什么成色」还能一眼认出 */
.apvs-pill::before {
  content: ""; position: absolute; left: 0; top: 9px; bottom: 9px; width: 2px;
  border-radius: 0 2px 2px 0;
  background: linear-gradient(180deg,
    rgba(123, 240, 194, 0.95) 0%, rgba(123, 240, 194, 0.06) 100%);
  box-shadow: 0 0 12px rgba(126, 201, 166, 0.55);
}
.apvs-pill[data-st="warn"]::before {
  background: linear-gradient(180deg,
    rgba(224, 169, 104, 0.95) 0%, rgba(224, 169, 104, 0.06) 100%);
  box-shadow: 0 0 12px rgba(224, 169, 104, 0.55);
}
.apvs-pill[data-st="fail"]::before {
  background: linear-gradient(180deg,
    rgba(223, 106, 74, 0.95) 0%, rgba(223, 106, 74, 0.06) 100%);
  box-shadow: 0 0 12px rgba(223, 106, 74, 0.55);
}
.apvs-pill[data-st="hold"]::before {
  background: linear-gradient(180deg,
    rgba(224, 169, 104, 0.95) 0%, rgba(224, 169, 104, 0.06) 100%);
  box-shadow: 0 0 12px rgba(224, 169, 104, 0.55);
}

/* 左簇：名称 + 判定 + 补救动作，三样贴在一起向右排。
   —— 用 span 包一层，是因为这一簇要「不铺满」：铺满的话，
      重新检测会被一起推到右端，又变回「两个动作挤在角上」的老样子 */
.apvs-pill-l {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center;
}
.apvs-pill-open {
  flex: 0 0 auto; min-width: 0;
  display: flex; align-items: center; gap: 12px;
  height: 100%; padding: 0; margin: 0; border: 0; background: none;
  font-family: inherit; color: inherit; cursor: pointer; text-align: left;
}
.apvs-pill-open:focus-visible {
  outline: 1px solid rgba(196, 228, 255, 0.66); outline-offset: -2px; border-radius: 6px;
}

/* 名称：与展开态抬头同字号、同字距、同色 */
.apvs-pill-t {
  font-size: 12.5px; letter-spacing: 1.5px;
  white-space: nowrap; color: #F0F6FB;
}
/* 判定：沿用 .apvs-verdict 的那两支。通过是近白（不是另一种绿），
   其余走琥珀——卡片里怎么分，这里就怎么分。
   卡片本身现在只有 ok / warn 两档，「不予放行」也落在 warn 上；
   要把它单独拎成第三档，得两边一起改，不能只在这一条上另立一个红 */
.apvs-pill-v {
  position: relative; padding-left: 13px;
  font-size: 12.5px; font-weight: 700; letter-spacing: 0.8px;
  white-space: nowrap; color: #F4FAFF;
}
.apvs-pill-v::before {
  content: ""; position: absolute; left: 0; top: 50%; margin-top: -5px;
  width: 1px; height: 10px; background: rgba(255, 255, 255, 0.13);
}
.apvs-pill[data-st="warn"] .apvs-pill-v { color: #FFC078; }
.apvs-pill[data-st="ok"] .apvs-pill-v { color: #8FE0BA; }
.apvs-pill[data-st="fail"] .apvs-pill-v { color: #FF9581; }
.apvs-pill[data-st="hold"] .apvs-pill-v { color: #FFC078; }
/* 重新检测：与判定同簇，但换一种「键」。
   —— 展开是这儿的主动作，走图标方键（与卡片右上那枚收起键同款）；
      重新检测是补救性质的次动作，走「图标 + 文字」的素键：无底、无框，
      只有悬停才起一层底。它带字，所以不必靠一个方的形状去说自己能按；
      展开不带字，所以它必须长成一枚键。两者都做成方键时，
      读者只看到并排两个一样的图标，分不出哪个是哪个 */
.apvs-pill-redo {
  flex-shrink: 0; height: 24px; margin-left: 8px;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 0 9px 0 8px;
  border: 0; border-radius: 6px;
  background: rgba(255, 255, 255, 0);
  font-family: inherit; font-size: 11.5px; letter-spacing: 0.5px;
  color: rgba(212, 228, 242, 0.72);
  cursor: pointer;
  transition: color 180ms ease, background 180ms ease;
}
.apvs-pill-redo svg { width: 13px; height: 13px; display: block; opacity: 0.86; }
.apvs-pill-redo:hover {
  color: #EAF3FB;
  background: rgba(150, 190, 226, 0.10);
}
.apvs-pill-redo:hover svg { opacity: 1; }
.apvs-pill-redo:active { background: rgba(150, 190, 226, 0.16); }
.apvs-pill-redo:focus-visible { outline: 1px solid rgba(196, 228, 255, 0.7); outline-offset: 1px; }

/* 两枚动作键：照搬 .apvs-collapse（卡片右上那枚收起键）的规格，
   一个像素都不另起——收起键长什么样，这两枚就长什么样 */
.apvs-pill-act {
  flex-shrink: 0; width: 22px; height: 22px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 6px;
  background: rgba(140, 178, 212, 0.10);
  box-shadow: inset 0 0 0 1px rgba(152, 192, 226, 0.30);
  color: rgba(206, 226, 242, 0.86); cursor: pointer;
  transition: background 200ms ease, box-shadow 200ms ease, color 200ms ease;
}
.apvs-pill-act + .apvs-pill-act { margin-left: 5px; }
.apvs-pill-act svg { width: 15px; height: 15px; display: block; }
.apvs-pill-act:hover {
  color: #FFFFFF;
  background: rgba(150, 190, 224, 0.22);
  box-shadow: inset 0 0 0 1px rgba(178, 210, 240, 0.56),
              0 0 16px rgba(140, 182, 218, 0.45);
}
.apvs-pill-act:focus-visible { outline: 1px solid rgba(196, 228, 255, 0.8); outline-offset: 1px; }

/* [hidden] 在 UA 样式里是 display:none，但上面那条 display:flex 优先级更高 */
.apvs-pill[hidden] { display: none; }

/* 结果条浮在正文底部：给它让出一条高度，滚到底时最后一行不会被条子压住 */
#apvr-panel.has-apvs-pill #apvr-content { padding-bottom: 52px; }

/* 面板描边随检测态转为钢蓝，并向外起一层极淡的冷光。
   —— 原来这一圈是 0.34 的电紫 + 72px 的紫晕，面板像是在发警报；
      现在只比常态亮一点点：说「这里在算」，不说「这里出事了」 */
#apvr-panel.apvs-on {
  border-color: rgba(140, 178, 212, 0.28);
  box-shadow:
    var(--shadow-float),
    0 0 0 1px rgba(140, 178, 212, 0.12),
    0 0 30px rgba(110, 158, 200, 0.22),
    0 0 70px rgba(90, 140, 190, 0.10),
    inset 0 1px 0 rgba(255, 255, 255, 0.05);
}

@media (max-width: 2047px) {
/* ============================================================
   ⑤ 不通过：同一条卡，紧一档
   —— 这一档比另两档多出一张冲突清单（1~3 行、每行一两句），总高会顶出
      滚动视口。不通过的那一屏最不能做的事，就是让「第三处冲突」藏在
      滚动条后面——结论卡没有滚动条可露，藏住了就是没有。
      所以从块距、块头、行高里各收一点，把位置换给冲突清单。
   —— 收窄只落在 [data-mood="fail"] 上：通过 / 提示两档的版面一格不动，
      这次改动不会连带改掉已经定过稿的那两屏。
   —— 整段再套一层 max-width: 2047px：2K 的滚动视口本来就高得多，不需要压，
      那里的冲突清单照旧用放大一档的行高，别让「不通过」在宽屏上瘪下去。
   ============================================================ */
.apvs-ai[data-mood="fail"] { padding: 10px; }
.apvs-ai[data-mood="fail"] .apvs-ai-hd { height: 20px; margin-bottom: 6px; }
.apvs-ai[data-mood="fail"] .apvs-hero { padding: 10px 12px 11px; margin-bottom: 5px; }
.apvs-ai[data-mood="fail"] .apvs-meter { margin-top: 8px; }
.apvs-ai[data-mood="fail"] .apvs-steps { gap: 5px; }
.apvs-ai[data-mood="fail"] .apvs-blk { padding-top: 8px; padding-bottom: 9px; }
.apvs-ai[data-mood="fail"] .apvs-b-hd { height: 17px; margin-bottom: 6px; padding-bottom: 6px; }
/* 雾的上沿跟着块头收：漏改这一行，解雾时会连标题一起蒙住 */
.apvs-ai[data-mood="fail"] .apvs-blk > .apvs-veil { top: 37px; }
.apvs-ai[data-mood="fail"] .apvs-item { height: 25px; }
/* 气象行收四档（30 → 26）：这一档要同时放下三行气象与三处冲突，
   卡片高度又被滚动视口卡死。收的是行间空气，字号一格不动 */
.apvs-ai[data-mood="fail"] .apvs-wx { gap: 4px; }
.apvs-ai[data-mood="fail"] .apvs-wx-row { height: 26px; }
.apvs-ai[data-mood="fail"] .apvs-conf { gap: 4px; }
.apvs-ai[data-mood="fail"] .apvs-conf-row { padding: 5px 9px 6px; }
}

/* 2K：整体放大一档。这个分辨率下 1px 的缝、10px 的字都会细到看不见 */
@media (min-width: 2048px) {
  .apvs-blk > .apvs-veil { top: 50px; }
  .apvs-core { height: 2.5px; top: -1.25px; }
  .apvs-fr.is-a { top: -20px; height: 19px; }
  .apvs-fr.is-b { top: 3px; height: 15px; }
  .apvs-ticks { height: 28px; }
  .apvs-corners i { width: 18px; height: 18px; }
  .apvs-layer { padding: 16px 10px; }
  .apvs-ai { padding: 14px; border-radius: 14px; }
  .apvs-hero { padding: 12px 14px 14px; border-radius: 10px; }
  .apvs-verdict { font-size: 19px; }
  .apvs-hero-k { font-size: 11px; letter-spacing: 1.7px; }
  .apvs-b-hd { height: 19px; }
  .apvs-b-hd > span { font-size: 13.5px; }
  .apvs-idx { font-size: 10.5px; }
  /* 这里的左右内边距一度被写成 0：2K 下面板宽 560，卡片跟着变宽，
     但标题、状态胶囊、气象行都顶到了卡片边框上；更糟的是标题下那条栏线
     是 left/right:-14px 画出来的，padding 一归零，它就伸出卡片外 14px。
     2K 的卡片比 1K 宽 72px，内边距跟着给 14，而不是收回 0 */
  .apvs-blk { --blk-x: 14px; padding-top: 14px; padding-bottom: 16px; }
  /* 2K 下卡片按内容长，行本身做厚一档（格子 30→36、气象行 32→40、零环 42→54），
     高度自然涨上去，不用再靠撑满去填 */
  .apvs-item { height: 36px; font-size: 12.5px; }
  .apvs-conf-row { grid-template-columns: 16px 1fr; gap: 10px; padding: 9px 12px 10px; }
  .apvs-hi { width: 15px; height: 15px; }
  .apvs-conf-k { font-size: 12.5px; }
  .apvs-conf-h > em { font-size: 10.5px; padding: 0 6px; }
  .apvs-conf-w { font-size: 11px; }
  .apvs-conf-d { font-size: 12px; }
  .apvs-chip { height: 20px; font-size: 11px; }
  .apvs-wx-row { height: 40px; grid-template-columns: 44px auto 1fr 1fr 1.34fr; }
  .apvs-report { font-size: 12.5px; letter-spacing: 0.6px; }
  .apvs-report svg { width: 13px; height: 13px; }
  .apvs-wx-m > em { font-size: 12px; }
  .apvs-wx-m > b { font-size: 14.5px; }
  .apvs-wx-t { font-size: 13px; }
  .apvs-zero-ring { width: 54px; height: 54px; }
  .apvs-zero-n { font-size: 28px; }
  .apvs-zero-t > b { font-size: 15px; }
  .apvs-zero-t > em { font-size: 12px; }
  .apvs-pill { height: 40px; padding: 0 9px 0 14px; border-radius: 10px; }
  #apvr-panel { --apvr-pill-h: 40px; }
  .apvs-pill-open { gap: 14px; }
  .apvs-pill-t { font-size: 13.5px; }
  .apvs-pill-v { font-size: 13.5px; padding-left: 15px; }
  .apvs-pill-redo { height: 26px; margin-left: 12px; font-size: 12px; }
  .apvs-pill-redo svg { width: 13px; height: 13px; }
  .apvs-pill-act { width: 26px; height: 26px; }
  .apvs-pill-act svg { width: 17px; height: 17px; }
  #apvr-panel.has-apvs-pill #apvr-content { padding-bottom: 58px; }
}

/* 减动效：扫描整段不播（脚本侧就不建舞台），雾面直接让开，结论直接写进去 */
@media (prefers-reduced-motion: reduce) {
  .apvs-ring, .apvs-bloom, .apvs-aura,
  .apvs-stage.is-scan .apvs-beam,
  .apvs-stage.is-scan .apvs-dots,
  .apvs-stage.is-scan .apvs-dim,
  .apvs-stage.is-scan .apvs-core,
  .apvs-ticks,
  .apvs-lit, .apvs-lit .apvr-dh > i,
  .apvs-blk.is-live .apvs-b-hd::after,
  .apvs-zero-ring::before,
  .apvs-ai:not(.is-done) .apvs-ai-hd > b::before { animation: none !important; }
  .apvs-ring, .apvs-bloom { --apvs-a: 26deg; }
  .apvs-veil { display: none !important; }
  .apvs-item, .apvs-wx-row, .apvs-conf-zero, .apvs-conf-row { opacity: 1 !important; transform: none !important; }
  /* 浮层与卡片不做位移与淡入：直接给出终态，模糊照旧（它是状态，不是动效） */
  .apvs-ai { transform: none !important; transition: none !important; }
  .apvs-layer { transition: none !important; }
  #apvr-panel .apvr-content { transition: none !important; }
}
