/* y nöbeti: the palace gate at night (js/tasks/bouncer.js).
   Shared task classes (.pill, .task-note, .love meter) stay in base.css;
   everything bouncer-only lives here. The costume walks the lane, the child
   waits at the end, and the y is both the button and the guard. */

.bouncer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.6em;
  margin-top: 1.4em;
  width: 100%;
}

/* The lane. The costume crosses it; the child stands at the right edge.
   On a phone it stops short of the screen edge, where the love meter lives:
   the child should wait at a doorstep, not lean on the furniture. */
.bn-track {
  position: relative;
  width: min(26em, 78vw);
  height: 3.2em;
  border-bottom: 1px solid rgba(154, 147, 184, 0.25);
}
.bn-word {
  position: absolute;
  left: 0;
  bottom: 0.35em;
  font-family: var(--serif);
  font-size: clamp(1.25rem, 3.6vw, 1.7rem);
  color: var(--gold);
  white-space: nowrap;
  opacity: 0;
}
.bn-word.walk { animation: bn-walk var(--bn-dur, 3.6s) linear forwards; }
@keyframes bn-walk {
  0%   { opacity: 0; transform: translateX(0); }
  6%   { opacity: 1; }
  100% { opacity: 1; transform: translateX(var(--walk, 200px)); }
}
.bn-suffix {
  position: absolute;
  right: 0;
  bottom: 0.35em;
  font-family: var(--serif);
  font-size: clamp(1.25rem, 3.6vw, 1.7rem);
  color: #74B0FF;
  text-shadow: 0 0 12px rgba(116, 176, 255, 0.45);
  white-space: nowrap;
}
/* The thrown y hovers over the doorstep gap, waiting for the meeting. */
.bn-thrown {
  position: absolute;
  bottom: 0.4em;
  font-family: var(--serif);
  font-size: clamp(1.25rem, 3.6vw, 1.7rem);
  color: #74B0FF;
  text-shadow: 0 0 14px rgba(116, 176, 255, 0.75);
  opacity: 0;
  transform: translateY(-1.4em) scale(0.5);
  pointer-events: none;
}
.bn-thrown.show { animation: bn-drop 0.4s cubic-bezier(0.3, 1.4, 0.4, 1) forwards; }
@keyframes bn-drop {
  to { opacity: 1; transform: translateY(0) scale(1); }
}
/* Thrown at a consonant: the y bounces off and rolls away, confused. */
.bn-thrown.awkward { animation: bn-awkward 1.1s ease forwards; }
@keyframes bn-awkward {
  0%   { opacity: 1; transform: translateY(0) scale(1) rotate(0deg); }
  100% { opacity: 0; transform: translate(-2.2em, 1.6em) scale(0.7) rotate(-160deg); }
}
/* The fuse: the ground line burns down in step with the walk, reddening as
   it runs out. Invisible between rounds (base width 0); the same --bn-dur
   the walk uses rides on the track, so the two can never drift apart. */
.bn-fuse {
  position: absolute;
  left: 0;
  bottom: -1px;
  height: 2px;
  width: 0;
  background: #74B0FF;
  box-shadow: 0 0 8px rgba(116, 176, 255, 0.5);
  pointer-events: none;
}
.bn-fuse.run { animation: bn-fuse var(--bn-dur, 3s) linear forwards; }
@keyframes bn-fuse {
  0%   { width: 100%; background: #74B0FF; box-shadow: 0 0 8px rgba(116, 176, 255, 0.5); }
  70%  { background: #74B0FF; }
  100% { width: 0; background: #E8776A; box-shadow: 0 0 8px rgba(232, 119, 106, 0.6); }
}

/* A wrong serve: BOTH sides take offense. They flush red, shake off the
   insult, and storm out opposite ways: the word back where it came from,
   the suffix out its own side. The word's tantrum starts from the walked
   position (the keyframes carry --walk), because this animation replaces
   the walk's forwards fill; without it the word would snap home first. */
.bn-track.rage .bn-word { animation: bn-rage-word 1.2s ease forwards; }
@keyframes bn-rage-word {
  0%   { opacity: 1; color: #E8776A; transform: translateX(var(--walk, 200px)); }
  12%  { transform: translateX(calc(var(--walk, 200px) - 11px)) rotate(-4deg); }
  28%  { transform: translateX(calc(var(--walk, 200px) + 9px)) rotate(4deg); }
  44%  { transform: translateX(calc(var(--walk, 200px) - 9px)) rotate(-3deg) scale(1.07); }
  58%  { opacity: 1; transform: translateX(calc(var(--walk, 200px) + 6px)) rotate(2deg) scale(1.09); }
  100% { opacity: 0; color: #E8776A; transform: translateX(-3em) rotate(-12deg) scale(0.88); }
}
.bn-track.rage .bn-suffix {
  color: #E8776A;
  text-shadow: none;
  animation: bn-rage-suffix 1.2s ease forwards;
}
@keyframes bn-rage-suffix {
  0%   { opacity: 1; transform: translateX(0); }
  14%  { transform: translateX(-8px) rotate(4deg); }
  30%  { transform: translateX(7px) rotate(-4deg); }
  46%  { transform: translateX(-7px) rotate(3deg) scale(1.07); }
  60%  { opacity: 1; transform: translateX(5px) rotate(-2deg) scale(1.09); }
  100% { opacity: 0; transform: translateX(3.2em) rotate(14deg) scale(0.88); }
}
/* Served: the pair bows out while the joined word takes the stage. */
.bn-track.served .bn-word,
.bn-track.served .bn-suffix,
.bn-track.served .bn-thrown { opacity: 0; transition: opacity 0.5s ease; }

/* The joined word: root gold, suffix azure, straight from markup. */
.bn-result {
  min-height: 1.5em;
  font-family: var(--serif);
  font-size: clamp(1.4rem, 4.2vw, 2rem);
  opacity: 0;
}
.bn-result.pop { animation: bn-pop 0.5s ease forwards; }
@keyframes bn-pop {
  from { opacity: 0; transform: translateY(10px) scale(0.85); }
  to   { opacity: 1; transform: none; }
}

/* The guard's one tool. Azure, round, and spent for the rest of the round
   once thrown: the y is in the gap now, not in your hand. */
.bn-y {
  width: 3.6em;
  height: 3.6em;
  border-radius: 50%;
  font-family: var(--serif);
  font-size: 1.15rem;
  color: #74B0FF;
  background: none;
  border: 1px solid rgba(116, 176, 255, 0.5);
  box-shadow: 0 0 12px rgba(116, 176, 255, 0.18);
  cursor: pointer;
  transition: border-color 0.25s ease, background 0.25s ease, box-shadow 0.25s ease, opacity 0.25s ease;
}
.bn-y:hover, .bn-y:focus-visible {
  border-color: #74B0FF;
  background: rgba(116, 176, 255, 0.1);
  box-shadow: 0 0 18px rgba(116, 176, 255, 0.35);
  outline: none;
}
.bn-y:active { transform: scale(0.92); }
.bn-y.spent { opacity: 0.35; pointer-events: none; }

/* Reduced motion: the costume stands at the doorstep instead of walking,
   and a refusal fades in place instead of storming. The fuse keeps burning:
   with no walk it is the one essential indicator of the time left, a small
   linear shrink rather than a lurch. */
@keyframes bn-fade { to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .bn-word.walk { animation: none; opacity: 1; transform: translateX(var(--walk, 200px)); }
  .bn-thrown.show { animation: none; opacity: 1; transform: none; }
  .bn-thrown.awkward { animation: none; opacity: 0; }
  .bn-track.rage .bn-word {
    animation: bn-fade 0.8s ease forwards;
    color: #E8776A;
    transform: translateX(var(--walk, 200px));
  }
  .bn-track.rage .bn-suffix { animation: bn-fade 0.8s ease forwards; }
  .bn-result.pop { animation: none; opacity: 1; }
}
