/* ============ 共享组件动效层 v3（纯 CSS，必不隐藏元素） ============ */
#view>*{animation:fadeUp .3s ease both}
.card,.kpi,.health-item,.decision,.ds-stat{animation:fadeUp .38s ease both}
.modal,.drawer,.pop,.toast,.empty,.notice{animation:fadeUp .24s ease both}

.nav-item,.chip,.btn,.icon-btn,.badge,.pager-num,.pager-btn,.r,.w{
  transition:background .16s ease,color .16s ease,border-color .16s ease,box-shadow .16s ease,transform .13s ease;
}
.chip:active,.btn:active,.icon-btn:active,.pager-num:active,.pager-btn:active{transform:scale(.96)}
.btn-primary:hover{filter:brightness(1.08);transform:translateY(-1px)}
.badge .dot{transition:transform .18s ease}
.badge:hover .dot{transform:scale(1.35)}
tbody tr,tr{transition:background .12s ease}
.filterbar,.card-head{transition:background .18s ease}
.searchbox,.chip{border-color:rgba(128,140,165,.28)}
.searchbox:hover,.chip:hover{border-color:rgba(128,140,165,.55)}

@keyframes fadeUp{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  #view>*,.card,.kpi,.health-item,.decision,.ds-stat,.modal,.drawer,.pop,.toast,.empty,.notice{animation:none}
  .nav-item,.chip,.btn,.icon-btn,.badge,.pager-num,.pager-btn{transition:none}
}

/* ============ 强化档：悬浮/按压/光效/状态脉冲 ============ */
.card{transition:transform .22s cubic-bezier(.2,.8,.3,1),box-shadow .22s ease,border-color .22s ease}
.card:hover{transform:translateY(-3px)}
.card-head .card-title{transition:color .18s ease}
.card:hover .card-title{color:var(--brand,#8b5cf6)}

.btn{position:relative;overflow:hidden}
.btn-primary::after{
  content:"";position:absolute;top:0;left:-120%;width:60%;height:100%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.35),transparent);
  transform:skewX(-20deg);transition:left .5s ease;
}
.btn-primary:hover::after{left:140%}
.btn-primary{box-shadow:0 4px 14px rgba(37,99,235,.22)}
.btn-primary:hover{box-shadow:0 8px 24px rgba(37,99,235,.34);transform:translateY(-2px)}
.btn-ghost:hover{transform:translateY(-1px)}

.icon-btn{transition:transform .16s ease,background .16s ease,color .16s ease}
.icon-btn:hover{transform:scale(1.12)}
.icon-btn:active{transform:scale(.94)}

.chip{transition:transform .14s ease,background .16s ease,color .16s ease,box-shadow .16s ease}
.chip:hover{transform:translateY(-1px);box-shadow:0 4px 10px rgba(0,0,0,.14)}
.chip.active,.chip.act{box-shadow:0 5px 14px rgba(37,99,235,.28)}

.nav-item{transition:transform .15s ease,background .16s ease,color .16s ease,box-shadow .16s ease}
.nav-item:hover{transform:translateX(2px)}
.nav-item.active{box-shadow:0 8px 22px -6px rgba(37,99,235,.38)}

tbody tr{position:relative}
tbody tr:hover td:first-child{border-left:3px solid var(--brand,#8b5cf6)}
tbody tr:hover td{border-left-color:transparent}
td:first-child{transition:border-left-color .15s ease;border-left:3px solid transparent}

.badge .dot,.dot-green,.dot-amber,.dot-red,.dot-gray{position:relative}
.b-green .dot::after,.dot-green::after,
.b-amber .dot::after,.dot-amber::after,
.b-red .dot::after,.dot-red::after{
  content:"";position:absolute;inset:-3px;border-radius:50%;
  animation:dotPulse 1.8s ease-out infinite;
}
.b-green .dot::after,.dot-green::after{box-shadow:0 0 0 0 rgba(18,183,106,.5)}
.b-amber .dot::after,.dot-amber::after{box-shadow:0 0 0 0 rgba(240,173,78,.5)}
.b-red .dot::after,.dot-red::after{box-shadow:0 0 0 0 rgba(240,68,56,.5)}
@keyframes dotPulse{0%{opacity:.8;transform:scale(.7)}70%{opacity:0;transform:scale(1.35)}100%{opacity:0;transform:scale(1.35)}}

.platform-tag{transition:transform .14s ease,box-shadow .16s ease}
.platform-tag:hover{transform:translateY(-1px);box-shadow:0 4px 10px rgba(0,0,0,.16)}

.bar-fill{position:relative;overflow:hidden}
.bar-fill::after{
  content:"";position:absolute;inset:0;background:linear-gradient(100deg,transparent,rgba(255,255,255,.45),transparent);
  transform:translateX(-100%);animation:barShine 2.6s ease-in-out infinite;
}
@keyframes barShine{0%,60%{transform:translateX(-100%)}100%{transform:translateX(100%)}}

.sync-badge{animation:softBlink 2.4s ease-in-out infinite}
@keyframes softBlink{0%,100%{opacity:1}50%{opacity:.72}}

.pager-num,.pager-btn{transition:transform .12s ease,background .15s ease,color .15s ease,box-shadow .15s ease}
.pager-num:not(.active):hover,.pager-btn:hover{transform:translateY(-1px)}

@media (prefers-reduced-motion:reduce){
  .card,.btn,.chip,.nav-item,.icon-btn,.platform-tag,.pager-num,.pager-btn{transition:none}
  .badge .dot::after,.dot-green::after,.dot-amber::after,.dot-red::after,.bar-fill::after,.sync-badge{animation:none}
}

/* ============ 强反馈档：水波 / 明显悬浮 / 鼠标动效 ============ */
.btn,.chip,.pager-btn,.pager-num,.icon-btn{position:relative;overflow:hidden;cursor:pointer}
.m-ripple{position:absolute;border-radius:50%;background:currentColor;opacity:.2;transform:scale(0);pointer-events:none;animation:mRipple .62s ease-out forwards}
@keyframes mRipple{to{transform:scale(3);opacity:0}}

.card{transform:translateZ(0)}
.card:hover{transform:translateY(-5px) scale(1.006)}
.kpi:hover{transform:translateY(-3px)}
.kpi{transition:transform .22s cubic-bezier(.2,.8,.3,1),box-shadow .22s ease,border-color .22s ease}
.kpi:hover{box-shadow:0 16px 40px -16px rgba(0,0,0,.35)}

.btn{transition:transform .15s ease,box-shadow .2s ease,filter .2s ease,background .2s ease}
.btn:hover{transform:translateY(-2px) scale(1.02)}
.btn:active{transform:translateY(0) scale(.97)}
.chip:hover{transform:translateY(-2px) scale(1.03)}
.icon-btn:hover{transform:scale(1.15) rotate(4deg)}
.nav-item:hover{transform:translateX(4px);background:rgba(128,140,165,.1)}
.nav-item{transition:transform .18s ease,background .18s ease,color .18s ease,box-shadow .18s ease}
.platform-tag:hover{transform:translateY(-2px) scale(1.04)}
.badge:hover{transform:scale(1.06)}
.badge{transition:transform .15s ease,box-shadow .15s ease}
.pager-btn:hover,.pager-num:not(.active):hover{transform:translateY(-2px) scale(1.05);box-shadow:0 4px 12px rgba(37,99,235,.18)}
.pager-num,.pager-btn{cursor:pointer}

tr{cursor:default}
tbody tr:hover{box-shadow:inset 2px 0 0 var(--brand,#8b5cf6)}
.card .btn,.card .chip{cursor:pointer}

/* 3D 卡片 / 按钮光斑 / 数字跳动 */
.card,.kpi{will-change:transform;transition:transform .18s ease,box-shadow .2s ease}
.card,.kpi,.btn{--mx:50%;--my:50%}
.btn::before{
  content:"";position:absolute;width:130px;height:130px;left:var(--mx);top:var(--my);
  transform:translate(-50%,-50%);background:radial-gradient(circle,rgba(255,255,255,.45),transparent 65%);
  opacity:0;transition:opacity .18s ease;pointer-events:none;z-index:0;
}
.btn:hover::before{opacity:1}
.btn-primary::after{z-index:0}
.numPop{animation:numPop .5s cubic-bezier(.2,.8,.3,1)}
@keyframes numPop{0%{opacity:.2;transform:translateY(8px) scale(.6)}55%{opacity:1;transform:translateY(-2px) scale(1.08)}100%{transform:none}}

/* 安全入场（只位移不变透明，绝不闪没） */
#view>*{animation:riseIn .3s ease both}
.card,.kpi,.health-item,.decision,.ds-stat{animation:riseIn .36s ease both}
@keyframes riseIn{from{transform:translateY(8px)}to{transform:none}}
@media (prefers-reduced-motion:reduce){#view>*,.card,.kpi,.health-item,.decision,.ds-stat{animation:none}}
.card,.kpi{backface-visibility:hidden;-webkit-backface-visibility:hidden;will-change:auto}
