Nyavokevin 113573866d
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
english
2025-10-13 19:28:06 +03:00

947 lines
26 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import CardShuffleTemplate from '@/components/template/CardShuffleTemplate.vue';
import { Card } from '@/types/cart';
import { router } from '@inertiajs/vue3';
import { computed, onMounted, ref, watchEffect } from 'vue';
const props = defineProps<{
drawCount?: number; // Optional: number of cards expected to be drawn
drawnCards?: Card[]; // Cards provided by the parent at start
clientSessionId?: string;
}>();
defineEmits(['drawCard']);
// Deck / animation state
const deckSize = 10; // spread ~10 cards as requested
const isSpread = ref(false);
const isDrawing = ref(false);
const drawingIndex = ref<number | null>(null);
const revealedCards = ref<Card[]>([]);
const isFlipped = ref<boolean[]>([]);
const isRestacking = ref(false);
const isAutoDrawing = ref(false);
const autoDrawProgress = ref(0);
const remainingDeckSize = computed(() => Math.max(0, deckSize - revealedCards.value.length));
const isFinished = computed(() => !!props.drawnCards && revealedCards.value.length >= props.drawnCards.length);
const shouldAutoDraw = computed(() => props.drawnCards?.length > 15);
console.log(props.drawnCards?.length);
// Auto-draw cards with beautiful animation
const startAutoDraw = async () => {
if (!props.drawnCards || isAutoDrawing.value) return;
isAutoDrawing.value = true;
isSpread.value = false;
const totalCards = props.drawnCards.length;
const delayBetweenCards = 200; // ms between each card
for (let i = 0; i < totalCards; i++) {
if (!isAutoDrawing.value) break; // Allow cancellation
autoDrawProgress.value = (i / totalCards) * 100;
// Add card with animation
const nextCard = props.drawnCards[i];
revealedCards.value.push(nextCard);
isFlipped.value.push(false);
// Wait before next card
if (i < totalCards - 1) {
await new Promise((resolve) => setTimeout(resolve, delayBetweenCards));
}
}
autoDrawProgress.value = 100;
isAutoDrawing.value = false;
// Auto-flip all cards after drawing
setTimeout(() => {
for (let i = 0; i < revealedCards.value.length; i++) {
setTimeout(() => {
isFlipped.value[i] = true;
}, i * 150);
}
}, 500);
};
const startDraw = (index: number) => {
if (!props.drawnCards || revealedCards.value.length >= props.drawnCards.length) return;
isDrawing.value = true;
drawingIndex.value = index;
const DRAW_DURATION = 1000; // keep in sync with CSS animation duration
setTimeout(() => {
const nextCard = props.drawnCards![revealedCards.value.length];
if (nextCard) {
revealedCards.value.push(nextCard);
isFlipped.value.push(false);
}
// Restack after drawing
isSpread.value = false;
// brief bounce to emphasize restack
isRestacking.value = true;
setTimeout(() => {
isRestacking.value = false;
}, 600);
drawingIndex.value = null;
isDrawing.value = false;
}, DRAW_DURATION);
};
const handleDeckClick = () => {
if (isDrawing.value || isAutoDrawing.value) return;
if (isFinished.value) return;
// If auto-draw is available and not started, start it
if (shouldAutoDraw.value && !isAutoDrawing.value && revealedCards.value.length === 0) {
startAutoDraw();
return;
}
// First click spreads the deck
if (!isSpread.value) {
isSpread.value = true;
return;
}
// If already spread, clicking deck auto-draws the middle card
if (props.drawnCards && revealedCards.value.length < props.drawnCards.length) {
const middleIndex = Math.ceil(remainingDeckSize.value / 2);
startDraw(middleIndex);
} else {
// No cards left to draw, just restack
isSpread.value = false;
isRestacking.value = true;
setTimeout(() => {
isRestacking.value = false;
}, 600);
}
};
const onCardClick = (i: number, e?: MouseEvent) => {
// Only handle and stop propagation when spread; otherwise let the deck click handler spread the deck
if (!isSpread.value || isDrawing.value || isAutoDrawing.value) return;
if (e) e.stopPropagation();
if (!props.drawnCards || revealedCards.value.length >= props.drawnCards.length) return;
startDraw(i);
};
const getCardStyle = (i: number) => {
if (drawingIndex.value === i) {
return {
transform: 'translateY(-220px) scale(1.05)',
zIndex: '100',
} as const;
}
if (isSpread.value) {
const mid = (remainingDeckSize.value + 1) / 2;
const offset = i - mid; // negative to left, positive to right
const x = offset * 40; // horizontal spacing
const rot = offset * 6; // slight fan rotation
return {
transform: `translateX(${x}px) rotate(${rot}deg)`,
zIndex: `${50 - Math.abs(offset)}`,
} as const;
}
// Stacked view with subtle 3D depth
return {
transform: `rotate(${-3 + i}deg) translateZ(-${10 * i}px)`,
} as const;
};
const flipCard = (index: number) => {
isFlipped.value[index] = !isFlipped.value[index];
};
// Reset local animation state whenever given cards change
watchEffect(() => {
if (props.drawnCards && props.drawnCards.length > 0) {
isSpread.value = false;
isDrawing.value = false;
drawingIndex.value = null;
revealedCards.value = [];
isFlipped.value = [];
isAutoDrawing.value = false;
autoDrawProgress.value = 0;
} else {
isSpread.value = false;
isDrawing.value = false;
drawingIndex.value = null;
revealedCards.value = [];
isFlipped.value = [];
isAutoDrawing.value = false;
autoDrawProgress.value = 0;
}
});
// Auto-start drawing if conditions are met
onMounted(() => {
if (shouldAutoDraw.value && props.drawnCards && props.drawnCards.length > 0) {
// Small delay to allow initial render
setTimeout(() => {
startAutoDraw();
}, 800);
}
});
const goToSelection = () => {
router.visit('/tirage');
};
const goToResult = () => {
if (props.clientSessionId) {
router.visit(`/resultat?client_session_id=${props.clientSessionId}`);
} else {
router.visit(`/resultat-gratuit?id=${props.drawnCards ? props.drawnCards[0].id : ''}`);
}
};
// Backward compatibility if a parent calls this method directly
const setDrawnCards = (cardData: Card[]) => {
if (cardData && cardData.length) {
isSpread.value = false;
isDrawing.value = false;
drawingIndex.value = null;
revealedCards.value = [];
isFlipped.value = new Array(cardData.length).fill(false);
isAutoDrawing.value = false;
autoDrawProgress.value = 0;
// Auto-start if conditions are met
if (shouldAutoDraw.value) {
setTimeout(() => {
startAutoDraw();
}, 800);
}
}
};
defineExpose({ setDrawnCards });
</script>
<template>
<CardShuffleTemplate>
<template #card-shuffle-slot>
<div class="card-container">
<!-- Auto-draw progress indicator -->
<div v-if="shouldAutoDraw && isAutoDrawing" class="auto-draw-progress">
<div class="progress-bar">
<div class="progress-fill" :style="{ width: `${autoDrawProgress}%` }"></div>
</div>
<div class="progress-text">Automatic distribution in progress... {{ Math.round(autoDrawProgress) }}%</div>
</div>
<!-- Always show the card stack -->
<transition class="card-stack-fade">
<div
class="card-stack relative mt-6 mb-8 flex h-[520px] w-[320px] items-center justify-center rounded-2xl border border-[var(--c-purple)]/30 bg-gradient-to-b from-[var(--card)] to-[var(--card)]/90 p-4 shadow-xl ring-1 ring-[var(--c-purple)]/40"
:class="{
spread: isSpread,
drawing: isDrawing,
restacking: isRestacking,
finished: isFinished,
'auto-drawing': isAutoDrawing,
}"
@click="handleDeckClick"
>
<div class="pointer-events-none absolute -top-16 -left-16 h-40 w-40 rounded-full bg-[var(--c-purple)]/20 blur-3xl"></div>
<div class="pointer-events-none absolute -right-16 -bottom-16 h-40 w-40 rounded-full bg-[var(--c-gold)]/15 blur-3xl"></div>
<!-- Auto-draw prompt -->
<div v-if="shouldAutoDraw && !isAutoDrawing && revealedCards.length === 0" class="auto-draw-prompt">
<div class="prompt-text">Click for automatic distribution</div>
</div>
<div v-for="i in remainingDeckSize" :key="i" class="card group/card" :style="getCardStyle(i)" @click="onCardClick(i, $event)">
<div class="card-back">
<div class="card-inner-content">
<img src="cards/1.png" alt="Card Back" class="card-back-image" />
</div>
</div>
</div>
</div>
</transition>
<!-- Show result only after clicking and when drawnCards is available -->
<transition class="card-result-slide">
<div v-if="revealedCards.length > 0" class="cards-result-container" :class="{ 'many-cards': shouldAutoDraw }">
<div v-for="(card, index) in revealedCards" :key="index" class="card-result-wrapper" :class="`card-${index}`">
<div class="result-card" :class="{ flipped: isFlipped[index], 'auto-flipped': isAutoDrawing }" @click="flipCard(index)">
<div class="card-face card-unknown-front">
<div class="card-inner-content">
<img src="cards/1.png" alt="Card Back" class="card-back-image" />
</div>
</div>
<div class="card-face card-known-back">
<img :src="`/cards/${card.id + 1}.png`" :alt="card.name" class="card-image" />
</div>
</div>
</div>
</div>
</transition>
<button
@click="goToSelection"
class="group mt-8 flex h-12 max-w-[480px] min-w-[200px] cursor-pointer items-center justify-center overflow-hidden rounded-full border border-[var(--c-purple)]/40 bg-gradient-to-r from-[var(--c-purple)]/20 to-[var(--c-purple)]/30 px-8 text-base font-bold tracking-wide text-[var(--c-white)] transition-all duration-300 hover:from-[var(--c-purple)]/40 hover:to-[var(--c-purple)]/50 hover:shadow-lg disabled:cursor-not-allowed disabled:opacity-60"
>
<span class="transition-transform duration-300 group-hover:translate-x-1">Return to card selection</span>
</button>
<button
@click="goToResult"
class="group mt-4 flex h-12 max-w-[480px] min-w-[200px] cursor-pointer items-center justify-center overflow-hidden rounded-full bg-gradient-to-r from-[var(--c-gold)] to-yellow-400 px-8 text-base font-bold tracking-wide text-[var(--c-purple)] shadow-lg transition-all duration-300 hover:shadow-[var(--c-gold)]/40 disabled:cursor-not-allowed disabled:opacity-60"
>
<span class="relative z-10">Draw result</span>
<svg
class="ml-2 h-5 w-5 -translate-x-2 transform opacity-0 transition-all duration-300 group-hover:translate-x-0 group-hover:opacity-100"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
</svg>
</button>
</div>
</template>
</CardShuffleTemplate>
</template>
<style scoped>
.card-container {
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
padding: 2rem 1rem;
}
/* Auto-draw progress indicator */
.auto-draw-progress {
width: 100%;
max-width: 500px;
margin-bottom: 2rem;
text-align: center;
}
.progress-bar {
width: 100%;
height: 8px;
background: rgba(128, 90, 213, 0.2);
border-radius: 4px;
overflow: hidden;
margin-bottom: 0.5rem;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, var(--c-purple), var(--c-gold));
border-radius: 4px;
transition: width 0.3s ease;
}
.progress-text {
font-size: 0.9rem;
color: var(--c-white);
opacity: 0.8;
}
/* Auto-draw prompt */
.auto-draw-prompt {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
z-index: 5;
background: rgba(0, 0, 0, 0.7);
padding: 1rem 1.5rem;
border-radius: 12px;
backdrop-filter: blur(10px);
border: 1px solid rgba(240, 186, 45, 0.3);
}
.prompt-icon {
font-size: 2rem;
margin-bottom: 0.5rem;
}
.prompt-text {
color: var(--c-white);
font-size: 0.9rem;
font-weight: 500;
}
.card {
width: 250px;
height: 400px;
background: radial-gradient(circle at 30% 20%, rgba(240, 186, 45, 0.06), transparent 60%), linear-gradient(145deg, #111, #1b1b1b);
border-radius: 18px;
border: 1px solid rgba(128, 90, 213, 0.25);
box-shadow:
0 12px 24px rgba(0, 0, 0, 0.35),
0 0 0 1px rgba(240, 186, 45, 0.15) inset;
position: absolute;
transition:
transform 0.5s ease-in-out,
box-shadow 0.5s ease-in-out;
cursor: pointer;
transform-style: preserve-3d;
backface-visibility: hidden;
}
/* Animation stack globale */
.card-stack {
transition: transform 0.6s ease-in-out;
display: flex;
align-items: center;
justify-content: center;
perspective: 1000px; /* ajoute profondeur */
}
/* Hover sur la pile */
.card-stack:not(.spread):not(.auto-drawing):hover {
transform: translateY(-10px) rotateX(2deg) rotateY(-2deg);
}
.card-stack:not(.spread):not(.auto-drawing):hover .card:nth-child(1) {
transform: rotateY(-5deg) rotateX(5deg) translateZ(30px) translateX(-20px);
}
.card-stack:not(.spread):not(.auto-drawing):hover .card:nth-child(2) {
transform: rotateY(0deg) rotateX(2deg) translateZ(20px);
}
.card-stack:not(.spread):not(.auto-drawing):hover .card:nth-child(3) {
transform: rotateY(5deg) rotateX(5deg) translateZ(10px) translateX(20px);
}
/* Glow doré subtil au hover */
.card-stack:not(.auto-drawing):hover .card-back {
box-shadow: 0 0 20px rgba(215, 186, 141, 0.6);
transition: box-shadow 0.6s ease-in-out;
}
/* Auto-drawing state */
.card-stack.auto-drawing {
cursor: default;
animation: gentle-pulse 2s infinite;
}
@keyframes gentle-pulse {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.02);
}
}
/* Animation click */
@keyframes card-click-tilt {
0% {
transform: translateY(-10px) rotateX(2deg) rotateY(-2deg);
}
30% {
transform: translateY(-5px) rotateX(-4deg) rotateY(4deg);
}
60% {
transform: translateY(-12px) rotateX(3deg) rotateY(-3deg);
}
100% {
transform: translateY(-10px) rotateX(2deg) rotateY(-2deg);
}
}
/* Drawing animation */
@keyframes card-drawing {
0% {
transform: translateY(-10px) rotateX(2deg) rotateY(-2deg);
}
25% {
transform: translateY(-30px) rotateX(10deg) rotateY(-10deg);
}
50% {
transform: translateY(-40px) rotateX(-5deg) rotateY(5deg);
}
75% {
transform: translateY(-30px) rotateX(5deg) rotateY(-5deg);
}
100% {
transform: translateY(-10px) rotateX(2deg) rotateY(-2deg);
}
}
/* Active sur clic */
.card-stack.clicked {
animation: card-click-tilt 0.4s ease-in-out;
}
.card-stack.drawing {
animation: card-drawing 1s ease-in-out;
}
/* Restack bounce animation to emphasize stack collapse */
.card-stack.restacking {
animation: stack-restack 0.5s ease-out;
}
/* Keep stack visible but inert when finished */
.card-stack.finished {
pointer-events: none;
opacity: 0.9;
}
@keyframes stack-restack {
0% {
transform: translateY(-8px) rotateX(3deg) rotateY(-3deg);
}
60% {
transform: translateY(2px) rotateX(-1deg) rotateY(1deg);
}
100% {
transform: translateY(0) rotateX(0) rotateY(0);
}
}
/* Back des cartes */
.card-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
border-radius: 18px;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(180deg, rgba(240, 186, 45, 0.2), rgba(240, 186, 45, 0.12));
border: 1px solid rgba(240, 186, 45, 0.35);
}
.card-inner-content {
width: calc(100% - 12px);
height: calc(100% - 12px);
background-color: #0c0c0c;
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
box-shadow: inset 0 0 0 1px rgba(128, 90, 213, 0.25);
}
.card-back-image {
width: 100%;
height: 100%;
object-fit: cover;
opacity: 0.95;
filter: saturate(0.9) contrast(1.05);
border-radius: 16px;
}
.card-result-wrapper {
width: clamp(140px, 12vw, 160px); /* target ~67 per row on wide screens */
aspect-ratio: 5 / 8; /* maintain 250x400 proportion */
perspective: 1000px;
border-radius: 18px;
transition: transform 0.5s ease;
}
.card-result-wrapper:hover {
transform: translateY(-10px);
}
.card-back-design-wrapper {
background: radial-gradient(circle, var(--midnight-blue) 0%, #121a2c 100%);
display: flex;
align-items: center;
justify-content: center;
}
.card-back-design {
width: 80%;
height: 80%;
border: 2px solid var(--subtle-gold);
border-radius: 8px;
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.card-back-design::before,
.card-back-design::after {
content: '';
position: absolute;
width: 50%;
height: 50%;
border-color: var(--subtle-gold);
opacity: 0.5;
}
.card-face {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
border-radius: 18px;
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.card-unknown-front {
background-color: var(--subtle-gold);
display: flex; /* Keep flexbox for centering its *own* content */
align-items: center;
justify-content: center;
}
.card-known-back {
background-color: var(--subtle-gold);
display: flex;
justify-content: center;
align-items: center;
transform: rotateY(180deg);
position: relative;
border-radius: 18px;
overflow: hidden;
}
.card-back-design::before {
top: -2px;
left: -2px;
border-top-width: 1px;
border-left-width: 1px;
border-top-style: solid;
border-left-style: solid;
border-top-left-radius: 8px;
}
.card-back-design::after {
bottom: -2px;
right: -2px;
border-bottom-width: 1px;
border-right-width: 1px;
border-bottom-style: solid;
border-right-style: solid;
border-bottom-right-radius: 8px;
}
/* Result card styles */
.cards-result-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 15px; /* tighter gaps to fit 67 per row */
margin-top: 2rem;
position: relative;
z-index: 10;
max-width: 100%;
padding: 0 1rem;
}
/* Enhanced layout for many cards */
.cards-result-container.many-cards {
gap: 15px;
justify-content: center; /* keep centered alignment even for many cards */
}
.cards-result-container.many-cards .card-result-wrapper {
width: clamp(140px, 12vw, 160px);
aspect-ratio: 5 / 8; /* keeps card proportions */
margin-bottom: 10px;
}
.card-result-container {
perspective: 1000px;
}
.result-card {
width: 100%;
height: 100%;
position: relative;
transform-style: preserve-3d;
transition: transform 0.8s;
cursor: pointer;
}
.result-card.flipped {
transform: rotateY(180deg);
}
.result-card.auto-flipped {
transition: transform 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.card-front,
.card-back-info {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
border-radius: 16px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 1rem;
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
text-align: center;
overflow-y: auto;
}
.card-back-info p {
color: var(--midnight-blue); /* Adjust color if needed */
}
.card-front {
background: linear-gradient(145deg, var(--pure-white), var(--linen));
color: var(--midnight-blue);
}
.card-back-info {
/* Replace the existing background property */
background-image: url('back-card.svg'); /* background-size: cover; /* This makes the image cover the entire element */
background-position: center; /* This centers the image in the element */
background-repeat: no-repeat; /* This prevents the image from repeating */
color: var(--pure-white);
transform: rotateY(180deg);
text-align: center;
overflow-y: auto;
}
.card-content-wrapper {
background: linear-gradient(145deg, var(--pure-white), var(--linen));
color: var(--midnight-blue);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 1rem;
transform: rotateY(180deg); /* This is the key part to make it the 'back' of the card */
}
.card-image {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 18px;
position: absolute;
top: 0;
left: 0;
}
.card-description-overlay {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.75) 100%);
padding: 12px;
color: white;
text-align: center;
border-bottom-left-radius: 18px;
border-bottom-right-radius: 18px;
box-shadow: 0 -6px 30px rgba(0, 0, 0, 0.35);
pointer-events: none;
}
.card-description-overlay h3 {
margin: 0; /* Remove default margin */
font-size: 1.8rem; /* Make the name larger */
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7); /* Add subtle shadow for readability */
color: var(--pure-white); /* Ensure it's clearly white */
letter-spacing: 1px; /* Add some letter spacing */
}
/* Hide these elements completely */
.card-description-overlay p.description,
.card-description-overlay p.orientation,
.card-description-overlay div.symbolism {
display: none;
}
.orientation {
font-style: italic;
margin-top: 0.5rem;
color: var(--spiritual-earth);
}
.description {
margin: 1rem 0;
font-size: 0.9rem;
}
.symbolism {
margin-top: 1rem;
font-size: 0.8rem;
}
.symbolism p {
margin: 0.3rem 0;
}
.click-hint {
margin-top: 1rem;
font-size: 0.7rem;
opacity: 0.7;
}
.card-stack-fade-leave-active {
transition: all 0.8s ease;
}
.card-stack-fade-leave-to {
opacity: 0;
transform: translateY(-50px) scale(0.9);
}
.cards-result-slide-enter-active {
transition: all 0.8s ease;
transition-delay: 0.3s;
}
.cards-result-slide-enter-from {
opacity: 0;
transform: translateY(50px);
}
/* Responsive design */
@media (max-width: 1200px) {
.cards-result-container .card-result-wrapper {
width: clamp(140px, 12vw, 160px);
/* height handled by aspect-ratio */
}
}
@media (max-width: 992px) {
.cards-result-container .card-result-wrapper {
width: clamp(140px, 20vw, 160px);
/* height handled by aspect-ratio */
}
.card {
width: 220px;
height: 352px;
}
.card-stack {
width: 280px;
height: 460px;
}
}
@media (max-width: 768px) {
.cards-result-container {
gap: 15px;
}
.cards-result-container .card-result-wrapper {
width: clamp(140px, 26vw, 160px);
/* height handled by aspect-ratio */
}
.card {
width: 200px;
height: 320px;
}
.card-stack {
width: 260px;
height: 420px;
}
.card-description-overlay h3 {
font-size: 1.4rem;
}
}
@media (max-width: 576px) {
.cards-result-container {
gap: 10px;
}
.cards-result-container .card-result-wrapper {
width: clamp(140px, 36vw, 160px);
/* height handled by aspect-ratio */
}
.card {
width: 180px;
height: 288px;
}
.card-stack {
width: 240px;
height: 380px;
}
.card-description-overlay h3 {
font-size: 1.2rem;
padding: 8px;
}
.auto-draw-prompt {
padding: 0.8rem 1rem;
}
.prompt-icon {
font-size: 1.5rem;
}
.prompt-text {
font-size: 0.8rem;
}
}
/* Animation for auto-drawing cards */
@keyframes card-appear {
0% {
opacity: 0;
transform: scale(0.8) translateY(20px);
}
100% {
opacity: 1;
transform: scale(1) translateY(0);
}
}
.cards-result-container .card-result-wrapper {
animation: card-appear 0.5s ease forwards;
}
/* Stagger animation for multiple cards */
.cards-result-container .card-result-wrapper:nth-child(1) {
animation-delay: 0.1s;
}
.cards-result-container .card-result-wrapper:nth-child(2) {
animation-delay: 0.2s;
}
.cards-result-container .card-result-wrapper:nth-child(3) {
animation-delay: 0.3s;
}
.cards-result-container .card-result-wrapper:nth-child(4) {
animation-delay: 0.4s;
}
.cards-result-container .card-result-wrapper:nth-child(5) {
animation-delay: 0.5s;
}
.cards-result-container .card-result-wrapper:nth-child(6) {
animation-delay: 0.6s;
}
.cards-result-container .card-result-wrapper:nth-child(7) {
animation-delay: 0.7s;
}
.cards-result-container .card-result-wrapper:nth-child(8) {
animation-delay: 0.8s;
}
.cards-result-container .card-result-wrapper:nth-child(9) {
animation-delay: 0.9s;
}
.cards-result-container .card-result-wrapper:nth-child(10) {
animation-delay: 1s;
}
.cards-result-container .card-result-wrapper:nth-child(n + 11) {
animation-delay: 1.1s;
}
</style>