feat: chytání motýlků síťkou s počítadlem
CI / Generate TypeScript types (push) Successful in 10s
CI / Server unit tests (push) Successful in 23s
CI / Build server (push) Successful in 35s
CI / Build client (push) Successful in 42s
CI / Playwright E2E tests (push) Successful in 1m27s
CI / Build and push Docker image (push) Successful in 42s
CI / Notify (push) Successful in 2s

Přidána síťka, kterou lze uchopit myší a lovit poletující motýly.
Po chycení přiletí nový (počet létajících se nemění), počet ulovených
se zobrazuje jako odznak a ukládá do local storage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stánek Pavel
2026-07-21 10:08:47 +02:00
co-authored by Claude Opus 4.8
parent 146c31b775
commit c8c5ecc60c
4 changed files with 440 additions and 5 deletions
+128
View File
@@ -48,9 +48,137 @@
}
}
// --- Síťka na chytání --------------------------------------------------------
.butterfly-net {
position: fixed;
top: 0;
left: 0;
background-repeat: no-repeat;
background-position: center;
background-size: contain;
pointer-events: auto;
cursor: grab;
z-index: 4;
will-change: transform;
filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.25));
transition: filter 0.15s ease;
// zabrání označování/scrollování při tažení na dotykových zařízeních
touch-action: none;
user-select: none;
&.grabbed {
cursor: grabbing;
filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.35));
}
&.catch-pop {
animation: butterfly-net-pop 0.3s ease-out;
}
}
@keyframes butterfly-net-pop {
0% {
filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.25)) brightness(1);
}
40% {
filter: drop-shadow(0 2px 8px rgba(120, 200, 120, 0.7)) brightness(1.25);
}
100% {
filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.25)) brightness(1);
}
}
// Prchavé „+1" v místě chycení
.butterfly-catch-fx {
position: fixed;
margin: -12px 0 0 10px;
font-weight: 700;
font-size: 1.1rem;
color: #2f9e44;
text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8);
pointer-events: none;
z-index: 5;
animation: butterfly-catch-float 0.75s ease-out forwards;
}
@keyframes butterfly-catch-float {
0% {
opacity: 0;
transform: translateY(0) scale(0.9);
}
20% {
opacity: 1;
transform: translateY(-6px) scale(1);
}
100% {
opacity: 0;
transform: translateY(-40px) scale(1);
}
}
// --- Počítadlo chycených motýlů ----------------------------------------------
.butterfly-counter {
position: fixed;
bottom: 16px;
left: 16px;
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 12px 6px 10px;
background: rgba(255, 255, 255, 0.85);
border: 1px solid rgba(0, 0, 0, 0.08);
border-radius: 999px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
backdrop-filter: blur(4px);
font-weight: 600;
font-size: 0.95rem;
color: #333;
z-index: 5;
user-select: none;
&.bump {
animation: butterfly-counter-bump 0.3s ease-out;
}
}
.butterfly-counter-icon {
display: inline-block;
width: 20px;
height: 20px;
background-image: url(butterfly-orange.svg);
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
.butterfly-counter-value {
min-width: 1ch;
text-align: center;
font-variant-numeric: tabular-nums;
}
@keyframes butterfly-counter-bump {
0% {
transform: scale(1);
}
40% {
transform: scale(1.18);
}
100% {
transform: scale(1);
}
}
// Ohleduplnost k uživatelům, kteří nechtějí pohyb
@media (prefers-reduced-motion: reduce) {
.butterfly-sprite {
animation: none;
}
.butterfly-net.catch-pop,
.butterfly-counter.bump {
animation: none;
}
}