/* ==========================================================================
   FinLearn 动效与视觉表现层（Motion & Expression）
   --------------------------------------------------------------------------
   设计取舍：内容是学术的，但界面不该沉闷。
   * 视觉张力：暖色网格底纹 + 顶部墨蓝→金渐变压边 + 关键词渐变字
   * 动效纪律：只用"入场 + 状态反馈"两类，时长 200—700ms，绝不循环干扰阅读
   * 无障碍：全部动效在 prefers-reduced-motion 下关闭；数字动画保留终值
   ========================================================================== */

/* ---------------------------- 1. 背景与氛围 ---------------------------- */
/* v3：白底为主，仅加极淡的冷色氛围，避免米色墙的旧问题 */
body {
  background-color: var(--bg);
  background-image:
    radial-gradient(1100px 520px at 88% -10%, rgba(83, 58, 253, 0.05), transparent 62%),
    radial-gradient(800px 420px at 4% 2%, rgba(6, 27, 49, 0.035), transparent 60%);
  background-repeat: no-repeat;
}

/* ---------------------------- 3. 入场动效 ---------------------------- */
@keyframes rise-in {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes slide-right {
  from { opacity: 0; transform: translateX(-14px); }
  to   { opacity: 1; transform: translateX(0); }
}

@keyframes pop-in {
  0%   { opacity: 0; transform: scale(0.94); }
  62%  { opacity: 1; transform: scale(1.015); }
  100% { opacity: 1; transform: scale(1); }
}

@keyframes draw-rule {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* 统一入场节奏：靠 CSS 变量控制延迟，避免每个元素写一遍 animation */
/* 注意：基类不再直接写 opacity:0。
   否则一旦 .is-settled 或任何规则覆盖了 animation，元素会回落到 0 而永久不可见
   （首页首屏曾出现整段标题消失）。初态改由下方 @supports 块提供。 */
[data-anim] {
  animation-duration: 620ms;
  animation-timing-function: cubic-bezier(0.22, 0.61, 0.36, 1);
  animation-fill-mode: forwards;
  animation-delay: var(--anim-delay, 0ms);
}

[data-anim="rise"]   { animation-name: rise-in; }
[data-anim="fade"]   { animation-name: fade-in; }
[data-anim="slide"]  { animation-name: slide-right; }
[data-anim="pop"]    { animation-name: pop-in; }

/* hero 区的装饰压边：从中间向两侧展开 */

/* ---------------------------- 4. 滚动揭示 ---------------------------- */
.reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 560ms cubic-bezier(0.22, 0.61, 0.36, 1),
              transform 560ms cubic-bezier(0.22, 0.61, 0.36, 1);
  transition-delay: var(--reveal-delay, 0ms);
}

.reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* 已经滚过的元素不要再重复动画（避免回滚时闪动） */
.reveal.is-settled { transition: none; }

/* ---------------------------- 5. 数字滚动 ---------------------------- */
.countup {
  font-variant-numeric: tabular-nums;
  /* 数字宽度固定，滚动时不会抖动整行 */
}

/* ---------------------------- 6. 卡片与按钮的动效反馈 ---------------------------- */
.card,
.stat,
.viz,
.org-node,
.board-card {
  transition: transform 240ms cubic-bezier(0.22, 0.61, 0.36, 1),
              box-shadow 240ms cubic-bezier(0.22, 0.61, 0.36, 1),
              border-color 240ms var(--ease-out);
}

.card--interactive:hover,
.card--interactive:focus-visible {
  box-shadow: var(--shadow-md);
  border-color: var(--color-border-strong);
}

.stat:hover {
  transform: translateY(-2px);
  border-color: var(--gold-300);
}

.stat:hover .stat__value {
  margin-bottom: var(--space-2);
  color: var(--ink-700);
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 2.4vw, 2.25rem);
  font-weight: var(--weight-black);
  line-height: 1.1;
  letter-spacing: -0.02em;
}

@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) .stat__value { color: var(--gold-300); }
}
html[data-theme="dark"] .stat__value { color: var(--gold-300); }

.stat__hint {
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  line-height: var(--leading-snug);
}

/* ---------- ③ 功能卡：统一 2px 顶线建立秩序 ---------- */
.grid > .card {
  position: relative;
  border-top: 2px solid var(--ink-700);
}

.grid > .card:hover {
  border-top-color: var(--gold-600);
  box-shadow: 0 10px 24px rgba(26, 23, 18, 0.09);
  transform: translateY(-2px);
}

.card__title {
  color: var(--color-heading);
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
}

.card ul li::marker { color: var(--gold-500); }

/* ---------- ④ 浅色区块底色收紧 ---------- */
.section--tinted {
  background: linear-gradient(180deg, var(--paper-050) 0%, #ffffff 100%);
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
}

/* ==========================================================================
   关键修正：入场动画的初态必须兜底可见
   --------------------------------------------------------------------------
   问题：入场动画把 [data-anim] 的初态设为 opacity:0，
        若动画因任何原因未触发（脚本未执行、CSP 拦截、浏览器差异），
        页面文字会永久透明 —— 首页首屏实测出现过整段标题不可见。
   做法：初态改为「仅在支持动画且允许动效时」才隐藏；
        并给不支持 animation 的环境直接置为可见（@supports 兜底）。
   ========================================================================== */
@supports not (animation-name: none) {
  [data-anim], .reveal { opacity: 1 !important; transform: none !important; }
}

@media (prefers-reduced-motion: reduce) {
  [data-anim], .reveal { opacity: 1 !important; transform: none !important; animation: none !important; }
}

/* 动画结束后保持终态，不回到初态 */
[data-anim].is-settled, .reveal.is-settled { opacity: 1; transform: none; }

/* ==========================================================================
   入场动画的正确写法（修复首屏文字永久透明的根因）
   --------------------------------------------------------------------------
   现象：首页首屏标题、正文、按钮、右侧产品预览全部不可见（透明度不是 1）。
   根因：基类写了 opacity: 0，靠 animation-fill-mode: forwards 撑到终态；
        但 motion.js 在动画结束后加了 .is-settled { opacity: 1; transform: none }，
        这条普通声明会取消动画，元素随即回落到基类的 opacity: 0 —— 永久透明。

   修法（三层保障）：
     1. 基类不写 opacity，默认即完全可见（最坏情况也不会消失）
     2. 仅当浏览器支持动画、且用户未要求减少动效时，才把初态设为透明
     3. .is-settled 用与动画终态一致的值，不再抢动画的优先级
   ========================================================================== */
@supports (animation-name: none) {
  @media (prefers-reduced-motion: no-preference) {
    [data-anim]:not(.is-settled):not(.is-visible) {
      opacity: 0;
    }
  }
}

/* 终态：与关键帧 to{} 完全一致，避免取消动画后视觉跳回 */
[data-anim].is-settled,
[data-anim].is-visible,
.reveal.is-settled,
.reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* 动画播放期间保持 forwards 终态 */
[data-anim] { animation-fill-mode: both; }

/* 减少动效 / 不支持动画：直接可见 */
@media (prefers-reduced-motion: reduce) {
  [data-anim], .reveal {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }
}
