/* The cheer-up line: Değil Gezegeni's görev (js/tasks/cheer.js).
   The chip, cloud, rain, rip, hop, heal and sparks all come from the shared
   gloom-* classes in base.css: the görev looks exactly like the lesson.
   Everything here is the clinic around the patient: the floor, the entrance,
   the tears, the flinch, the sad exit, and the option pills. */

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

/* The floor holds one patient; a fixed height so the room never jumps
   between a short sentence and a long one. */
.cheer-floor {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 5.2em;
  width: 100%;
}

.cheer-sent {
  position: relative;
  padding: 0.4em 0.6em;
  opacity: 0;
}
/* It walks in from the right, head down: the next one in the line. */
.cheer-sent.in { animation: cheer-in 0.6s ease forwards; }
@keyframes cheer-in {
  0% { opacity: 0; transform: translateX(3.5em); }
  100% { opacity: 1; transform: translateX(0); }
}
/* Its own tears, falling from under the words while it waits. */
.cheer-tear {
  position: absolute;
  top: 78%;
  width: 3px;
  height: 0.42em;
  border-radius: 0 0 3px 3px;
  background: rgba(127, 199, 217, 0.65);
  animation: cheer-cry 2.1s ease-in infinite;
  pointer-events: none;
}
@keyframes cheer-cry {
  0% { transform: translateY(0) scaleY(0.6); opacity: 0; }
  18% { opacity: 0.85; }
  100% { transform: translateY(1.6em) scaleY(1); opacity: 0; }
}
/* Healed or ripped, the crying stops at once: hope arrives early. */
.cheer-sent.ripped .cheer-tear, .cheer-sent.healed .cheer-tear { animation: none; opacity: 0; }

/* Tapped somewhere that is not değil: a small flinch, nothing more. */
.cheer-sent.flinch .gloom-row { animation: cheer-flinch 0.35s ease; }
@keyframes cheer-flinch {
  0%, 100% { transform: translateX(0); }
  30% { transform: translateX(-5px); }
  65% { transform: translateX(4px); }
}

/* The wrong ending landed and joined the word. The whole join flushes red and
   shakes it off: the point is that akıllıyum is READABLE for a moment, wrong
   and in front of you, before the sentence gives up. The colour is forced
   over the markup's own gold and azure, because right now the word is not a
   word, it is a mistake. */
.cheer-sent.wrong .gloom-word,
.cheer-sent.wrong .gloom-word * {
  color: #E8776A;
  text-shadow: 0 0 16px rgba(232, 119, 106, 0.6);
}
.cheer-sent.wrong .gloom-word { animation: cheer-reject 0.5s ease; }
@keyframes cheer-reject {
  0%, 100% { transform: translateX(0); }
  15% { transform: translateX(-7px) rotate(-1.5deg); }
  40% { transform: translateX(6px) rotate(1.5deg); }
  70% { transform: translateX(-4px); }
}

/* The wrong home was chosen: it droops away down and off, still grey. */
.cheer-sent.sadoff { animation: cheer-sadoff 1.3s ease forwards; }
@keyframes cheer-sadoff {
  0% { opacity: 1; transform: translateX(0) translateY(0) rotate(0deg); }
  100% { opacity: 0; transform: translateX(-2.6em) translateY(2em) rotate(-5deg); }
}

/* Healed: one warm lift, then it strolls off the other way, lighter. */
.cheer-sent.healed { animation: cheer-happyoff 1.9s ease forwards; }
@keyframes cheer-happyoff {
  0% { opacity: 1; transform: translateX(0) translateY(0); }
  30% { transform: translateY(-0.35em); }
  55% { opacity: 1; transform: translateX(0.4em) translateY(0); }
  100% { opacity: 0; transform: translateX(3.2em) translateY(-0.5em); }
}

/* The sky: where the ripped ending scatters into its candidates, and the four
   walls they bounce off. The box is the playfield, so its size is the physics:
   js/tasks/cheer.js reads clientWidth/clientHeight every frame. */
.cheer-sky {
  position: relative;
  width: min(30em, 92vw);
  height: 11.5em;
  overflow: hidden;
}
/* In the görev the ending never flies home on its own: it bursts into the
   candidates instead (the demos keep their hop). It dissolves off değil as
   the sky fills, because it is BECOMING the three chips. */
.cheer-sent.ripped .gloom-suffix { animation: none; opacity: 0; transition: opacity 0.3s ease 0.1s; }

/* A loose ending: azure, restless, dash-ringed like the loose letters this
   universe teaches with.
   The OUTER chip's transform belongs to the physics loop and to nothing else:
   no CSS animation may touch it, or the bouncing and the animation would
   fight over the same property and the chip would teleport. Entrances and
   exits are therefore transitions, which compose with an inline transform
   instead of overriding it. Only the inner ring animates on its own, and only
   things the physics does not own: fade, scale, spin. */
.cheer-fly {
  position: absolute;
  left: 0;
  top: 0;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
}
.cheer-fly-i {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.6em;
  height: 2.6em;
  border-radius: 50%;
  border: 1px dashed rgba(116, 176, 255, 0.5);
  font-family: var(--serif);
  font-size: clamp(1rem, 3vw, 1.25rem);
  color: #74B0FF;
  text-shadow: 0 0 14px rgba(116, 176, 255, 0.65);
  background: rgba(13, 18, 32, 0.55);
}
/* Born out of the tear: it pops into being while the physics throws it. */
.cheer-fly.in .cheer-fly-i { animation: cheer-fly-pop 0.5s cubic-bezier(0.25, 1.3, 0.45, 1) backwards; }
@keyframes cheer-fly-pop {
  from { opacity: 0; transform: scale(0.2) rotate(-40deg); }
}
.cheer-fly:hover .cheer-fly-i, .cheer-fly:focus-visible .cheer-fly-i {
  border-color: #74B0FF;
  border-style: solid;
  box-shadow: 0 0 18px rgba(116, 176, 255, 0.35);
}
.cheer-fly:focus-visible { outline: none; }

/* Leaving, all three ways. The transition is added with the class, so the
   physics writes one last transform and CSS carries it from there. */
.cheer-fly.home, .cheer-fly.flee, .cheer-fly.burst {
  pointer-events: none;
  transition: transform 0.5s cubic-bezier(0.3, 0.8, 0.4, 1), opacity 0.5s ease;
  opacity: 0;
}
/* Caught: it sails home and the word swallows it, so it goes out bright. */
.cheer-fly.home { transition-duration: 0.45s; }
.cheer-fly.home .cheer-fly-i {
  border-color: var(--gold);
  color: var(--gold);
  text-shadow: 0 0 20px rgba(232, 193, 106, 0.9);
  transition: color 0.25s ease, border-color 0.25s ease;
}
/* A wrong-colored cousin crumbles red where it floats. */
.cheer-fly.burst { transition-duration: 0.6s; }
.cheer-fly.burst .cheer-fly-i {
  color: #E8776A;
  border-color: rgba(232, 119, 106, 0.75);
  text-shadow: 0 0 16px rgba(232, 119, 106, 0.7);
  animation: cheer-flinch 0.35s ease;
}

/* Reduced motion: entrances and exits become fades, the tears hold still,
   and the candidates stand in place instead of drifting. The catch still
   heals; only the journey is skipped. */
@media (prefers-reduced-motion: reduce) {
  .cheer-sent.in { animation: none; opacity: 1; }
  .cheer-tear { animation: none; opacity: 0.4; }
  .cheer-sent.flinch .gloom-row { animation: none; }
  .cheer-sent.sadoff, .cheer-sent.healed { animation: cheer-fade 0.8s ease forwards; }
  /* The endings stand still in their corners: no physics loop runs at all
     (js/tasks/cheer.js places them and returns), so catching is a plain tap. */
  .cheer-fly.in .cheer-fly-i { animation: none; }
  .cheer-fly.home, .cheer-fly.flee, .cheer-fly.burst { transition: opacity 0.4s ease; }
  .cheer-fly.burst .cheer-fly-i { animation: none; }
}
@keyframes cheer-fade { to { opacity: 0; } }
