/* ==========================================================================
   party.css — THE BIRTHDAY LAYER.
   --------------------------------------------------------------------------
   Everything in here is decoration bolted on top of styles.css. It does not
   move a single element: no layout, no spacing, no type sizes, and the glass
   panels are untouched — all of this sits BEHIND them, which is exactly what
   frosted glass wants (more going on to blur).

   What it adds:
     1. bunting + fairy lights strung across the top
     2. confetti and ribbon drifting down the whole page, slowly
     3. balloons you can actually pop (markup is built in party.js)
     4. sparkles from the cursor and from every tap
     5. small flourishes: confetti dots on headings, twinkles round her name

   Colours all come from the same theme variables as everything else, so
   swapping the theme block at the top of styles.css recolours this too.
   Every animation is switched off at the bottom under reduced motion.
   ========================================================================== */

/* ──────────────────────────────────────────────────────────────────────────
   1. BUNTING — strung across the top of the screen, gently swaying.
   Built by party.js so the number of flags matches the screen width.
   z-index 3 keeps it behind the gate and the chapters (both z-index 4).
   ────────────────────────────────────────────────────────────────────────── */
#garland {
  position: fixed; top: 0; left: 0; right: 0; height: 132px;
  z-index: 3; pointer-events: none; overflow: hidden;
  opacity: 0; animation: garland-drop 1.4s var(--ease-back) .35s forwards;
}
@keyframes garland-drop { from { opacity: 0; transform: translateY(-46px); } to { opacity: 1; transform: none; } }

/* once she is inside, the bunting steps back so it decorates rather than
   competes with what she is reading */
body.in-journey #garland { top: 0; opacity: .38; animation: none; }

/* the string itself */
#garland svg { display: block; width: 100%; height: 100%; overflow: visible; }
#garland path {
  fill: none;
  stroke: rgba(255, 255, 255, .3);
  stroke-width: 1.6; stroke-linecap: round;
}

/* the flags */
#garland i {
  position: absolute; display: block;
  width: 21px; height: 27px; margin-left: -10.5px;
  background: var(--c);
  background: linear-gradient(180deg, var(--c), color-mix(in srgb, var(--c) 55%, #000));
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  transform-origin: 50% 0;
  animation: flag-sway 5.2s ease-in-out infinite;
  animation-delay: var(--d, 0s);
  opacity: .88;
}
@keyframes flag-sway {
  0%, 100% { transform: rotate(-3.5deg); }
  50%      { transform: rotate(3.5deg); }
}

/* the little bulbs strung between the flags */
#garland u {
  position: absolute; display: block;
  width: 7px; height: 7px; margin-left: -3.5px;
  border-radius: 50%;
  background: var(--c);
  box-shadow: 0 0 9px 2px var(--c);
  animation: bulb-glow 3.4s ease-in-out infinite;
  animation-delay: var(--d, 0s);
}
@keyframes bulb-glow {
  0%, 100% { opacity: .3;  transform: scale(.8); }
  50%      { opacity: .95; transform: scale(1.12); }
}

/* ──────────────────────────────────────────────────────────────────────────
   2. DRIFT — confetti and ribbon falling down the page all the time.
   Sparse and slow on purpose: atmosphere, not a screensaver.
   ────────────────────────────────────────────────────────────────────────── */
#drift { position: fixed; inset: 0; z-index: 1; pointer-events: none; overflow: hidden; }
#drift i {
  position: absolute; display: block;
  left: var(--x); top: 0;
  width: var(--w); height: var(--h);
  background: var(--c);
  opacity: var(--o, .3);
  border-radius: 1px;
  will-change: transform;
  animation: drift-fall var(--dur) linear infinite;
  animation-delay: var(--del);
}
#drift i.is-round  { border-radius: 50%; }
#drift i.is-ribbon { border-radius: 999px; }
@keyframes drift-fall {
  0%   { transform: translate3d(0, -16vh, 0) rotate(0deg); }
  25%  { transform: translate3d(var(--sx), 16vh, 0) rotate(180deg); }
  50%  { transform: translate3d(0, 48vh, 0) rotate(360deg); }
  75%  { transform: translate3d(calc(var(--sx) * -1), 80vh, 0) rotate(540deg); }
  100% { transform: translate3d(0, 116vh, 0) rotate(720deg); }
}

/* ──────────────────────────────────────────────────────────────────────────
   3. BALLOONS — rounder, warmer, and poppable.
   Markup: <b> does the rising, the <i> inside is the balloon itself, so a pop
   can scale the <i> without cancelling the rise animation on the <b>.
   ────────────────────────────────────────────────────────────────────────── */
#balloons { position: fixed; inset: 0; z-index: 1; pointer-events: none; overflow: hidden; }
#balloons b {
  position: absolute; bottom: -26vh; display: block;
  width: var(--w); height: calc(var(--w) * 1.22);
  animation: rise-balloon var(--dur) linear infinite;
  animation-delay: var(--del);
  will-change: transform;
}
#balloons b > i {
  position: absolute; inset: 0; display: block;
  border-radius: 50% 50% 47% 47% / 44% 44% 56% 56%;
  background:
    radial-gradient(circle at 30% 24%, rgba(255, 255, 255, .72), transparent 42%),
    radial-gradient(circle at 72% 78%, rgba(0, 0, 0, .22), transparent 46%),
    var(--c);
  opacity: .3;
  filter: drop-shadow(0 6px 18px rgba(0, 0, 0, .5));
  transition: opacity .3s var(--ease), transform .3s var(--ease-back);
}
/* the knot */
#balloons b > i::before {
  content: ''; position: absolute; top: 98%; left: 50%;
  width: 9px; height: 8px; margin-left: -4.5px;
  background: var(--c);
  clip-path: polygon(50% 0, 100% 100%, 0 100%);
}
/* the curly string */
#balloons b > i::after {
  content: ''; position: absolute; top: calc(98% + 7px); left: 50%;
  width: 16px; height: 78px; margin-left: -8px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='80' viewBox='0 0 16 80'%3E%3Cpath d='M8 0C2 15 14 29 8 45 3 59 12 67 8 80' fill='none' stroke='%23ffffff' stroke-opacity='.5' stroke-width='1.3'/%3E%3C/svg%3E") no-repeat center top;
}
@keyframes rise-balloon {
  0%   { transform: translate3d(0, 0, 0) rotate(-5deg); }
  50%  { transform: translate3d(22px, -66vh, 0) rotate(4deg); }
  100% { transform: translate3d(0, -140vh, 0) rotate(-3deg); }
}

/* inside the journey there is text everywhere, so they step back and just
   drift about behind it */
body.in-journey #balloons b > i { opacity: .19; }

/* hovering one lights it up, so she works out they can be popped */
#balloons b.is-hot > i { opacity: .62; transform: scale(1.07); }
body.in-journey #balloons b.is-hot > i { opacity: .5; }
body.balloon-near { cursor: pointer; }

/* and popping one */
#balloons b.is-pop > i { animation: balloon-pop .3s ease-out forwards; }
@keyframes balloon-pop {
  0%   { transform: scale(1);    opacity: .5; }
  38%  { transform: scale(1.32); opacity: .85; }
  100% { transform: scale(.15);  opacity: 0; }
}
#balloons b.is-pop > i::before,
#balloons b.is-pop > i::after { opacity: 0; transition: opacity .18s; }

/* ──────────────────────────────────────────────────────────────────────────
   4. SPARKLES — thrown by taps, clicks and the cursor. Above the confetti
   canvas (z-index 90) so nothing eats them.
   ────────────────────────────────────────────────────────────────────────── */
#sparkles { position: fixed; inset: 0; z-index: 91; pointer-events: none; overflow: hidden; }
#sparkles span {
  position: absolute; display: block;
  width: var(--s); height: var(--s);
  margin: calc(var(--s) / -2) 0 0 calc(var(--s) / -2);
  background: var(--c);
  border-radius: 50%;
  box-shadow: 0 0 8px var(--c);
  animation: spark-out var(--dur) var(--ease) forwards;
}
#sparkles span.is-star {
  border-radius: 0; box-shadow: 0 0 10px var(--c);
  clip-path: polygon(50% 0%, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0% 50%, 39% 39%);
}
@keyframes spark-out {
  0%   { opacity: 1; transform: translate3d(0, 0, 0) scale(.35) rotate(0deg); }
  100% { opacity: 0; transform: translate3d(var(--tx), var(--ty), 0) scale(1.1) rotate(var(--rot)); }
}

/* the cursor trail: no travel, just a warm fade downward */
#sparkles span.is-trail { animation-name: spark-trail; box-shadow: 0 0 12px var(--c); }
@keyframes spark-trail {
  0%   { opacity: .95; transform: translate3d(0, 0, 0) scale(1); }
  100% { opacity: 0;   transform: translate3d(var(--tx), 22px, 0) scale(.2); }
}

/* ──────────────────────────────────────────────────────────────────────────
   5. FLOURISHES on things that were already there.
   ────────────────────────────────────────────────────────────────────────── */

@keyframes candle-breathe { 50% { opacity: .5; transform: translate(-50%, -50%) scale(1.08); } }


/* primaries get a warmer halo on top of the pink one they already had */
.btn-primary {
  box-shadow:
    0 14px 36px -12px rgba(255, 10, 108, .75),
    0 0 30px -14px var(--gold),
    inset 0 1px 0 rgba(255, 255, 255, .5);
}

/* the things-about-you rows get a confetti tick that cycles the palette.
   It lives on .tf-text because that is the card now — see the timeline in
   styles.css section 3b. */
.tf-text { position: relative; }
.tf-item .tf-text::after {
  content: ''; position: absolute; right: 16px; top: 50%;
  width: 6px; height: 6px; margin-top: -3px; border-radius: 50%;
  background: var(--gold); opacity: 0; transform: scale(.4);
  transition: opacity .3s var(--ease), transform .3s var(--ease-back);
}
.tf-item:hover .tf-text::after { opacity: .9; transform: scale(1); }
.tf-item:nth-child(5n+2) .tf-text::after { background: var(--pink); }
.tf-item:nth-child(5n+3) .tf-text::after { background: var(--cyan); }
.tf-item:nth-child(5n+4) .tf-text::after { background: var(--mint); }
.tf-item:nth-child(5n+5) .tf-text::after { background: var(--orange); }

/* ──────────────────────────────────────────────────────────────────────────
   PHONES — fewer moving parts, smaller decorations.
   ────────────────────────────────────────────────────────────────────────── */
@media (max-width: 700px) {
  #garland { height: 104px; }
  #garland i { width: 17px; height: 22px; margin-left: -8.5px; }
  #garland u { width: 6px; height: 6px; margin-left: -3px; }
  #balloons b > i { opacity: .22; }
  body.in-journey #balloons b > i { opacity: .15; }
}

/* ──────────────────────────────────────────────────────────────────────────
   REDUCED MOTION — decorations that only exist to move are removed outright;
   the ones that read fine standing still simply stop.
   ────────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  #drift, #sparkles, #balloons { display: none; }
  #garland { opacity: 1; transform: none; animation: none; }
  #garland i, #garland u { animation: none; }
  #garland u { opacity: .8; }
  .gate-title .tw { opacity: .8; animation: none; }
}

/* ──────────────────────────────────────────────────────────────────────────
   PRINT — none of this belongs on paper.
   ────────────────────────────────────────────────────────────────────────── */
@media print {
  #garland, #drift, #sparkles, #balloons { display: none !important; }
}
