
/* ══════════════════════════════════════════════
   动效层
   原则：只动 transform / opacity，避免触发布局重排；
   列表用统一缓动 + 小步长错峰，切换不闪白。
   ══════════════════════════════════════════════ */
:root{
  --ease-out:cubic-bezier(.22,.61,.36,1);
  --ease-spring:cubic-bezier(.34,1.3,.64,1);
  --ease-io:cubic-bezier(.4,0,.2,1);
  --d1:.16s;--d2:.26s;--d3:.38s;
}

@keyframes fadeIn{from{opacity:0}to{opacity:1}}
@keyframes fadeOut{from{opacity:1}to{opacity:0}}
@keyframes panelIn{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:none}}
@keyframes cardIn{from{opacity:0;transform:translateY(10px) scale(.985)}to{opacity:1;transform:none}}
@keyframes modalIn{from{opacity:0;transform:translateY(16px) scale(.96)}to{opacity:1;transform:none}}
@keyframes modalOut{from{opacity:1;transform:none}to{opacity:0;transform:translateY(12px) scale(.97)}}
@keyframes flipNum{0%{opacity:1;transform:none}35%{opacity:0;transform:translateY(-6px) scale(.94)}65%{opacity:0;transform:translateY(6px) scale(.94)}100%{opacity:1;transform:none}}
@keyframes shimmer{from{background-position:-180px 0}to{background-position:180px 0}}
@keyframes popIn{from{opacity:0;transform:scale(.86)}to{opacity:1;transform:none}}
@keyframes hitPulse{0%{box-shadow:0 0 0 0 rgba(180,35,24,.28)}70%{box-shadow:0 0 0 5px rgba(180,35,24,0)}100%{box-shadow:0 0 0 0 rgba(180,35,24,0)}}
@keyframes dotPulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.82)}}

/* ① 面板切换：淡入 + 微位移 */
.panel.on{animation:panelIn var(--d2) var(--ease-out) both}

/* ② Tab 滑块指示器 */
.tabs{position:relative;overflow:hidden}
.tab{position:relative;z-index:1;background:transparent!important;box-shadow:none!important;transition:color var(--d1) var(--ease-io)}
.tab-ind{
  position:absolute;top:4px;left:0;height:calc(100% - 8px);border-radius:9px;
  background:#fff;box-shadow:0 1px 3px rgba(16,24,40,.08);
  z-index:0;pointer-events:none;opacity:0;
  transition:transform var(--d3) var(--ease-out),width var(--d3) var(--ease-out),opacity var(--d1);
}
.tab-ind.ready{opacity:1}

/* ③ 列表错峰入场 */
.card.enter,.dup-item.enter{
  will-change:transform,opacity;
  animation:cardIn var(--d3) var(--ease-out) backwards;
  animation-delay:calc(var(--i,0) * 34ms);
}
.mon-card.enter{
  animation:cardIn var(--d3) var(--ease-out) backwards;
  animation-delay:calc(var(--i,0) * 30ms);
}

/* ④ 统计卡：按压回弹 + 数字跳动 */
.stat{transition:border-color var(--d1),background var(--d1),transform var(--d1) var(--ease-out)}
.stat:active{transform:scale(.965)}
.stat b{transition:color var(--d2) var(--ease-io)}
.stat b.counting{color:var(--blue)}
@media(hover:hover){.stat:hover{border-color:#DCE3F0;background:#FCFDFF}}

/* ⑤ 期号切换：翻转 */
.hero-issue.flip{animation:flipNum .42s var(--ease-io)}

/* ⑥ 骨架屏 */
.skel{
  background:#fff;border:1px solid var(--line);border-radius:14px;padding:15px;margin-bottom:10px;
  animation:fadeIn var(--d2) var(--ease-out) both;animation-delay:calc(var(--i,0) * 40ms);
}
.skel .sk-l{
  display:block;height:11px;border-radius:6px;margin-bottom:9px;
  background:linear-gradient(90deg,#F1F3F7 25%,#E8EBF1 37%,#F1F3F7 63%);
  background-size:360px 100%;animation:shimmer 1.15s linear infinite;
}
.skel .sk-l.w40{width:40%}
.skel .sk-l.w70{width:70%}
.skel .sk-l.w55{width:55%}
.skel .sk-nums{display:flex;gap:6px;margin-top:12px}
.skel .sk-nums i{
  width:52px;height:22px;border-radius:7px;
  background:linear-gradient(90deg,#F1F3F7 25%,#E8EBF1 37%,#F1F3F7 63%);
  background-size:360px 100%;animation:shimmer 1.15s linear infinite;
}

/* ⑦ 号码胶囊：入场与命中脉冲 */
.c-nums .hl-num{transition:transform var(--d1) var(--ease-out)}
@media(hover:hover){.c-nums .hl-num:hover{transform:translateY(-1px)}}
.dup-num{
  transition:background var(--d1),border-color var(--d1),color var(--d1),transform var(--d1) var(--ease-out);
  animation:popIn var(--d2) var(--ease-spring) backwards;
  animation-delay:calc(var(--i,0) * 16ms);
}
.dup-num.hit{
  animation:popIn var(--d2) var(--ease-spring) backwards,
    hitPulse 1.4s var(--ease-out) .3s backwards;
  animation-delay:calc(var(--i,0) * 16ms),.3s;
}
@media(hover:hover){.dup-num:hover{transform:translateY(-1px);border-color:#D3D9E4}}

/* ⑧ 弹窗：进出场 */
.rs-mask.on{display:block;animation:fadeIn var(--d1) var(--ease-io) both}
.rs-mask.on .rs-card{animation:modalIn var(--d3) var(--ease-spring) both}
.rs-mask.closing{animation:fadeOut var(--d1) var(--ease-io) forwards}
.rs-mask.closing .rs-card{animation:modalOut var(--d1) var(--ease-io) forwards}

/* ⑨ 按钮与交互元素统一反馈 */
.csv-btn,.page-tools button,.rs-btn,.s-clear,.rs-x,.linkbtn,.chip,.notice-btn{
  transition:transform .12s var(--ease-out),background var(--d1),border-color var(--d1),color var(--d1),opacity var(--d1)}
.csv-btn:active,.rs-btn:active,.notice-btn:active{transform:scale(.975)}
.page-tools button:active:not(:disabled),.s-clear:active,.rs-x:active{transform:scale(.88)}
.chip{transition:transform .14s var(--ease-out),background var(--d1),border-color var(--d1),color var(--d1)}
.chip:active{transform:scale(.95)}
@media(hover:hover){
  .chip:not(.on):hover{border-color:#CBD5E6;color:#475467}
  .csv-btn:not(:disabled):hover{background:#F5F8FF}
  .csv-btn.solid:hover{background:#1D4ED8}
  .page-tools button:not(:disabled):hover{background:#F5F8FF;border-color:#C7D9FD;color:var(--blue)}
}

/* ⑩ 输入框聚焦更柔和 */
.searchbox input{transition:border-color var(--d2) var(--ease-io),box-shadow var(--d2) var(--ease-io),background var(--d2)}
.s-clear{transition:opacity var(--d1),transform .12s var(--ease-out),background var(--d1)}
.s-clear.show{display:block;animation:fadeIn var(--d1) var(--ease-out) both}

/* ⑪ 状态点呼吸 */
.hero-pill.pend .dot,.hero-pill.ok .dot{animation:dotPulse 2.2s var(--ease-io) infinite}

/* ⑫ 空态与加载淡入 */
.empty,.spin{animation:fadeIn var(--d2) var(--ease-out) both}

/* ⑬ 移动端滚动更顺 */
main{-webkit-overflow-scrolling:touch}

/* ⑭ 尊重系统减弱动效：必须放最后，覆盖上面所有 */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important;
  }
  .card.enter,.dup-item.enter,.mon-card.enter,.skel{animation:none!important;opacity:1!important;transform:none!important}
}
