Add VHS glitch animation to vaporwave theme cards
- Periodic jitter, red/cyan title split, and a tracking band sweep on each card for a few hundred ms every cycle - Stagger three phases (10s/13s/17s) with offsets so the board flickers organically instead of in lockstep - Gate with :not(.opacity-50) so dnd-kit's inline transform isn't overridden by the animation while a card is being dragged
This commit is contained in:
parent
7fcfcbdb5b
commit
50881b8534
127
app/globals.css
127
app/globals.css
|
|
@ -1710,6 +1710,133 @@ html.theme-vaporwave .vw-palm--right-small {
|
|||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
/* VHS hiccup: every so often a card drops out of the signal for half a
|
||||
second -- a 1-2px jitter, a red/cyan split on the title, and a tracking
|
||||
band sweeping down the panel, all inside one short window (the first 5%
|
||||
of each cycle). Cards run three alternating phases with different periods
|
||||
and offsets, so the board flickers organically instead of in lockstep.
|
||||
The :not(.opacity-50) guard matters: while dnd-kit drives a drag it sets
|
||||
an inline `transform` on the card, and a running animation would override
|
||||
that inline value (animations sit above inline styles in the cascade) --
|
||||
the card stops following the pointer. opacity-50 is exactly the class the
|
||||
card gets while dragging, so the hiccup stands down for the duration.
|
||||
(overflow: hidden keeps the tracking band clipped to the card while it
|
||||
sweeps; the hover lift uses the separate `translate` property, so the
|
||||
jitter doesn't fight it.) */
|
||||
html.theme-vaporwave [data-group-card]:not(.opacity-50) {
|
||||
overflow: hidden;
|
||||
animation: vw-card-glitch 10s linear infinite;
|
||||
}
|
||||
html.theme-vaporwave [data-group-card]:not(.opacity-50) > div:first-child h3 {
|
||||
animation: vw-title-glitch 10s linear infinite;
|
||||
}
|
||||
html.theme-vaporwave [data-group-card]:not(.opacity-50)::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: -12%;
|
||||
height: 12px;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
background:
|
||||
repeating-linear-gradient(0deg, oklch(0.45 0.15 330 / 0.28) 0 1px, transparent 1px 3px),
|
||||
linear-gradient(
|
||||
180deg,
|
||||
transparent 0%,
|
||||
oklch(0.72 0.2 350 / 0.22) 20%,
|
||||
oklch(0.99 0.01 220 / 0.4) 50%,
|
||||
oklch(0.78 0.15 200 / 0.22) 80%,
|
||||
transparent 100%
|
||||
);
|
||||
animation: vw-tracking 10s linear infinite;
|
||||
}
|
||||
/* Phase B: a longer period and an offset start, so neighbors don't hiccup
|
||||
together. (Static styles above are the idle state -- before a card's
|
||||
first delay elapses, and under reduced motion, everything just sits still.) */
|
||||
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n + 2) [data-group-card]:not(.opacity-50),
|
||||
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n + 2) [data-group-card]:not(.opacity-50) > div:first-child h3,
|
||||
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n + 2) [data-group-card]:not(.opacity-50)::after {
|
||||
animation-duration: 13s;
|
||||
animation-delay: 3s;
|
||||
}
|
||||
/* Phase C: the longest period, offset furthest. */
|
||||
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n) [data-group-card]:not(.opacity-50),
|
||||
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n) [data-group-card]:not(.opacity-50) > div:first-child h3,
|
||||
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n) [data-group-card]:not(.opacity-50)::after {
|
||||
animation-duration: 17s;
|
||||
animation-delay: 7s;
|
||||
}
|
||||
@keyframes vw-card-glitch {
|
||||
0%,
|
||||
5%,
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
0.8% {
|
||||
transform: translateX(-1.5px);
|
||||
}
|
||||
1.6% {
|
||||
transform: translateX(-1.5px);
|
||||
}
|
||||
2.4% {
|
||||
transform: translateX(1px);
|
||||
}
|
||||
3.2% {
|
||||
transform: translateX(1px);
|
||||
}
|
||||
4% {
|
||||
transform: translateX(-0.75px);
|
||||
}
|
||||
4.6% {
|
||||
transform: translateX(0.5px);
|
||||
}
|
||||
}
|
||||
@keyframes vw-title-glitch {
|
||||
0%,
|
||||
5%,
|
||||
100% {
|
||||
text-shadow: none;
|
||||
}
|
||||
0.8% {
|
||||
text-shadow:
|
||||
1.5px 0 oklch(0.68 0.2 350 / 0.55),
|
||||
-1.5px 0 oklch(0.85 0.15 200 / 0.55);
|
||||
}
|
||||
1.6% {
|
||||
text-shadow:
|
||||
-1.5px 0 oklch(0.68 0.2 350 / 0.55),
|
||||
1.5px 0 oklch(0.85 0.15 200 / 0.55);
|
||||
}
|
||||
2.4% {
|
||||
text-shadow:
|
||||
1px 0 oklch(0.68 0.2 350 / 0.55),
|
||||
-1px 0 oklch(0.85 0.15 200 / 0.55);
|
||||
}
|
||||
3.2% {
|
||||
text-shadow:
|
||||
-0.5px 0 oklch(0.68 0.2 350 / 0.55),
|
||||
0.5px 0 oklch(0.85 0.15 200 / 0.55);
|
||||
}
|
||||
}
|
||||
@keyframes vw-tracking {
|
||||
0% {
|
||||
top: -12%;
|
||||
opacity: 0;
|
||||
}
|
||||
0.8% {
|
||||
opacity: 0.85;
|
||||
}
|
||||
4.8% {
|
||||
opacity: 0.85;
|
||||
}
|
||||
5%,
|
||||
100% {
|
||||
top: 112%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Primary blooms with a soft magenta glow; focus glows electric cyan. */
|
||||
html.theme-vaporwave .bg-primary {
|
||||
box-shadow: 0 4px 18px oklch(0.62 0.25 350 / 0.35);
|
||||
|
|
|
|||
Loading…
Reference in New Issue