/* ============================================================
   page-anims.css
   通用动画 + 页面切换动画。
   - 首屏淡入（preanim / anim-ready）
   - 页面退出（page-leaving）
   - 通用涟漪 + 扫光（按钮 / 磁贴 / 卡片 / 链接 / 行）
   - 视口入场（.fx-fade-up / .fx-stagger / .tile / .svc）
   - 标签页 / 面板（.tab / [data-panel]）
   - 减少动画偏好全部退化
   ============================================================ */

/* ---------- 首屏加载遮罩：未完全加载渲染好前，黑屏 + loading 图标 ----------
   用 html 伪元素实现（不靠 JS 插入 DOM），因为 page-anims.css 在 <head>
   会阻塞首屏渲染，所以 CSS 一到位黑屏即生效、首帧就是黑屏，避免“闪一下”。
   JS 加载完成后给 <html> 加 .boot-done 使其淡出。 */
html::before{
  content: "";
  position: fixed;
  inset: 0;
  z-index: 2147483000;
  background: #0d1424;
  opacity: 1;
  will-change: opacity;             /* 只列可合成属性，确保提升到独立图层 → 淡出顺滑 */
  transform: translateZ(0);         /* 强制 GPU 合成层，避免主线程逐帧重绘整屏 */
  transition: opacity .5s cubic-bezier(.4,0,.2,1), visibility .5s;
}
html::after{
  content: "";
  position: fixed;
  top: 50%;
  left: 50%;
  width: 46px;
  height: 46px;
  margin: -23px 0 0 -23px;
  box-sizing: border-box;
  border-radius: 50%;
  border: 3px solid rgba(255,255,255,.16);
  border-top-color: rgba(255,255,255,.92);
  z-index: 2147483001;
  opacity: 1;
  will-change: transform;           /* 仅 transform 可合成，旋转走合成器线程 */
  animation: bootSpin .8s linear infinite;
  transition: opacity .5s cubic-bezier(.4,0,.2,1), visibility .5s;
}
html.boot-done::before,
html.boot-done::after{
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
@keyframes bootSpin{
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce){
  html::after{ animation: none; border-top-color: rgba(255,255,255,.6); }
}

/* ---------- 首屏：仅做轻微上移入场，不再整体隐藏（避免黑屏） ---------- */
/* 注意：preanim 目前未被任何脚本注入，这里保留规则仅作兜底，
   且绝不再用 opacity:0 隐藏整页，否则会露出深色背景形成“黑屏”。 */
html{ background: var(--bg0); }
html[data-theme="light"]{ background: var(--bg1); }

html.preanim body{ transform: translateY(6px); }
html.preanim body.anim-ready{
  transform: none;
  transition: transform .4s var(--ease, cubic-bezier(.2,.9,.2,1));
}
@media (prefers-reduced-motion: reduce){
  html.preanim body{ transform: none !important; }
}

/* ============================================================
   防首屏黑屏：入场元素默认就可见，只保留“上移”等位移动画，
   不再从 opacity:0 淡入（否则在深色背景上会先黑屏再浮现）。
   ============================================================ */
.reveal{ opacity: 1 !important; }
.svc{ opacity: 1 !important; }
.tile{ opacity: 1 !important; }
.fx-fade-up,
.fx-fade-in,
.fx-pop-in,
.fx-slide-left,
.fx-slide-right{ opacity: 1 !important; }
.fx-stagger > *{ opacity: 1 !important; }

/* ---------- 页面退出 ---------- */
html.page-leaving body{
  opacity: 0;
  transform: translateY(-6px) scale(.995);
  transition:
    opacity .18s ease,
    transform .18s ease;
}
@media (prefers-reduced-motion: reduce){
  html.page-leaving body{ opacity: 1 !important; transform: none !important; filter: none !important; }
}

/* ---------- 导航栏常驻：切换页面时不被 body 淡出影响 ---------- */
/* body 整体淡入/淡出时，把 .nav 提升到独立合成层并强制不透明，
   使其始终可见；同时切换瞬间不播放入场动画，避免“闪一下”。 */
html.preanim body .nav,
html.page-leaving body .nav{
  opacity: 1 !important;
  filter: none !important;
  transform: none !important;
  animation: none !important;
  z-index: 1000;
}
html.preanim body.anim-ready .nav{
  animation: none !important;
}

/* ---------- 通用涟漪（任何位置、任何尺寸） ---------- */
.ripple{
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  background: radial-gradient(circle, rgba(255,255,255,.55) 0%, rgba(255,255,255,.30) 40%, rgba(255,255,255,0) 70%);
  transform: translate(-50%, -50%) scale(0);
  opacity: .85;
  animation: rippleAnim .65s cubic-bezier(.2,.9,.2,1) forwards;
  z-index: 0;
}
@keyframes rippleAnim{
  0%   { transform: translate(-50%,-50%) scale(0);   opacity: .85; }
  60%  { transform: translate(-50%,-50%) scale(2.4); opacity: .35; }
  100% { transform: translate(-50%,-50%) scale(3.4); opacity: 0;  }
}

/* 光泽扫光：仅 pill 按钮有，减少伪元素层数 */
.pill::after{
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  left: -120%;
  width: 60%;
  background: linear-gradient(120deg,
              rgba(255,255,255,0) 0%,
              rgba(255,255,255,.16) 45%,
              rgba(255,255,255,.28) 50%,
              rgba(255,255,255,.16) 55%,
              rgba(255,255,255,0) 100%);
  transform: skewX(-18deg);
  pointer-events: none;
  z-index: 0;
  transition: left .8s var(--ease, cubic-bezier(.2,.9,.2,1));
}
.pill:hover::after{ left: 130%; }

/* 涟漪/扫光要落在元素之内 */
.btn, .pill, .luck-again, .iconbtn, .tile, .svc, .card, .row, .action, .logo, .tab, .chip, .nav-links a{
  isolation: isolate;
  position: relative;
  overflow: hidden;
}

/* ---------- logo bump ---------- */
.logo.click-bump{ animation: logoBump .42s cubic-bezier(.2,.9,.2,1); }
@keyframes logoBump{
  0%   { transform: scale(1)    rotate(0deg); }
  35%  { transform: scale(.88)  rotate(-6deg); }
  70%  { transform: scale(1.10) rotate(10deg); }
  100% { transform: scale(1)    rotate(0deg); }
}

/* ---------- 导航链接下划线 ---------- */
.nav-links a::after{
  content: "";
  position: absolute;
  left: 10px; right: 10px; bottom: 4px;
  height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, #1664ff, #387bff);
  transform: scaleX(0);
  transform-origin: left center;
  opacity: .85;
  transition: transform .32s var(--ease, cubic-bezier(.2,.9,.2,1)), opacity .25s var(--ease, cubic-bezier(.2,.9,.2,1));
}
.nav-links a:hover::after,
.nav-links a:focus-visible::after{ transform: scaleX(1); }
.nav-links a:active{ transform: translateY(0) scale(.97); }

/* ---------- 按钮按下反馈 ---------- */
.btn:not(.small):active, .pill:active, .luck-again:active, .tab:active{
  transform: translateY(0) scale(.97);
  transition: transform .12s var(--ease, cubic-bezier(.2,.9,.2,1));
}
.btn.primary:hover{ box-shadow: 0 18px 38px rgba(22,100,255,.35), 0 0 0 1px rgba(255,255,255,.15) inset; }

/* ---------- Top3 .svc ---------- */
.svc{
  opacity: 1;
  transform: translateY(10px);
  transition:
    transform .55s cubic-bezier(.16,1,.3,1),
    opacity .55s cubic-bezier(.16,1,.3,1),
    background .35s cubic-bezier(.2,.9,.2,1),
    border-color .35s cubic-bezier(.2,.9,.2,1);
}
.svc.in{ opacity: 1; transform: translateY(0); }
.svc.in:hover{ transform: translateY(-3px); }
.svc .svc-ico{ transition: transform .35s cubic-bezier(.2,.9,.2,1); }
.svc:hover .svc-ico{ transform: translateY(-2px) rotate(-4deg) scale(1.05); }
.svc .badge{ transition: transform .25s var(--ease, cubic-bezier(.2,.9,.2,1)); }
.svc:hover .badge{ transform: translateY(-1px); }

/* ---------- 磁贴 .tile ---------- */
.tile .tile-inner img,
.tile .tile-inner > div{ transition: transform .5s cubic-bezier(.16,1,.3,1); }
.tile:hover .tile-inner img,
.tile:hover .tile-inner > div{ transform: translateY(-4px) rotate(-3deg) scale(1.05); }
.tile h3{ transition: transform .35s cubic-bezier(.2,.9,.2,1), letter-spacing .35s cubic-bezier(.2,.9,.2,1); }
.tile:hover h3{ transform: translateY(-2px); letter-spacing: -.4px; }
.tile.pressed{ animation: tilePress .35s cubic-bezier(.2,.9,.2,1); }
@keyframes tilePress{
  0%   { transform: translateY(0)   scale(1); }
  35%  { transform: translateY(2px) scale(.985); }
  100% { transform: translateY(0)   scale(1); }
}
@keyframes popUp{ /* 兼容原 index.html 已有 .tile.pop 触发 */
  0%   { transform: translateY(-1px) scale(.985); }
  55%  { transform: translateY(-6px) scale(1.01); }
  100% { transform: translateY(-4px) scale(1); }
}
.tile.pop{ animation: popUp 260ms cubic-bezier(.16,1,.3,1) both; }

/* ---------- 模态分数翻转（主页 luck 模态） ---------- */
.luck-score span{ display: inline-block; transition: transform .55s cubic-bezier(.16,1,.3,1); }
.luck-score.flip span{ animation: scoreFlip .8s cubic-bezier(.16,1,.3,1) both; }
@keyframes scoreFlip{
  0%   { transform: translateY(0)    rotateX(0deg);   opacity: 1; }
  40%  { transform: translateY(-12px) rotateX(90deg); opacity: 0; }
  60%  { transform: translateY(12px) rotateX(-90deg); opacity: 0; }
  100% { transform: translateY(0)    rotateX(0deg);   opacity: 1; }
}

/* ---------- toast ---------- */
.toast{ transform: translateX(-50%) translateY(16px) scale(.96); opacity: 0; }
.toast.show{ transform: translateX(-50%) translateY(0) scale(1); opacity: 1; }

/* ---------- chips ---------- */
.chip{ transition: transform .25s var(--ease, cubic-bezier(.2,.9,.2,1)), background .25s var(--ease, cubic-bezier(.2,.9,.2,1)), color .25s var(--ease, cubic-bezier(.2,.9,.2,1)), border-color .25s var(--ease, cubic-bezier(.2,.9,.2,1)); }
.chip:hover{ transform: translateY(-2px); }

/* ===========================================================
   通用入场工具类
   =========================================================== */
.fx-fade-up{
  opacity: 0;
  transform: translateY(14px);
  transition: opacity .7s cubic-bezier(.16,1,.3,1), transform .7s cubic-bezier(.16,1,.3,1);
}
.fx-fade-up.in{ opacity: 1; transform: translateY(0); }

.fx-fade-in{ opacity: 0; transition: opacity .6s ease; }
.fx-fade-in.in{ opacity: 1; }

.fx-pop-in{ opacity: 0; transform: scale(.96); transition: opacity .45s ease, transform .45s cubic-bezier(.16,1,.3,1); }
.fx-pop-in.in{ opacity: 1; transform: scale(1); }

.fx-slide-left{ opacity: 0; transform: translateX(20px); transition: opacity .55s ease, transform .55s cubic-bezier(.16,1,.3,1); }
.fx-slide-left.in{ opacity: 1; transform: translateX(0); }
.fx-slide-right{ opacity: 0; transform: translateX(-20px); transition: opacity .55s ease, transform .55s cubic-bezier(.16,1,.3,1); }
.fx-slide-right.in{ opacity: 1; transform: translateX(0); }

/* 父容器内子元素错开 */
.fx-stagger > *{
  opacity: 0;
  transform: translateY(12px);
  transition: opacity .55s cubic-bezier(.16,1,.3,1), transform .55s cubic-bezier(.16,1,.3,1);
}
.fx-stagger > *.in{ opacity: 1; transform: translateY(0); }
.fx-stagger > *:nth-child(1){ transition-delay: 0ms; }
.fx-stagger > *:nth-child(2){ transition-delay: 60ms; }
.fx-stagger > *:nth-child(3){ transition-delay: 120ms; }
.fx-stagger > *:nth-child(4){ transition-delay: 180ms; }
.fx-stagger > *:nth-child(5){ transition-delay: 240ms; }
.fx-stagger > *:nth-child(6){ transition-delay: 300ms; }
.fx-stagger > *:nth-child(7){ transition-delay: 360ms; }
.fx-stagger > *:nth-child(8){ transition-delay: 420ms; }
.fx-stagger > *:nth-child(n+9){ transition-delay: 480ms; }

/* ===========================================================
   Tab / Panel
   =========================================================== */
.tab{
  cursor: pointer;
  transition: background .25s var(--ease, cubic-bezier(.2,.9,.2,1)), color .25s var(--ease, cubic-bezier(.2,.9,.2,1)), transform .2s var(--ease, cubic-bezier(.2,.9,.2,1));
}
.tab:hover{ transform: translateY(-1px); }
.tab.active{ transform: translateY(0); }

[data-panel]{
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .4s ease, transform .4s cubic-bezier(.16,1,.3,1);
  display: none;
}
[data-panel].in{ opacity: 1; transform: translateY(0); display: block; }

/* 行 / 列表项 hover 抬起 */
.row, .action{
  transition: transform .25s var(--ease, cubic-bezier(.2,.9,.2,1)), background .25s var(--ease, cubic-bezier(.2,.9,.2,1)), border-color .25s var(--ease, cubic-bezier(.2,.9,.2,1));
}
.row:hover, .action:hover{ transform: translateY(-2px); }

/* 卡片 hover 抬起（如果页面已有 .card 自定义 hover，与之叠加） */
.card{ transition: transform .35s cubic-bezier(.16,1,.3,1), box-shadow .35s cubic-bezier(.16,1,.3,1), border-color .35s cubic-bezier(.16,1,.3,1); }
.card:hover{ transform: translateY(-3px); }

/* ===========================================================
   减少动画：兜底退化
   =========================================================== */
@media (prefers-reduced-motion: reduce){
  .btn::after, .pill::after, .tile::after, .svc::after, .card::after, .row::after, .action::after{ display: none !important; }
  .ripple{ display: none !important; }
  .logo.click-bump, .tile.pressed, .luck-score.flip span{ animation: none !important; }
  .fx-fade-up, .fx-fade-in, .fx-pop-in, .fx-slide-left, .fx-slide-right, .fx-stagger > *{ opacity: 1 !important; transform: none !important; }
  .svc{ opacity: 1 !important; transform: none !important; }
  [data-panel]{ opacity: 1 !important; transform: none !important; display: block !important; }
}
