/* announce.css — ゲーム中アナウンスの見た目（指示書_アナウンス演出.md）。
   board.css の後に読み込むこと（--stroke-selected-color 等を参照するため）。

   2種類ある。混ぜないこと（指示書 §2）:
     .cutin  … 出来事。1.0〜1.6秒で勝手に消える。画面中央を横断する
     .banner … 状態。続く限り出続ける。#screen-game の中に置く（今の #turn-banner の位置）

   ★アナウンス層は pointer-events:none。盤面のタップを絶対に食わないこと（指示書 §5-1）。 */

:root {
  /* --- カットインの尺。①②③⑤の全長は in + hold + out = 1.0s --- */
  --cutin-in-ms: 260ms;   /* 帯が飛び込む */
  --cutin-hold-ms: 520ms; /* 静止して読ませる */
  --cutin-out-ms: 220ms;  /* 抜ける */

  --cutin-band-h: 26vh;
  --cutin-skew: -4deg;
  --cutin-shake: 6px; /* 画面揺れの振幅 */

  /* --- ④正解！だけ別尺（指示書 §3-4） --- */
  /* ★この4つには守るべき関係がある:
       --correct-fall-delay + 5 * --correct-fall-stagger + --correct-fall-ms <= --correct-ms
     右辺を超えると、一番上の段が落ちきる前にカットインごと消えてポップアップが出る
     （最初これで 1875ms > 1600ms になっていた）。1つ動かしたら必ず足し直すこと。
     現在: 620 + 250 + 700 = 1570 <= 1600 */
  --correct-ms: 1600ms;         /* 全長。これが過ぎてから結果ポップアップを出す */
  --correct-fall-delay: 620ms;  /* 崩れ始めるまで */
  --correct-fall-stagger: 50ms; /* 段ごとの時間差（下の段から落ちる） */
  --correct-fall-ms: 700ms;     /* 1段が落ちきる時間 */
  /* ④の文字の白縁（ユーザー要望・2026-08-21）。★em で持つこと。
     文字は clamp(52px, 22vw, 150px) で3倍近く変わるので、px 固定にすると
     小さい端末で縁だけ太く見え、大きい画面では消える。 */
  --correct-outline: 0.07em;

  --banner-h: 40px;

  /* 盤面で「今まさに抜こうとしている画」と同じ桃色。桃＝緊張、という意味が
     既に画面の中で通っているので、新しい色を増やさない（指示書 §3-3）。 */
  --announce-danger: var(--stroke-selected-color);
}

/* ============================================================
   アナウンス層
   ============================================================ */

#announce {
  position: fixed;
  inset: 0;
  z-index: 170; /* #char-overlay(auto) と #result-overlay(150) の上、#avatar-overlay(200) の下 */
  /* ★これを外さないこと。inset:0 の全画面要素なので、既定のままだと
     カットインが出ている1秒間、盤面のタップが全部死ぬ（指示書 §5-1）。 */
  pointer-events: none;
  overflow: hidden;
}

/* カットインの中身は #app と同じ幅の柱の中に収める。
   こうしておくと、PCの検証で見えている絵とスマホで見える絵が一致する。 */
.cutin-stage {
  position: absolute;
  inset: 0;
  max-width: 480px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ============================================================
   カットイン（①あなたの番／②お題を選べ／③崩しにきた／⑤残念）
   ============================================================ */

.cutin {
  position: absolute;
  inset: 0;
  /* 既定値。kind ごとに .cutin--* が上書きする */
  --band-bg: var(--ink);
  --band-fg: var(--yellow);
  --flash-color: var(--yellow);
  --flash-peak: 0.55;
}

/* --- フラッシュ（帯が止まる瞬間に画面全体を1枚塗る） --- */
.cutin-flash {
  position: absolute;
  inset: 0;
  background: var(--flash-color);
  opacity: 0;
  /* ★forwards にすること（both にしない）。both だと遅延中にも 0% の状態
     （opacity:var(--flash-peak)）が適用され、帯が飛び込んでいる260ms のあいだ
     ずっと画面全体が塗られたままになる。「着地した瞬間に1枚」にならない。 */
  animation: kanje-flash 160ms ease-out var(--cutin-in-ms) forwards;
}

@keyframes kanje-flash {
  0% { opacity: var(--flash-peak); }
  100% { opacity: 0; }
}

/* --- 速度線（帯の背後を逆方向に流れる） --- */
.cutin-speed {
  position: absolute;
  left: -30%;
  right: -30%;
  top: 50%;
  height: calc(var(--cutin-band-h) * 1.7);
  transform: translateY(-50%) skewY(var(--cutin-skew));
  background: repeating-linear-gradient(
    90deg,
    transparent 0 7px,
    var(--band-bg) 7px 9px
  );
  opacity: 0;
  /* 中心を抜いて、両端だけに線が残るようにする（帯の裏で線が透けない） */
  -webkit-mask-image: linear-gradient(90deg, #000 0%, transparent 42%, transparent 58%, #000 100%);
  mask-image: linear-gradient(90deg, #000 0%, transparent 42%, transparent 58%, #000 100%);
  animation: kanje-speed var(--cutin-in-ms) linear both;
}

@keyframes kanje-speed {
  0% { opacity: 0.85; transform: translateY(-50%) translateX(14%) skewY(var(--cutin-skew)); }
  100% { opacity: 0; transform: translateY(-50%) translateX(-10%) skewY(var(--cutin-skew)); }
}

/* --- 帯 --- */
.cutin-band {
  position: absolute;
  left: -6%;
  right: -6%;
  top: 50%;
  height: var(--cutin-band-h);
  margin-top: calc(var(--cutin-band-h) / -2);
  background: var(--band-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  /* ★in と out を2本立てる。out は forwards（both にしないこと）。
     both にすると遅延中に out の開始状態が in を上書きし、帯が最初から居座って見える。 */
  animation:
    kanje-band-in var(--cutin-in-ms) cubic-bezier(0.16, 1.1, 0.3, 1) both,
    kanje-band-out var(--cutin-out-ms) ease-in calc(var(--cutin-in-ms) + var(--cutin-hold-ms)) forwards;
}

@keyframes kanje-band-in {
  0% { transform: translateX(-112%) skewY(var(--cutin-skew)); }
  100% { transform: translateX(0) skewY(var(--cutin-skew)); }
}

@keyframes kanje-band-out {
  0% { transform: translateX(0) skewY(var(--cutin-skew)); opacity: 1; }
  100% { transform: translateX(112%) skewY(var(--cutin-skew)); opacity: 0; }
}

/* --- 文字 --- */
.cutin-text {
  font-family: var(--font-name);
  font-size: clamp(34px, 13vw, 96px);
  line-height: 1.1;
  letter-spacing: 0.08em;
  /* letter-spacing は最後の字の右にも入るので、その分だけ戻して中央に見せる */
  margin-right: -0.08em;
  color: var(--band-fg);
  white-space: nowrap;
  /* ★帯より 60ms 遅らせる。同時に動かすと1枚の絵に見えて、当たった感じが出ない */
  animation: kanje-cutin-text 260ms cubic-bezier(0.16, 1.2, 0.3, 1) 60ms both;
}

@keyframes kanje-cutin-text {
  0% { transform: scale(1.35); opacity: 0; }
  60% { opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* --- ①あなたの番／②お題を選べ: 既定のまま（黒帯・黄文字） --- */

/* --- ③崩しにきた！: 桃の文字。帯が2回明滅してから止まる --- */
.cutin--attack {
  --band-fg: var(--announce-danger);
  --flash-color: var(--announce-danger);
  --flash-peak: 0.8;
}

.cutin--attack .cutin-band {
  animation:
    kanje-band-in var(--cutin-in-ms) cubic-bezier(0.16, 1.1, 0.3, 1) both,
    kanje-band-blink 200ms steps(1, end) var(--cutin-in-ms) 2,
    kanje-band-out var(--cutin-out-ms) ease-in calc(var(--cutin-in-ms) + var(--cutin-hold-ms)) forwards;
}

@keyframes kanje-band-blink {
  0%, 49% { background: var(--band-bg); }
  50%, 100% { background: var(--announce-danger); }
}

/* --- ⑤残念！: 桃の帯・黒文字。フラッシュなし。文字は傾いて踏みとどまる --- */
.cutin--wrong {
  --band-bg: var(--announce-danger);
  --band-fg: var(--ink);
  --flash-peak: 0;
}

.cutin--wrong .cutin-text {
  animation: kanje-cutin-text-tilt 420ms cubic-bezier(0.2, 0.9, 0.3, 1.4) 60ms both;
}

/* 崩れかけて、踏みとどまる（落ちない）。正解＝崩れる との対比 */
@keyframes kanje-cutin-text-tilt {
  0% { transform: scale(1.3) rotate(0deg); opacity: 0; }
  35% { transform: scale(1) rotate(-7deg); opacity: 1; }
  70% { transform: scale(1) rotate(4deg); }
  100% { transform: scale(1) rotate(0deg); opacity: 1; }
}

/* 誤答の文字列を帯の下に小さく添える。抜き手には footer で既に見えている情報 */
.cutin-sub {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(50% + var(--cutin-band-h) / 2 + 10px);
  text-align: center;
  /* バナーと同じ理由（16px は --font-name には小さすぎる） */
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 17px;
  color: var(--ink);
  animation: kanje-cutin-sub 200ms ease-out 200ms both;
}

@keyframes kanje-cutin-sub {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: none; }
}

/* ============================================================
   ④正解！（専用構造。指示書 §3-4）
   ============================================================ */

.cutin--correct {
  --flash-color: var(--yellow);
}

/* 頭の白飛び。帯より前に、遅延なしで出す */
.cutin--correct .cutin-flash {
  background: #fff;
  animation: kanje-correct-flash 340ms ease-out both;
}

@keyframes kanje-correct-flash {
  0% { opacity: 1; }
  30% { opacity: 0.75; }
  100% { opacity: 0; }
}

/* 集中線。回りながら広がる */
.correct-rays {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 210vmax;
  height: 210vmax;
  margin: -105vmax 0 0 -105vmax;
  background: repeating-conic-gradient(
    from 0deg,
    var(--ink) 0deg 2.4deg,
    transparent 2.4deg 9deg
  );
  opacity: 0;
  /* 中心を抜かないと文字が読めない */
  -webkit-mask-image: radial-gradient(circle, transparent 0 16%, #000 42%);
  mask-image: radial-gradient(circle, transparent 0 16%, #000 42%);
  animation: kanje-rays 900ms ease-out 80ms both;
}

@keyframes kanje-rays {
  0% { opacity: 0; transform: rotate(-14deg) scale(0.35); }
  22% { opacity: 0.5; }
  100% { opacity: 0; transform: rotate(10deg) scale(1); }
}

.correct-word {
  position: relative;
  width: 100%;
  height: calc(var(--cutin-band-h) * 1.5);
  animation: kanje-correct-slam 260ms cubic-bezier(0.14, 1.3, 0.3, 1) 80ms both;
}

@keyframes kanje-correct-slam {
  0% { transform: scale(2.4); opacity: 0; }
  55% { opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* ★同じ文字を6枚重ね、clip-path で横に切り分ける。
   1文字ずつ span に割る方法だと「正解！」が横に散るだけで、
   縦に崩れるジェンガの見立てにならない（指示書 §3-4）。 */
.correct-slice {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-name);
  font-size: clamp(52px, 22vw, 150px);
  line-height: 1;
  letter-spacing: 0.04em;
  margin-right: -0.04em;
  color: var(--ink);
  white-space: nowrap;
  /* 白縁（ユーザー要望・2026-08-21）。黄色地に黒文字だと集中線と重なって
     字が沈むので、白で抜いて手前に立たせる。
     ★paint-order: stroke fill を必ず添えること。既定の描画順（fill→stroke）だと
     縁が字の内側を半分食って、Dela Gothic One の太い線が痩せて見える。 */
  -webkit-text-stroke: var(--correct-outline) #fff;
  paint-order: stroke fill;
  /* 6等分した i 段目だけを見せる（16.6667% = 100/6） */
  -webkit-clip-path: inset(calc(var(--i) * 16.6667%) 0 calc((5 - var(--i)) * 16.6667%) 0);
  clip-path: inset(calc(var(--i) * 16.6667%) 0 calc((5 - var(--i)) * 16.6667%) 0);
  /* 下の段から崩れる。落下は board.css の kanje-stroke-fall と同じ ease-in にして、
     盤面で画が抜けて落ちる演出と地続きに見せる（指示書 §3-1）。 */
  animation: kanje-correct-fall var(--correct-fall-ms) ease-in
    calc(var(--correct-fall-delay) + (5 - var(--i)) * var(--correct-fall-stagger)) forwards;
}

@keyframes kanje-correct-fall {
  0% { transform: translateY(0) rotate(0deg); opacity: 1; }
  100% { transform: translateY(120%) rotate(var(--fall-rot, 6deg)); opacity: 0; }
}

/* 段ごとに倒れる向きを変える。1枚の板が落ちるのではなく、崩れて見える */
.correct-slice:nth-child(odd) { --fall-rot: -7deg; }
.correct-slice:nth-child(even) { --fall-rot: 8deg; }

/* ============================================================
   画面揺れ（#app に付ける。announce.js が付け外しする）
   ============================================================ */

/* ★#app に付けること。body に transform を付けてはいけない。
   body に transform が付くと position:fixed の包含ブロックが body になり、
   #announce / #toast / #char-overlay の全画面固定が壊れる。 */
#app.kanje-shake {
  animation: kanje-shake 240ms cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
}

#app.kanje-shake-long {
  animation: kanje-shake 420ms cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
}

@keyframes kanje-shake {
  0%, 100% { transform: translateX(0); }
  12% { transform: translateX(calc(var(--cutin-shake) * -1)); }
  28% { transform: translateX(var(--cutin-shake)); }
  44% { transform: translateX(calc(var(--cutin-shake) * -0.6)); }
  60% { transform: translateX(calc(var(--cutin-shake) * 0.6)); }
  78% { transform: translateX(calc(var(--cutin-shake) * -0.25)); }
}

/* ============================================================
   常設バナー（②' ③' と崩し手側の「画を選んでいます」）
   ============================================================ */

/* ★1本に統合すること。2本並べると、低いウィンドウで footer のボタンに
   届かなくなる（#app は overflow:hidden。地雷#24）。 */
#banner {
  flex: none;
  height: var(--banner-h);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 0 12px;
  background: var(--ink);
  color: var(--yellow);
  /* ★--font-name（Dela Gothic One）を使わないこと。
     18px では線の太さに対して漢字の懐が足りず、黒地の上で潰れて読めない
     （ユーザー報告・2026-08-21）。小さい文字は --font-ui にする。 */
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 19px;
  letter-spacing: 0.02em;
  line-height: 1;
  overflow: hidden;
  /* ゆっくり脈打たせる。ずっと見えているので控えめに */
  animation: kanje-banner-pulse 2.4s ease-in-out infinite;
}

@keyframes kanje-banner-pulse {
  0%, 100% { transform: scaleY(1); }
  50% { transform: scaleY(1.04); }
}

.banner-text {
  display: flex;
  align-items: baseline;
  min-width: 0;
}

/* 名前だけ桃色にして、誰の話かを一目で分かるようにする。
   ★はみ出したときに削るのは名前の方。行ごと省略すると
   「あいうえおかきさんがお題を選ん…」となって、肝心の動作が消える。 */
.banner-who {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--announce-danger);
}

/* 「さんが崩しています」の側。ここは絶対に削らない */
.banner-act {
  flex: none;
  white-space: nowrap;
}

/* 「…」の点々の代わり。3つのブロックが順に光る（ジェンガの語彙に寄せる） */
.banner-blocks {
  flex: none;
  display: flex;
  gap: 4px;
}

.banner-blocks i {
  width: 9px;
  height: 14px;
  background: var(--yellow);
  opacity: 0.25;
  animation: kanje-banner-blocks 1.2s steps(1, end) infinite;
}

.banner-blocks i:nth-child(2) { animation-delay: 0.4s; }
.banner-blocks i:nth-child(3) { animation-delay: 0.8s; }

@keyframes kanje-banner-blocks {
  0%, 33% { opacity: 1; }
  34%, 100% { opacity: 0.25; }
}

/* ============================================================
   動きを減らす設定（指示書 §4-2）
   ★消してはいけない。情報が失われる。動きだけ止めて、同じ尺だけ静止表示する。
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
  .cutin-speed,
  .correct-rays,
  #app.kanje-shake,
  #app.kanje-shake-long,
  .banner-blocks i {
    animation: none;
  }

  .cutin-speed,
  .correct-rays { opacity: 0; }
  .banner-blocks i { opacity: 1; }

  #banner { animation: none; }

  .cutin-flash { animation: none; opacity: 0; }

  /* 帯と文字は「出て、消える」だけにする。飛び込みも崩れもしない */
  .cutin-band,
  .cutin--attack .cutin-band {
    animation: kanje-fade-hold calc(var(--cutin-in-ms) + var(--cutin-hold-ms) + var(--cutin-out-ms))
      linear both;
    transform: skewY(var(--cutin-skew));
  }

  .cutin-text,
  .cutin--wrong .cutin-text,
  .cutin-sub { animation: none; }

  .correct-word { animation: none; }

  .correct-slice {
    animation: kanje-fade-hold var(--correct-ms) linear both;
  }

  @keyframes kanje-fade-hold {
    0% { opacity: 0; }
    6% { opacity: 1; }
    88% { opacity: 1; }
    100% { opacity: 0; }
  }
}
