/* =========================================== */
/* ==                                       == */
/* ==        Blow & Pop Bubble - CSS        == */
/* ==                                       == */
/* =========================================== */
/*
  SHARED FILE - used by EVERY page of the site (index.html, blog.html, credits.html,
  terms-of-use.html, privacy-policy.html and all the coloring pages).
  Change something here once and it changes on all pages.

  The bubble that appears when Worksheets, Holidays, Craft, Blog or Mandala is
  clicked in the top menu (train), the side menu (cubes) or the footer.
  Bubble effect based on "Bubble Pop & Blow Button" by Kieran Nebel:
  https://codepen.io/Kieran-Nebel/pen/ExJbrNm
  Colored rings + glow around it based on "Pop-up design" by fajjet:
  https://codepen.io/fajjet/pen/oqLGgq

  How the pieces fit together:
  - kp-bubble.js (also in the site's main folder) creates the bubble HTML on
    the page and adds/removes these classes:
      .is-blowing  on .kp-bubble         -> bubble visible + "blow up" animation
      .is-on       on .kp-bubble-aura    -> colored rings ripple out + glow around the bubble
      .is-open     on .kp-bubble-layer   -> clicks outside the bubble pop it
      .is-popping  on .kp-bubble-splash  -> droplets visible + "pop" animation
  - Each page loads both files with two lines in its <head>.
  - Everything below is hidden until one of those classes is added.

  ONE SIZE FOR EVERYTHING:
  The bubble's size is ONE setting, --bubble-size (in section 1 below):
    phones 250px, tablets 280px, desktops 312px.
  Everything else - text, hover size, rings, glow, the hole in the rings,
  the pop splash - is calculated from it with calc(var(--bubble-size) * number),
  so it all grows and shrinks together and always stays in proportion.
  Example: calc(var(--bubble-size) * 1.1) = 10% bigger than the bubble.

  All class names start with "kp-" so they can never clash with other styles
  on the site (e.g. there are many other "...-container" classes).

  EASY TWEAKS:
  - Bubble size ............ --bubble-size in section 1 (one value per screen size)
  - How see-through ........ opacity in .kp-bubble (1 = solid, 0 = invisible)
  - Bubble text size ....... the "* 0.136" in .kp-bubble font-size (and kp-blow / kp-pulse)
  - Blow-up speed .......... "kp-blow 1s" in .kp-bubble.is-blowing
  - Bubble colors .......... .kp-bubble__purple / __blue / __pink and .kp-splash
  - Rings / glow ........... see the EASY TWEAKS in section 2b
  - The text itself ........ BUBBLE_TEXT at the top of kp-bubble.js
*/

/* Load the round "Sniglet" font used for the text inside the bubble.
   (@import must be the very first rule in a CSS file, after comments.) */
@import url("https://fonts.googleapis.com/css2?family=Sniglet:wght@400;800&display=swap");

/* ---------------------------------------------------------------------------
   1) THE LAYER (+ the bubble size)
   An invisible box that covers the whole screen (the browser window, not the
   page), so whatever is inside it is always in the exact center of the screen,
   even when the page is scrolled.
   --------------------------------------------------------------------------- */
.kp-bubble-layer {
  /* THE BUBBLE SIZE. Everything inside the layer uses this value.
     Phones (narrower than 768px): 250px - the original size. */
  --bubble-size: 250px;

  position: fixed; /* stick to the screen, not to the page */
  inset: 0; /* top/right/bottom/left = 0 -> covers the whole screen */
  z-index: 99999; /* above the page content (the Language modal is still higher: 999999) */
  display: grid; /* grid + place-items: center = perfect centering */
  place-items: center;
  pointer-events: none; /* clicks go THROUGH the layer to the page underneath... */
}
/* Tablets (768px to 1199px wide): 30px bigger. */
@media (min-width: 768px) {
  .kp-bubble-layer {
    --bubble-size: 280px;
  }
}
/* Desktops (1200px and wider): 62px bigger. */
@media (min-width: 1200px) {
  .kp-bubble-layer {
    --bubble-size: 312px;
  }
}
/* ...but while a bubble is showing, the script adds "is-open" and the layer
   catches clicks, so clicking anywhere OUTSIDE the bubble pops it too
   (instead of clicking whatever is behind it on the page). */
.kp-bubble-layer.is-open {
  pointer-events: auto;
}
/* Put the aura, the bubble and the splash in the same grid cell, so they
   overlap: the aura behind the bubble, the splash exactly where the bubble was. */
.kp-bubble-layer > * {
  grid-area: 1 / 1;
}

/* ---------------------------------------------------------------------------
   2) THE BUBBLE (a <button>)
   --------------------------------------------------------------------------- */
.kp-bubble {
  position: relative; /* so the layers inside can be positioned on top of it */
  display: none; /* HIDDEN by default - the script shows it with .is-blowing */
  align-items: center;
  font-size: calc(var(--bubble-size) * 0.136); /* text size: 34px at 250px (the text inside inherits this) */
  padding: 0;
  background-color: #b141b9; /* base purple, mostly covered by the color layers */
  height: var(--bubble-size); /* full bubble size */
  width: var(--bubble-size);
  opacity: 92%; /* only a little see-through, so the bubble stands out clearly */
  /* 1) a thin light outline right at the edge (spread 1px, no blur) = sharp edge
     2) a soft turquoise glow around it */
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.55),
    0px 0px 14px 0px #6aebe2cc;
  border: none;
  border-radius: 44% 52% 44% 50%; /* not a perfect circle -> looks more "wobbly" */
  cursor: pointer; /* hand cursor: it can be clicked */
  pointer-events: auto; /* ...except the bubble itself, which DOES catch clicks (see the layer above) */
  -webkit-tap-highlight-color: transparent; /* no gray flash when tapped on phones */
  user-select: none; /* the text can't be accidentally selected/highlighted */
  transition: all 0.3s; /* smooth size change on hover / click (below) */
}
/* A crisp light rim drawn ON TOP of the color layers, following the bubble's
   wobbly shape ("border-radius: inherit" copies the bubble's corners, also while
   they wobble). It makes the bubble's outline sharp and clear.
   pointer-events: none = it never gets in the way of clicks. */
.kp-bubble::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  border: 2px solid rgba(255, 255, 255, 0.7);
  z-index: 7;
  pointer-events: none;
}
/* Added by the script when a menu link is clicked: show the bubble and animate it.
   Two animations run one after the other:
   - kp-blow   : 1 second, grows the bubble from a tiny dot to full size
   - kp-wobble : starts after 1s (the "1s" delay), then slowly wobbles the shape forever */
.kp-bubble.is-blowing {
  display: flex;
  animation:
    kp-blow 1s,
    kp-wobble 4s linear 1s infinite alternate;
}
/* Mouse over the bubble: it grows 10% and glows stronger. */
.kp-bubble:hover {
  height: calc(var(--bubble-size) * 1.1);
  width: calc(var(--bubble-size) * 1.1);
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.6),
    0px 0px 40px 2px #6aebe2ee;
  font-size: calc(var(--bubble-size) * 0.156);
}
/* While the mouse button is held down on it: it squeezes 10% smaller. */
.kp-bubble:active {
  height: calc(var(--bubble-size) * 0.9);
  width: calc(var(--bubble-size) * 0.9);
  transition: all 0.2s;
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.5),
    0px 0px 6px 0px #6aebe2aa;
  font-size: calc(var(--bubble-size) * 0.12);
}

/* The small white shine in the top-left corner (a tilted white oval). */
.kp-bubble__highlight {
  position: absolute;
  top: 12%;
  left: 13%;
  width: 25%;
  height: 10%;
  transform: rotateZ(-40deg); /* tilt it */
  border-radius: 50%; /* oval */
  background-color: #ffffffee; /* white, almost solid -> a bright, clear shine */
  z-index: 5; /* above the color layers */
  animation: kp-move 4s linear 1s infinite alternate; /* gently drifts back and forth */
}

/* The text in the middle of the bubble. */
.kp-bubble__text {
  position: absolute; /* centered with the top/left 50% + translate trick */
  top: 50%;
  left: 50%;
  transform: translateY(-50%) translateX(-50%);
  width: 100%;
  z-index: 6; /* on top of everything inside the bubble */
  font-family: "Sniglet", "Comic Relief", "Comic Neue", sans-serif; /* Sniglet is loaded by the @import above */
  font-weight: 800; /* extra bold */
  color: white;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.25); /* a soft dark shadow so the white text stands out */
  text-align: center;
  word-break: normal; /* the site sets "word-break: break-all" on everything; undo it here */
  white-space: nowrap; /* never wrap the text by itself (a <br> in the text still makes a new line) */
  animation: kp-pulse 4s linear 1s infinite alternate; /* text slowly grows and shrinks */
}

/* The three color layers. They are the same size as the bubble, but each one
   is shifted by a few pixels (top/left), so their edges peek out at slightly
   different places -> the shimmering rainbow edge of a soap bubble.
   All three wobble with the same animation as the bubble. */
.kp-bubble__purple,
.kp-bubble__blue,
.kp-bubble__pink {
  position: absolute;
  height: 100%;
  width: 100%;
  border-radius: 44% 52% 44% 50%;
  animation: kp-wobble 4s linear 1s infinite alternate;
}
/* Main visible layer: green -> blue -> pink gradient (on top of the other two). */
.kp-bubble__purple {
  top: 1px;
  left: -1px;
  background-image: linear-gradient(225deg, #83f2b4 0%, #6fa7e1 60%, #e175e5 100%);
  z-index: 3;
}
/* Turquoise edge, peeking out to the left. */
.kp-bubble__blue {
  top: 2px;
  left: -3px;
  background-color: #6aebe2;
  z-index: 1;
}
/* Pink edge, peeking out at the bottom. */
.kp-bubble__pink {
  top: 3px;
  left: 1px;
  background-color: #e175e5;
  z-index: 1;
}

/* ---------------------------------------------------------------------------
   2b) THE COLORED AURA AROUND THE BUBBLE
   Effect based on "Pop-up design" by fajjet: https://codepen.io/fajjet/pen/oqLGgq
   (only its colored effect: the rings that ripple out + the purple/green glow).

   - .kp-bubble-aura is an invisible circle exactly the size of the bubble,
     sitting behind it with the same center (same grid cell in the layer).
   - Inside it, .kp-aura-rings holds 7 colorful rings that grow from nothing,
     one after the other (biggest first), then fade away - like ripples.
     It has a HOLE in the middle (see "mask" below) that is a bit bigger than
     the bubble - even when the bubble grows 10% on hover - so the rings only
     show AROUND the bubble and never overlap it or show through it.
   - The aura circle itself then gets a soft glow: purple on the left, green
     on the right. The glow stays until the bubble pops.
   All sizes are "bubble size x number", so they grow with the bubble.

   EASY TWEAKS:
   - How light the rings are ... --ring-opacity in .kp-bubble-aura (0 = invisible, 1 = solid)
   - Ring colors ......... the background lines of .kp-aura-ring:nth-child(1..7)
   - Ring sizes .......... the "* number" in --size of .kp-aura-ring:nth-child(1..7)
                           (1 = bubble size; keep them above 1.18 so they stay outside the hole)
   - Ring speed .......... "kp-aura-ring 1.2s" in .kp-bubble-aura.is-on .kp-aura-ring
   - Glow colors/size .... the box-shadow at the end of @keyframes kp-aura-glow
   --------------------------------------------------------------------------- */
.kp-bubble-aura {
  display: none; /* HIDDEN by default - the script shows it with .is-on */
  position: relative; /* the rings box is positioned inside this circle */
  width: var(--bubble-size); /* same size as the bubble */
  height: var(--bubble-size);
  border-radius: 50%; /* round, so the glow follows the bubble's shape */
  --ring-opacity: 0.4; /* rings are partly see-through (40%), so they look light and bright */
}
/* Added by the script together with the bubble. The glow fades in after
   0.7s (while the bubble finishes blowing up) and then stays ("both" =
   keep the first frame before it starts and the last frame after it ends). */
.kp-bubble-aura.is-on {
  display: block;
  animation: kp-aura-glow 0.5s ease 0.7s both;
}
/* The box that holds the rings: a square 2.8x the bubble size, centered on
   the bubble (big enough for the largest ring when it grows while fading out).
   mask = which parts are visible: a circle-shaped gradient that is
   "transparent" (hidden) up to 0.57 x bubble size from the center and solid
   black (visible) from 0.59 x bubble size outward. The bubble's radius is
   0.5 x its size (0.55 when it grows on hover), so the hole is always a bit
   bigger than the bubble: the rings never overlap it, and the small gap
   keeps the bubble's edge sharp and clear. */
.kp-aura-rings {
  position: absolute;
  width: calc(var(--bubble-size) * 2.8);
  height: calc(var(--bubble-size) * 2.8);
  left: calc(50% - var(--bubble-size) * 1.4);
  top: calc(50% - var(--bubble-size) * 1.4);
  pointer-events: none;
  -webkit-mask-image: radial-gradient(
    circle at center,
    transparent calc(var(--bubble-size) * 0.57),
    #000 calc(var(--bubble-size) * 0.59)
  );
  mask-image: radial-gradient(
    circle at center,
    transparent calc(var(--bubble-size) * 0.57),
    #000 calc(var(--bubble-size) * 0.59)
  );
}
/* One ring. Its size comes from --size (set per ring below); left/top
   center it in the rings box. */
.kp-aura-ring {
  position: absolute;
  width: var(--size);
  height: var(--size);
  left: calc(50% - var(--size) / 2);
  top: calc(50% - var(--size) / 2);
  border-radius: 50%;
  transform: scale(0); /* starts as nothing */
}
/* When the aura is on, every ring plays the ripple animation.
   "both" keeps each ring invisible (scale 0) until its own delay is over. */
.kp-bubble-aura.is-on .kp-aura-ring {
  animation: kp-aura-ring 1.2s ease var(--delay) both; /* var(--delay) = each ring's own start time, set below */
}
/* The 7 rings: from the biggest (outside, starts first) to the smallest
   (inside, starts last), 0.1s apart like the CodePen. Later rings are drawn
   on top of earlier ones, so together they form colorful circles.
   - Rings 1 + 2 = two extra colorful rings (pink -> orange, turquoise -> blue),
     added around the outside.
   - Rings 3 to 7 = the CodePen's own purple-to-green colors, each one a bit
     lighter than the one before.
   Sizes are "bubble size x number" (all bigger than the hole, so every ring
   is seen around the bubble). */
.kp-aura-ring:nth-child(1) {
  --size: calc(var(--bubble-size) * 2.2);
  background: linear-gradient(to right, #ff4fc8, #ffa53d); /* pink -> orange (extra) */
  --delay: 0s; /* when this ring starts */
}
.kp-aura-ring:nth-child(2) {
  --size: calc(var(--bubble-size) * 2);
  background: linear-gradient(to right, #29d8e8, #4b7bff); /* turquoise -> blue (extra) */
  --delay: 0.1s;
}
.kp-aura-ring:nth-child(3) {
  --size: calc(var(--bubble-size) * 1.82);
  background: linear-gradient(to right, #504bff, #4cfa63); /* CodePen ring 1 */
  --delay: 0.2s;
}
.kp-aura-ring:nth-child(4) {
  --size: calc(var(--bubble-size) * 1.66);
  background: linear-gradient(to right, #6665ff, #69fa7f); /* CodePen ring 2 */
  --delay: 0.3s;
}
.kp-aura-ring:nth-child(5) {
  --size: calc(var(--bubble-size) * 1.52);
  background: linear-gradient(to right, #8583ff, #85fa99); /* CodePen ring 3 */
  --delay: 0.4s;
}
.kp-aura-ring:nth-child(6) {
  --size: calc(var(--bubble-size) * 1.4);
  background: linear-gradient(to right, #aaaaff, #a7fab7); /* CodePen ring 4 */
  --delay: 0.5s;
}
.kp-aura-ring:nth-child(7) {
  --size: calc(var(--bubble-size) * 1.28);
  background: linear-gradient(to right, #c9c8ff, #c3fad1); /* CodePen ring 5 */
  --delay: 0.6s;
}

/* ---------------------------------------------------------------------------
   3) THE SPLASH (shown for a moment when the bubble pops)
   6 little droplets arranged in a ring. When popping, the ring quickly grows
   bigger and fades out, so the droplets look like they fly away.
   --------------------------------------------------------------------------- */
.kp-bubble-splash {
  display: none; /* HIDDEN by default - the script shows it with .is-popping */
  position: relative; /* the droplets are positioned inside this box */
  width: var(--bubble-size);
  height: var(--bubble-size);
}
/* Added by the script when the bubble is clicked. The animation lasts 0.2s;
   "forwards" keeps the last frame (fully faded out) until the script removes
   the class again. */
.kp-bubble-splash.is-popping {
  display: block;
  animation: kp-splash 0.2s forwards;
}
/* One droplet: a small circle with the same gradient as the bubble
   and a thin white line at its bottom. */
.kp-splash {
  position: absolute;
  height: 30px;
  width: 30px;
  border-bottom: 1px solid #ffffffcc;
  border-radius: 50%;
  background-image: linear-gradient(225deg, #83f2b4 0%, #6fa7e1 60%, #e175e5 100%);
  z-index: 1;
}
/* The droplet's "tail": a thin curved white line above it (a tail inside a
   tail gives two lines), so the droplet looks like it is moving. */
.kp-splash__tail {
  position: absolute;
  top: -30%;
  left: 20%;
  width: 60%;
  height: 60%;
  border-radius: 50%;
  border-top: 1px solid #ffffffcc;
}
/* Place the 6 droplets around the ring and turn each one so its tail
   points back toward the center:
   1 = top-left, 2 = top-right, 3 = middle-left, 4 = middle-right,
   5 = bottom-left, 6 = bottom-right. */
.kp-splash:nth-child(1) {
  top: 0;
  left: 15%;
  transform: rotateZ(120deg);
}
.kp-splash:nth-child(2) {
  top: 0;
  right: 15%;
  transform: rotateZ(-120deg);
}
.kp-splash:nth-child(3) {
  top: 45%;
  left: 0;
  transform: rotateZ(100deg);
}
.kp-splash:nth-child(4) {
  top: 45%;
  right: 0;
  transform: rotateZ(-100deg);
}
.kp-splash:nth-child(5) {
  bottom: 0;
  left: 15%;
  transform: rotateZ(60deg);
}
.kp-splash:nth-child(6) {
  bottom: 0;
  right: 15%;
  transform: rotateZ(-60deg);
}

/* ---------------------------------------------------------------------------
   4) ANIMATIONS
   (All names start with "kp-" so they don't clash with the site's other animations.)
   --------------------------------------------------------------------------- */

/* Wobble: slowly changes the rounded corners, so the bubble's outline
   gently "breathes" like a real soap bubble. */
@keyframes kp-wobble {
  0% { border-radius: 44% 52% 44% 50%; }
  20% { border-radius: 46% 50% 45% 48%; }
  30% { border-radius: 48% 48% 46% 46%; }
  40% { border-radius: 50% 46% 50% 44%; }
  50% { border-radius: 52% 45% 52% 45%; }
  60% { border-radius: 50% 46% 54% 46%; }
  70% { border-radius: 48% 48% 52% 47%; }
  80% { border-radius: 47% 50% 50% 48%; }
  90% { border-radius: 45% 52% 47% 49%; }
  100% { border-radius: 44% 50% 44% 50%; }
}

/* Move: the white shine drifts 5px down-right and back. */
@keyframes kp-move {
  50% { transform: translate(5px, 5px) rotateZ(-41deg); }
}

/* Splash: the ring of droplets grows from small to big while fading out
   (sizes are "bubble size x number": 120x90px -> 350x260px at 250px). */
@keyframes kp-splash {
  0% { width: calc(var(--bubble-size) * 0.48); height: calc(var(--bubble-size) * 0.36); }
  50% { opacity: 1; }
  100% { width: calc(var(--bubble-size) * 1.4); height: calc(var(--bubble-size) * 1.04); opacity: 0; }
}

/* Pulse: the text grows a little bigger and back (38px at 250px). */
@keyframes kp-pulse {
  50% { font-size: calc(var(--bubble-size) * 0.152); }
}

/* Aura ring: grows from nothing to its full size, then keeps growing a
   little while fading away - like a ripple in water.
   var(--ring-opacity) = how see-through the rings are (set on .kp-bubble-aura). */
@keyframes kp-aura-ring {
  0% { transform: scale(0); opacity: var(--ring-opacity); }
  45% { transform: scale(1); opacity: var(--ring-opacity); }
  100% { transform: scale(1.25); opacity: 0; }
}

/* Aura glow: from no glow to a soft purple glow on the left and a green
   glow on the right (the same colors as the CodePen popup).
   The CodePen uses "-50px 0 200px -50px" on a plain white page; on this
   site's colorful background that was almost invisible, so the glow here is
   a bit smaller, with see-through colors:
   rgba(red, green, blue, opacity) - the last number (0.6) = 60% strength.
   (Higher number = darker/stronger glow, lower = lighter.)
   Offsets/blur/spread are "bubble size x number" (40px / 120px / 10px at 250px).
   box-shadow: <left/right offset> <up/down offset> <blur> <spread> <color> */
@keyframes kp-aura-glow {
  from { box-shadow: 0 0 0 0 transparent, 0 0 0 0 transparent; }
  to {
    box-shadow:
      calc(var(--bubble-size) * -0.16) 0 calc(var(--bubble-size) * 0.48) calc(var(--bubble-size) * 0.04) rgba(80, 75, 255, 0.6),
      calc(var(--bubble-size) * 0.16) 0 calc(var(--bubble-size) * 0.48) calc(var(--bubble-size) * 0.04) rgba(76, 250, 99, 0.6);
  }
}

/* Blow: the bubble grows from a 20px dot to its full size.
   The text stays invisible (font-size 0) for the first 15% so it doesn't
   squeeze into the tiny dot, then grows with the bubble. */
@keyframes kp-blow {
  0% { height: 20px; width: 20px; border-radius: 50%; font-size: 0px; }
  15% { font-size: 0px; }
  100% {
    height: var(--bubble-size);
    width: var(--bubble-size);
    border-radius: 44% 52% 44% 50%;
    font-size: calc(var(--bubble-size) * 0.136);
  }
}
