/* ==========================================================================
   fx.css · 视觉增强层 v2（材质 / 动效 / 3D 舞台）
   --------------------------------------------------------------------------
   设计来源：用户已确认的效果图原型 v2（原型文件 webapp/preview-ui.html 已验收后删除）
   加载顺序：tokens.css → main.css → fx.css（同特异性时本文件胜出）
   回滚方式：删掉 index.html 里 fx.css 的 <link> 即可，main.css 完全不受影响
   色值纪律：本文件不新增色相，全部引用 tokens.css 的 v2 材质令牌
   ========================================================================== */

/* ------------------------------------------------------------------ 舞台 -- */
/* 3D canvas 容器：负层级垫底，永不吃点击 */
.fx-stage {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}
.fx-stage canvas { display: block; width: 100%; height: 100%; }

/* 3D 不可用时的 CSS 极光降级层（不白屏） */
body.fx-fallback .fx-stage {
  background:
    radial-gradient(60% 45% at 18% 12%, rgba(78,110,140,0.16) 0%, rgba(78,110,140,0) 60%),
    radial-gradient(55% 40% at 82% 20%, rgba(80,121,91,0.13) 0%, rgba(80,121,91,0) 62%),
    radial-gradient(70% 55% at 50% 96%, rgba(216,180,106,0.10) 0%, rgba(216,180,106,0) 64%);
  filter: blur(12px);
  animation: aurora-drift 34s var(--ease-in-out) infinite alternate;
}
@keyframes aurora-drift {
  from { transform: translate3d(-2%, -1%, 0) scale(1.02); }
  to   { transform: translate3d(2%, 1%, 0) scale(1.08); }
}

/* ---------------------------------------------------- 材质①：渐变网格底 -- */
/* z-index 0，与 .fx-stage 同级；DOM 顺序上 body::before 先绘制 → 网格在粒子下 */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right,  var(--grid-line-major) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-line-major) 1px, transparent 1px),
    linear-gradient(to right,  var(--grid-line-minor) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-line-minor) 1px, transparent 1px);
  background-size:
    var(--grid-major) var(--grid-major),
    var(--grid-major) var(--grid-major),
    var(--grid-minor) var(--grid-minor),
    var(--grid-minor) var(--grid-minor);
  -webkit-mask-image: var(--grid-mask);
  mask-image: var(--grid-mask);
}

/* ------------------------------------------------------ 材质②：颗粒纹理 -- */
/* 压在内容之上、Toast/弹层之下（400 < --z-toast 800），全站一层胶片颗粒 */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 400;
  pointer-events: none;
  opacity: var(--grain-opacity);
  mix-blend-mode: overlay;
  background-size: var(--grain-tile) var(--grain-tile);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180' viewBox='0 0 180 180'%3E%3Cfilter id='g' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)'/%3E%3C/svg%3E");
}

/* 内容抬到网格之上（网格 z-index 0） */
.main { position: relative; z-index: 1; }

/* ------------------------------------------------- 材质③：毛玻璃通用配方 -- */
/* 只用在「数量少、位置固定」的面上：header / tabbar / 入口大卡 / 投放区 / 弹层。
   数据卡片（.card）故意不用 backdrop-filter —— 列表里几十个会重算模糊拖垮帧率，
   改走下面的 .solid-lift（不透明面 + 多层柔阴影 + 内高光），视觉几乎一致。 */
.glass {
  background-image: var(--glass-sheen), var(--glass-base);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-inset), var(--shadow-soft-2);
}

/* 不透明面的「伪毛玻璃」：多层柔阴影 + 1px 内高光 */
.solid-lift {
  box-shadow: var(--glass-inset), var(--shadow-soft-1);
}

/* ------------------------------------------------------------ 组件升级 -- */

/* Header / TabBar —— 真正的毛玻璃 */
.header {
  background-image: var(--glass-sheen), var(--glass-base);
  background-color: transparent;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-inset), var(--shadow-soft-1);
}
.tabbar {
  background-image: var(--glass-sheen), var(--glass-base);
  background-color: transparent;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-inset), 0 -2px 12px rgba(0,0,0,0.32);
}

/* 入口大卡 —— 毛玻璃 + 战纹底 + 金辉光 */
.entry {
  background-image: var(--glass-sheen), var(--glass-base), var(--pattern-battle);
  background-color: transparent;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-inset), var(--shadow-soft-2);
}
.entry--primary {
  box-shadow: var(--glass-inset), var(--shadow-soft-2), var(--shadow-gold-lift);
}

/* 卡片 / stat —— 不透明面 + 柔阴影（性能优先） */
.card {
  box-shadow: var(--glass-inset), var(--shadow-soft-2);
}
.stat {
  box-shadow: var(--glass-inset), var(--shadow-soft-1);
  transition: box-shadow var(--dur-2) var(--ease-out),
              transform var(--dur-3) var(--ease-out),
              border-color var(--dur-2) var(--ease-out);
}
.stat:hover {
  border-color: var(--glass-border-hi);
  box-shadow: var(--glass-inset), var(--shadow-lift);
}
.chip {
  box-shadow: var(--glass-inset);
}

/* 弹层 / Toast —— 毛玻璃 */
.modal {
  background-image: var(--glass-sheen), var(--glass-base);
  background-color: transparent;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-inset), var(--shadow-soft-3);
}
.toast {
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-inset), var(--shadow-soft-2);
  animation: toast-in-spring var(--dur-3) var(--ease-spring);
}
@keyframes toast-in-spring {
  from { opacity: 0; transform: translateY(14px) scale(0.97); }
  to   { opacity: 1; transform: none; }
}

/* 投放区 —— 毛玻璃 */
.dropzone {
  background-image: var(--glass-sheen), var(--glass-base);
  background-color: transparent;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-inset), var(--shadow-soft-1);
}
.dropzone.is-dragover {
  box-shadow: var(--glass-inset), var(--shadow-soft-2), var(--gold-glow);
  transform: scale(1.01);
}

/* 预览缩略图 */
.preview-item { box-shadow: var(--glass-inset), var(--shadow-soft-1); }

/* ==========================================================================
   动效②：微交互 + 弹性
   ========================================================================== */

/* 卡片 / 入口卡：位移改用 --ty 变量，好让 JS 的 3D tilt 叠加进来而不打架 */
.card, .entry {
  transform: perspective(900px) translateY(var(--ty, 0px))
             rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: border-color var(--dur-2) var(--ease-out),
              box-shadow   var(--dur-2) var(--ease-out),
              transform    var(--dur-2) var(--ease-out);
}
.card--interactive:hover, .entry:hover { --ty: -4px; }
.entry--primary:hover { --ty: -6px; }
.card--interactive:active, .entry:active { --ty: 0px; }

/* 按钮：按下回弹 */
.btn { transition-property: background-color, background-image, border-color, color, box-shadow, transform, opacity; }
.btn:active:not([disabled]) { transform: scale(0.97); }
.btn--filled:hover:not([disabled]) {
  box-shadow: var(--glass-inset), var(--shadow-gold-lg);
  transform: translateY(-2px);
}
.btn--outlined:hover:not([disabled]) { transform: translateY(-2px); }
.icon-btn { transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-spring); }
.icon-btn:hover { transform: translateY(-1px) rotate(-10deg); }
.icon-btn:active { transform: scale(0.92); }

/* 输入框：focus 时描边流光（用背景扫光代替描边动画，input 不支持伪元素） */
.input:focus-visible {
  background-image: linear-gradient(100deg, transparent 18%, rgba(216,180,106,0.10) 46%, transparent 72%);
  background-size: 220% 100%;
  animation: input-sheen 2.4s var(--ease-in-out) infinite;
}
@keyframes input-sheen {
  from { background-position: -120% 0; }
  to   { background-position: 220% 0; }
}

/* 上传图标缓慢浮动 */
.dropzone__icon { animation: float-y 3.6s var(--ease-in-out) infinite; }
@keyframes float-y {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-5px); }
}
.entry__icon { animation: float-y 4.8s var(--ease-in-out) infinite; }

/* 战果徽标：出现时弹性一下 */
.badge { animation: badge-pop var(--dur-3) var(--ease-spring); }
@keyframes badge-pop {
  0% { transform: scale(1); }
  45% { transform: scale(1.18); }
  100% { transform: scale(1); }
}

/* ------------------------------------------------------ 动效③：滚动渐入 -- */
/* 用 translate（独立变换属性）+ transform（tilt）分离，两者互不覆盖 */
.rv {
  opacity: 0;
  translate: 0 var(--rv-shift);
  transition: opacity var(--dur-4) var(--ease-out),
              translate var(--dur-4) var(--ease-spring);
  transition-delay: var(--rv-d, 0ms);
}
.rv.is-in { opacity: 1; translate: none; }

/* 战果行 / 列表项递进 */
.main .section > * + * { }

/* ==========================================================================
   降级与偏好
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .rv, .rv.is-in {
    opacity: 1 !important;
    translate: none !important;
    transition: none !important;
  }
  .dropzone__icon, .entry__icon, .badge, body.fx-fallback .fx-stage {
    animation: none !important;
  }
  .input:focus-visible { animation: none !important; }
  .card, .entry { transform: none !important; }
}

/* 不支持 backdrop-filter 时退回不透明面，别留半透明糊底 */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .header, .tabbar, .entry, .modal, .dropzone {
    background-image: var(--glass-sheen), linear-gradient(180deg, #22262F 0%, #1E212B 100%);
  }
}
