/* ==============================================================================
 * 启宇科技官网 — 入场动画（纯 CSS3，2026-10-13）
 *
 * 【为什么需要本文件】
 * 原方案用 AOS 库做入场动画，但 AOS 的工作方式是：
 *   aos.css 用 CSS 把 [data-aos^=fade] 设为 opacity:0（隐藏态）
 *   → 滚动时由 aos.js 添加 .aos-animate 类才显示。
 * 问题：**没有 JS 就永远不显示**。而 GPTBot / ClaudeBot / OAI-SearchBot /
 * PerplexityBot 等 AI 抓取器（robots.txt 已明确放行）普遍不执行 JS，
 * 它们读到的正文是"隐藏"的 —— 这与本站的 GEO 目标直接冲突。
 * 实测：屏蔽 JS 后有 33 个元素（含 H1、hero 描述、about 正文）恒为 opacity:0。
 *
 * 【本文件的方案】
 * 改用 CSS `@keyframes` 动画。CSS 动画的三个关键特性使其天然满足 SEO/GEO：
 *   1. **不需要 JS**：浏览器解析到 CSS 即刻播放，渲染型爬虫能看到动画结束后的内容；
 *   2. **自动完成**：动画播完就停在 to 状态（opacity:1），不会像 AOS 那样
 *      依赖"滚动到视口"这个事件，因此不存在"永远不显示"的失败模式；
 *   3. **优雅降级**：`opacity:0` 只写在 keyframes 的 from 里，
 *      若浏览器不支持动画，整条 animation 声明被忽略 → 元素直接可见。
 *      注意这正是与原 AOS 方案的本质区别（AOS 把 opacity:0 写在静态规则里）。
 *
 * 【延迟策略】
 * HTML 里保留了 data-aos-delay（100~1400ms），那是为"滚动触发"设计的节奏。
 * 用于"载入播放"时按 1/4 压缩（最大 350ms），既保留错落感，
 * 又保证全部内容在约 1 秒内可见，不拖慢首屏信息到达。
 *
 * 【无障碍】
 * 尊重 prefers-reduced-motion: reduce —— 直接关闭动画并确保元素可见。
 * ============================================================================== */

/* ------------------------------------------------------------------------------
 * 1. 关键帧定义
 *    位移方向与原 AOS 保持一致，使观感与之前相同。
 *    距离做了收敛（100px → 32px）：载入动画若位移过大会显得晃动。
 * ---------------------------------------------------------------------------- */

/* 向上淡入（原 fade-up / slide-up） */
@keyframes qy-enter-up {
  from {
    opacity: 0;
    transform: translate3d(0, 32px, 0);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

/* 向下淡入（原 fade-down）— 位移略小，用于导航等顶部元素 */
@keyframes qy-enter-down {
  from {
    opacity: 0;
    transform: translate3d(0, -16px, 0);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

/* 自右向左淡入（原 fade-left：初始在右侧） */
@keyframes qy-enter-from-right {
  from {
    opacity: 0;
    transform: translate3d(32px, 0, 0);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

/* 自左向右淡入（原 fade-right / slide-right） */
@keyframes qy-enter-from-left {
  from {
    opacity: 0;
    transform: translate3d(-32px, 0, 0);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

/* 放大淡入（原 zoom-in） */
@keyframes qy-enter-zoom {
  from {
    opacity: 0;
    transform: scale(0.94);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

/* 纯淡入（原 fade-in） */
@keyframes qy-enter-fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* ------------------------------------------------------------------------------
 * 2. 动画绑定
 *    animation-fill-mode: both 的两点作用：
 *      · 延迟期间应用 from 状态（形成"等待入场"的观感）
 *      · 结束后保留 to 状态（确保最终 opacity:1）
 *    缓动与时长：0.7s ease-out-cubic，接近原 AOS 的 800ms / ease-out-cubic。
 * ---------------------------------------------------------------------------- */
[data-aos="fade-up"],
[data-aos="slide-up"] {
  animation: qy-enter-up 0.7s cubic-bezier(0.215, 0.61, 0.355, 1) both;
}

[data-aos="fade-down"] {
  animation: qy-enter-down 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) both;
}

[data-aos="fade-left"] {
  animation: qy-enter-from-right 0.7s cubic-bezier(0.215, 0.61, 0.355, 1) both;
}

[data-aos="fade-right"],
[data-aos="slide-right"] {
  animation: qy-enter-from-left 0.7s cubic-bezier(0.215, 0.61, 0.355, 1) both;
}

[data-aos="slide-left"] {
  animation: qy-enter-from-right 0.7s cubic-bezier(0.215, 0.61, 0.355, 1) both;
}

[data-aos="zoom-in"] {
  animation: qy-enter-zoom 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) both;
}

[data-aos="fade-in"] {
  animation: qy-enter-fade 0.7s cubic-bezier(0.215, 0.61, 0.355, 1) both;
}

/* 兜底：任何未在上面列出的 data-aos 取值（含历史遗留的 bounce）都按向上淡入处理，
   避免出现"有 data-aos 却没有动画"的空档。 */
[data-aos]:not([data-aos="fade-up"]):not([data-aos="slide-up"]):not([data-aos="fade-down"]):not([data-aos="fade-left"]):not([data-aos="fade-right"]):not([data-aos="slide-right"]):not([data-aos="slide-left"]):not([data-aos="zoom-in"]):not([data-aos="fade-in"]) {
  animation: qy-enter-up 0.7s cubic-bezier(0.215, 0.61, 0.355, 1) both;
}

/* ------------------------------------------------------------------------------
 * 3. 延迟映射
 *    HTML 的 data-aos-delay 取值集合为 100~1400（步长 100），共 14 档。
 *    为保持错落感同时不让内容等太久，按约 1/4 压缩。
 *    说明：这里必须逐档列出 —— CSS 无法把属性值做算术运算。
 * ---------------------------------------------------------------------------- */
[data-aos-delay="100"] { animation-delay: 25ms; }
[data-aos-delay="200"] { animation-delay: 50ms; }
[data-aos-delay="300"] { animation-delay: 75ms; }
[data-aos-delay="400"] { animation-delay: 100ms; }
[data-aos-delay="500"] { animation-delay: 125ms; }
[data-aos-delay="600"] { animation-delay: 150ms; }
[data-aos-delay="700"] { animation-delay: 175ms; }
[data-aos-delay="800"] { animation-delay: 200ms; }
[data-aos-delay="900"] { animation-delay: 225ms; }
[data-aos-delay="1000"] { animation-delay: 250ms; }
[data-aos-delay="1100"] { animation-delay: 275ms; }
[data-aos-delay="1200"] { animation-delay: 300ms; }
[data-aos-delay="1300"] { animation-delay: 325ms; }
[data-aos-delay="1400"] { animation-delay: 350ms; }

/* under-construction.html 使用 data-aos-duration="1000"，做一次兼容映射 */
[data-aos][data-aos-duration="1000"] { animation-duration: 0.8s; }

/* ------------------------------------------------------------------------------
 * 4. 首屏关键元素不做延迟
 *    H1 与 hero 副标题是首屏信息主体，任何延迟都会削弱 LCP 观感。
 *    （其父级 .hero-section 内的元素若带 delay，在此清零。）
 * ---------------------------------------------------------------------------- */
.hero-section [data-aos-delay] {
  animation-delay: 0ms;
}

/* 导航栏位于 fixed 定位，位移类动画会让 logo 有"下坠"感；改为纯淡入更稳。 */
#mainNavbar [data-aos] {
  animation-name: qy-enter-fade;
  animation-duration: 0.5s;
}

/* ==============================================================================
 * 7. 观感增强（2026-10-14）
 * 目标：解决"删掉 GSAP 后显得生硬"的问题 —— 全部用纯 CSS3 完成，
 *      不引入任何 JS 依赖，因此不影响 SEO/GEO（无 JS 时同样可见）。
 * ============================================================================== */

/* ------------------------------------------------------------------------------
 * 7.1 卡片组交错入场
 *      原先 4 张服务卡/优势卡各自带 data-aos-delay（100/200/…），
 *      但 delay 值偏小且步进均匀，视觉上接近"同时出现"，缺少层次。
 *      这里用 nth-child 让同组卡片依次错开，形成明确的序列感。
 *      注意：只在【入场】时用 animation-delay 影响一次，
 *      动画结束后 fill-mode:both 保留终态，不影响 hover 等后续交互。
 * ---------------------------------------------------------------------------- */
.services-grid > .service-card:nth-child(1) { animation-delay: 60ms; }
.services-grid > .service-card:nth-child(2) { animation-delay: 140ms; }
.services-grid > .service-card:nth-child(3) { animation-delay: 220ms; }
.services-grid > .service-card:nth-child(4) { animation-delay: 300ms; }

.advantages-grid > .advantage-card:nth-child(1) { animation-delay: 60ms; }
.advantages-grid > .advantage-card:nth-child(2) { animation-delay: 140ms; }
.advantages-grid > .advantage-card:nth-child(3) { animation-delay: 220ms; }
.advantages-grid > .advantage-card:nth-child(4) { animation-delay: 300ms; }

.values-grid > .value-item:nth-child(1) { animation-delay: 60ms; }
.values-grid > .value-item:nth-child(2) { animation-delay: 130ms; }
.values-grid > .value-item:nth-child(3) { animation-delay: 200ms; }
.values-grid > .value-item:nth-child(4) { animation-delay: 270ms; }

.about-stats > .stat-item:nth-child(1) { animation-delay: 80ms; }
.about-stats > .stat-item:nth-child(2) { animation-delay: 160ms; }
.about-stats > .stat-item:nth-child(3) { animation-delay: 240ms; }
.about-stats > .stat-item:nth-child(4) { animation-delay: 320ms; }

.about-highlights > .highlight-item:nth-child(1) { animation-delay: 60ms; }
.about-highlights > .highlight-item:nth-child(2) { animation-delay: 140ms; }
.about-highlights > .highlight-item:nth-child(3) { animation-delay: 220ms; }

/* ------------------------------------------------------------------------------
 * 7.2 卡片入场后的"落定"质感
 *      位移到位后加一个极轻微的缩放回落（1.008 → 1），
 *      让元素看起来是"落下来"而不是"滑过来"。幅度必须很小，
 *      否则连续 4 张卡同时回弹会显得廉价。
 * ---------------------------------------------------------------------------- */
@keyframes qy-settle {
  from { transform: scale(1.012); }
  to { transform: scale(1); }
}

.services-grid > .service-card,
.advantages-grid > .advantage-card {
  /* 两段动画串联：先入场位移，再轻微落定 */
  animation-name: qy-enter-up, qy-settle;
  animation-duration: 0.68s, 0.28s;
  animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1), ease-out;
  animation-fill-mode: both, both;
}

/* 上面用了双动画，需为这两类卡片重新声明各自的 delay（两段同步） */
.services-grid > .service-card:nth-child(1),
.advantages-grid > .advantage-card:nth-child(1) { animation-delay: 60ms, 560ms; }
.services-grid > .service-card:nth-child(2),
.advantages-grid > .advantage-card:nth-child(2) { animation-delay: 140ms, 640ms; }
.services-grid > .service-card:nth-child(3),
.advantages-grid > .advantage-card:nth-child(3) { animation-delay: 220ms, 720ms; }
.services-grid > .service-card:nth-child(4),
.advantages-grid > .advantage-card:nth-child(4) { animation-delay: 300ms, 800ms; }

/* ------------------------------------------------------------------------------
 * 7.3 图片淡入（避免图片"啪"地出现）
 *      纯 CSS：图片加载完成前不显示，完成后淡入。
 *      仅对首屏外、带 lazy 的图片生效，避免影响 LCP 图（hero 背景）。
 * ---------------------------------------------------------------------------- */
@keyframes qy-img-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.about-image img,
.contact-item img,
.clients-cloud-wrapper img {
  animation: qy-img-in 0.6s ease-out both;
}

/* LCP 候选图（hero 背景）绝不加动画：会推迟绘制、直接劣化 LCP */
.hero-bg-image,
.hero-section img {
  animation: none !important;
}

/* ------------------------------------------------------------------------------
 * 7.4 导航链接 hover 下划线
 *      ⚠️ 注意：style.css 中已存在 .nav-link::after 的下划线实现
 *      （linear-gradient 渐变条 + .active 常驻），实测原本就工作正常。
 *      为避免重复定义互相覆盖，此处【不再重写】，仅补充原实现缺失的
 *      hover 过渡缓动，使下划线展开更顺滑。
 * ---------------------------------------------------------------------------- */
.navbar-nav .nav-link::after {
  transition: width 0.28s cubic-bezier(0.215, 0.61, 0.355, 1),
              opacity 0.28s ease-out;
}

/* ------------------------------------------------------------------------------
 * 7.5 主 CTA 按钮的流光扫过
 *      用 ::before 做一条斜向高光，hover 时从左扫到右。
 *      overflow:hidden 保证高光不溢出圆角。
 * ---------------------------------------------------------------------------- */
.btn-primary.hero-btn-primary,
.services-cta,
.contact-btn,
.form-submit .btn {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

@keyframes qy-shine {
  from { transform: translateX(-130%) skewX(-18deg); }
  to { transform: translateX(230%) skewX(-18deg); }
}

.btn-primary.hero-btn-primary::before,
.services-cta::before,
.contact-btn::before,
.form-submit .btn::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 42%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.38), transparent);
  transform: translateX(-130%) skewX(-18deg);
  pointer-events: none;
  z-index: 1;
  opacity: 0;
}

.btn-primary.hero-btn-primary:hover::before,
.services-cta:hover::before,
.contact-btn:hover::before,
.form-submit .btn:hover::before {
  opacity: 1;
  animation: qy-shine 0.75s ease-out;
}

/* ------------------------------------------------------------------------------
 * 7.6 统计数字的"呼吸"高亮
 *      数字计数由 main.js 负责（GSAP 已移除后走 else 分支直接赋值），
 *      这里只给最终数字加一层不易察觉的强调，避免计数完成的瞬间过于突兀。
 * ---------------------------------------------------------------------------- */
@keyframes qy-stat-pop {
  0% { transform: scale(1); }
  45% { transform: scale(1.06); }
  100% { transform: scale(1); }
}

.about-stats .stat-number.counting {
  animation: qy-stat-pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

/* ------------------------------------------------------------------------------
 * 7.7 客户词云兜底列表的入场（仅无 JS 时出现，见 index.html noscript）
 * ---------------------------------------------------------------------------- */
.clients-fallback-list li {
  animation: qy-enter-up 0.5s cubic-bezier(0.215, 0.61, 0.355, 1) both;
}

.clients-fallback-list li:nth-child(1) { animation-delay: 20ms; }
.clients-fallback-list li:nth-child(2) { animation-delay: 40ms; }
.clients-fallback-list li:nth-child(3) { animation-delay: 60ms; }
.clients-fallback-list li:nth-child(4) { animation-delay: 80ms; }
.clients-fallback-list li:nth-child(5) { animation-delay: 100ms; }
.clients-fallback-list li:nth-child(6) { animation-delay: 120ms; }
.clients-fallback-list li:nth-child(n+7) { animation-delay: 140ms; }

/* ------------------------------------------------------------------------------
 * 5. 无障碍：尊重"减少动态效果"偏好
 *    直接关闭动画。此时 keyframes 里的 opacity:0 不再生效
 *    （动画被移除后元素回到自身静态样式），内容立即可见。
 * ---------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  [data-aos],
  [data-aos][data-aos-duration="1000"],
  .services-grid > .service-card,
  .advantages-grid > .advantage-card,
  .values-grid > .value-item,
  .about-stats > .stat-item,
  .about-highlights > .highlight-item,
  .about-image img,
  .contact-item img,
  .clients-cloud-wrapper img,
  .clients-fallback-list li,
  .about-stats .stat-number.counting {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .navbar-nav .nav-link::after {
    transition: none !important;
  }
}

/* ------------------------------------------------------------------------------
 * 6. 打印：不播放动画，确保打印输出含完整内容
 * ---------------------------------------------------------------------------- */
@media print {
  [data-aos] {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}
