/* Battle feel (ADR-027): named threats, counter cues, vulnerability and breach feedback. */

/* Telegraph: attack name + countdown, then the answer on its own line. */
#game .telegraph {
  grid-template-columns: 1fr auto;
  row-gap: 4px;
  --threat: 221, 152, 68;
  border-color: rgba(var(--threat), 0.8);
  box-shadow: 0 0 24px rgba(var(--threat), 0.3);
}
#game .telegraph[data-kind="barrage"] { --threat: 232, 92, 78; color: #ffc9bd; }
#game .telegraph[data-kind="ward"] { --threat: 120, 196, 255; color: #d5ecff; }
#game .telegraph[data-kind="erase"] { --threat: 214, 224, 228; color: #f2f5f4; }
#game .telegraph.active { animation: threatPulse 700ms ease-in-out infinite alternate; }
#game .telegraph-counter {
  grid-column: 1 / -1;
  font: 600 11px/1.3 var(--ui-font-body, system-ui, sans-serif);
  letter-spacing: 0.1em;
  color: rgba(var(--threat), 1);
  filter: brightness(1.35);
}
#game .telegraph-track i { background: rgb(var(--threat)); }
#game .telegraph-mask { height: 96px; }

/* The one skill that answers the threat. */
#game .bottom-panel .skill.counter-cue {
  border-color: rgba(255, 214, 140, 0.95);
  animation: counterCue 520ms ease-in-out infinite alternate;
}
#game[data-threat="barrage"] .bottom-panel .skill.counter-cue { border-color: rgba(255, 170, 150, 0.95); }
#game[data-threat="ward"] .bottom-panel .skill.counter-cue { border-color: rgba(170, 220, 255, 0.95); }
#game[data-threat="erase"] .bottom-panel .skill.counter-cue { border-color: rgba(235, 240, 238, 0.98); }
#game .bottom-panel .skill.breach-cue {
  border-color: rgba(255, 206, 112, 0.95);
  box-shadow: inset 0 0 0 3px rgba(4, 7, 11, 0.72), 0 0 22px rgba(255, 190, 90, 0.55);
}

/* Barrier glow on the enemy while a ward is up. */
#game[data-threat="ward"] .enemy-sprite:not(.hit):not(.defeated) {
  filter: drop-shadow(0 0 10px rgba(120, 196, 255, 0.85)) drop-shadow(0 0 26px rgba(120, 196, 255, 0.4));
}

/* Vulnerability badge under the boss bar. */
#game .boss-hud { position: relative; }
#game .enemy-status {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 3px 9px;
  border: 1px solid rgba(255, 196, 110, 0.7);
  border-radius: var(--ui-radius, 4px);
  background: rgba(30, 18, 8, 0.88);
  color: #ffd391;
  font: 600 11px/1.3 var(--ui-font-body, system-ui, sans-serif);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 140ms ease, transform 140ms ease;
  pointer-events: none;
}
#game .enemy-status.active { opacity: 1; transform: translateY(0); }
#game .enemy-status i { font-style: normal; font-variant-numeric: tabular-nums; color: #fff0d6; }

/* The message line (showToast). In battle it has its own lane right above the
   health bars (--battle-panel-height is measured in game.js), so it covers
   neither the telegraph and fighters nor the bars. Over a city screen it rises
   above that screen at the bottom. The left edge shows the tone. */
#game .combat-toast {
  top: auto;
  bottom: calc(var(--battle-panel-height, 210px) - 8px);
  width: max-content; /* left: 50% would otherwise wrap it at half the screen */
  max-width: min(90%, 380px);
  padding: 7px 14px 7px 12px;
  border-left: 3px solid var(--toast-edge, var(--ui-line));
  font-weight: 600;
  letter-spacing: .01em;
  text-align: center;
  text-transform: none;
  text-wrap: balance;
  white-space: normal;
  transform: translate(-50%, 6px);
}
#game .combat-toast.visible { transform: translate(-50%, 0); }
#game .combat-toast[data-tone="good"] { --toast-edge: var(--ui-success); }
#game .combat-toast[data-tone="warn"] { --toast-edge: #e8a25c; }
#game .combat-toast[data-place="screen"] {
  z-index: 40;
  bottom: max(20px, calc(env(safe-area-inset-bottom) + 14px));
  box-shadow: 0 10px 28px rgba(0, 0, 0, .55);
}

/* Damage numbers. */
#game .damage-number.breach {
  color: #ffd27a;
  font-size: 30px;
  text-shadow: 0 2px 6px black, 0 0 16px rgba(255, 180, 70, 0.75);
  animation-duration: 950ms;
}
#game .damage-number.warded { color: #a9d6ff; font-size: 18px; opacity: 0.85; }
#game .damage-number.player.guarded { color: #8fe9f5; font-size: 20px; }

/* Screen-level flashes: hurt vignette, breach burst, threat announcement. */
#game .damage-layer::before,
#game .damage-layer::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
}
#game .damage-layer::before {
  background: radial-gradient(ellipse at 50% 55%, transparent 52%, rgba(170, 20, 34, 0.42) 100%);
}
#game.hit .damage-layer::before { animation: screenFlash 320ms ease-out; }
#game.breach-flash .damage-layer::after {
  background: radial-gradient(circle at 67% 42%, rgba(255, 200, 110, 0.38), transparent 42%);
  animation: screenFlash 420ms ease-out;
}
#game.threat-crush .damage-layer::after,
#game.threat-barrage .damage-layer::after,
#game.threat-ward .damage-layer::after { animation: screenFlash 520ms ease-out; }
#game.threat-crush .damage-layer::after { background: radial-gradient(ellipse at 50% 20%, rgba(221, 152, 68, 0.3), transparent 60%); }
#game.threat-barrage .damage-layer::after { background: radial-gradient(ellipse at 50% 20%, rgba(232, 92, 78, 0.32), transparent 60%); }
#game.threat-ward .damage-layer::after { background: radial-gradient(ellipse at 67% 42%, rgba(120, 196, 255, 0.34), transparent 50%); }

@keyframes threatPulse {
  from { box-shadow: 0 0 10px rgba(var(--threat), 0.2); }
  to { box-shadow: 0 0 32px rgba(var(--threat), 0.5); }
}
@keyframes counterCue {
  from { box-shadow: inset 0 0 0 3px rgba(4, 7, 11, 0.72), 0 0 6px rgba(255, 214, 140, 0.2); }
  to { box-shadow: inset 0 0 0 3px rgba(4, 7, 11, 0.72), 0 0 26px rgba(255, 214, 140, 0.7); }
}
@keyframes screenFlash {
  from { opacity: 1; }
  to { opacity: 0; }
}

/* First-session polish: the prologue never opens on a black frame. */
#game [data-ui-screen] .cutscene-visual, #game [data-ui-screen][data-cinema="true"] .cutscene-visual { background: radial-gradient(ellipse at 50% 35%, #1c2633 0%, #0d1219 60%, #07090d 100%); }
#game .cutscene-backdrop { transition: opacity 280ms ease; }
#game .cutscene-backdrop:not(.scene-ready) { opacity: 0; }

/* A victory that moves the story names what the Seeker carries away. */
#game .story-find {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr);
  align-items: center;
  gap: 12px;
  margin: 10px 0 4px;
  padding: 10px 12px;
  border: 1px solid rgba(230, 188, 124, 0.5);
  border-radius: var(--ui-radius, 4px);
  background: linear-gradient(90deg, rgba(48, 32, 14, 0.85), rgba(14, 14, 18, 0.9));
  text-align: left;
  animation: storyFindIn 600ms ease-out both;
}
#game .story-find[hidden] { display: none; }
#game .story-find img { width: 56px; height: 56px; object-fit: contain; filter: drop-shadow(0 0 10px rgba(255, 196, 110, 0.45)); }
#game .story-find-mark { display: grid; place-items: center; width: 56px; height: 56px; color: #ffd391; font-size: 28px; text-shadow: 0 0 14px rgba(255, 190, 90, 0.7); }
#game .story-find div { display: grid; gap: 3px; min-width: 0; }
#game .story-find small { color: #e6bc7c; font: 600 11px/1.3 var(--ui-font-body, system-ui, sans-serif); letter-spacing: 0.1em; text-transform: uppercase; }
#game .story-find strong { color: #fff0d6; font: 500 16px/1.3 var(--ui-font-display, Georgia, serif); }
#game .story-find span:not(.story-find-mark) { color: rgba(232, 222, 204, 0.78); font-size: 12px; line-height: 1.4; }
@keyframes storyFindIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* Detail shots (a prop in close-up) always soften the room behind it, on
   every frame of the beat, so the item reads first. */
#game [data-cinema="true"][data-cinema-mode="detail"] :is(.cutscene-backdrop, .story-backdrop) {
  filter: saturate(.8) brightness(.7) blur(1.5px);
}

/* Loot reveal: the verdict line, and a celebration for rare and better drops. */
#game .drop-notice .drop-verdict { grid-column: 2; font-style: normal; font-size: 12px; font-weight: 600; letter-spacing: .02em; }
#game .drop-notice .drop-verdict.tone-upgrade { color: #8fe9a8; }
#game .drop-notice .drop-verdict.tone-plain { color: rgba(214, 222, 228, 0.6); }
#game .drop-notice .drop-kicker { grid-column: 1 / -1; color: var(--item-rarity); font: 600 11px/1.3 var(--ui-font-body, system-ui, sans-serif);
  letter-spacing: .14em; text-transform: uppercase; }
#game .drop-notice.notable-drop { position: relative; overflow: hidden; animation: dropReveal 620ms cubic-bezier(.2, .9, .3, 1.2) both;
  box-shadow: 0 0 22px color-mix(in srgb, var(--item-rarity) 45%, transparent), inset 0 0 18px color-mix(in srgb, var(--item-rarity) 18%, transparent); }
#game .drop-notice.notable-drop::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(105deg, transparent 35%, color-mix(in srgb, var(--item-rarity) 40%, white 10%) 50%, transparent 65%);
  transform: translateX(-120%); animation: dropShine 1300ms 350ms ease-out forwards; }
#game .drop-notice.item-rarity-legendary.notable-drop { animation-duration: 820ms; }
@keyframes dropReveal { from { opacity: 0; transform: scale(.9); } to { opacity: 1; transform: none; } }
@keyframes dropShine { to { transform: translateX(120%); } }
#game .drop-notice > :first-child:not(.drop-kicker) { grid-row: 1 / 5; }
#game .drop-notice.notable-drop > :nth-child(2) { grid-row: 2 / 6; }

/* Стирание (ADR-030): the marked skill pulses; an erased one loses its name. */
#game[data-threat="erase"] .enemy-sprite:not(.hit):not(.defeated) {
  filter: drop-shadow(0 0 12px rgba(230, 236, 234, 0.7));
}
#game .bottom-panel .skill.erased .skill-icon img { filter: grayscale(1) brightness(0.55); }
#game .bottom-panel .skill.erased .skill-name {
  letter-spacing: 0.12em;
  color: rgba(214, 224, 228, 0.55);
  font-style: italic;
}
#game .bottom-panel .skill.erased { border-style: dashed; }
#game.threat-erase .damage-layer::after { animation: screenFlash 520ms ease-out; background: radial-gradient(ellipse at 50% 85%, rgba(220, 230, 228, 0.28), transparent 60%); }

/* Escort: the column of the nameless shares the enemy's blows. */
#game .escort-row { margin-top: 6px; }
#game .escort-row .name-row { font-size: 11px; color: #d8cfb6; }
#game .escort-bar { height: 6px; }
#game .escort-bar .bar-fill { background: linear-gradient(90deg, #8d7a55, #d6c08a); }
#game .escort-row.low .escort-bar .bar-fill { background: linear-gradient(90deg, #8f3b32, #d7745e); }
#game .escort-row.hit { animation: escortHit 360ms ease-out; }
#game .damage-number.escort { left: 23%; top: 70%; color: #e6c98f; font-size: 18px; }
@keyframes escortHit { from { filter: brightness(1.8); } to { filter: none; } }
@media (prefers-reduced-motion: reduce) {
  #game .escort-row.hit { animation: none; }
}

/* Шторм (chapter IV): sea-teal threat; the spray shields the enemy like a Барьер,
   then the wave comes (data-storm = spray | wave | wall when the spray held). */
#game .telegraph[data-kind="storm"] { --threat: 96, 214, 200; color: #d3f6f0; }
#game[data-threat="storm"] .bottom-panel .skill.counter-cue { border-color: rgba(140, 236, 222, 0.95); }
#game[data-threat="storm"][data-storm="spray"] .enemy-sprite:not(.hit):not(.defeated) {
  filter: drop-shadow(0 0 10px rgba(96, 214, 200, 0.85)) drop-shadow(0 0 26px rgba(96, 214, 200, 0.4));
}
#game[data-threat="storm"][data-storm="wall"] .enemy-sprite:not(.hit):not(.defeated) {
  filter: drop-shadow(0 0 14px rgba(96, 214, 200, 0.6)) brightness(1.08);
}
#game.threat-storm .damage-layer::after { animation: screenFlash 520ms ease-out;
  background: radial-gradient(ellipse at 50% 30%, rgba(96, 214, 200, 0.32), transparent 60%); }
