/* ============================================================
   Code-Wanderer — 动画关键帧
   ============================================================ */

@keyframes blink { 0%,100%{opacity:1} 50%{opacity:0} }
@keyframes fadeIn { from{opacity:0} to{opacity:1} }
@keyframes fadeOut { from{opacity:1} to{opacity:0} }
@keyframes slideUp { from{transform:translateY(40px);opacity:0} to{transform:translateY(0);opacity:1} }
@keyframes slideDown { from{transform:translateY(-40px);opacity:0} to{transform:translateY(0);opacity:1} }
@keyframes neon-pulse { 0%,100%{box-shadow:0 0 10px var(--color-primary-glow)} 50%{box-shadow:0 0 25px var(--color-primary-glow),0 0 50px rgba(0,240,255,0.2)} }
@keyframes breathe { 0%,100%{opacity:0.6} 50%{opacity:1} }

@keyframes glitch-in {
  0%{opacity:0;transform:translate(-50%,-48%) skewX(2deg);clip-path:inset(0 0 100% 0)}
  20%{opacity:1;transform:translate(-52%,-52%) skewX(-1deg);clip-path:inset(0 0 0 0)}
  40%{transform:translate(-48%,-50%) skewX(1deg)}
  100%{opacity:1;transform:translate(-50%,-50%) skewX(0);clip-path:inset(0 0 0 0)}
}

@keyframes scanline { 0%{top:-2px} 100%{top:100%} }

@keyframes success-flash {
  0%{background:transparent}
  20%{background:rgba(0,240,255,0.12)}
  100%{background:transparent}
}

@keyframes achievement-pulse {
  0%{transform:translate(-50%,-50%) scale(1)}
  50%{transform:translate(-50%,-50%) scale(1.05)}
  100%{transform:translate(-50%,-50%) scale(1)}
}

@keyframes node-pulse {
  0%,100%{box-shadow:0 0 15px var(--color-gold-glow)}
  50%{box-shadow:0 0 30px var(--color-gold-glow),0 0 60px rgba(255,204,0,0.2)}
}

@keyframes side-mission-glimmer {
  0%,100%{box-shadow:0 0 5px var(--color-gold-glow)}
  50%{box-shadow:0 0 20px var(--color-gold-glow),0 0 40px rgba(255,204,0,0.15)}
}

@keyframes bounce-in {
  0%{transform:scale(0.3);opacity:0}
  50%{transform:scale(1.05)}
  70%{transform:scale(0.95)}
  100%{transform:scale(1);opacity:1}
}

@keyframes spin { from{transform:rotate(0deg)} to{transform:rotate(360deg)} }

/* ============================================================
   角色立绘动画（视觉小说式站位）
   ============================================================ */

/* 说话者浮动 */
@keyframes portrait-float {
  0%,100%{transform:translateY(0)}
  50%{transform:translateY(-5px)}
}
/* 全息呼吸（底座/身体层透明度起伏） */
@keyframes holo-breathe {
  0%,100%{opacity:0.45}
  50%{opacity:0.8}
}
/* 核心脉冲 */
@keyframes core-pulse {
  0%,100%{transform:scale(1);opacity:0.75}
  50%{transform:scale(1.18);opacity:1}
}
/* 新 NPC 扫描入场（clip-path 自下而上扫出，不与浮动 transform 冲突） */
@keyframes portrait-scan-in {
  0%{clip-path:inset(100% 0 0 0);opacity:0.15}
  55%{clip-path:inset(0 0 0 0);opacity:1}
  100%{clip-path:inset(0 0 0 0);opacity:1}
}
/* 旧 NPC 故障退场 */
@keyframes portrait-glitch-out {
  0%{opacity:1;transform:translate(0)}
  25%{opacity:0.4;transform:translate(3px,-2px) skewX(4deg)}
  50%{opacity:0.8;transform:translate(-3px,1px)}
  75%{opacity:0.3;transform:translate(2px,2px) skewX(-3deg)}
  100%{opacity:0;transform:translate(0)}
}
/* VOID 消散（遗言后数据化分解） */
@keyframes portrait-dissolve {
  0%{opacity:1;clip-path:inset(0 0 0 0)}
  30%{opacity:0.9;transform:translate(2px,-2px) skewX(2deg);clip-path:inset(0 0 12% 0)}
  60%{opacity:0.55;transform:translate(-2px,-14px);clip-path:inset(8% 0 40% 0)}
  100%{opacity:0;transform:translate(0,-34px);clip-path:inset(60% 0 80% 0)}
}
/* VOID 间歇故障抖动（常态低频） */
@keyframes void-jitter {
  0%,92%,100%{transform:translate(0,0)}
  93%{transform:translate(2px,-1px) skewX(2deg)}
  95%{transform:translate(-2px,1px)}
  97%{transform:translate(1px,1px) skewX(-1deg)}
}
/* VOID 高频冲击抖动（void-shock 特效期间） */
@keyframes void-shock-jitter {
  0%,100%{transform:translate(0,0)}
  25%{transform:translate(3px,-2px)}
  50%{transform:translate(-3px,2px)}
  75%{transform:translate(2px,1px)}
}
/* VOID 裂纹透光脉冲 */
@keyframes crack-pulse {
  0%,100%{stroke-opacity:0.5}
  50%{stroke-opacity:1}
}
/* 数据剥落粒子 */
@keyframes peel-fall {
  0%{opacity:0.9;transform:translate(0,0)}
  100%{opacity:0;transform:translate(var(--tx,0px),var(--ty,-50px))}
}
/* 动漫眨眼（大眼周期性闭眼） */
@keyframes anime-blink {
  0%,92%,100%{transform:scaleY(1)}
  95%{transform:scaleY(0.08)}
  97%{transform:scaleY(1)}
}
/* NEXUS 悬浮浮动（Q版全息 AI 专属） */
@keyframes nexus-float {
  0%,100%{transform:translateY(0)}
  50%{transform:translateY(-6px)}
}
