/* ============================================================
   众泰云 动效系统 v1.0 (UI-3)
   动效用来说明状态变化，不是装饰

   依赖：design-system.css
     - 过渡时间：--transition-fast(var(--duration-150)) / --transition-base(var(--duration-normal)) / --transition-slow(var(--duration-slow))
     - 颜色令牌：--color-interactive / --color-success / --color-bg-* 等
     - 阴影令牌：--shadow-color / --shadow-color-md / --shadow-color-lg
     - 圆角令牌：--radius-* / 间距令牌：--space-*

   命名约定：
     - 本文件使用 .anim-* 前缀，避免与 design-system.css 中已有的
       .animate-* 基础工具类冲突。
     - design-system.css 的 .skeleton-shimmer 关键帧已存在，本文件
       仅扩展骨架屏变体，不重复定义同名关键帧。

   设计原则（来自 UI 优化方案）：
     1. 过渡时间：快速反馈 var(--duration-150) / 标准过渡 var(--duration-normal) / 强调 var(--duration-slow)
     2. 缓动函数：ease-out（入场）/ ease-in（出场）/ cubic-bezier(0.4,0,0.2,1)（强调）
     3. 性能优化：只用 transform 和 opacity（触发 GPU 加速）
     4. 尊重 prefers-reduced-motion
   ============================================================ */

/* ============================================================
   1. 全局过渡变量（补充 design-system.css）
   design-system.css 已定义 --transition-* 时长变量；
   本节补充缓动函数变量，供后续动画复用。
   ============================================================ */
:root {
    /* 缓动函数：批15 F5 清偿，--ease-out / --ease-in / --ease-in-out /
       --ease-spring 收敛至 tokens-authoritative.css 单一事实源，本文件不再重复定义 */
    /* 动画时长：--duration-fast / --duration-slow 收敛至权威层；
       --duration-base 为本文件内部别名，引用权威 --duration-normal(200ms) */
    --duration-base: var(--duration-normal);

    /* 入场位移距离 */
    --anim-distance-sm: 8px;
    --anim-distance-md: 16px;
    --anim-distance-lg: 24px;

    /* 发光效果颜色（暗色主题下覆盖） */
    --glow-color: rgba(99, 102, 241, 0.35);          /* indigo-500 半透明 */
    --glow-color-strong: rgba(99, 102, 241, 0.55);
}

/* 暗色主题下发光更明显 */
[data-theme="dark"] {
    --glow-color: rgba(129, 140, 248, 0.4);          /* indigo-400 半透明 */
    --glow-color-strong: rgba(129, 140, 248, 0.65);
}

/* ============================================================
   2. 入场动画（6种）
   每种包含 @keyframes 定义和动画类。
   使用 .anim- 前缀，与 design-system.css 的 .animate-* 区分。
   ============================================================ */

/* 2.1 淡入 */
.anim-fade-in {
    animation: anim-fade-in var(--duration-base) var(--ease-out) both;
    will-change: opacity;
}
@keyframes anim-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* 2.2 从下方淡入 */
.anim-fade-in-up {
    animation: anim-fade-in-up var(--duration-slow) var(--ease-out) both;
    will-change: opacity, transform;
}
@keyframes anim-fade-in-up {
    from { opacity: 0; transform: translateY(var(--anim-distance-lg)); }
    to   { opacity: 1; transform: translateY(0); }
}

/* 2.3 从上方淡入 */
.anim-fade-in-down {
    animation: anim-fade-in-down var(--duration-slow) var(--ease-out) both;
    will-change: opacity, transform;
}
@keyframes anim-fade-in-down {
    from { opacity: 0; transform: translateY(calc(-1 * var(--anim-distance-lg))); }
    to   { opacity: 1; transform: translateY(0); }
}

/* 2.4 缩放淡入 */
.anim-scale-in {
    animation: anim-scale-in var(--duration-base) var(--ease-out) both;
    will-change: opacity, transform;
}
@keyframes anim-scale-in {
    from { opacity: 0; transform: scale(0.95); }
    to   { opacity: 1; transform: scale(1); }
}

/* 2.5 从右侧滑入 */
.anim-slide-in-right {
    animation: anim-slide-in-right var(--duration-slow) var(--ease-out) both;
    will-change: opacity, transform;
}
@keyframes anim-slide-in-right {
    from { opacity: 0; transform: translateX(var(--anim-distance-lg)); }
    to   { opacity: 1; transform: translateX(0); }
}

/* 2.6 从左侧滑入 */
.anim-slide-in-left {
    animation: anim-slide-in-left var(--duration-slow) var(--ease-out) both;
    will-change: opacity, transform;
}
@keyframes anim-slide-in-left {
    from { opacity: 0; transform: translateX(calc(-1 * var(--anim-distance-lg))); }
    to   { opacity: 1; transform: translateX(0); }
}

/* ============================================================
   3. 交互微动效（6种）
   只用 transform / opacity / box-shadow，触发 GPU 加速。
   ============================================================ */

/* 3.1 悬停上浮 */
.hover-lift {
    transition: transform var(--duration-fast) var(--ease-out),
                box-shadow var(--duration-fast) var(--ease-out);
    will-change: transform;
}
.hover-lift:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-color-lg);
}

/* 3.2 悬停缩放 */
.hover-scale {
    transition: transform var(--duration-fast) var(--ease-out);
    will-change: transform;
}
.hover-scale:hover {
    transform: scale(1.02);
}

/* 3.3 悬停发光 */
.hover-glow {
    transition: box-shadow var(--duration-base) var(--ease-out);
    will-change: box-shadow;
}
.hover-glow:hover {
    box-shadow: 0 0 0 3px var(--glow-color),
                0 0 20px var(--glow-color);
}

/* 3.4 按下回弹 */
.press-down {
    transition: transform var(--duration-fast) var(--ease-out);
    will-change: transform;
}
.press-down:active {
    transform: scale(0.98);
}

/* 3.5 聚焦焦点环动画 */
.focus-ring {
    transition: box-shadow var(--duration-fast) var(--ease-out);
    will-change: box-shadow;
}
.focus-ring:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--color-interactive-subtle),
                0 0 0 1px var(--color-border-focus);
}

/* 3.6 脉冲动画（用于通知/提醒） */
.pulse {
    animation: pulse var(--duration-slow) var(--ease-in-out) infinite;
    will-change: opacity, transform;
}
@keyframes pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50%      { opacity: 0.6; transform: scale(1.05); }
}

/* ============================================================
   4. 加载动画（4种）
   design-system.css 已有 .skeleton 基础类，本节扩展其余加载形态。
   ============================================================ */

/* 4.1 旋转加载器 */
.spinner-ds {
    display: inline-block;
    width: 20px;
    height: 20px;
    border: 2px solid var(--color-bg-hover);
    border-top-color: var(--color-interactive);
    border-radius: 50%;
    animation: spinner-rotate var(--duration-slowest) linear infinite;
    will-change: transform;
}
@keyframes spinner-rotate {
    to { transform: rotate(360deg); }
}

/* 4.2 三点跳动加载 */
.dots-loading {
    display: inline-flex;
    gap: 4px;
    align-items: center;
}
.dots-loading::before,
.dots-loading::after,
.dots-loading > .dot {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--color-interactive);
    animation: dots-bounce var(--duration-1400) var(--ease-in-out) infinite both;
}
.dots-loading::before { animation-delay: calc(-1 * var(--duration-320)); }
.dots-loading > .dot  { animation-delay: calc(-1 * var(--duration-160)); }
.dots-loading::after  { animation-delay: 0s; }
@keyframes dots-bounce {
    0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; }
    40%           { transform: scale(1);   opacity: 1; }
}

/* 4.3 进度条加载（不定进度） */
.bar-loading {
    position: relative;
    width: 100%;
    height: 4px;
    background: var(--color-bg-subtle);
    border-radius: var(--radius-full);
    overflow: hidden;
}
.bar-loading::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 40%;
    height: 100%;
    background: var(--color-interactive);
    border-radius: var(--radius-full);
    animation: bar-loading-move var(--duration-1200) var(--ease-in-out) infinite;
    will-change: transform;
}
@keyframes bar-loading-move {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(350%); }
}

/* 4.4 骨架屏扩展（基础 shimmer 由 design-system.css 提供）
   本节定义变体类，配合 .skeleton 使用。
   用法：<div class="skeleton skeleton-text-sm"></div>
*/
.skeleton-shimmer {
    /* 别名：显式标注 shimmer 行为，等价于 .skeleton */
    background: linear-gradient(
        90deg,
        var(--color-bg-subtle) 0%,
        var(--color-bg-hover) 50%,
        var(--color-bg-subtle) 100%
    );
    background-size: 200% 100%;
    animation: skeleton-shimmer var(--duration-1500) infinite;
    border-radius: var(--radius-base);
}

/* ============================================================
   5. 页面切换动画（3种）
   适用于 SPA 路由切换、Tab 切换等场景。
   ============================================================ */

/* 5.1 页面入场（从右滑入 + 淡入） */
.page-enter {
    animation: page-enter var(--duration-slow) var(--ease-out) both;
    will-change: opacity, transform;
}
@keyframes page-enter {
    from { opacity: 0; transform: translateX(var(--anim-distance-md)); }
    to   { opacity: 1; transform: translateX(0); }
}

/* 5.2 页面出场（向左滑出 + 淡出） */
.page-exit {
    animation: page-exit var(--duration-fast) var(--ease-in) both;
    will-change: opacity, transform;
}
@keyframes page-exit {
    from { opacity: 1; transform: translateX(0); }
    to   { opacity: 0; transform: translateX(calc(-1 * var(--anim-distance-md))); }
}

/* 5.3 简单淡入淡出 */
.page-fade {
    animation: page-fade var(--duration-base) var(--ease-out) both;
    will-change: opacity;
}
@keyframes page-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* ============================================================
   6. 板块差异化动效
   针对不同业务板块定制的动效语义。
   ============================================================ */

/* ---------- 6.1 AI 对话板块 ---------- */

/* AI 消息入场（从左淡入 + 轻微上移） */
.ai-msg-enter {
    animation: ai-msg-enter var(--duration-slow) var(--ease-out) both;
    will-change: opacity, transform;
}
@keyframes ai-msg-enter {
    from { opacity: 0; transform: translateX(calc(-1 * var(--anim-distance-sm))) translateY(var(--anim-distance-sm)); }
    to   { opacity: 1; transform: translateX(0) translateY(0); }
}

/* 打字指示器（三点交替跳动） */
.ai-typing {
    display: inline-flex;
    gap: 4px;
    align-items: center;
    padding: var(--space-2) var(--space-3);
    background: var(--color-bg-subtle);
    border-radius: var(--radius-lg);
}
.ai-typing::before,
.ai-typing::after,
.ai-typing > .dot {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--color-text-muted);
    animation: ai-typing-bounce var(--duration-1200) var(--ease-in-out) infinite;
}
.ai-typing::before { animation-delay: 0s; }
.ai-typing > .dot  { animation-delay: var(--duration-normal); }
.ai-typing::after  { animation-delay: var(--duration-slower); }
@keyframes ai-typing-bounce {
    0%, 60%, 100% { transform: translateY(0);   opacity: 0.4; }
    30%           { transform: translateY(-4px); opacity: 1; }
}

/* 气泡弹出效果 */
.ai-bubble-pop {
    animation: ai-bubble-pop var(--duration-slow) var(--ease-spring) both;
    will-change: opacity, transform;
    transform-origin: bottom left;
}
@keyframes ai-bubble-pop {
    0%   { opacity: 0; transform: scale(0.8); }
    60%  { opacity: 1; transform: scale(1.03); }
    100% { opacity: 1; transform: scale(1); }
}

/* ---------- 6.2 数据看板板块 ---------- */

/* 数字增长动画（需配合 JS 设置 --count-from / --count-to 自定义属性） */
.stat-count-up {
    animation: stat-count-up var(--duration-slow) var(--ease-out) both;
    will-change: opacity;
}
@keyframes stat-count-up {
    from { opacity: 0; transform: translateY(var(--anim-distance-sm)); }
    to   { opacity: 1; transform: translateY(0); }
}

/* 图表绘制动画（stroke-dashoffset）
   用法：SVG path 设置 stroke-dasharray + 此类
*/
.chart-draw {
    stroke-dasharray: var(--chart-length, 1000);
    stroke-dashoffset: var(--chart-length, 1000);
    animation: chart-draw var(--duration-1200) var(--ease-out) forwards;
    will-change: stroke-dashoffset;
}
@keyframes chart-draw {
    to { stroke-dashoffset: 0; }
}

/* 进度条填充（需配合 JS 设置 --progress 0~1） */
.progress-fill {
    width: 0;
    width: calc(var(--progress, 0) * 100%);
    transition: width var(--duration-slow) var(--ease-out);
    will-change: width;
}

/* ---------- 6.3 管理后台板块 ---------- */

/* 表格行入场（依次淡入，配合 .delay-* 实现错峰） */
.table-row-enter {
    animation: table-row-enter var(--duration-base) var(--ease-out) both;
    will-change: opacity, transform;
}
@keyframes table-row-enter {
    from { opacity: 0; transform: translateY(var(--anim-distance-sm)); }
    to   { opacity: 1; transform: translateY(0); }
}

/* 卡片翻转效果（需配合 JS 切换 .is-flipped 类） */
.card-flip {
    perspective: 1000px;
}
.card-flip-inner {
    position: relative;
    width: 100%;
    height: 100%;
    transition: transform var(--duration-slow) var(--ease-in-out);
    transform-style: preserve-3d;
    will-change: transform;
}
.card-flip.is-flipped .card-flip-inner {
    transform: rotateY(180deg);
}
.card-flip-front,
.card-flip-back {
    position: absolute;
    inset: 0;
    backface-visibility: hidden;
}
.card-flip-back {
    transform: rotateY(180deg);
}

/* 抽屉滑入（从右侧） */
.drawer-slide {
    animation: drawer-slide var(--duration-slow) var(--ease-out) both;
    will-change: transform;
}
@keyframes drawer-slide {
    from { transform: translateX(100%); }
    to   { transform: translateX(0); }
}

/* ============================================================
   7. 滚动触发动画
   - 现代浏览器：使用 animation-timeline: view() 纯 CSS 实现
   - 回退方案：无 JS 时直接显示（初始 opacity:1）
   - 增强方案：JS IntersectionObserver 添加 .is-visible 类触发
   ============================================================ */

/* 增强方案：JS 配合（推荐，兼容性最好） */
.reveal-on-scroll {
    opacity: 0;
    transform: translateY(var(--anim-distance-md));
    transition: opacity var(--duration-slow) var(--ease-out),
                transform var(--duration-slow) var(--ease-out);
    will-change: opacity, transform;
}
.reveal-on-scroll.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* 现代浏览器：纯 CSS animation-timeline（渐进增强） */
@supports (animation-timeline: view()) {
    .reveal-on-scroll {
        animation: reveal-timeline linear both;
        animation-timeline: view();
        animation-range: entry 0% entry 80%;
        opacity: 0;
        transform: translateY(var(--anim-distance-md));
        transition: none; /* 避免与 animation 冲突 */
    }
    @keyframes reveal-timeline {
        to {
            opacity: 1;
            transform: translateY(0);
        }
    }
}

/* 回退方案：无 JS 且不支持 animation-timeline 时直接显示 */
@media (scripting: none) {
    .reveal-on-scroll {
        opacity: 1;
        transform: none;
    }
}

/* ============================================================
   8. 骨架屏变体
   配合 design-system.css 的 .skeleton 基础类使用。
   用法：<div class="skeleton skeleton-text-sm"></div>
   ============================================================ */

.skeleton-text-sm {
    height: 12px;
    width: 100%;
    margin-bottom: var(--space-1);
    border-radius: var(--radius-sm);
}

.skeleton-text-lg {
    height: 20px;
    width: 100%;
    margin-bottom: var(--space-2);
    border-radius: var(--radius-sm);
}

.skeleton-circle {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-full);
    flex-shrink: 0;
}

.skeleton-rect {
    width: 100%;
    height: 120px;
    border-radius: var(--radius-lg);
}

/* 暗色主题下骨架屏对比度调整 */
[data-theme="dark"] .skeleton,
[data-theme="dark"] .skeleton-shimmer {
    background: linear-gradient(
        90deg,
        var(--stone-800) 0%,
        var(--stone-700) 50%,
        var(--stone-800) 100%
    );
    background-size: 200% 100%;
}

/* ============================================================
   9. 通知 / Toast 动画
   适用于右上角通知中心、Toast 提示。
   ============================================================ */

/* Toast 入场（从右上角滑入） */
.toast-enter {
    animation: toast-enter var(--duration-slow) var(--ease-out) both;
    will-change: opacity, transform;
}
@keyframes toast-enter {
    from { opacity: 0; transform: translateX(100%); }
    to   { opacity: 1; transform: translateX(0); }
}

/* Toast 出场（向右滑出） */
.toast-exit {
    animation: toast-exit var(--duration-fast) var(--ease-in) both;
    will-change: opacity, transform;
}
@keyframes toast-exit {
    from { opacity: 1; transform: translateX(0); }
    to   { opacity: 0; transform: translateX(100%); }
}

/* Toast 进度条倒计时（需配合 JS 设置 --toast-duration） */
.toast-progress {
    height: 3px;
    width: 100%;
    background: var(--color-interactive-subtle);
    border-radius: var(--radius-full);
    overflow: hidden;
}
.toast-progress::after {
    content: '';
    display: block;
    height: 100%;
    width: 100%;
    background: var(--color-interactive);
    transform-origin: left;
    animation: toast-progress-shrink var(--toast-duration, var(--duration-4000)) linear forwards;
    will-change: transform;
}
@keyframes toast-progress-shrink {
    from { transform: scaleX(1); }
    to   { transform: scaleX(0); }
}

/* ============================================================
   10. 模态框动画
   配合 design-system.css 的 .modal-ds / .modal-ds-backdrop 使用。
   ============================================================ */

/* 模态框入场（scale + fade） */
.modal-enter {
    animation: modal-enter var(--duration-slow) var(--ease-spring) both;
    will-change: opacity, transform;
}
@keyframes modal-enter {
    from { opacity: 0; transform: scale(0.92); }
    to   { opacity: 1; transform: scale(1); }
}

/* 模态框出场 */
.modal-exit {
    animation: modal-exit var(--duration-fast) var(--ease-in) both;
    will-change: opacity, transform;
}
@keyframes modal-exit {
    from { opacity: 1; transform: scale(1); }
    to   { opacity: 0; transform: scale(0.96); }
}

/* 背景遮罩淡入 */
.backdrop-enter {
    animation: backdrop-enter var(--duration-base) var(--ease-out) both;
    will-change: opacity;
}
@keyframes backdrop-enter {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* 背景遮罩淡出 */
.backdrop-exit {
    animation: backdrop-exit var(--duration-fast) var(--ease-in) both;
    will-change: opacity;
}
@keyframes backdrop-exit {
    from { opacity: 1; }
    to   { opacity: 0; }
}

/* ============================================================
   11. 动画延迟工具类
   配合 .anim-* / .table-row-enter 等实现错峰入场。
   ============================================================ */
.delay-100  { animation-delay: var(--duration-fast); }
.delay-200  { animation-delay: var(--duration-normal); }
.delay-300  { animation-delay: var(--duration-slow); }
.delay-500  { animation-delay: var(--duration-500); }
.delay-700  { animation-delay: var(--duration-700); }
.delay-1000 { animation-delay: var(--duration-1000); }

/* 延迟类需要配合 both 填充模式，避免延迟期间闪烁 */
.delay-100,
.delay-200,
.delay-300,
.delay-500,
.delay-700,
.delay-1000 {
    animation-fill-mode: both;
}

/* ============================================================
   12. 减少动画偏好（A11y）
   design-system.css 已有全局 @media (prefers-reduced-motion: reduce)
   此处为本文件引入的动画提供显式禁用，确保即使被局部覆盖也安全。
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
    .anim-fade-in,
    .anim-fade-in-up,
    .anim-fade-in-down,
    .anim-scale-in,
    .anim-slide-in-right,
    .anim-slide-in-left,
    .pulse,
    .spinner-ds,
    .dots-loading::before,
    .dots-loading::after,
    .dots-loading > .dot,
    .bar-loading::after,
    .page-enter,
    .page-exit,
    .page-fade,
    .ai-msg-enter,
    .ai-typing::before,
    .ai-typing::after,
    .ai-typing > .dot,
    .ai-bubble-pop,
    .stat-count-up,
    .chart-draw,
    .table-row-enter,
    .drawer-slide,
    .reveal-on-scroll,
    .toast-enter,
    .toast-exit,
    .toast-progress::after,
    .modal-enter,
    .modal-exit,
    .backdrop-enter,
    .backdrop-exit {
        animation: none !important;
        transition: none !important;
        opacity: 1 !important;
        transform: none !important;
    }

    /* 骨架屏在减少动画模式下停止 shimmer，保留占位外观 */
    .skeleton,
    .skeleton-shimmer {
        animation: none !important;
        background: var(--color-bg-subtle) !important;
    }

    /* 交互微动效在减少动画模式下保持静态 */
    .hover-lift:hover,
    .hover-scale:hover,
    .press-down:active {
        transform: none !important;
        box-shadow: var(--shadow-color) !important;
    }
    .hover-glow:hover {
        box-shadow: none !important;
    }

    /* 卡片翻转改为瞬时切换 */
    .card-flip-inner {
        transition: none !important;
    }

    /* 进度条填充改为瞬时 */
    .progress-fill {
        transition: none !important;
    }
}

/* ============================================================
   13. 增强动效（v5.7 世界级补强）
   - 列表项交错入场（stagger）
   - 卡片悬浮 3D 效果（perspective + rotateX/Y）
   - 数字滚动动画（@property 渐进增强）
   - 脉冲加载增强（pulse-ring）
   ============================================================ */

/* ---------- 13.1 列表项交错入场（stagger） ----------
   用法：父容器加 .stagger-list，子项加 .stagger-item。
   通过 --stagger-index（JS 或内联 style 设置）控制延迟。
   未设置 index 时按 var(--duration-50) 递增（通过 :nth-child 兜底）。
   ------------------------------------------------------- */
.stagger-list .stagger-item {
    opacity: 0;
    transform: translateY(var(--anim-distance-md, 16px));
    animation: stagger-item-in var(--duration-slow, var(--duration-slow)) var(--ease-out, cubic-bezier(0,0,0.2,1)) both;
    animation-delay: calc(var(--stagger-index, 0) * var(--duration-60));
    will-change: opacity, transform;
}
/* 兜底：未设置 --stagger-index 时按 nth-child 递增（最多 12 项） */
.stagger-list .stagger-item:nth-child(1)  { animation-delay: 0ms;    }
.stagger-list .stagger-item:nth-child(2)  { animation-delay: var(--duration-60);   }
.stagger-list .stagger-item:nth-child(3)  { animation-delay: var(--duration-120);  }
.stagger-list .stagger-item:nth-child(4)  { animation-delay: var(--duration-180);  }
.stagger-list .stagger-item:nth-child(5)  { animation-delay: var(--duration-240);  }
.stagger-list .stagger-item:nth-child(6)  { animation-delay: var(--duration-slow);  }
.stagger-list .stagger-item:nth-child(7)  { animation-delay: var(--duration-360);  }
.stagger-list .stagger-item:nth-child(8)  { animation-delay: var(--duration-420);  }
.stagger-list .stagger-item:nth-child(9)  { animation-delay: var(--duration-480);  }
.stagger-list .stagger-item:nth-child(10) { animation-delay: var(--duration-540);  }
.stagger-list .stagger-item:nth-child(11) { animation-delay: var(--duration-slowest);  }
.stagger-list .stagger-item:nth-child(12) { animation-delay: var(--duration-660);  }
@keyframes stagger-item-in {
    from { opacity: 0; transform: translateY(var(--anim-distance-md, 16px)); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ---------- 13.2 卡片悬浮 3D 效果（tilt） ----------
   用法：父容器 .tilt-3d，内部 .tilt-3d__inner。
   鼠标移动时 JS 设置 --tilt-x / --tilt-y（角度）。
   无 JS 时 hover 产生轻微前倾。
   ------------------------------------------------------- */
.tilt-3d {
    perspective: 1000px;
}
.tilt-3d__inner {
    transform: rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg));
    transform-style: preserve-3d;
    transition: transform var(--duration-fast, var(--duration-150)) var(--ease-out, cubic-bezier(0,0,0.2,1));
    will-change: transform;
}
.tilt-3d:hover .tilt-3d__inner {
    /* 无 JS 时的兜底：轻微前倾 + 上浮 */
    transform: rotateX(2deg) translateY(-4px);
}
/* 3D 层次：内部元素可设置 translateZ 产生视差 */
.tilt-3d__layer {
    transform: translateZ(40px);
    transform-style: preserve-3d;
}
.tilt-3d__layer--deep {
    transform: translateZ(80px);
}

/* ---------- 13.3 数字滚动动画 ----------
   方案 A（现代浏览器）：@property 注册 --count 为 integer，
   配合 counter() 输出。JS 设置 --count-to 即可滚动到目标值。
   方案 B（兜底）：仅淡入上移，数字由 JS 直接写入文本。
   ------------------------------------------------------- */

/* 方案 A：@property 渐进增强（Chrome 85+ / Edge 85+ / Safari 16.4+） */
@supports (animation-timeline: view()) {
    @property --count-num {
        syntax: '<integer>';
        initial-value: 0;
        inherits: false;
    }
    .count-up {
        --count-num: 0;
        counter-reset: countup var(--count-num);
        animation: count-up-prop var(--count-duration, var(--duration-1600)) var(--ease-out, cubic-bezier(0,0,0.2,1)) forwards;
    }
    .count-up::after {
        content: counter(countup);
    }
    @keyframes count-up-prop {
        from { --count-num: var(--count-from, 0); }
        to   { --count-num: var(--count-to, 100); }
    }
}

/* 方案 B：兜底（不支持 @property 的浏览器仅做淡入） */
.count-up {
    opacity: 0;
    animation: count-up-fallback var(--duration-slow) var(--ease-out, cubic-bezier(0,0,0.2,1)) both;
}
@keyframes count-up-fallback {
    from { opacity: 0; transform: translateY(var(--anim-distance-sm, 8px)); }
    to   { opacity: 1; transform: translateY(0); }
}
/* 支持 @property 时覆盖兜底的 opacity（让 ::after 接管显示） */
@supports (animation-timeline: view()) {
    .count-up {
        opacity: 1;
    }
}

/* 老虎机式数字滚动（垂直位移，适用于统计卡） */
.count-roll {
    display: inline-block;
    overflow: hidden;
    height: 1em;
    line-height: 1;
    vertical-align: bottom;
}
.count-roll__track {
    display: block;
    animation: count-roll var(--count-duration, var(--duration-1200)) var(--ease-out, cubic-bezier(0,0,0.2,1)) both;
    will-change: transform;
}
@keyframes count-roll {
    from { transform: translateY(0); }
    to   { transform: translateY(var(--roll-distance, -90%)); }
}

/* ---------- 13.4 脉冲加载增强 ----------
   pulse-ring：扩散波纹（用于在线状态 / 加载占位）
   ------------------------------------------------------- */
.pulse-ring {
    position: relative;
}
.pulse-ring::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: var(--color-interactive, var(--ti-500, #0E7C7B));
    opacity: 0.5;
    animation: pulse-ring-spread var(--duration-1800) var(--ease-out, cubic-bezier(0,0,0.2,1)) infinite;
    will-change: transform, opacity;
    z-index: -1;
}
@keyframes pulse-ring-spread {
    0%   { transform: scale(0.8); opacity: 0.5; }
    80%  { transform: scale(1.6); opacity: 0; }
    100% { transform: scale(1.6); opacity: 0; }
}

/* 呼吸式加载（常驻脉冲，比 .pulse 更柔和） */
.pulse-breath {
    animation: pulse-breath var(--duration-2400) var(--ease-in-out, cubic-bezier(0.4,0,0.2,1)) infinite;
    will-change: opacity, transform;
}
@keyframes pulse-breath {
    0%, 100% { opacity: 1; transform: scale(1); }
    50%      { opacity: 0.85; transform: scale(1.015); }
}

/* ---------- 13.5 减少动画偏好覆盖（新增动画） ---------- */
@media (prefers-reduced-motion: reduce) {
    .stagger-list .stagger-item,
    .tilt-3d__inner,
    .count-up,
    .count-roll__track,
    .pulse-ring::before,
    .pulse-breath {
        animation: none !important;
        transition: none !important;
        opacity: 1 !important;
        transform: none !important;
    }
    .tilt-3d:hover .tilt-3d__inner {
        transform: none !important;
    }
}
