/* ===========================================================================
   Dev-Mail motion layer
   ---------------------------------------------------------------------------
   全站共用的动效。原则只有三条:

   1. 只动 transform 和 opacity。动 width/height/top 会让浏览器每帧重排,
      在 2 核的源站机器上配合低端手机就是掉帧,那比不做动效更糟。
   2. 时长分三档(快 160ms / 中 260ms / 慢 520ms),缓动只有两条曲线。
      每个组件自己挑一套数值,页面看起来就是一盘散沙。
   3. prefers-reduced-motion 全部关掉。这不是可选项:前庭障碍的人看到位移动画
      会真的不舒服。
   =========================================================================== */

:root {
  /* 出场曲线:起步快、收尾慢,东西"落位"而不是"飘到位"。 */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  /* 回弹:只用在用户按下去的那一下,给一点点物理反馈。 */
  --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
  --t-fast: 160ms;
  --t-mid: 260ms;
  --t-slow: 520ms;
}

/* ---------- 滚动进场 ---------- */
/* .js 前缀:没有 JS 的时候内容必须照常可见,而不是永远停在 opacity:0。 */
.js [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 20px, 0);
  will-change: opacity, transform;
}
.js [data-reveal].is-in {
  opacity: 1;
  transform: none;
  transition: opacity var(--t-slow) var(--ease-out),
              transform var(--t-slow) var(--ease-out);
}
/* 一组元素依次进场。延迟由 JS 写成内联变量,CSS 只负责用。 */
.js [data-reveal].is-in { transition-delay: var(--reveal-delay, 0ms); }

/* ---------- 可交互元素的手感 ---------- */
.btn,
.plan,
.chip,
.mail,
.tg-cta,
[data-lift] {
  transition: transform var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out),
              box-shadow var(--t-mid) var(--ease-out),
              background-color var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out);
}
.btn:hover,
[data-lift]:hover { transform: translateY(-1px); }
/* 按下去要立刻有反应:160ms 的回弹比任何视觉效果都更让人觉得"跟手"。 */
.btn:active,
[data-lift]:active { transform: translateY(0) scale(0.975); transition-duration: 90ms; }

.plan:hover,
.mail:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 24px -12px rgba(39, 36, 32, 0.28);
}

/* 焦点环也动一下。键盘用户是唯一一批全程看着焦点走的人。 */
:focus-visible { transition: outline-offset var(--t-fast) var(--ease-out); }

/* ---------- 复制反馈 ---------- */
/* 复制成功时按钮上的对勾。用 scale 从 0 弹出来,比直接换文字更容易被余光捕捉到。 */
.copy-ok {
  display: inline-block;
  transform: scale(0);
  transition: transform var(--t-mid) var(--ease-spring);
}
.is-copied .copy-ok { transform: scale(1); }

/* ---------- 新邮件到达 ---------- */
/* 收验证码的人整页只盯着这一处。新信进来必须一眼看见,又不能跳得让人烦。 */
@keyframes mailIn {
  from { opacity: 0; transform: translate3d(0, -10px, 0) scale(0.99); }
  to   { opacity: 1; transform: none; }
}
.mail--new { animation: mailIn var(--t-mid) var(--ease-out) both; }

@keyframes codePop {
  0%   { transform: scale(0.94); }
  55%  { transform: scale(1.04); }
  100% { transform: scale(1); }
}
.code-chip--new { animation: codePop 420ms var(--ease-spring) both; }

/* 验证码那块的高亮扫过。只扫一次,不循环——循环的动效两分钟后就变成噪音。 */
@keyframes sweep {
  from { transform: translateX(-120%); }
  to   { transform: translateX(220%); }
}
.sweep { position: relative; overflow: hidden; }
.sweep::after {
  content: "";
  position: absolute; inset: 0 auto 0 0; width: 40%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.55), transparent);
  transform: translateX(-120%);
  pointer-events: none;
}
.sweep.is-fresh::after { animation: sweep 900ms var(--ease-out) 1; }

/* ---------- 等待状态 ---------- */
/* 骨架屏而不是转圈:轮询验证码时用户盯着的是"信来了没有",
   一个占位的信件形状比一个 spinner 更接近那件事。 */
@keyframes shimmer {
  from { background-position: -420px 0; }
  to   { background-position: 420px 0; }
}
.skeleton {
  background: linear-gradient(90deg, var(--line) 0%, #f3f1ec 40%, var(--line) 80%);
  background-size: 420px 100%;
  animation: shimmer 1.4s linear infinite;
  border-radius: 6px;
  color: transparent !important;
}

/* ---------- 面板展开 ---------- */
/* 付款面板出现时从下方推上来一点。grid-template-rows 的 0fr→1fr 是目前唯一
   能给未知高度做过渡又不触发重排的写法。 */
.panel-in {
  animation: panelIn var(--t-slow) var(--ease-out) both;
}
@keyframes panelIn {
  from { opacity: 0; transform: translate3d(0, 14px, 0); }
  to   { opacity: 1; transform: none; }
}

/* ---------- 弹窗 ---------- */
dialog[open] { animation: dlgIn var(--t-mid) var(--ease-out) both; }
dialog[open]::backdrop { animation: fadeIn var(--t-mid) var(--ease-out) both; }
@keyframes dlgIn {
  from { opacity: 0; transform: translate3d(0, 12px, 0) scale(0.97); }
  to   { opacity: 1; transform: none; }
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

/* ---------- 提示条 ---------- */
.toast-in { animation: toastIn var(--t-mid) var(--ease-spring) both; }
@keyframes toastIn {
  from { opacity: 0; transform: translate3d(0, 14px, 0); }
  to   { opacity: 1; transform: none; }
}

/* ---------- 倒计时 ---------- */
/* 地址还剩多久被回收。数字每秒跳一下会很吵,所以只在进入最后一小时时变色。 */
.countdown { font-variant-numeric: tabular-nums; transition: color var(--t-slow) var(--ease-out); }
.countdown--soon { color: var(--err); }

/* ---------- 全局开关 ---------- */
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1 !important; transform: none !important; }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
