/* 公共交互组件：加载中按钮、骨架屏、弹簧曲线。三个页面共用。 */

:root {
  /* 弹簧曲线（阻尼振动采样，见 ui.js 注释）。--spring 有回弹，--spring-soft 几乎不过冲 */
  --spring: cubic-bezier(.34, 1.56, .64, 1);
  --spring-soft: cubic-bezier(.22, 1.2, .36, 1);
  --spring-dur: .75s;
}
@supports (transition-timing-function: linear(0, 1)) {
  :root {
    --spring: linear(0, 0.043, 0.152, 0.299, 0.461, 0.62, 0.763, 0.885, 0.98, 1.05, 1.095, 1.119, 1.126, 1.121, 1.108, 1.089, 1.069, 1.049, 1.031, 1.015, 1.003, 0.994, 0.988, 0.985, 0.984, 0.985, 0.986, 0.989, 0.991, 0.994, 0.996, 0.998, 1, 1.001, 1.001, 1.002, 1);
    --spring-soft: linear(0, 0.038, 0.13, 0.249, 0.376, 0.498, 0.61, 0.706, 0.787, 0.852, 0.903, 0.941, 0.969, 0.988, 1.001, 1.009, 1.013, 1.015, 1.015, 1.014, 1.012, 1.01, 1.008, 1.007, 1.005, 1.004, 1.003, 1.002, 1);
  }
}

/* ---------- 加载中按钮：文字隐去（保留宽度），中间转圈 ---------- */
.ui-btn { position: relative; }
.ui-btn .ui-spin {
  position: absolute; left: 50%; top: 50%; width: 18px; height: 18px; margin: -9px 0 0 -9px;
  opacity: 0; transform: scale(.4);
  transition: opacity .2s, transform var(--spring-dur) var(--spring);
  pointer-events: none;
}
.ui-btn .ui-spin::before {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  border: 2px solid var(--spin-color, currentColor); border-right-color: transparent;
  animation: ui-rot .7s linear infinite;
}
.ui-btn .ui-label { display: inline-block; transition: opacity .18s, transform var(--spring-dur) var(--spring); }
.ui-btn[aria-busy="true"] { cursor: progress; }
.ui-btn[aria-busy="true"] .ui-label { opacity: 0; transform: scale(.85); }
.ui-btn[aria-busy="true"] .ui-spin { opacity: 1; transform: scale(1); }
.btn-pixel.ui-btn[aria-busy="true"]:disabled { opacity: 1; }
@keyframes ui-rot { to { transform: rotate(360deg); } }

/* ---------- 独立的加载提示（区块读取中） ---------- */
.ui-loader { display: inline-flex; align-items: center; gap: 10px; font: 12px var(--mono); letter-spacing: .15em; color: var(--muted); }
.ui-loader::before {
  content: ""; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid var(--lime); border-right-color: transparent; animation: ui-rot .7s linear infinite;
}

/* ---------- 骨架屏 ---------- */
.ui-skel {
  position: relative; overflow: hidden; background: rgba(255,255,255,.05);
  border-radius: 2px; color: transparent !important; user-select: none;
}
.ui-skel::after {
  content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(212,255,58,.08), rgba(255,255,255,.07), transparent);
  animation: ui-shimmer 1.3s ease-in-out infinite;
}
@keyframes ui-shimmer { to { transform: translateX(100%); } }
.ui-skel-line { display: block; height: 12px; margin: 10px 0; }

/* 数字/文字刚换上新值时的弹入 */
.ui-pop { animation: ui-pop var(--spring-dur) var(--spring); }
@keyframes ui-pop { from { transform: scale(.6); opacity: .2; } }

@media (prefers-reduced-motion: reduce) {
  .ui-btn .ui-spin, .ui-btn .ui-label { transition: none; }
  .ui-skel::after { animation: none; }
  .ui-pop { animation: none; }
}
