/* BappaPlay — the shell every activity shares.
 *
 * A game's mechanic is always different; what surrounds it never is. The child
 * meets the same rhythm each time — someone explains, someone reacts, someone
 * celebrates — no matter whether they are tapping coins, tracing a letter or
 * dragging things into a basket.
 *
 * Dependency-free and self-contained, like the frame, so a downloaded folder
 * still behaves on a classroom laptop with no internet.
 */

.bp-hidden { display: none !important; }

/* ── start card ───────────────────────────────────────────────────────────
   Also the audio unlock. Browsers refuse to play sound before a real tap, so
   an instruction that spoke on load would be silently swallowed. Making the
   first tap deliberate turns that limitation into a proper opening beat. */
.bp-start {
  position: fixed;
  inset: 0;
  z-index: 2147482000;
  display: grid;
  place-items: center;
  padding: 1rem;
  background: radial-gradient(ellipse at 50% 20%, rgba(255, 245, 214, .97), rgba(247, 200, 120, .97));
  animation: bpFade .3s ease-out;
}
.bp-start__card {
  width: min(520px, 92vw);
  text-align: center;
  padding: 1.6rem 1.4rem 1.8rem;
  border-radius: 28px;
  background: #fff;
  box-shadow: 0 10px 0 #E0B776, 0 22px 34px rgba(0, 0, 0, .28);
}
.bp-start__title {
  margin: 0 0 .3em;
  font-size: clamp(1.3rem, 5.5vw, 2rem);
  font-weight: 700;
  color: #2B2118;
}
.bp-start__line {
  margin: 0 0 1.2rem;
  font-size: clamp(1rem, 4vw, 1.25rem);
  color: #6D5B4B;
  font-weight: 600;
}
.bp-start__go {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .85rem 1.8rem;
  border: 0;
  border-radius: 999px;
  font: inherit;
  font-weight: 700;
  font-size: clamp(1.05rem, 4.2vw, 1.3rem);
  color: #fff;
  background: linear-gradient(180deg, #FFB03A, #FF8A1E);
  box-shadow: 0 6px 0 #C76F16, 0 12px 18px rgba(0, 0, 0, .25);
  cursor: pointer;
  animation: bpBeat 1.8s ease-in-out infinite;
}
.bp-start__go:active { transform: translateY(4px); box-shadow: 0 2px 0 #C76F16; }

@keyframes bpBeat {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.05); }
}
@keyframes bpFade { from { opacity: 0; } to { opacity: 1; } }

/* ── progress tray ────────────────────────────────────────────────────── */
.bp-progress {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  min-height: 44px;
  padding: .35rem .9rem;
  margin: 0 auto .55rem;
  width: fit-content;
  border-radius: 999px;
  background: linear-gradient(180deg, #C98A3C, #A96A24);
  box-shadow:
    inset 0 2px 4px rgba(255, 255, 255, .45),
    inset 0 -3px 6px rgba(90, 50, 0, .45),
    0 4px 0 #7D4D15,
    0 8px 12px rgba(0, 0, 0, .22);
}
.bp-progress__slot {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(80, 45, 5, .42);
  box-shadow: inset 0 2px 3px rgba(0, 0, 0, .4);
  transition: transform .3s cubic-bezier(.2, .9, .3, 1.5), background .3s;
}
.bp-progress__slot.is-on {
  background: radial-gradient(circle at 34% 26%, #FFF6CE, #FFD24A 45%, #E09B12 100%);
  box-shadow:
    inset 0 -2px 3px rgba(120, 70, 0, .5),
    inset 0 2px 3px rgba(255, 255, 255, .7),
    0 1px 3px rgba(0, 0, 0, .3);
  transform: scale(1.14);
}

/* ── the spoken line ──────────────────────────────────────────────────── */
.bp-say {
  margin: .85rem 0 0;
  min-height: 2.1rem;
  font-size: clamp(1rem, 4vw, 1.35rem);
  font-weight: 700;
  color: #2B2118;
}
.bp-say.is-warm { color: #C2410C; }

/* ── finish ───────────────────────────────────────────────────────────── */
.bp-finish {
  position: fixed;
  inset: 0;
  z-index: 2147482000;
  display: grid;
  place-items: center;
  padding: 1rem;
  background: radial-gradient(ellipse at 50% 15%, rgba(255, 247, 222, .97), rgba(255, 205, 120, .97));
  overflow: hidden;
}
.bp-finish__card {
  position: relative;
  z-index: 2;
  width: min(520px, 92vw);
  text-align: center;
  padding: 1.4rem 1.4rem 1.7rem;
  border-radius: 28px;
  background: #fff;
  box-shadow: 0 10px 0 #E0B776, 0 22px 34px rgba(0, 0, 0, .28);
  animation: bpRise .55s cubic-bezier(.2, .9, .3, 1.4);
}
@keyframes bpRise {
  0% { opacity: 0; transform: translateY(40px) scale(.9); }
  100% { opacity: 1; transform: none; }
}

.bp-finish__trophy {
  width: clamp(84px, 26vw, 120px);
  margin: 0 auto .4rem;
  animation: bpTrophy 2.4s ease-in-out infinite;
}
@keyframes bpTrophy {
  0%, 100% { transform: translateY(0) rotate(-4deg); }
  50% { transform: translateY(-9px) rotate(4deg); }
}

.bp-finish__title {
  margin: 0 0 1rem;
  font-size: clamp(1.25rem, 5.5vw, 1.9rem);
  font-weight: 700;
  color: #2B2118;
}

.bp-cta {
  display: inline-block;
  margin: .3rem;
  padding: .75rem 1.5rem;
  border-radius: 999px;
  border: none;
  font: inherit;
  font-weight: 700;
  font-size: 1.05rem;
  background: #FF9933;
  color: #fff;
  text-decoration: none;
  cursor: pointer;
  box-shadow: 0 5px 0 #C76F16, 0 10px 14px rgba(0, 0, 0, .2);
}
.bp-cta:active { transform: translateY(3px); box-shadow: 0 2px 0 #C76F16; }
.bp-cta--yt { background: #E53935; box-shadow: 0 5px 0 #A52422, 0 10px 14px rgba(0, 0, 0, .2); }
.bp-cta--yt:active { box-shadow: 0 2px 0 #A52422; }

/* Tertiary action. Text, not a button — it should be findable without competing
   with replay or the video. */
.bp-next {
  display: block;
  margin: .9rem auto 0;
  padding: .3rem;
  width: fit-content;
  font-size: .95rem;
  font-weight: 700;
  color: #00897B;
  text-decoration: none;
  border-bottom: 2px dashed rgba(0, 137, 123, .45);
}
.bp-next:hover { color: #00695C; border-bottom-style: solid; }

/* ── celebration ──────────────────────────────────────────────────────── */
.bp-confetti {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  overflow: hidden;
}
.bp-confetti i {
  position: absolute;
  top: -12%;
  width: 12px;
  height: 18px;
  border-radius: 3px;
  opacity: 0;
  animation: bpFall linear forwards;
}
@keyframes bpFall {
  0% { opacity: 0; transform: translateY(-10vh) rotate(0deg); }
  8% { opacity: 1; }
  100% { opacity: .9; transform: translateY(112vh) rotate(760deg); }
}

/* A ring of coins bursting outward from the trophy. */
.bp-burst {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 26px;
  height: 26px;
  margin: -13px 0 0 -13px;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 26%, #FFF6CE, #FFD24A 45%, #E09B12 100%);
  box-shadow: inset 0 -2px 3px rgba(120, 70, 0, .5), 0 2px 4px rgba(0, 0, 0, .3);
  opacity: 0;
  animation: bpBurst .9s ease-out forwards;
}
@keyframes bpBurst {
  0% { opacity: 1; transform: translate(0, 0) scale(.4); }
  100% { opacity: 0; transform: translate(var(--bx), var(--by)) scale(1.1); }
}

/* Music toggle. Bottom-right, opposite Bappa, small and out of the way — but a
   child who finds music annoying must be able to stop it without help. */
.bp-music {
  position: fixed;
  right: max(10px, env(safe-area-inset-right));
  bottom: max(10px, env(safe-area-inset-bottom));
  z-index: 2147481600;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .82);
  box-shadow: 0 3px 0 rgba(120, 70, 0, .28), 0 6px 12px rgba(0, 0, 0, .2);
  font-size: 1.15rem;
  line-height: 1;
  cursor: pointer;
}
.bp-music:active { transform: translateY(3px); box-shadow: 0 1px 0 rgba(120, 70, 0, .28); }

/* ── Bappa, the companion ─────────────────────────────────────────────────
   Bottom of the screen, out of the way of the game, changing pose with what
   just happened: waving at the start, watching while you think, clapping when
   you get it, palms open when you don't, high-five at the end.
   
   Decorative only. If the artwork never loads the game is untouched — which is
   also why it can live at one shared URL instead of inside every folder. */
.bp-bappa {
  position: fixed;
  left: max(8px, env(safe-area-inset-left));
  bottom: max(4px, env(safe-area-inset-bottom));
  z-index: 2147481500;
  width: clamp(74px, 17vw, 132px);
  pointer-events: none;
  filter: drop-shadow(0 8px 10px rgba(90, 50, 0, .3));
  animation: bpBreathe 4.2s ease-in-out infinite;
  transition: opacity .25s;
}
.bp-bappa img {
  display: block;
  width: 100%;
  height: auto;
}

/* A small settle each time the pose changes, so the swap reads as a reaction
   rather than a flicker. */
.bp-bappa.is-swap { animation: bpPose .45s cubic-bezier(.2, .9, .3, 1.5); }

@keyframes bpBreathe {
  0%, 100% { transform: translateY(0) rotate(-1deg); }
  50%      { transform: translateY(-6px) rotate(1deg); }
}
@keyframes bpPose {
  0%   { transform: translateY(6px) scale(.86) rotate(-4deg); }
  55%  { transform: translateY(-4px) scale(1.06) rotate(2deg); }
  100% { transform: translateY(0) scale(1) rotate(0deg); }
}

/* On the finish screen he belongs with the celebration, not pinned to a corner. */
.bp-bappa.is-done {
  position: static;
  width: clamp(96px, 26vw, 150px);
  margin: 0 auto -.4rem;
  animation: bpBreathe 3s ease-in-out infinite;
}

/* Narrow phones: the game needs the room more than he does. */
@media (max-width: 380px) {
  .bp-bappa { width: 64px; opacity: .92; }
}

@media (prefers-reduced-motion: reduce) {
  .bp-bappa, .bp-bappa.is-swap { animation: none; }
}

@media (prefers-reduced-motion: reduce) {
  .bp-confetti, .bp-burst { display: none; }
  .bp-start__go, .bp-finish__trophy, .bp-finish__card { animation: none; }
}

/* ── short screens ────────────────────────────────────────────────────────
   A phone held sideways leaves about 390px of height, and the celebration card
   wants 477. Centred inside a box with overflow hidden, that put Play again and
   the video link below the bottom edge with no way to reach them: the game
   ended and the child was stranded on it.

   Two separate things are wrong with that, so two fixes. The overlay now
   scrolls instead of clipping, which guarantees nothing can ever be out of
   reach whatever the screen. And on a short screen the card packs itself down
   so it fits without needing to be scrolled at all — a celebration you have to
   go looking for is not much of a celebration. */
.bp-start,
.bp-finish {
  overflow-y: auto;
  /* `safe` is what keeps the top of a too-tall card reachable: it aligns to the
     start rather than centring and pushing the top out of the scroll area. */
  align-items: safe center;
  justify-items: center;
}

@media (max-height: 560px) {
  .bp-start__card,
  .bp-finish__card { padding: .9rem 1.1rem 1.1rem; }

  /* Sized against the height now, not the width — the trophy is competing for
     vertical room, and on a wide-but-short screen 26vw was enormous. */
  .bp-finish__trophy { width: clamp(48px, 13vh, 78px); margin-bottom: .25rem; }

  .bp-finish__title { margin-bottom: .55rem; font-size: clamp(1.05rem, 3.6vh, 1.4rem); }
  .bp-start__title { font-size: clamp(1.05rem, 3.8vh, 1.5rem); }
  .bp-start__line { margin-bottom: .65rem; font-size: clamp(.9rem, 2.8vh, 1.1rem); }

  .bp-cta { padding: .5rem 1.1rem; font-size: .98rem; margin: .22rem; }
  .bp-start__go { padding: .55rem 1.4rem; font-size: 1.05rem; }
  .bp-next { margin-top: .5rem; }
}

/* ── our own pictures ─────────────────────────────────────────────────────
   Sized by the box they sit in, because the boards they appear on already
   decide how big a choice should be. The emoji fallback is set in font size
   instead, so if a picture ever fails to load it lands at the same weight
   rather than collapsing to a full stop. */
/* Bounded BY the box, never sizing it.
   `height: 100%` looks equivalent and is not: it makes the picture's own shape
   force the container taller, which beat the square well the cards rely on and
   left a tall ice cream pushing its word half an inch below the others. A
   maximum constrains; a length demands. */
.bp-art {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}
.bp-art--emoji {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  font-size: min(100%, 3rem);
  line-height: 1;
}
