# Meccaniche di Suspense e Reveal: slot machine, ruote della fortuna e loot box > Ricerca applicata alla nostra app: assegniamo le persone alle stanze tramite un algoritmo (risultato **predeterminato**), ma lo riveliamo con un'animazione che costruisce **attesa ed eccitazione**, esattamente come lo "spin" di una slot machine. Questo documento raccoglie la psicologia, le meccaniche di animazione e le tecniche JS/CSS concrete per farlo bene. --- ## 1. La psicologia dello "spin & reveal" Il punto centrale, ripetuto in quasi tutta la letteratura di game design, è controintuitivo ma fondamentale per noi: > **Il momento della rivelazione (lo spin, il rallentamento, il drumroll) genera più coinvolgimento del premio stesso.** Un'animazione di 3-5 secondi fa "più lavoro motivazionale" del contenuto effettivo che viene rivelato. Questo significa che, anche se la stanza è già decisa dall'algoritmo, è la **coreografia della rivelazione** a creare l'emozione. Ecco i meccanismi psicologici da sfruttare. ### 1.1 Anticipazione e dopamina Il cervello rilascia **più dopamina nell'anticipazione di una ricompensa incerta** che di fronte a una garantita ("dopamine release is significantly higher when a reward is uncertain than when it's guaranteed"). L'incertezza percepita — non il risultato — è il motore emotivo. Da qui la regola: **allungare e drammatizzare la fase di attesa**, non accorciarla. ### 1.2 Variable reward (rinforzo a rapporto variabile) Le slot machine funzionano su uno **schedule di rinforzo a rapporto variabile** (variable ratio reinforcement), lo stesso principio comportamentale (Skinner) che rende difficile smettere: la ricompensa arriva in modo imprevedibile, e il cervello resta in stato di anticipazione costante. Nel nostro caso l'assegnazione avviene una volta sola, ma possiamo comunque sfruttare l'**imprevedibilità percepita** dell'esito (quale stanza?) durante lo spin. ### 1.3 Effetto near-miss (quasi-vincita) Il **near-miss** è la situazione in cui i simboli si fermano *quasi* allineati (due jackpot allineati, il terzo a una posizione di distanza). Pur essendo tecnicamente una perdita, stimola il cervello **quasi come una vittoria reale**, rilasciando dopamina e alimentando la sensazione che il colpo grosso sia "a un passo". Applicazione al nostro reveal: durante lo scorrimento, far **passare vicino** ad altre stanze/opzioni prima di fermarsi su quella finale amplifica la tensione ("stava per uscire l'altra stanza..."). È la stessa logica della roulette CS:GO che rallenta sfiorando altri item. ### 1.4 Escalation ed escalation sensoriale I designer aumentano deliberatamente l'**arousal** prima di mostrare il contenuto: - In *Overwatch*, la loot box **trema e vibra** prima di aprirsi. - Fasci di luce dorati e particellari **segnalano un drop raro PRIMA** che l'item appaia. - Suoni, animazioni temporizzate e persino lo **screen shake** enfatizzano l'impatto emotivo. L'escalation crea una **curva di tensione crescente**: più segnali "sta per succedere qualcosa di importante" accumuli, più forte è il picco al reveal. ### 1.5 Il rallentamento finale (slow-down / easing) Elemento chiave e più imitabile: verso la fine, lo spin **decelera progressivamente**. Questo rallentamento è ciò che il cervello legge come "sta per fermarsi, dove cadrà?" — è il momento di massima tensione. In termini tecnici è una curva di **easing-out** (veloce all'inizio, lento alla fine), spesso con un piccolo **overshoot/rimbalzo** finale (`back-out`) per un "settle" soddisfacente (vedi §2.2). ### 1.6 Principi di design etico da mystery box (da Yu-kai Chou) Riassunto delle leve applicabili in modo sano: 1. **Basso costo di partecipazione** — l'utente accetta l'incertezza se lo sforzo è minimo. 2. **Investire nel reveal** — il momento teatrale conta più del premio. 3. **Pacing dei reveal** — reveal troppo frequenti diluiscono l'impatto e la sensibilità dopaminergica; spaziarli mantiene la novità. 4. **Floor garantito / "pity"** — nessuno esce a mani vuote; anche l'esito "comune" deve sembrare significativo (importante per noi: qualunque stanza deve essere presentata come una "bella" assegnazione). --- ## 2. Meccaniche di animazione dei rulli (slot reel) ### 2.1 Come gira un rullo Il rullo è tipicamente una **striscia verticale di simboli** (un contenitore lungo dentro una finestra con `overflow: hidden`). Lo spin si ottiene traslando la striscia in verticale (`transform: translateY(...)`), non spostando i singoli simboli. Approcci comuni: - **CSS transition/animation** su `translateY` con easing (semplice, performante). - **Web Animations API** (`element.animate`) per controllo dinamico del valore finale (consigliato per risultato predeterminato — vedi §7). - **requestAnimationFrame** per controllo frame-by-frame (fisica custom, blur di movimento). Per la **velocità percepita**, durante la fase veloce si può aggiungere un leggero **motion blur** (es. `filter: blur()` verticale) o semplicemente ripetere i simboli in modo che scorrano rapidamente. ### 2.2 Curve di easing: le più importanti Il carattere dell'animazione dipende quasi tutto dalla **timing function**. Riferimento pratico (`easings.net`): | Effetto | Keyword / cubic-bezier | Uso | |---|---|---| | `ease-out` | `cubic-bezier(0, 0, 0.58, 1)` | Decelerazione base a fine spin | | `easeOutBack` (overshoot) | `cubic-bezier(0.34, 1.56, 0.64, 1)` | Il rullo supera il target e torna indietro → "settle" con rimbalzo | | Wheel of fortune (con molla) | `cubic-bezier(0.440, -0.205, 0.000, 1.130)` | Decelerazione + micro-bounce elastico | | `ease-in` | `cubic-bezier(0.42, 0, 1, 1)` | Accelerazione iniziale (partenza dello spin) | **Nota tecnica cruciale sui cubic-bezier**: gli assi `x` (tempo) devono stare tra 0 e 1, ma **`y` (progresso) può uscire da 0–1**. Un `y > 1` produce **overshoot** (l'elemento supera la destinazione e rientra → effetto "back"/molla); un `y < 0` produce undershoot. È così che si ottiene la sensazione elastica del rimbalzo finale con **due sole maniglie**. Per un vero **elastic/bounce multi-oscillazione** (più rimbalzi smorzati), un singolo cubic-bezier non basta: serve un `@keyframes` complesso o una libreria (GSAP, Motion, Svelte easing). `easeOutElastic` dà "l'illusione di un rullo che ruota e poi si assesta". ### 2.3 Struttura tipica dello spin di un rullo 1. **Accelerazione** breve (`ease-in`) o partenza istantanea. 2. **Fase veloce** a velocità costante (loop di simboli, eventuale blur). 3. **Decelerazione** lunga (`ease-out`) — è qui che nasce la suspense. 4. **Settle / bounce** finale (`easeOutBack`) — il rullo si allinea al simbolo con un micro-scatto. ### 2.4 Stagger tra i rulli (fermata sequenziale) Elemento firma delle slot: i rulli **non si fermano tutti insieme**, ma **uno dopo l'altro da sinistra a destra**. Questo: - prolunga la tensione (l'esito totale si scopre solo all'ultimo rullo); - abilita l'effetto **near-miss** (i primi rulli mostrano il simbolo giusto, l'ultimo tiene sul filo). Implementazione: si applica un **delay incrementale** per indice di rullo (es. `delay = index * 400ms`, oppure lo step di aggiornamento è `50ms + index*stagger`). Con Web Animations API basta impostare `delay` diverso per ogni rullo; con CSS, `transition-delay` o `animation-delay` scalati. ### 2.5 Il "bounce/settle" finale I videogiochi di slot inseriscono "un piccolo rimbalzo nei rulli verso la fine dello spin, subito prima che l'esito finale venga mostrato". Tecnicamente: si fa fermare il rullo **poco oltre** la posizione target e lo si riporta indietro con un `easeOutBack` o un keyframe che overshoota di ~1 riga e rientra. È il dettaglio che rende la fermata "soddisfacente" invece che secca. **Riferimenti implementativi slot**: - Victor Toschi, *How to create a Slot Machine animation with CSS and JavaScript* (metodi `init` / `spin` / `shuffle`) + CodePen `toschivictor/pen/JjNZjEj`. - `ezslots` (jQuery toolkit) e `HTML-slot-machine-example` (vanilla) su GitHub. - CodePen `MrFirthy/pen/oGVWqK` (CSS/JS slot machine). --- ## 3. Ruota della fortuna / spinning wheel (fisica e landing) ### 3.1 Struttura La ruota è un cerchio suddiviso in spicchi; ogni spicchio è ruotato di `360° / n * indice` con `transform-origin` sul bordo/centro. Si anima la **rotazione dell'intera ruota** (`transform: rotate(...)`) e un puntatore fisso indica il vincitore in cima. ### 3.2 Decelerazione (l'anima dell'effetto) Come per i rulli, la magia è nella curva: la ruota parte veloce e **decelera** fino a fermarsi. Esempio reale dall'articolo DEV Community *Wheel of Fortune with CSS* (Web Animations API): ```js animation = wheel.animate( [ { transform: `rotate(${previousEndDegree}deg)` }, { transform: `rotate(${newEndDegree}deg)` } ], { duration: 4000, easing: 'cubic-bezier(0.440, -0.205, 0.000, 1.130)', // decelerazione + micro-bounce fill: 'forwards', iterations: 1 } ); ``` ### 3.3 Atterrare su un target (landing predeterminato) Formula generale: ``` angoloSpicchio = 360 / numeroSpicchi offsetTarget = angoloSpicchio * indiceVincitore rotazioneTotale = (giriInteri * 360) + offsetTarget // ± correzione per il puntatore ``` - Diversi **giri interi** (es. `Math.random() * 360 + 1800`, cioè ≥5 giri) servono a rendere l'effetto credibile: "spinnare direttamente sul premio non sembra giusto, servono dei giri completi". - Si aggiunge una **randomizzazione entro lo spicchio** così che il puntatore non cada sempre esattamente al centro (più realistico). - Importante: **cancellare l'animazione precedente** (`animation.cancel()`) prima di rilanciarne una nuova, per evitare conflitti. ### 3.4 Riferimenti wheel - `dev.to/madsstoumann/wheel-of-fortune-with-css` (Web Animations API, cubic-bezier a molla). - `jamesrwilliams.ca/posts/css-wheel-of-fortune` (approccio CSS puro). - **Winwheel.js** (`dougtesting.net/winwheel`) — libreria dedicata con `animation.stopAngle`, spin verso segmento predeterminato. - **Konva** (`konvajs.org/docs/sandbox/Wheel_of_Fortune.html`) — canvas 2D. - Emanuele Feronato — *JavaScript + CSS 3D Wheel of Fortune*. --- ## 4. Card flip, scratch card, box/envelope e loot box Alternative allo spin che possiamo usare come **variazione del reveal** (o come "atto finale" dopo lo spin). ### 4.1 Card flip (rivelazione a carta girata) Tecnica CSS 3D standard (David DeSandro, *Intro to CSS 3D transforms — Card Flip*): - `perspective` sul contenitore genitore → contesto 3D. - `transform-style: preserve-3d` sulla carta. - Due facce sovrapposte; il retro con `backface-visibility: hidden` e pre-ruotato `rotateY(180deg)`. - Al click/hover si applica `transform: rotateY(180deg)` per rivelare. Ottimo come **reveal secco e teatrale**: la carta si gira e mostra la stanza. Si combina bene con un piccolo delay/drumroll prima del flip. ### 4.2 Scratch card (gratta e vinci) Con `` e composite operation: - Si disegna la copertura opaca sul canvas. - `ctx.globalCompositeOperation = "destination-out"` fa sì che il movimento del cursore **cancelli** la copertura, rivelando il contenuto sotto. - Si tracciano archi (`ctx.arc`) alla posizione del puntatore e si può calcolare la **percentuale di area grattata** per auto-rivelare al superamento di una soglia. Vantaggio: introduce **interazione fisica** (l'utente "scopre" la propria stanza), aumentando ownership ed engagement. Riferimenti: Envato Tuts+ *scratch card effect in vanilla JavaScript*; Medium (Mr Zouraiz) *Digital Scratch Card*. ### 4.3 Box / envelope / loot box open Pattern loot box (Overwatch-style): 1. Oggetto (box/busta) che **vibra e trema** (keyframe di shake) con intensità crescente. 2. Build-up di **particellari e luce** che anticipa la rarità/importanza. 3. **Apertura** (scale + fade + burst) e uscita del contenuto (la stanza). Lo shake si fa con un `@keyframes` di piccole traslazioni/rotazioni alternate; l'escalation con `animation-duration` decrescente o ampiezza crescente. Il picco luminoso PRIMA del contenuto è il trucco che "vende" il reveal. --- ## 5. Countdown, drumroll ed escalation della tensione Prima dello spin/reveal, un **build-up** temporizzato aumenta l'attesa. - **Countdown ring animato**: si anima `stroke-dasharray` di un cerchio SVG per "svuotare" un anello nel tempo, o si sovrappone un anello colorato che si consuma come progress bar (CSS-Tricks, *How to Create an Animated Countdown Timer*). - **Drumroll audio + visivo**: rullo di tamburi con vibrazione/pulsazione crescente dell'elemento centrale sincronizzata; il picco coincide con l'inizio dello spin. - **Escalation**: aumentare progressivamente frequenza dei flash, ampiezza dello shake, pitch/volume del suono. La curva di tensione deve **salire** fino al reveal e poi **scaricarsi** al settle. - **Attenzione UX**: i countdown troppo aggressivi generano stress/panico (Medium, *The Stress of Countdown Clocks*). Per noi il countdown deve essere **eccitante, non ansiogeno** → durate brevi (2-3s), tono celebrativo, nessuna penalità reale. --- ## 6. Come far sembrare RANDOM un risultato PREDETERMINATO Questo è il cuore del nostro caso d'uso: l'algoritmo ha già scelto la stanza, ma l'animazione deve costruire suspense come se fosse un sorteggio dal vivo. **Principio guida**: in *tutti* questi sistemi (slot, CS:GO case, loot box) **l'esito è già deciso prima dell'animazione** — "the weapon contained in a case is already predetermined... there is no roulette". L'animazione è pura scenografia. Quindi possiamo replicarlo in modo legittimo. ### Ricetta pratica 1. **Decidi il risultato server-side** (la stanza) e passalo al client. 2. **Costruisci una lista visiva** che *contiene* il risultato in una posizione nota, circondato da distrattori (altre stanze). Es. per una roulette orizzontale stile CS:GO: array lungo di item con il vincitore posizionato vicino alla fine, poi altri item dopo per poter "sfiorare" e superare. 3. **Anima verso quella posizione** con easing-out lungo, così l'utente vede scorrere molte opzioni e non può prevedere dove si fermerà. 4. **Sfrutta il near-miss**: fai passare/rallentare vicino ad altre stanze prima di fermarti su quella giusta (l'effetto "stava per uscire l'altra"). 5. **Settle con bounce** (`easeOutBack`) sull'elemento vincitore + highlight/particellari. 6. **Non rivelare mai la posizione target in anticipo** nel DOM visibile: l'ordine può essere reale ma l'occhio non deve poter contare gli spicchi. ### Roulette orizzontale (CS:GO-style) — la più adatta a "assegnazione stanza" È il pattern che mappa meglio sul nostro problema (una lista di stanze che scorre e si ferma su una). - Striscia orizzontale di card (le stanze, ripetute/mischiate), dentro una finestra con `overflow: hidden` e un **marker centrale** fisso. - Si anima `translateX` negativo fino a portare la card vincitrice sotto il marker, con `ease-out` lungo (3-6s). - La distanza finale include un piccolo **offset random dentro la card** così che non si fermi sempre perfettamente al centro → sembra fisico. - Riferimenti CodePen: `killerek/pen/gLBgWd` (case opening animation), `marctannous/pen/xGRGBz` (layout CS:GO + winner selection), `memir0/pen/QPEPxm` (random name picker side-scrolling). Discussione GSAP: *Creating CS:GO Roulette Horizontal Spinner*. --- ## 7. Tecniche JS/CSS pratiche ### 7.1 Web Animations API (`element.animate`) — consigliata per risultato dinamico Ideale quando il valore finale (posizione/rotazione) è calcolato a runtime dall'esito dell'algoritmo. ```js const spin = strip.animate( [ { transform: 'translateX(0)' }, { transform: `translateX(${-targetX}px)` } ], { duration: 5000, easing: 'cubic-bezier(0.12, 0.8, 0.2, 1)', // decelerazione forte fill: 'forwards' } ); // Sapere quando è finita → trigger del settle/celebrazione spin.finished.then(() => { highlightWinner(); }); // oppure: spin.onfinish = () => { ... } ``` Opzioni chiave: `duration` (ms), `easing`, `iterations`, `delay` (per lo **stagger** dei rulli), `fill: 'forwards'` (mantiene lo stato finale). Controllo: `play/pause/reverse/finish/cancel`; `cancel()` prima di un nuovo spin per evitare conflitti. ### 7.2 CSS transition/animation Semplice e performante per spin a target fisso o loop: ```css .reel { transition: transform 4s cubic-bezier(0.12, 0.8, 0.2, 1); } .reel.spinning { transform: translateY(-3000px); } /* settle con overshoot */ .reel.settle { transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); } ``` Per lo stagger: `transition-delay` / `animation-delay` scalati per indice. Nota: un cubic-bezier a 2 maniglie **non** fa bounce multipli → usare `@keyframes` o libreria. ### 7.3 requestAnimationFrame (fisica custom) Quando serve controllo totale: decelerazione basata su velocità/attrito, snap al simbolo più vicino, motion blur dipendente dalla velocità. ```js function frame() { velocity *= friction; // attrito → decelerazione offset += velocity; strip.style.transform = `translateY(${-offset}px)`; if (velocity > threshold) requestAnimationFrame(frame); else snapToNearest(); // allineamento finale + bounce } ``` `requestAnimationFrame` sincronizza il callback con il ciclo di paint del browser → animazioni fluide ed efficienti. ### 7.4 Performance - Animare **solo `transform` e `opacity`** (compositor-only, no reflow/repaint). - Evitare di animare `top/left/width/height`. - `will-change: transform` sugli elementi che spinnano; rimuoverlo a fine animazione. - Preferire un **singolo loop rAF** condiviso a molti loop indipendenti. ### 7.5 Librerie utili - **GSAP** — timeline, easing avanzati (`back`, `elastic`, `bounce`), usato spesso per roulette CS:GO. - **Motion / Web Animations API improvements** (`motion.dev`) — spring nativi, DX migliorata. - **Winwheel.js** — ruote della fortuna con landing su segmento. - **Konva** — animazioni canvas 2D (ruota, particellari). --- ## 8. Applicazione consigliata al nostro reveal "assegnazione stanza" Sequenza proposta, orchestrando i pezzi sopra: 1. **Build-up** (2-3s): countdown ring + drumroll, elemento centrale che pulsa/vibra con escalation. Tono celebrativo, non ansiogeno (§5). 2. **Spin**: roulette orizzontale CS:GO-style (§6) o rulli slot (§2) che scorrono le stanze, con blur/velocità alta. 3. **Decelerazione** lunga con `ease-out` (§2.2, §3.2): momento di massima tensione. 4. **Near-miss**: rallenta sfiorando 1-2 stanze alternative prima del target (§1.3). 5. **Settle** con `easeOutBack` sul target + burst di luce/particellari (§1.4, §2.5). 6. **Reveal finale**: opzionale card flip / apertura box sulla stanza assegnata (§4) con celebrazione. 7. **Floor positivo**: presentare qualsiasi stanza come esito desiderabile (§1.6, punto pity). Il risultato è deciso dall'algoritmo al passo 0, ma l'utente vive un sorteggio dal vivo credibile ed eccitante. --- ## Fonti **Psicologia (near-miss, variable reward, anticipazione, loot box)** - The Psychology Behind Near Misses in Slot Games — https://news.eternalslots.com/the-psychology-behind-near-misses-in-slot-games/ - Slot Machine Psychology: How the Near Miss Effect Drives Player Behavior — https://www.casinocenter.com/slot-machine-psychology-how-the-near-miss-effect-drives-player-behavior-in-online-gaming/ - The Slot Machine Psyche: Variable Ratio Reinforcement (PSU) — https://www.psu.com/news/the-slot-machine-psyche-how-variable-ratio-reinforcement-drives-modern-gaming-engagement/ - The Psychology Behind Slot Machines (problemgambling.com) — https://www.problemgambling.com/post/the-psychology-behind-slot-machines-how-they-keep-you-gambling - Yu-kai Chou — Decoding the Mystery Box: Reward Design — https://yukaichou.com/advanced-gamification/decoding-the-mystery-box-a-dive-into-the-intricacies-of-reward-design/ - Rare Loot Box Rewards Trigger Larger Arousal and Reward Responses (PMC) — https://pmc.ncbi.nlm.nih.gov/articles/PMC7882574/ - Loot Boxes Hook Players — How We Used the Same Psychology Ethically (Medium) — https://medium.com/avianu/loot-boxes-hook-players-heres-how-we-used-the-same-psychology-ethically-296f44261917 - Zelda's Treasure Chests and the Psychology of Random Rewards (GameTyrant) — https://gametyrant.com/news/zelda-random-rewards-psychology **Animazione rulli slot** - Victor Toschi — Slot Machine animation with CSS and JavaScript (Medium) — https://medium.com/@victortoschi/how-to-create-a-slot-machine-animation-with-css-and-javascript-9073ab9db9ea - CodePen — CSS/JS Slot machine (MrFirthy) — https://codepen.io/MrFirthy/pen/oGVWqK - ezslots (jQuery slots toolkit, GitHub) — https://github.com/kirkjerk/ezslots - HTML slot machine example (vanilla JS, GitHub) — https://github.com/flixrp/HTML-slot-machine-example - Create a slot machine game in vanilla JavaScript (Envato Tuts+) — https://webdesign.tutsplus.com/how-to-create-a-slot-machine-game-in-vanilla-javascript--cms-108974t **Ruota della fortuna** - Wheel of Fortune with CSS (DEV / madsstoumann) — https://dev.to/madsstoumann/wheel-of-fortune-with-css-p-pi-1ne9 - A CSS wheel of fortune (James R. Williams) — https://jamesrwilliams.ca/posts/css-wheel-of-fortune - Winwheel.js — Wheel of Fortune example — https://dougtesting.net/winwheel/examples/wheel_of_fortune - Wheel of Fortune (Konva canvas) — https://konvajs.org/docs/sandbox/Wheel_of_Fortune.html - JavaScript + CSS 3D Wheel of Fortune (Emanuele Feronato) — https://emanueleferonato.com/2025/10/31/javascript-css-3d-wheel-of-fortune/ **Roulette orizzontale / case opening (risultato predeterminato)** - CSGO Roulette Wheel Explained — https://csgoskins.games/csgo-roulette-wheel/ - Case opening animation (CodePen, killerek) — https://codepen.io/killerek/pen/gLBgWd - CS:GO layout + winner selection (CodePen, marctannous) — https://codepen.io/marctannous/pen/xGRGBz - CS:GO-like side-scrolling random name picker (CodePen, memir0) — https://codepen.io/memir0/pen/QPEPxm - GSAP forum — Creating CS:GO Roulette Horizontal Spinner — https://gsap.com/community/forums/topic/42002-help-needed-creating-csgo-roulette-horizontal-spinner/ **Card flip, scratch card** - Card Flip — Intro to CSS 3D transforms (David DeSandro) — https://3dtransforms.desandro.com/card-flip - How To Create a Flip Card with CSS (W3Schools) — https://www.w3schools.com/howto/howto_css_flip_card.asp - Scratch card effect in vanilla JavaScript (Envato Tuts+) — https://webdesign.tutsplus.com/how-to-create-a-scratch-card-effect-in-vanilla-javascript--cms-108922t - Digital Scratch Card HTML/CSS/JS (Medium, Mr Zouraiz) — https://medium.com/@mr.zouraiz1580/digital-scratch-card-html-8eaf1dad6095 **Countdown / drumroll / tensione** - How to Create an Animated Countdown Timer (CSS-Tricks) — https://css-tricks.com/how-to-create-an-animated-countdown-timer-with-html-css-and-javascript/ - The Stress of Countdown Clocks in UX Psychology (Medium) — https://medium.com/design-bootcamp/the-stress-of-countdown-clocks-understanding-panic-inducing-timers-in-ux-psychology-b8d1a6333691 **Easing e tecniche JS/CSS** - Easing Functions Cheat Sheet — https://easings.net/ - cubic-bezier() (CSS-Tricks Almanac) — https://css-tricks.com/almanac/functions/c/cubic-bezier/ - Understanding easing and cubic-bezier curves (Josh Collinsworth) — https://joshcollinsworth.com/blog/easing-curves - Incorporating elastic ease in CSS animations (LogRocket) — https://blog.logrocket.com/how-to-incorporate-elastic-ease-in-css-animations/ - Using the Web Animations API (MDN) — https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API - Improvements to the Web Animations API (Motion) — https://motion.dev/docs/improvements-to-the-web-animations-api-dx - JavaScript Animations with requestAnimationFrame and WAAPI — https://tutorialreference.com/javascript/advanced-topics/animation/javascript-animations-with-requestanimationframe-and-web-animations-api