/* ============================================================
   兰华托管中心 · 全站动效层
   仅使用 transform / opacity / filter，保障 60fps
   ============================================================ */

/* ---------------- 关键帧 ---------------- */
@keyframes fadeUp      {from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}
@keyframes fadeUpSm    {from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@keyframes fadeIn      {from{opacity:0}to{opacity:1}}
@keyframes zoomIn      {from{opacity:0;transform:scale(.94)}to{opacity:1;transform:none}}
@keyframes slideLeft   {from{opacity:0;transform:translateX(-18px)}to{opacity:1;transform:none}}
@keyframes popIn       {from{opacity:0;transform:translateY(10px) scale(.96)}to{opacity:1;transform:none}}
@keyframes floatY      {0%,100%{transform:translateY(0)}50%{transform:translateY(-16px)}}
@keyframes pulseRing   {0%{box-shadow:0 0 0 0 rgba(240,68,56,.55)}70%{box-shadow:0 0 0 7px rgba(240,68,56,0)}100%{box-shadow:0 0 0 0 rgba(240,68,56,0)}}
@keyframes glowBreath  {0%,100%{box-shadow:0 6px 16px rgba(42,108,246,.42)}50%{box-shadow:0 6px 26px rgba(42,108,246,.68)}}
/* LOGO 是透明底图片，呼吸用轻微缩放代替 box-shadow，避免描出方形阴影 */
@keyframes logoBreath  {0%,100%{transform:scale(1)}50%{transform:scale(1.055)}}
@keyframes sheen       {from{transform:translateX(-120%) skewX(-18deg)}to{transform:translateX(320%) skewX(-18deg)}}
@keyframes barGrow     {from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes spinSlow    {to{transform:rotate(360deg)}}
@keyframes countPop    {0%{transform:scale(1)}40%{transform:scale(1.06)}100%{transform:scale(1)}}

/* ---------------- 首屏进入 ---------------- */
body.boot .sidebar{animation:slideLeft .5s var(--ease) both;}
body.boot .topbar{animation:fadeIn .4s ease .05s both;}
body.boot .login-card{animation:popIn .55s cubic-bezier(.2,.9,.3,1.08) both;}
body.boot .login-bg{animation:fadeIn .8s ease both;}
body.boot .login-foot{animation:fadeUpSm .6s ease .25s both;}

/* ---------------- 内容区页面切换 ---------------- */
.content > *{will-change:transform,opacity;}
.content.anim > *{animation:fadeUp .5s var(--ease) both;}
.content.anim > *:nth-child(1){animation-delay:.00s}
.content.anim > *:nth-child(2){animation-delay:.06s}
.content.anim > *:nth-child(3){animation-delay:.12s}
.content.anim > *:nth-child(4){animation-delay:.17s}
.content.anim > *:nth-child(5){animation-delay:.22s}
.content.anim > *:nth-child(n+6){animation-delay:.26s}

/* ---------------- KPI 卡片 ---------------- */
.kpis .kpi{animation:fadeUp .48s var(--ease) both;}
.kpis .kpi:nth-child(1){animation-delay:.04s}
.kpis .kpi:nth-child(2){animation-delay:.10s}
.kpis .kpi:nth-child(3){animation-delay:.16s}
.kpis .kpi:nth-child(4){animation-delay:.22s}
.kpi .kpi-ico{transition:transform .3s var(--ease);}
.kpi:hover .kpi-ico{transform:scale(1.12) rotate(-6deg);}
.kpi-val.counting{animation:countPop .35s var(--ease);}

/* ---------------- 面板 / 图表 ---------------- */
.panel{animation:fadeUpSm .45s var(--ease) both;}
.chart-grid .chart-card{animation:zoomIn .5s var(--ease) both;}
.chart-grid .chart-card:nth-child(1){animation-delay:.06s}
.chart-grid .chart-card:nth-child(2){animation-delay:.13s}
.chart-grid .chart-card:nth-child(3){animation-delay:.20s}
.chart-grid .chart-card:nth-child(4){animation-delay:.27s}
.chart-grid .chart-card:nth-child(n+5){animation-delay:.32s}
.chart-card canvas{animation:fadeIn .6s ease .18s both;}

/* ---------------- 表格行 ---------------- */
#tablePanel tbody tr,
.table-wrap tbody tr{
  animation:fadeUpSm .36s var(--ease) both;
}
tbody tr:nth-child(1){animation-delay:.03s}
tbody tr:nth-child(2){animation-delay:.06s}
tbody tr:nth-child(3){animation-delay:.09s}
tbody tr:nth-child(4){animation-delay:.12s}
tbody tr:nth-child(5){animation-delay:.15s}
tbody tr:nth-child(6){animation-delay:.18s}
tbody tr:nth-child(7){animation-delay:.21s}
tbody tr:nth-child(8){animation-delay:.24s}
tbody tr:nth-child(9){animation-delay:.27s}
tbody tr:nth-child(n+10){animation-delay:.30s}

/* ---------------- 侧栏 ---------------- */
.mgroup{animation:slideLeft .45s var(--ease) both;}
.mgroup:nth-child(1){animation-delay:.03s}
.mgroup:nth-child(2){animation-delay:.06s}
.mgroup:nth-child(3){animation-delay:.09s}
.mgroup:nth-child(4){animation-delay:.12s}
.mgroup:nth-child(5){animation-delay:.15s}
.mgroup:nth-child(6){animation-delay:.18s}
.mgroup:nth-child(7){animation-delay:.21s}
.mgroup:nth-child(8){animation-delay:.24s}
.logo-img{animation:logoBreath 3.6s ease-in-out infinite;transform-origin:center;}
.mgroup.active>.mhead{position:relative;overflow:hidden;}
.mgroup.active>.mhead::after{
  content:"";position:absolute;left:0;top:0;bottom:0;width:3px;border-radius:0 3px 3px 0;
  background:#fff;
  animation:barGrow .3s var(--ease) both;transform-origin:top;
}
.msub a.on{animation:popIn .32s var(--ease);}

/* ---------------- 按钮 ---------------- */
.btn::after{
  content:"";position:absolute;top:0;bottom:0;left:0;width:40%;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.42),transparent);
  opacity:0;pointer-events:none;
}
.btn:hover::after{opacity:1;animation:sheen .7s var(--ease);}
.btn-primary,.btn-blue{background-size:180% 180%;}
.btn-primary:hover,.btn-blue:hover{background-position:100% 0;}

/* 涟漪 */
.ripple{
  position:absolute;border-radius:50%;pointer-events:none;
  background:rgba(255,255,255,.55);transform:scale(0);opacity:.85;
  animation:rippleOut .6s var(--ease) forwards;
}
.btn:not(.btn-primary):not(.btn-blue) .ripple{background:rgba(42,108,246,.22);}
@keyframes rippleOut{to{transform:scale(2.6);opacity:0}}

/* ---------------- 顶栏 ---------------- */
.badge-dot::after{animation:pulseRing 2s infinite;}
.user{transition:background .2s,transform .2s var(--ease);}
.user:hover{transform:translateY(-1px);}
.avatar{transition:transform .3s var(--ease),box-shadow .3s;}
.user:hover .avatar{transform:scale(1.08) rotate(-4deg);box-shadow:0 6px 16px rgba(22,82,240,.3);}
.page-ico{transition:transform .34s var(--ease),box-shadow .3s;}
.page-head:hover .page-ico{transform:rotate(-8deg) scale(1.06);}

/* ---------------- 标签 / 徽标 ---------------- */
.tag{transition:transform .18s var(--ease),box-shadow .2s;}
.tag:hover{transform:translateY(-1px);box-shadow:0 4px 10px rgba(21,27,43,.1);}
.lnk{position:relative;}
.lnk::after{
  content:"";position:absolute;left:0;right:0;bottom:-2px;height:1px;
  background:currentColor;transform:scaleX(0);transform-origin:left;
  transition:transform .24s var(--ease);
}
.lnk:hover{text-decoration:none;}
.lnk:hover::after{transform:scaleX(1);}

/* ---------------- 登录页光斑 ---------------- */
.login .orb{
  position:absolute;border-radius:50%;filter:blur(38px);opacity:.55;
  background:radial-gradient(circle,rgba(255,236,170,.95),rgba(255,180,60,0) 68%);
}
.login .orb.o1{width:320px;height:320px;left:-70px;top:6%;animation:floatY 9s ease-in-out infinite;}
.login .orb.o2{width:250px;height:250px;right:-60px;top:26%;animation:floatY 11s ease-in-out infinite reverse;}
.login .orb.o3{width:200px;height:200px;left:38%;bottom:-60px;animation:floatY 13s ease-in-out infinite;}
.lv-logo{animation:logoBreath 4.4s ease-in-out infinite;transform-origin:center;}
.login-head h1{
  background-size:220% auto;
  animation:shineText 5s linear infinite;
}
@keyframes shineText{
  0%{background-position:0% center}
  100%{background-position:220% center}
}
.field input,.field select,.field textarea{transition:border-color .22s,background .22s,box-shadow .22s,transform .22s var(--ease);}
.field input:focus,.field select:focus,.field textarea:focus{transform:translateY(-1px);}

/* ---------------- 校区卡片 ---------------- */
.campus-cards .ccard{animation:fadeUp .45s var(--ease) both;}
.campus-cards .ccard:nth-child(1){animation-delay:.05s}
.campus-cards .ccard:nth-child(2){animation-delay:.13s}
.campus-cards .ccard:nth-child(3){animation-delay:.21s}
.campus-cards .ccard:nth-child(4){animation-delay:.29s}
.campus-cards .ccard:nth-child(n+5){animation-delay:.34s}
.ccard .stats b{transition:color .2s;}
.ccard:hover .stats b{color:var(--brand-2);}

/* ---------------- 待办 / 快捷 ---------------- */
.todo-list .todo-item{animation:fadeUpSm .4s var(--ease) both;}
.todo-item:nth-child(1){animation-delay:.05s}
.todo-item:nth-child(2){animation-delay:.11s}
.todo-item:nth-child(3){animation-delay:.17s}
.todo-item:nth-child(4){animation-delay:.23s}
.todo-item:nth-child(n+5){animation-delay:.28s}
.quick-grid .quick{animation:fadeUpSm .4s var(--ease) both;}
.quick:nth-child(1){animation-delay:.05s}
.quick:nth-child(2){animation-delay:.09s}
.quick:nth-child(3){animation-delay:.13s}
.quick:nth-child(4){animation-delay:.17s}
.quick:nth-child(5){animation-delay:.21s}
.quick:nth-child(6){animation-delay:.25s}

/* ---------------- 课表格子 ---------------- */
.slot{animation:zoomIn .34s var(--ease) both;}
table.schedule tbody tr:nth-child(1) .slot{animation-delay:.02s}
table.schedule tbody tr:nth-child(2) .slot{animation-delay:.06s}
table.schedule tbody tr:nth-child(3) .slot{animation-delay:.10s}
table.schedule tbody tr:nth-child(4) .slot{animation-delay:.14s}
table.schedule tbody tr:nth-child(5) .slot{animation-delay:.18s}
table.schedule tbody tr:nth-child(n+6) .slot{animation-delay:.22s}
.slot .s{transition:transform .2s var(--ease);}
.slot:hover .s{transform:scale(1.08);}

/* ---------------- 抽屉消息 ---------------- */
.msg-item:nth-child(1){animation-delay:.04s}
.msg-item:nth-child(2){animation-delay:.09s}
.msg-item:nth-child(3){animation-delay:.14s}
.msg-item:nth-child(4){animation-delay:.19s}
.msg-item:nth-child(n+5){animation-delay:.24s}

/* ---------------- 路由进度条 ---------------- */
#routeBar{
  position:fixed;top:0;left:0;height:2.5px;width:100%;z-index:500;
  transform:scaleX(0);transform-origin:left;
  background:linear-gradient(90deg,var(--brand-l),var(--brand),var(--blue));
  box-shadow:0 0 10px rgba(42,108,246,.55);
  transition:transform .35s var(--ease),opacity .3s;
  opacity:0;pointer-events:none;
}
#routeBar.on{transform:scaleX(.82);opacity:1;transition:transform 1.4s cubic-bezier(.1,.8,.2,1),opacity .1s;}
#routeBar.done{transform:scaleX(1);opacity:0;transition:transform .28s ease,opacity .34s ease .12s;}

/* ---------------- 骨架屏进入 ---------------- */
.sk{animation:fadeIn .2s ease both;}

/* ---------------- 弹窗 / 抽屉元素 ---------------- */
.modal-mask.show .modal .form-grid > *{animation:fadeUpSm .36s var(--ease) both;}
.modal-mask.show .modal .form-grid > *:nth-child(1){animation-delay:.04s}
.modal-mask.show .modal .form-grid > *:nth-child(2){animation-delay:.08s}
.modal-mask.show .modal .form-grid > *:nth-child(3){animation-delay:.12s}
.modal-mask.show .modal .form-grid > *:nth-child(4){animation-delay:.16s}
.modal-mask.show .modal .form-grid > *:nth-child(5){animation-delay:.20s}
.modal-mask.show .modal .form-grid > *:nth-child(n+6){animation-delay:.24s}
.modal-mask.show .modal-foot{animation:fadeUpSm .36s var(--ease) .22s both;}

/* ---------------- 加载转圈 ---------------- */
.spin{animation:spinSlow .9s linear infinite;}

/* ---------------- 移动端：解除入场动画对变换的锁定 ----------------
   slideLeft 使用 both 填充，会把 transform 永久锁定为 none，
   导致 ≤1024px 时侧栏被强制显示、遮住正文。此处取消动画，
   让 style.css 中的 translateX(-102%) 生效（侧栏改为抽屉式）。 */
@media (max-width:1024px){
  body.boot .sidebar{animation:none;}
}

/* ---------------- 工作台：业务模块 / 列表 / 简报 / 快捷入口 ---------------- */
.biz-grid .biz{animation:fadeUpSm .42s var(--ease) both;}
.biz:nth-child(1){animation-delay:.04s}
.biz:nth-child(2){animation-delay:.08s}
.biz:nth-child(3){animation-delay:.12s}
.biz:nth-child(4){animation-delay:.16s}
.biz:nth-child(5){animation-delay:.20s}
.biz:nth-child(6){animation-delay:.24s}
.biz:nth-child(7){animation-delay:.28s}
.biz:nth-child(8){animation-delay:.32s}
.biz:nth-child(n+9){animation-delay:.36s}

.warn-list .warn-item{animation:fadeUpSm .4s var(--ease) both;}
.warn-item:nth-child(1){animation-delay:.05s}
.warn-item:nth-child(2){animation-delay:.10s}
.warn-item:nth-child(3){animation-delay:.15s}
.warn-item:nth-child(n+4){animation-delay:.20s}

.notice-list .notice-item{animation:fadeUpSm .4s var(--ease) both;}
.notice-item:nth-child(1){animation-delay:.05s}
.notice-item:nth-child(2){animation-delay:.10s}
.notice-item:nth-child(3){animation-delay:.15s}
.notice-item:nth-child(n+4){animation-delay:.20s}

.brief-grid .brief{animation:zoomIn .4s var(--ease) both;}
.brief:nth-child(1){animation-delay:.06s}
.brief:nth-child(2){animation-delay:.12s}
.brief:nth-child(3){animation-delay:.18s}
.brief:nth-child(4){animation-delay:.24s}

.quick-tiles .qtile{animation:zoomIn .4s var(--ease) both;}
.qtile:nth-child(1){animation-delay:.06s}
.qtile:nth-child(2){animation-delay:.12s}
.qtile:nth-child(3){animation-delay:.18s}
.qtile:nth-child(4){animation-delay:.24s}
.qtile:nth-child(n+5){animation-delay:.30s}

/* 迷你趋势线：进入时整体淡入 */
.kpi-spark{animation:fadeIn .7s ease .2s both;}

/* ---------------- 降级 ---------------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
  }
}
