.birthday-container { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: 9999; overflow: hidden; contain: strict; } .birthday-symbol { position: fixed; top: 0; left: 0; animation: birthday-rise linear infinite forwards; opacity: 0.95; z-index: 40; pointer-events: none; } .birthday-sway { will-change: transform; animation-name: birthday-sway; animation-timing-function: ease-in-out; animation-iteration-count: infinite; animation-direction: alternate; } .birthday-inner { pointer-events: auto; /* Allow hover over the actual item */ cursor: crosshair; display: inline-block; } /* MARK: Balloon Size */ .birthday-symbol img { width: 18vh; height: auto; max-width: 100px; object-fit: contain; } .birthday-confetti-wrapper { position: fixed; top: 0; left: 0; z-index: 30; will-change: transform; animation-name: birthday-confetti-fall; animation-timing-function: linear; animation-iteration-count: infinite; pointer-events: none; } .birthday-confetti { width: 8px; height: 16px; background-color: rgb(0, 0, 0); will-change: transform; animation-name: birthday-flutter; animation-timing-function: linear; animation-iteration-count: infinite; } .birthday-confetti.circle { width: 8px; height: 8px; border-radius: 50%; } .birthday-confetti.square { width: 8px; height: 8px; } .birthday-confetti.triangle { width: 10px; height: 10px; clip-path: polygon(50% 0%, 0% 100%, 100% 100%); } @keyframes birthday-rise { 0% { transform: translate3d(var(--x-pos, 0vw), 110vh, 0) rotate(var(--start-rot, 0deg)); opacity: 0; } 10% { opacity: 1; } 90% { opacity: 1; } 100% { transform: translate3d(var(--x-pos, 0vw), -20vh, 0) rotate(calc(var(--start-rot, 0deg) * -1)); opacity: 0; } } @keyframes birthday-confetti-fall { 0% { transform: translate3d(var(--x-pos, 0vw), -10vh, 0); } 100% { transform: translate3d(var(--x-pos, 0vw), 110vh, 0); } } @keyframes birthday-sway { 0% { transform: translateX(calc(var(--sway-amount, 50px) * -1)); } 100% { transform: translateX(var(--sway-amount, 50px)); } } @keyframes birthday-flutter { 0% { transform: rotate3d(var(--rx, 1), var(--ry, 1), var(--rz, 0), 0deg); } 100% { transform: rotate3d(var(--rx, 1), var(--ry, 1), var(--rz, 0), var(--rot-dir, 360deg)); } } @keyframes birthday-pop { 0% { transform: scale(1); opacity: 1; filter: brightness(1); } 30% { transform: scale(1.3); opacity: 1; filter: brightness(1.5); } 100% { transform: scale(0); opacity: 0; filter: brightness(2); } } .birthday-burst-wrapper { position: absolute; pointer-events: none; z-index: 1000; will-change: transform, opacity; animation: birthday-burst-y 1.2s cubic-bezier(0.42, 0, 1, 1) forwards; } .birthday-burst-confetti { will-change: transform; animation: birthday-burst-x 1.2s cubic-bezier(0.25, 1, 0.5, 1) forwards; } .birthday-burst-confetti.circle { border-radius: 50%; } .birthday-burst-confetti.triangle { width: 10px; height: 10px; clip-path: polygon(50% 0%, 0% 100%, 100% 100%); } @keyframes birthday-burst-y { 0% { transform: translateY(0); opacity: 1; } 100% { transform: translateY(calc(var(--burst-y) + 150px)); /* Gravity pull downwards */ opacity: 0; } } @keyframes birthday-burst-x { 0% { transform: translateX(0) rotate3d(var(--rx), var(--ry), var(--rz), 0deg); } 100% { transform: translateX(calc(var(--burst-x) * 1.5)) rotate3d(var(--rx), var(--ry), var(--rz), var(--rot-dir)); } }