


@property --rv-tx   { syntax: "<length>";      inherits: false; initial-value: 0px }
@property --rv-ty   { syntax: "<length>";      inherits: false; initial-value: 0px }
@property --rv-ts   { syntax: "<number>";      inherits: false; initial-value: 1 }
@property --rv-rx   { syntax: "<angle>";       inherits: false; initial-value: 0deg }
@property --rv-ry   { syntax: "<angle>";       inherits: false; initial-value: 0deg }
@property --rv-opsz { syntax: "<number>";      inherits: false; initial-value: 120 }
@property --rv-wght { syntax: "<number>";      inherits: false; initial-value: 600 }
@property --rv-wonk { syntax: "<number>";      inherits: false; initial-value: 1 }
@property --rv-x    { syntax: "<percentage>";  inherits: true;  initial-value: 50% }
@property --rv-y    { syntax: "<percentage>";  inherits: true;  initial-value: 50% }


@property --rv-vel  { syntax: "<number>";      inherits: false; initial-value: 0 }

:root {
  --rv-step: 62ms;
  --rv-max-step: 10;
  --rv-dur-curtain: 0.9s;
  --rv-dur-rise: 0.8s;
  --rv-dur-settle: 1.15s;
  --rv-dur-draw: 0.75s;
  --rv-dip: 30px;
  --rv-side: 44px;
  --rv-ease: cubic-bezier(0.16, 1, 0.3, 1);
  --rv-ease-spring: cubic-bezier(0.3, 1.32, 0.56, 1);
  --rv-ease-settle: cubic-bezier(0.22, 0.86, 0.24, 1);
  --rv-vel: 0;
}


@keyframes rvCurtainDown { from { clip-path: inset(0 0 100% 0) } to { clip-path: inset(-150% -150% -150% -150%) } }
@keyframes rvCurtainUp   { from { clip-path: inset(100% 0 0 0) } to { clip-path: inset(-150% -150% -150% -150%) } }
@keyframes rvCurtainLeft { from { clip-path: inset(0 100% 0 0) } to { clip-path: inset(-150% -150% -150% -150%) } }
@keyframes rvCurtainRight{ from { clip-path: inset(0 0 0 100%) } to { clip-path: inset(-150% -150% -150% -150%) } }




html.js section.reveal,
html.js section.reveal-left,
html.js section.reveal-right,
html.js section.reveal-scale,
html.js section.reveal-stagger,
html.js section.rv,
html.js section.rv-pop {
  opacity: 1;
  transform: none;
  animation: none;
}


html.js .rv,
html.js .reveal,
html.js .reveal-left,
html.js .reveal-right,
html.js .reveal-scale,
html.js .rv-pop,
html.js .reveal-stagger > *,
html.js .rv-t {
  transform: translate3d(var(--rv-tx), var(--rv-ty), 0) scale(var(--rv-ts));
}
html.js .rv-t {
  transform: perspective(920px) rotateX(var(--rv-rx)) rotateY(var(--rv-ry)) translate3d(var(--rv-tx), var(--rv-ty), 0) scale(var(--rv-ts));
}

html.js .rv,
html.js .reveal        { opacity: 0; --rv-ty: var(--rv-dip); --rv-ts: .988 }
html.js .reveal-left   { opacity: 0; --rv-tx: calc(var(--rv-side) * -1) }
html.js .reveal-right  { opacity: 0; --rv-tx: var(--rv-side) }
html.js .reveal-scale  { opacity: 0; --rv-ty: 24px; --rv-ts: .955 }
html.js .rv-pop        { opacity: 0; --rv-ty: 14px; --rv-ts: .93 }
html.js .reveal-stagger > * { opacity: 0; --rv-ty: 22px }


/* The entrance interpolates the resolved transform, not the --rv-* properties that feed it. A
   transition on a registered custom property can only run on the main thread, so every element
   crossing the viewport re-resolved its transform each frame, and motion.js's rect reads then forced
   a full style+layout behind it (measured while scrolling: 20.5fps, 619ms of forced layout).
   Transform interpolation is compositable and reaches the identical endpoint, because the custom
   properties still hold the start and rest values. Longhands rather than the shorthand, so the
   per-index transition-delay rules below keep winning. */
html.js .rv, html.js .reveal, html.js .reveal-left, html.js .reveal-right,
html.js .reveal-scale, html.js .rv-pop, html.js .reveal-stagger > * {
  transition-property: opacity, transform;
  transition-duration: var(--rv-dur-rise), var(--rv-dur-rise);
  transition-timing-function: var(--rv-ease), var(--rv-ease-spring);
}
html.js .rv-pop { transition-duration: .5s, .62s }


html.js [data-rv-dir="up"] .rv:not(.rv-in),
html.js [data-rv-dir="up"] .reveal:not(.rv-in)   { --rv-ty: calc(var(--rv-dip) * -1) }
html.js [data-rv-dir="up"] .reveal-scale:not(.rv-in) { --rv-ty: -22px }
html.js [data-rv-dir="up"] .rv-pop:not(.rv-in)       { --rv-ty: -12px }
html.js [data-rv-dir="up"] .reveal-stagger:not(.rv-in) > * { --rv-ty: -18px }

html.js .rv.rv-in,
html.js .reveal.rv-in,
html.js .reveal-left.rv-in,
html.js .reveal-right.rv-in,
html.js .reveal-scale.rv-in,
html.js .rv-pop.rv-in,
html.js .reveal-stagger.rv-in > * { opacity: 1; --rv-tx: 0px; --rv-ty: 0px; --rv-ts: 1 }

html.js .rv.rv-in,
html.js .reveal.rv-in,
html.js .reveal-scale.rv-in  { animation: rvCurtainDown var(--rv-dur-curtain) var(--rv-ease) backwards }
html.js .reveal-left.rv-in   { animation: rvCurtainRight var(--rv-dur-curtain) var(--rv-ease) backwards }
html.js .reveal-right.rv-in  { animation: rvCurtainLeft var(--rv-dur-curtain) var(--rv-ease) backwards }
html.js .rv-pop.rv-in         { animation: rvCurtainDown .62s var(--rv-ease) backwards }
html.js .reveal-stagger.rv-in > * { animation: rvCurtainDown .74s var(--rv-ease) backwards }

html.js [data-rv-dir="up"] .rv.rv-in,
html.js [data-rv-dir="up"] .reveal.rv-in,
html.js [data-rv-dir="up"] .reveal-scale.rv-in,
html.js [data-rv-dir="up"] .reveal-stagger.rv-in > * { animation-name: rvCurtainUp }


html.js .reveal-stagger.rv-in > * {
  transition-delay: calc(min(var(--rv-i, 0), var(--rv-max-step)) * var(--rv-step));
  animation-delay: calc(min(var(--rv-i, 0), var(--rv-max-step)) * var(--rv-step));
}


html.js .rv.rv-in,
html.js .reveal.rv-in,
html.js .reveal-left.rv-in,
html.js .reveal-right.rv-in,
html.js .reveal-scale.rv-in,
html.js .rv-pop.rv-in,
html.js .rv-settle.rv-in,
html.js .rv-index.rv-in,
html.js .rv-draw.rv-in {
  transition-delay: calc(min(var(--rv-i, 0), var(--rv-max-step)) * var(--rv-step));
  animation-delay: calc(min(var(--rv-i, 0), var(--rv-max-step)) * var(--rv-step));
}


.rv-settle {
  
  font-variation-settings: "opsz" var(--rv-opsz), "wght" var(--rv-wght), "WONK" var(--rv-wonk);
  --rv-opsz: var(--rv-opsz-rest, 120);
  --rv-wght: var(--rv-wght-rest, 600);
  --rv-wonk: var(--rv-wonk-rest, 1);
  transition: --rv-opsz var(--rv-dur-settle) var(--rv-ease-settle),
              --rv-wght var(--rv-dur-settle) var(--rv-ease-settle);
}
.js .rv-settle:not(.rv-in) { --rv-opsz: 9; --rv-wght: var(--rv-wght-light, 380) }

/* An em inside a settling headline used to inherit the heading's resolved font-variation-settings, and
   font-variation-settings outranks font-weight — so every "480" written on an emphasised word was dead
   and the italic landed at the same weight as the roman around it. The emphasised words now carry the
   same animation with their own lighter rest, so the italic reads as the softer voice it is for. */
.rv-settle em {
  font-variation-settings: "opsz" var(--rv-opsz), "wght" var(--rv-wght), "WONK" var(--rv-wonk);
  --rv-opsz: var(--rv-opsz-rest, 120);
  --rv-wght: calc(var(--rv-wght-rest, 600) - 70);
  transition: --rv-opsz var(--rv-dur-settle) var(--rv-ease-settle),
              --rv-wght var(--rv-dur-settle) var(--rv-ease-settle);
}
.js .rv-settle:not(.rv-in) em { --rv-opsz: 9; --rv-wght: var(--rv-wght-light, 380) }


.rv-word { display: inline-block; white-space: pre }
html.js .rv-word {
  opacity: 0;
  --rv-ty: .58em;
  transform: translate3d(var(--rv-tx), var(--rv-ty), 0) scale(var(--rv-ts));
  transition: opacity .5s var(--rv-ease), transform .68s var(--rv-ease-spring);
  transition-delay: calc(min(var(--rv-i, 0), 8) * var(--rv-step));
}
html.js .rv-word.rv-in { opacity: 1; --rv-ty: 0px }
html.js [data-rv-dir="up"] .rv-word:not(.rv-in) { --rv-ty: -.44em }
html.js .rv-word.rv-done { opacity: 1; --rv-ty: 0px; transition: none; animation: none }


html.js .rv-settle .rv-word.rv-in { transition-delay: calc(140ms + min(var(--rv-i, 0), 8) * var(--rv-step)) }

.rv-head { opacity: 1 }


@keyframes rvDrawX { from { transform: scaleX(0) } to { transform: scaleX(1) } }
html.js .rv-draw { transform: scaleX(0); transform-origin: 0 50% }
html.js .rv-draw.rv-in { animation: rvDrawX var(--rv-dur-draw) var(--rv-ease) both }


@keyframes rvIndex {
  from { opacity: 0; transform: translate3d(-9px, 0, 0); letter-spacing: .4em }
  to   { opacity: 1; transform: translate3d(0, 0, 0);    letter-spacing: .26em }
}
html.js .rv-index { opacity: 0 }
html.js .rv-index.rv-in { animation: rvIndex .58s var(--rv-ease) both }


.rv-t { position: relative }
.rv-sheen {
  position: absolute;
  inset: 0;
  z-index: 4;
  border-radius: inherit;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-med, .36s) var(--rv-ease);
}
.rv-sheen::before {
  content: "";
  position: absolute;
  inset: -30%;
  background: radial-gradient(240px circle at var(--rv-x) var(--rv-y), rgba(196, 181, 253, .18), rgba(167, 139, 250, .07) 36%, transparent 66%);
}
@media (hover: hover) and (pointer: fine) {
  .rv-t:hover > .rv-sheen { opacity: 1 }
}


html.js .rv-t {
  transition: opacity var(--rv-dur-rise) var(--rv-ease),
              --rv-tx var(--rv-dur-rise) var(--rv-ease-spring),
              --rv-ty var(--rv-dur-rise) var(--rv-ease-spring),
              --rv-ts var(--rv-dur-rise) var(--rv-ease-spring),
              --rv-rx .5s var(--rv-ease),
              --rv-ry .5s var(--rv-ease),
              border-color .4s var(--rv-ease),
              box-shadow .4s var(--rv-ease);
}

/* The tilt cards take the same compositor path, but only while entering. Once parked the rule above
   is left in charge, so the pointer tilt keeps its .5s ease follow and the hover lift its .8s spring
   instead of collapsing both into one transform curve. */
html.js .rv-t.rv-in:not(.rv-done) {
  transition-property: opacity, transform, border-color, box-shadow;
  transition-duration: var(--rv-dur-rise), var(--rv-dur-rise), .4s, .4s;
  transition-timing-function: var(--rv-ease), var(--rv-ease-spring), var(--rv-ease), var(--rv-ease);
}

html.js .rv-t.rv-done { animation: none }


html.js .rv-t:hover {
  transform: perspective(920px) rotateX(var(--rv-rx)) rotateY(var(--rv-ry))
             translate3d(var(--rv-tx), calc(var(--rv-ty) + var(--rv-lift, -4px)), 0)
             scale(var(--rv-ts));
}
.value-card, .stat-card-v2, .discord-hero-card, .media-card, .sup-card { --rv-lift: -4px }
.staff-card { --rv-lift: -6px }
.reviews-card { --rv-lift: -5px }
.game-card { --rv-lift: -6px }


.rv-here-light {
  position: absolute;
  left: 3%;
  right: 3%;
  top: 0;
  height: 1px;
  pointer-events: none;
  z-index: 1;
  background: linear-gradient(90deg, transparent, rgba(196, 181, 253, .5) 26%, rgba(240, 171, 252, .38) 54%, transparent);
  transform-origin: 50% 50%;
  animation: rvDrawX .9s var(--rv-ease) both;
}


#scrollProgressBar { filter: brightness(calc(1 + var(--rv-vel) * 0.005)) }


@media (prefers-reduced-motion: reduce) {
  :root { --rv-step: 0ms; --rv-dur-curtain: 1ms; --rv-dur-rise: 1ms; --rv-dur-settle: 1ms; --rv-dur-draw: 1ms; --rv-dip: 0px; --rv-side: 0px }
  .js .rv, .js .reveal, .js .reveal-left, .js .reveal-right, .js .reveal-scale,
  .js .reveal-stagger > *, .js .rv-pop, .js .rv-word, .js .rv-settle,
  .js .rv-settle em,
  .js .rv-index, .js .rv-draw {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
    animation: none !important;
    transition: none !important;
  }
  .rv-settle, .rv-settle em { --rv-opsz: var(--rv-opsz-rest, 120); --rv-wght: var(--rv-wght-rest, 600) }
  .rv-draw { transform: none !important }
  .rv-sheen { display: none }
  .rv-here-light { animation: none }
  #scrollProgressBar { filter: none }
}


html.js[data-rv-tier="lite"] #scrollProgressBar { filter: none }
html.js[data-rv-tier="lite"] .rv-sheen { display: none }


html:not(.js) .rv,
html:not(.js) .reveal,
html:not(.js) .reveal-stagger > *,
html:not(.js) .rv-word,
html:not(.js) .rv-index,
html:not(.js) .rv-draw { opacity: 1; transform: none }


html.rv-force :where(.rv, .reveal, .reveal-left, .reveal-right, .reveal-scale,
                     .reveal-stagger, .reveal-stagger > *, .rv-pop, .rv-word,
                     .rv-index, .rv-draw, .rv-settle, .rv-settle em) {
  opacity: 1 !important;
  transform: none !important;
  clip-path: none !important;
  animation: none !important;
  transition: none !important;
}
html.rv-force .rv-here-light,
html.rv-force .rv-sheen { display: none }
html.rv-force body:not(.is-ready) .hero > * { opacity: 1 !important }
