  /* ============ animation.css: 複数箇所から共有される汎用keyframes ============ */
  @keyframes screenFadeIn { from { opacity: 0; } to { opacity: 1; } }
  @keyframes logCharFadeIn { from { opacity: 0; } to { opacity: 1; } }
  /* 0.05秒ほど間を置いてから跳ねる(ヒットストップ風の一瞬の間)。跳ね自体も少しオーバーシュートさせて
     弾みを持たせる(爽快感重視、暴れすぎないよう振れ幅は控えめにしてある) */
  @keyframes dmgFloat {
    0% { opacity: 0; transform: translate(-50%, 8px) scale(0.7); }
    5% { opacity: 0; transform: translate(-50%, 8px) scale(0.7); }
    18% { opacity: 1; transform: translate(-50%, -12px) scale(1.3); }
    30% { transform: translate(-50%, -4px) scale(1.02); }
    42% { transform: translate(-50%, -9px) scale(1.12); }
    55% { transform: translate(-50%, -7px) scale(1); }
    100% { opacity: 0; transform: translate(-50%, -42px) scale(1); }
  }
  /* ヒットストップ: シェイク/フラッシュの開始を0.05秒だけ遅らせ、一瞬の「間」を作ってから反応させる。
     .hit-shakeと.hit-flashは常にセットで付与される(shakeClassFor参照)ため、
     両方が同時に付いた状態を1つのセレクタでまとめてanimationプロパティに指定する必要がある。
     .hit-shake単体/.hit-flash単体でそれぞれanimationを宣言すると、同じプロパティを取り合って
     どちらか片方(カスケードで後勝ちした方)しか実際には再生されない不具合があったための修正。
     通常ヒットはhitShakeNormal(振幅/時間ともに基準の0.8倍)、会心/スキル攻撃はhitShakeStrong
     (同1.2倍)を使い分ける(shakeClassForが.hit-shake-normal/.hit-shake-strongを付与する) */
  @keyframes hitFlash {
    0%, 100% { filter: brightness(1); }
    30% { filter: brightness(2.4); }
  }
  .hit-shake.hit-flash.hit-shake-normal {
    animation: hitShakeNormal 144ms ease-in-out 0.05s backwards, hitFlash var(--dw-t-dmg) ease-out 0.05s backwards;
  }
  .hit-shake.hit-flash.hit-shake-strong {
    animation: hitShakeStrong 216ms ease-in-out 0.05s backwards, hitFlash var(--dw-t-dmg) ease-out 0.05s backwards;
  }
  /* 小刻みな振動(以前の数回の大きな横揺れから、細かく素早い振幅の小さい揺れに変更)。基準(1倍)の値 */
  @keyframes hitShakeNormal {
    0%, 100% { transform: translate(0, 0); }
    10% { transform: translate(-2.4px, 0.8px); }
    20% { transform: translate(2.4px, -0.8px); }
    30% { transform: translate(-2.4px, 0.8px); }
    40% { transform: translate(1.6px, -0.8px); }
    50% { transform: translate(-1.6px, 0.8px); }
    60% { transform: translate(1.6px, -0.8px); }
    70% { transform: translate(-0.8px, 0.8px); }
    80% { transform: translate(0.8px, 0); }
    90% { transform: translate(-0.8px, 0); }
  }
  @keyframes hitShakeStrong {
    0%, 100% { transform: translate(0, 0); }
    10% { transform: translate(-3.6px, 1.2px); }
    20% { transform: translate(3.6px, -1.2px); }
    30% { transform: translate(-3.6px, 1.2px); }
    40% { transform: translate(2.4px, -1.2px); }
    50% { transform: translate(-2.4px, 1.2px); }
    60% { transform: translate(2.4px, -1.2px); }
    70% { transform: translate(-1.2px, 1.2px); }
    80% { transform: translate(1.2px, 0); }
    90% { transform: translate(-1.2px, 0); }
  }
  @keyframes pathDimIn { from { opacity: 0; } to { opacity: 1; } }
