/* dpg-feel.css — 関所B の試作（2026-10-15 Cowork）。dpg-guide.css の決まり（トークン）を使う。
   T4 案2「4段で弾む」＝答えたときの手応え。値は関所A の見本（gateA/T4_見本.html の案2）と同じ。
     押した … 70ms 沈む（縦 0.94・横 1.02）→ 離して 120ms 少し行き過ぎて戻る
     止め   … 離してから 60ms（正誤の色・✓✕・判定の行をまだ出さない）
     決め   … 正解: 押した所から緑が広がる 240ms ＋ ✓ のスタンプ 180ms ＋ 問題のカードが縦に2回うなずく 240ms
               不正解: ✕ のスタンプ ＋ 横に1回だけ 4px 160ms。正解の肢は 120ms あとに緑
     余韻   … 正解の緑が 240ms で引いて今の色に着地。何も止めない（「次へ」はいつでも押せる。pointer-events には触らない）
   ほかに: 進みの線が伸びて少し行き過ぎて戻る 260ms／結果の数字の数え上げ 600ms／満点の演出の前の溜め 300ms（dpg-feel.js）。
   クラス（dpg-fx-*）は assets/dpg-feel.js が、答えた直後の描き直しにだけ付ける（同じ問題の描き直しでは付け直さない。
   動きの途中で描き直されたときだけ、負の animation-delay で途中から続ける）。
   ★ 色は直書きしない ★ 決めの後の色は今の .qz-choice--correct / --wrong / --dim のまま。ここに書くのは「決めの前の色」
     （押した肢＝--accent・--accent-soft、ほかの肢＝押す前の色。dpg-feel.js が押した瞬間に読んで --fx-n-* に入れる）
     からの動きだけで、keyframes の to を書かない（＝今の色へ向かう）。例外は、緑が広がる間だけ下の面を紫に保つ
     dpg-fx-hit の背景（広がり切った時点で今の色に替わる）。
   ★ 動きを減らす設定（prefers-reduced-motion: reduce）では何も動かさない ★ dpg-feel.js がクラスを付けず、決めの状態
     （色・✓✕・文字・最終の数字）がすぐ出る。念のため、このファイルの最後でも止める。 */
:root {
  --fx-press: 70ms;      /* 押して沈む */
  --fx-release: 120ms;   /* 離して戻る（少し行き過ぎる） */
  --fx-hold: 60ms;       /* 正誤を出す前の止め（dpg-feel.js が読む） */
  --fx-wipe: 240ms;      /* 正解: 押した所から緑が広がる */
  --fx-wash-out: 240ms;  /* 正解: 広がった緑が今の面の色へ引いていく（余韻） */
  --fx-stamp: 180ms;     /* ✓✕ のスタンプ */
  --fx-nod: 240ms;       /* 正解: 問題のカードが縦に2回うなずく */
  --fx-nudge: 160ms;     /* 不正解: 横に1回だけ動く */
  --fx-late: 120ms;      /* 不正解のとき、正解の肢が緑になるまでの遅れ */
  --fx-fade: 120ms;      /* 色が今の色へ戻る・判定の行が出る */
  --fx-bar: 260ms;       /* 進みの線（dpg-feel.js が読む） */
  --fx-count: 600ms;     /* 結果の数字の数え上げ（dpg-feel.js が読む） */
  --fx-charge: 300ms;    /* 満点の演出の前の溜め（dpg-feel.js が読む） */
  --fx-spring: cubic-bezier(.34, 1.56, .64, 1);  /* 少し行き過ぎて戻る */
  --fx-pop: cubic-bezier(.2, .9, .3, 1.4);        /* スタンプ */
}

/* --- 押した: 沈む → 離して戻る --------------------------------------------------------------
   沈むのは :active の間（指・マウスを押している間）。押した瞬間に面の色も返す（C-12）。
   離すと 120ms で少し行き過ぎて戻る。答えると画面ごと作り直されるので、作り直した後の同じ肢は
   dpg-fx-release（キーで押したときは dpg-fx-tap＝沈んで戻るまで）で続きを動かす。 */
#app .qz-choice {
  transition: background-color var(--dur, 280ms) var(--ease-out, ease-out),
    border-color var(--dur, 280ms) var(--ease-out, ease-out),
    opacity var(--dur, 280ms) var(--ease-out, ease-out),
    transform var(--fx-release) var(--fx-spring);
}
#app .qz-choice:not(:disabled):active {
  transform: scale(1.02, .94);
  background-color: var(--accent-soft);
  border-color: var(--accent);
  transition-duration: var(--fx-press);
  transition-timing-function: ease-out;
}
/* 構え: 離してから作り直されるまで（答えの保存を待つ間。端末によって数十〜百数十 ms）、押した肢は押した色のまま。
   これが無いと、離した瞬間に白へ戻りかけてから、作り直した後の「止め」の紫へまた戻る（ちらつく）。
   素早いタップ（沈み切る 70ms より前に離す）でも、離した瞬間に紫にする（色の補間は待たない）。戻りの弾み（transform）はそのまま。 */
#app .qz-choice.dpg-fx-armed {
  background-color: var(--accent-soft);
  border-color: var(--accent);
  transition: transform var(--fx-release) var(--fx-spring);
}

/* 1つの肢に付く動きは3本まで（1: 押した・2: 色・3: 横の揺れ）。どれも付かない枠は none。 */
#app .qz-choice.dpg-fx {
  animation: var(--fx-a1, none), var(--fx-a2, none), var(--fx-a3, none);
}
#app .qz-choice.dpg-fx-release {
  --fx-a1: dpg-fx-release var(--fx-release) cubic-bezier(.34, 1.56, .64, 1) var(--fx-rel, 0ms) backwards;
}
#app .qz-choice.dpg-fx-tap {
  --fx-a1: dpg-fx-tap calc(var(--fx-press) + var(--fx-release)) linear var(--fx-rel, 0ms) backwards;
}
@keyframes dpg-fx-release {
  from { transform: scale(var(--fx-sx, 1.02), var(--fx-sy, .94)); }
  to { transform: none; }
}
/* キーで押したとき（1〜4 など）: 押した瞬間から 70ms 沈み、120ms で行き過ぎて戻る（70/190 ≒ 36.8%） */
@keyframes dpg-fx-tap {
  0% { transform: none; animation-timing-function: ease-out; }
  36.8% { transform: scale(1.02, .94); animation-timing-function: cubic-bezier(.34, 1.56, .64, 1); }
  100% { transform: none; }
}

/* --- 止め → 決め -----------------------------------------------------------------------------
   --fx-dec は「決め」までの残り（止めの残り。描き直しの途中から続けるときは負）。
   fill は backwards だけ: 止めの間は from（決めの前の色）を見せ、終わったら何も残さない（今の色に戻る）。 */

/* 正解の押した肢: 止めの間は紫（押した色）。決めで押した所から緑が広がり（下の ::before）、広がり切ったら
   下の面は今の色に替わり、緑はそのまま 240ms で引いていく（余韻）。今の紙のテーマは正解の肢の面が白
   （theme-dpg.css の .qz-choice の背景が後から効く）なので、緑を残すと描き直しのときに急に消える。引かせて
   今の色（緑の縁・✓・「正解」）に着地させる。面を緑にする CSS が入った場合は、引いても同じ色なので見えない。 */
#app .qz-choice.dpg-fx-hit {
  --fx-a2: dpg-fx-hit var(--fx-wipe) linear var(--fx-dec, 0ms) backwards;
  position: relative;
  isolation: isolate;
}
@keyframes dpg-fx-hit {
  from { background-color: var(--accent-soft); border-color: var(--accent); color: var(--text); }
  to { background-color: var(--accent-soft); }
}
/* 緑の広がり（--success を薄くした --success-soft）。文字の下に敷く（isolation と z-index:-1）。
   広がる 240ms（clip-path の円）→ 引く 240ms（opacity）。終わると opacity 0 に戻り、何も残らない。 */
#app .qz-choice.dpg-fx-hit::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--success-soft);
  opacity: 0;
  pointer-events: none;
  animation: dpg-fx-wipe var(--fx-wipe) ease-out var(--fx-dec, 0ms) backwards,
    dpg-fx-wash-out var(--fx-wash-out) ease-in-out calc(var(--fx-dec, 0ms) + var(--fx-wipe)) backwards;
}
@keyframes dpg-fx-wipe {
  from { opacity: 1; clip-path: circle(0px at var(--fx-x, 50%) var(--fx-y, 50%)); }
  to { opacity: 1; clip-path: circle(150% at var(--fx-x, 50%) var(--fx-y, 50%)); }
}
@keyframes dpg-fx-wash-out {
  from { opacity: 1; }
  to { opacity: 0; }
}

/* 不正解の押した肢: 止めの間は紫。決めで今の色（赤）へ 120ms、横に1回だけ 4px（責めない）。 */
#app .qz-choice.dpg-fx-miss {
  --fx-a2: dpg-fx-miss var(--fx-fade) ease-out var(--fx-dec, 0ms) backwards;
  --fx-a3: dpg-fx-nudge var(--fx-nudge) ease-out var(--fx-dec, 0ms) backwards;
}
@keyframes dpg-fx-miss {
  from { background-color: var(--accent-soft); border-color: var(--accent); color: var(--text); }
}
@keyframes dpg-fx-nudge {
  0% { translate: 0 0; }
  40% { translate: 4px 0; }
  100% { translate: 0 0; }
}

/* 正解だが押していない肢（不正解・わからないのとき）: 押す前の色のまま、決めの 120ms あとに緑へ。 */
#app .qz-choice.dpg-fx-late {
  --fx-a2: dpg-fx-late var(--fx-fade) ease-out calc(var(--fx-dec, 0ms) + var(--fx-late)) backwards;
}
@keyframes dpg-fx-late {
  from { background-color: var(--fx-n-bg, var(--surface)); border-color: var(--fx-n-bd, var(--separator)); color: var(--fx-n-fg, var(--text)); }
}

/* ほかの肢: 止めの間は押す前の濃さ、決めで今の薄さへ。 */
#app .qz-choice.dpg-fx-dim {
  --fx-a2: dpg-fx-dim var(--fx-fade) ease-out var(--fx-dec, 0ms) backwards;
}
@keyframes dpg-fx-dim {
  from { opacity: 1; }
}

/* ✓✕ のスタンプ（1.6 倍・透明 → 等倍）と、「正解」「不正解」の文字。遅れて緑になる肢はその時に合わせる。
   結論のカード（[data-role=conclusion]。答えた後の画面の担当が作る）の中の印は data-feel="stamp" を付ければ同じく押される。 */
#app .dpg-fx-hit .qz-choice__icon,
#app .dpg-fx-miss .qz-choice__icon,
#app .qz-verdict.dpg-fx-appear .qz-verdict__icon,
#app .dpg-fx-stamp {
  animation: dpg-fx-stamp var(--fx-stamp) var(--fx-pop) var(--fx-dec, 0ms) backwards;
}
#app .dpg-fx-late .qz-choice__icon {
  animation: dpg-fx-stamp var(--fx-stamp) var(--fx-pop) calc(var(--fx-dec, 0ms) + var(--fx-late)) backwards;
}
@keyframes dpg-fx-stamp {
  from { scale: 1.6; opacity: 0; }
  to { scale: 1; opacity: 1; }
}
#app .dpg-fx-hit .qz-choice__status,
#app .dpg-fx-miss .qz-choice__status,
#app .qz-verdict.dpg-fx-appear {
  animation: dpg-fx-appear var(--fx-fade) ease-out var(--fx-dec, 0ms) backwards;
}
#app .dpg-fx-late .qz-choice__status {
  animation: dpg-fx-appear var(--fx-fade) ease-out calc(var(--fx-dec, 0ms) + var(--fx-late)) backwards;
}
@keyframes dpg-fx-appear {
  from { opacity: 0; }
}

/* 正解: 問題のカードが縦に小さく2回うなずく（0 → 3px → -1px → 0）。 */
#app .qz-question.dpg-fx-nod {
  animation: dpg-fx-nod var(--fx-nod) ease-out var(--fx-dec, 0ms) backwards;
}
@keyframes dpg-fx-nod {
  0% { translate: 0 0; }
  30% { translate: 0 3px; }
  60% { translate: 0 -1px; }
  100% { translate: 0 0; }
}

/* --- 結果の数字の数え上げ（dpg-feel.js） ------------------------------------------------------
   見える数字（aria-hidden）は数え上げ、読み上げには最後の数字（.dpg-fx-sr・見えない）を最初から渡す。
   幅は最後の数字の桁で固定し、数えている間に「/」の位置が動かないようにする。終わったら元の文字に戻す。 */
#app .dpg-fx-count {
  display: inline-block;
  text-align: right;
}
#app .dpg-fx-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --- 満点の演出の前の溜め（dpg-feel.js の DpgFeel.charge。app.js の celebrate が呼ぶ） ------------
   300ms で画面が少し暗くなり、そこへ今の演出（.qz-fanfare。同じ z-index で後から body に載る）が重なって解放。
   色は演出の幕と同じ --qz-fx-scrim。押す操作は止めない（pointer-events: none）。 */
.dpg-fx-charge {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: var(--qz-fx-scrim, var(--text));
  opacity: 0;
  pointer-events: none;
  animation: dpg-fx-charge var(--fx-charge) ease-in forwards;
}
.dpg-fx-charge--out {
  animation: dpg-fx-charge-out 240ms ease-out forwards;
}
@keyframes dpg-fx-charge {
  from { opacity: 0; }
  to { opacity: .4; }
}
@keyframes dpg-fx-charge-out {
  from { opacity: .4; }
  to { opacity: 0; }
}

/* --- 動きを減らす: 補間・揺れ・溜め・数え上げを全部止める（dpg-feel.js もクラスを付けない。ここは念のため） --- */
@media (prefers-reduced-motion: reduce) {
  #app .qz-choice,
  #app .qz-choice:not(:disabled):active { transform: none; transition: none; }
  #app .dpg-fx,
  #app .dpg-fx::before,
  #app .dpg-fx *,
  #app .dpg-fx-appear,
  #app .dpg-fx-appear *,
  #app .dpg-fx-nod,
  #app .dpg-fx-stamp { animation: none !important; }
  #app .qz-choice.dpg-fx-hit::before { content: none; }
  .dpg-fx-charge { display: none; }
}
