/* =====================================================================
 * fx.css —— 视觉增强层 V5.0（图标排布 / 动效 / 光效 / HUD 质感）
 * 依赖 styles.css 的主题变量；只做叠加，不改动布局骨架。
 * 原则：动画只跑 transform / opacity，必要时才用 filter；
 *       全部动效在 prefers-reduced-motion 下自动关闭。
 * ===================================================================== */
:root{ --fx:cubic-bezier(.22,.61,.36,1); }

/* ============ 1. 图标基础 ============ */
svg.ic{display:inline-block; vertical-align:-2px; flex:none;}
.btn svg.ic,.thbtn svg.ic,.lnk svg.ic{vertical-align:0;}
.btn.has-ic{gap:6px;}
.panel>h2 .h2ic{display:inline-flex; align-items:center; color:var(--navy-d); filter:drop-shadow(0 0 6px rgba(47,155,255,.5));}
body.light .panel>h2 .h2ic{filter:none;}
.tbl caption svg.ic{color:var(--navy); margin-right:6px;}
.empty-ico{color:var(--faint); opacity:.45; margin-bottom:9px;}
.empty-ico svg{width:30px; height:30px;}
.qn svg.ic{opacity:.6;}
#btnLogout{display:inline-flex; align-items:center; gap:4px;}

/* 在线呼吸点 */
.live{display:inline-block; width:6px; height:6px; border-radius:50%; background:var(--ok);
  margin-right:6px; vertical-align:1px; box-shadow:0 0 8px var(--ok); animation:livePulse 2.4s ease-in-out infinite;}
@keyframes livePulse{0%,100%{opacity:.5; transform:scale(.82);} 50%{opacity:1; transform:scale(1.1);}}

/* ============ 2. 首页 ============ */
.hwleft{display:flex; align-items:center; gap:13px;}
.hwmark{width:44px; height:44px; border-radius:13px; flex:none; display:flex; align-items:center; justify-content:center;
  color:var(--orange-ink);
  background:linear-gradient(145deg,rgba(255,138,61,.24),rgba(47,155,255,.14));
  border:1px solid rgba(255,138,61,.34);
  box-shadow:0 0 28px -8px rgba(255,138,61,.85), inset 0 1px 0 rgba(255,255,255,.14);
  position:relative; overflow:hidden;}
.hwmark::after{content:""; position:absolute; inset:-45%; pointer-events:none;
  background:linear-gradient(115deg,transparent 42%,rgba(255,255,255,.35) 50%,transparent 60%);
  transform:translateX(-80%); animation:sheen 5.2s ease-in-out infinite;}
@keyframes sheen{0%,68%{transform:translateX(-80%);} 100%{transform:translateX(80%);}}
.hlic b{display:inline-flex; align-items:center; gap:5px;}
.hlic svg.ic{opacity:.75;}
.hsec{display:flex; align-items:center; gap:7px; margin:8px 0 10px; font-size:14px; color:var(--ink);}
.hsec svg.ic{color:var(--navy-d);}
.hsec span{font-size:11px; color:var(--faint); font-weight:400;}

.ccard{transition:transform .3s var(--fx), box-shadow .3s var(--fx), border-color .3s;}
.ccard:hover{transform:translateY(-4px);
  box-shadow:0 24px 48px -22px rgba(0,0,0,.95), 0 0 0 1px rgba(47,155,255,.3), 0 0 36px -14px rgba(47,155,255,.6);}
.ccard h4{display:flex; align-items:center; gap:9px;}
.cico{width:32px; height:32px; border-radius:9px; display:inline-flex; align-items:center; justify-content:center; flex:none;
  color:var(--navy-d); background:linear-gradient(150deg,rgba(47,155,255,.26),rgba(47,155,255,.06));
  border:1px solid var(--line); box-shadow:inset 0 1px 0 rgba(255,255,255,.1);}
.ccard.core .cico{color:var(--orange-ink);
  background:linear-gradient(150deg,rgba(255,138,61,.28),rgba(255,138,61,.06)); border-color:rgba(255,138,61,.4);}
.ccard .cspec i{display:inline-flex; align-items:center; gap:5px;}
.ccard .cspec svg.ic{opacity:.7; color:var(--navy-d);}
body.light .ccard .cspec svg.ic{color:var(--navy);}

.pcard{position:relative; overflow:hidden; transition:transform .28s var(--fx), box-shadow .28s, border-color .28s;}
.pcard:hover{transform:translateY(-3px); border-color:var(--navy);
  box-shadow:0 18px 36px -20px rgba(0,0,0,.9), 0 0 28px -14px rgba(47,155,255,.75);}
.pcard::after{content:""; position:absolute; left:0; right:0; top:0; height:2px;
  background:linear-gradient(90deg,transparent,var(--navy),var(--orange),transparent);
  opacity:0; transition:opacity .3s;}
.pcard:hover::after{opacity:.9;}
.pct{display:flex; align-items:center; gap:7px;}
.pct .pic{width:24px; height:24px; border-radius:7px; display:inline-flex; align-items:center; justify-content:center; flex:none;
  color:var(--navy-d); background:rgba(47,155,255,.13); border:1px solid var(--line);}
.pct .pty{font-size:10.5px; color:var(--navy); letter-spacing:.5px;}
body.light .pct .pty{color:var(--navy);}
.pcard i{display:flex; align-items:center; gap:4px;}
.pcard i svg.ic{color:var(--ok);}
.fnote{display:flex; gap:10px; align-items:flex-start; margin-top:16px; padding:12px 14px;
  border:1px dashed var(--line); border-radius:8px; font-size:11.5px; color:var(--faint); line-height:1.9;}
.fnote svg.ic{color:var(--orange-ink); flex:none; margin-top:3px;}

/* ============ 3. KPI / 卡片微交互 ============ */
.kpi{transition:transform .3s var(--fx), box-shadow .3s;}
.kpi .kico{position:absolute; right:10px; top:9px; color:var(--navy-d); opacity:.45;}
body.light .kpi .kico{color:var(--navy); opacity:.5;}
.kpi:hover{transform:perspective(900px) rotateX(0deg) translateY(-3px);
  box-shadow:0 20px 42px -18px rgba(0,0,0,.9), 0 0 0 1px rgba(47,155,255,.32), 0 0 30px -12px rgba(47,155,255,.65);}
.kpi:hover .v{text-shadow:0 0 28px rgba(47,155,255,1);}
body.light .kpi:hover{transform:translateY(-3px);}

/* 鼠标跟随光斑（--mx 由 JS 写入） */
.rcard,.ccard{--mx:50%;}
.rcard::after,.ccard::after{content:""; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  background:radial-gradient(340px 170px at var(--mx) 0%, rgba(110,190,255,.17), transparent 72%);
  opacity:0; transition:opacity .35s; z-index:0;}
.rcard:hover::after,.ccard:hover::after{opacity:1;}
body.light .rcard::after,body.light .ccard::after{background:radial-gradient(340px 170px at var(--mx) 0%, rgba(23,69,110,.09), transparent 72%);}

/* ============ 4. 模块入场 / 切换 ============ */
@keyframes viewIn{from{opacity:0; transform:translateY(9px); filter:blur(3px);} to{opacity:1; transform:none; filter:none;}}
#centerBody>*{animation:viewIn .4s var(--fx) both;}
#centerBody>*:nth-child(2){animation-delay:.05s;}
#centerBody>*:nth-child(3){animation-delay:.1s;}
#centerBody>*:nth-child(4){animation-delay:.14s;}
#ctxBody>*{animation:viewIn .44s var(--fx) both;}
#ctxBody>*:nth-child(n+2){animation-delay:.07s;}
#ctxBody>*:nth-child(n+4){animation-delay:.12s;}

@keyframes modalIn{from{opacity:0; transform:translateY(16px) scale(.972);} to{opacity:1; transform:none;}}
.modal .mbox{animation:modalIn .32s var(--fx) both;}

@keyframes panelPulse{
  0%{box-shadow:var(--shadow), 0 0 0 0 rgba(47,155,255,0);}
  35%{box-shadow:var(--shadow), 0 0 0 1px rgba(47,155,255,.42), 0 0 34px -10px rgba(47,155,255,.6);}
  100%{box-shadow:var(--shadow), 0 0 0 0 rgba(47,155,255,0);}}
body.modswitch .panel{animation:panelPulse .62s ease-out both;}
body.modswitch .panel:nth-child(2){animation-delay:.04s;}
body.modswitch .panel:nth-child(3){animation-delay:.09s;}

/* ============ 5. 按钮 ============ */
.btn{position:relative; overflow:hidden;}
.btn::after{content:""; position:absolute; top:-70%; bottom:-70%; left:-140%; width:55%; pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.3),transparent);
  transform:rotate(16deg); transition:left .62s var(--fx); opacity:0;}
.btn:hover::after{left:150%; opacity:1;}
.btn.primary::after,.btn.accent::after{background:linear-gradient(90deg,transparent,rgba(255,255,255,.45),transparent);}
.btn:active{transform:translateY(0) scale(.985);}
.btn.on::before{content:""; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  box-shadow:inset 0 0 18px -6px rgba(255,138,61,.8);}
.thbtn{transition:color .15s, border-color .15s, box-shadow .15s, transform .15s;}
.thbtn:hover{transform:translateY(-1px);}

.lgbtn::before{content:""; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  box-shadow:0 0 0 0 rgba(47,155,255,.55); animation:btnPulse 2.8s ease-out infinite;}
@keyframes btnPulse{0%{box-shadow:0 0 0 0 rgba(47,155,255,.5);} 70%{box-shadow:0 0 0 12px rgba(47,155,255,0);} 100%{box-shadow:0 0 0 0 rgba(47,155,255,0);}}

/* ============ 6. 顶栏 / 背景 ============ */
@keyframes headerScan{0%{background-position:140% 0;} 100%{background-position:-90% 0;}}
header::before{content:""; position:absolute; inset:0; pointer-events:none; z-index:0;
  background:linear-gradient(105deg,transparent 34%,rgba(120,200,255,.11) 45%,rgba(255,255,255,.06) 50%,transparent 62%);
  background-size:240% 100%; animation:headerScan 9s linear infinite;}
header>*{position:relative; z-index:1;}

@keyframes bgDrift{0%{transform:translate3d(-1.4%,-.8%,0) scale(1.03);} 100%{transform:translate3d(1.4%,1%,0) scale(1.08);}}
body:not(.light)::before{animation:bgDrift 30s ease-in-out infinite alternate;}

/* ============ 7. 状态 / 表格 / 步骤 / 导航 ============ */
.badge{display:inline-flex; align-items:center; gap:5px;}
.badge.st-ok::before,.badge.st-wait::before,.badge.st-no::before,.badge.st-gray::before{
  content:""; width:5px; height:5px; border-radius:50%; flex:none;}
.badge.st-ok::before{background:var(--ok); box-shadow:0 0 7px var(--ok); animation:livePulse 2.2s infinite;}
.badge.st-wait::before{background:var(--warn); box-shadow:0 0 7px var(--warn); animation:livePulse 1.8s infinite;}
.badge.st-no::before{background:var(--danger); box-shadow:0 0 7px var(--danger);}
.badge.st-gray::before{background:var(--faint);}

.tbl tbody tr{transition:background .2s;}
.tbl tbody tr:hover td:first-child{box-shadow:inset 2px 0 0 var(--navy);}

@keyframes stepGlow{0%,100%{box-shadow:0 0 10px -2px rgba(255,138,61,.75);} 50%{box-shadow:0 0 20px 0 rgba(255,138,61,1);}}
.step.on .n{animation:stepGlow 2.4s ease-in-out infinite;}

nav .mi{transition:background .18s, color .18s, padding-left .18s;}
nav .mi:hover{padding-left:15px;}
nav .mi.on::before{content:""; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(90deg,rgba(255,138,61,.16),transparent 72%); animation:navIn .45s ease-out;}
@keyframes navIn{from{opacity:0; transform:translateX(-8px);} to{opacity:1; transform:none;}}

/* ============ 8. 登录门 ============ */
@keyframes gridScan{0%{background-position:0 0,0 0;} 100%{background-position:34px 34px,34px 34px;}}
#loginGate .lgdeco{animation:gridScan 14s linear infinite;}
@keyframes gateIn{from{opacity:0; transform:translateY(18px) scale(.986);} to{opacity:1; transform:none;}}
@keyframes gateGlow{
  0%,100%{box-shadow:var(--shadow), 0 0 60px -24px rgba(47,155,255,.5);}
  50%{box-shadow:var(--shadow), 0 0 90px -20px rgba(47,155,255,.85), 0 0 60px -30px rgba(255,138,61,.6);}}
.lgwrap{animation:gateIn .6s var(--fx) both, gateGlow 7s 1s ease-in-out infinite;}
.lgbox h2{padding-bottom:9px; border-bottom:1px solid var(--line2);}
.lgbrand h1{background:linear-gradient(92deg,var(--ink-strong),#9ed3ff 46%,var(--orange-ink));
  -webkit-background-clip:text; background-clip:text; color:transparent;}

/* ============ 9. Toast ============ */
.toast{display:flex; align-items:center; gap:9px;}
.toast::before{content:""; width:3px; height:15px; border-radius:2px; flex:none;
  background:linear-gradient(180deg,var(--navy),var(--orange));}
.toast.show{animation:toastIn .32s var(--fx);}
@keyframes toastIn{from{transform:translateX(-50%) translateY(14px) scale(.96);} to{transform:translateX(-50%) translateY(0) scale(1);}}

/* ============ 10. 其它细节 ============ */
::selection{background:rgba(47,155,255,.34);}
.uploadbox,.vidslot{transition:border-color .2s, box-shadow .2s, transform .2s;}
.uploadbox:hover{transform:translateY(-1px);}
.snum:hover{transform:translateY(-1px); border-color:var(--navy);}
.cwblk:hover .k{box-shadow:0 0 12px -2px rgba(47,155,255,.9);}

/* ============ 11. 降低动效偏好 ============ */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important; animation-iteration-count:1 !important;
    transition-duration:.001ms !important; scroll-behavior:auto !important;
  }
}
