/* Halftone layer animations. Each layer: .hl__layer[data-fx][data-after] > img. The img runs the entrance, the wrapper the loop. */
.hl { position: relative; overflow: hidden; background: #000; }
.hl__layer, .hl__layer img, .hl__scene { position: absolute; inset: 0; width: 100%; height: 100%; }
.hl__layer img {
  display: block;
  animation-duration: var(--dur); animation-delay: var(--at);
  animation-timing-function: var(--ease); animation-fill-mode: both;
}
.hl [data-fx="reveal-right"] img { animation-name: hl-reveal-right; }
.hl [data-fx="reveal-left"] img { animation-name: hl-reveal-left; }
.hl [data-fx="reveal-up"] img { animation-name: hl-reveal-up; }
.hl [data-fx="reveal-down"] img { animation-name: hl-reveal-down; }
.hl [data-fx="fade"] img { animation-name: hl-fade; }
.hl [data-fx="neon"] img { animation-name: hl-neon; animation-timing-function: steps(1); }
.hl [data-fx="pop"] img { animation-name: hl-pop; transform-origin: var(--cx) var(--cy); }
/* Moving layers stay hidden until `at`: a backwards-filled start offset would otherwise sit visible during the delay. */
.hl [data-fx="fly-in"] img, .hl [data-fx="rise"] img {
  animation: hl-wait var(--at) linear, hl-fly-in var(--dur) var(--at) var(--ease) both;
}
/* The wrapper does not move with the image: a rising layer emerges from behind its own bottom edge. */
.hl [data-fx="rise"] { clip-path: inset(0 0 calc(100% - var(--y2)) 0); }
.hl [data-fx="wipe"] img { animation-name: hl-wipe; }

/* Start 1% beyond the box so pixel rounding never leaves a hairline visible before the reveal. */
@keyframes hl-reveal-right { from { clip-path: inset(0 calc(101% - var(--x1)) 0 0); } to { clip-path: inset(0 calc(100% - var(--x2)) 0 0); } }
@keyframes hl-reveal-left { from { clip-path: inset(0 0 0 calc(var(--x2) + 1%)); } to { clip-path: inset(0 0 0 var(--x1)); } }
@keyframes hl-reveal-up { from { clip-path: inset(calc(var(--y2) + 1%) 0 0 0); } to { clip-path: inset(var(--y1) 0 0 0); } }
@keyframes hl-reveal-down { from { clip-path: inset(0 0 calc(101% - var(--y1)) 0); } to { clip-path: inset(0 0 calc(100% - var(--y2)) 0); } }
@keyframes hl-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes hl-neon {
  0%, 15%, 25%, 55%, 65% { opacity: 0; }
  10%, 20%, 40%, 60%, 80%, 100% { opacity: 1; }
}
@keyframes hl-pop { from { transform: scale(0); } 70% { transform: scale(1.3); } to { transform: scale(1); } }
@keyframes hl-wait { from, to { opacity: 0; } }
@keyframes hl-fly-in { from { transform: translate(var(--from-x), var(--from-y)); } to { transform: none; } }
@keyframes hl-wipe { from { clip-path: var(--wipe-from); } to { clip-path: var(--wipe-to); } }

.hl [data-after="blink"] { animation: hl-blink 5s calc(var(--after-at) + 2s) infinite; }
.hl [data-after="twinkle"] { animation: hl-twinkle 2.2s var(--after-at) infinite ease-in-out; }
.hl [data-after="nudge"] { animation: hl-nudge .3s var(--after-at) steps(1); }
.hl [data-after="float"] { animation: hl-float 3.2s var(--after-at) steps(1) infinite; }
.hl [data-after="drift"] { animation: hl-drift 10s var(--after-at) steps(1) infinite; }
.hl [data-after="rumble"] { animation: hl-rumble .24s var(--after-at) steps(1) infinite; }
.hl [data-after="flicker"] { animation: hl-flicker 2.9s var(--after-at) steps(1) infinite; }
@keyframes hl-blink { 0%, 95%, 100% { opacity: 1; } 96%, 98% { opacity: 0; } }
@keyframes hl-twinkle { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
@keyframes hl-nudge {
  0%, 50%, 100% { transform: none; }
  12.5%, 37.5%, 62.5%, 87.5% { transform: translateX(var(--px-x)); }
  25%, 75% { transform: translateX(calc(2 * var(--px-x))); }
}
@keyframes hl-float {
  0% { transform: none; }
  25%, 75% { transform: translateY(calc(-1 * var(--px-y))); }
  50% { transform: translateY(calc(-2 * var(--px-y))); }
}
@keyframes hl-drift {
  0% { transform: none; }
  25%, 75% { transform: translateX(var(--px-x)); }
  50% { transform: translateX(calc(2 * var(--px-x))); }
}
@keyframes hl-rumble {
  0% { transform: none; }
  25% { transform: translateX(var(--px-x)); }
  50% { transform: translateY(var(--px-y)); }
  75% { transform: translateX(calc(-1 * var(--px-x))); }
}
@keyframes hl-flicker {
  0%, 9%, 45%, 73%, 100% { opacity: 1; }
  7% { opacity: .4; }
  43% { opacity: .7; }
  71% { opacity: .3; }
}
.hl [data-after="twinkle"]:nth-of-type(3n+1) { animation-duration: 1.7s; }
.hl [data-after="twinkle"]:nth-of-type(3n+2) { animation-duration: 2.7s; }

.hl__cursor {
  position: absolute; width: var(--cur-w); height: var(--cur-h); background: #fff;
  left: var(--cur-x1); top: var(--cur-y1);
  animation:
    hl-cursor-blink .4s 0s steps(1) var(--cur-blinks),
    hl-cursor-type var(--cur-dur) var(--cur-at) var(--cur-ease) both,
    hl-cursor-blink .4s calc(var(--cur-at) + var(--cur-dur)) steps(1),
    hl-cursor-off 0s var(--cur-off) both;
}
@keyframes hl-cursor-blink { 50% { opacity: 0; } }
@keyframes hl-cursor-type { from { left: var(--cur-x1); top: var(--cur-y1); } to { left: var(--cur-x2); top: var(--cur-y2); } }
@keyframes hl-cursor-off { to { visibility: hidden; } }

@media (prefers-reduced-motion: reduce) {
  .hl *, .hl__layer img { animation: none !important; }
  .hl__cursor { display: none; }
}
