/* ==========================================================================
   D Planet — motion
   ========================================================================== */

/* --- Keyframes ----------------------------------------------------------- */
@keyframes spin {
  to { transform: rotate(360deg); }
}

@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes fadeUp {
  from { opacity: 0; transform: translate3d(0, 30px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

/* The track holds two copies of its content, so translating by exactly
   -50% loops seamlessly. */
@keyframes marquee {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

@keyframes lineUp {
  from { transform: translateY(115%); }
  to   { transform: translateY(0); }
}

@keyframes grain {
  0%   { transform: translate(0, 0); }
  20%  { transform: translate(-3%, 2%); }
  40%  { transform: translate(2%, -3%); }
  60%  { transform: translate(-2%, -1%); }
  80%  { transform: translate(3%, 3%); }
  100% { transform: translate(0, 0); }
}

@keyframes preloaderFailsafe {
  to { opacity: 0; visibility: hidden; pointer-events: none; }
}

/* A neon tube striking up: stutter, catch, glow */
@keyframes neonFlicker {
  0%   { opacity: 0;   filter: brightness(.4); }
  8%   { opacity: .9;  filter: brightness(1.2); }
  10%  { opacity: .1; }
  18%  { opacity: 1; }
  20%  { opacity: .25; }
  30%  { opacity: 1;   filter: brightness(1.1); }
  33%  { opacity: .5; }
  36%  { opacity: 1; }
  100% { opacity: 1;   filter: brightness(1) drop-shadow(0 0 22px rgba(58, 215, 255, .55)); }
}
@keyframes neonFlickerSoft {
  0%, 100% { opacity: 1; }
  4%  { opacity: .35; }
  6%  { opacity: 1; }
  9%  { opacity: .55; }
  11% { opacity: 1; }
  58% { opacity: 1; }
  60% { opacity: .6; }
  61% { opacity: 1; }
}

@keyframes kenBurns {
  from { transform: scale(1.18); }
  to   { transform: scale(1.02); }
}

@keyframes lightSweep {
  0%   { opacity: 0; transform: skewX(-18deg) translateX(0); }
  20%  { opacity: 1; }
  100% { opacity: 0; transform: skewX(-18deg) translateX(560%); }
}

@keyframes cueDrop {
  0%   { transform: scaleY(0); transform-origin: top; }
  45%  { transform: scaleY(1); transform-origin: top; }
  55%  { transform: scaleY(1); transform-origin: bottom; }
  100% { transform: scaleY(0); transform-origin: bottom; }
}
@keyframes cueSlide {
  0%   { transform: scaleX(0); transform-origin: left; }
  45%  { transform: scaleX(1); transform-origin: left; }
  55%  { transform: scaleX(1); transform-origin: right; }
  100% { transform: scaleX(0); transform-origin: right; }
}

@keyframes washDrift {
  from { transform: translate3d(-4%, -2%, 0) rotate(0deg); }
  to   { transform: translate3d(4%, 3%, 0) rotate(8deg); }
}

@keyframes pulseRing {
  0%   { transform: scale(.4); opacity: 0; }
  15%  { opacity: 1; }
  100% { transform: scale(2.6); opacity: 0; }
}

@keyframes borderTravel {
  to { --brd-angle: 360deg; }
}

@keyframes eqBounce {
  0%, 100% { transform: scaleY(.25); }
  25%      { transform: scaleY(1); }
  50%      { transform: scaleY(.45); }
  75%      { transform: scaleY(.8); }
}

@keyframes beamOn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes beamSway {
  from { transform: rotate(var(--from)); }
  to   { transform: rotate(var(--to)); }
}

@keyframes smokeIn {
  from { opacity: 0; transform: scale(1.15) translate3d(-3%, 2%, 0); }
  to   { opacity: var(--o, 1); transform: none; }
}

@keyframes dancerIn {
  from { opacity: 0; transform: translate3d(0, 8%, 0) scale(.96); filter: blur(10px) brightness(2); }
  60%  { filter: blur(0) brightness(1.2); }
  to   { opacity: 1; transform: none; }
}

@keyframes ringOn {
  0%   { opacity: 0; }
  20%  { opacity: .9; }
  25%  { opacity: .2; }
  40%  { opacity: 1; }
  100% { opacity: 1; }
}

@keyframes nudge {
  0%, 100% { transform: translateX(0); }
  50%      { transform: translateX(6px); }
}

/* ==========================================================================
   Scroll reveals
   Elements start hidden and are unhidden by IntersectionObserver. If JS never
   runs, the `no-js` fallback at the bottom of this file shows everything.
   ========================================================================== */
.reveal {
  opacity: 0;
  transform: translate3d(0, 50px, 0);
  filter: blur(6px);
  transition: opacity 1100ms var(--ease-out),
              transform 1300ms var(--ease-out),
              filter 1100ms var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
.reveal.is-visible {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  filter: none;
}

.reveal--left  { transform: translate3d(-60px, 0, 0); }
.reveal--right { transform: translate3d(60px, 0, 0); }
.reveal--scale { transform: scale(.92); }
.reveal--fade  { transform: none; }

.reveal--left.is-visible,
.reveal--right.is-visible { transform: translate3d(0, 0, 0); }
.reveal--scale.is-visible { transform: scale(1); }

/* Children of a stagger container rise in sequence; the delay step is
   written onto each child by reveal.js. */
.reveal-group > * {
  opacity: 0;
  transform: translate3d(0, 60px, 0) scale(.96);
  transition: opacity 1000ms var(--ease-out),
              transform 1200ms var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
.reveal-group.is-visible > * {
  opacity: 1;
  transform: none;
}

/* ==========================================================================
   Back-to-top — a ring that fills with the page's scroll progress
   ========================================================================== */
.to-top {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 600;
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 50%;
  border: 0;
  background:
    radial-gradient(closest-side, var(--bg) 88%, transparent 90%),
    conic-gradient(var(--magenta) calc(var(--scroll, 0) * 360deg), rgba(255, 255, 255, .12) 0);
  color: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transform: translateY(16px) scale(.8);
  box-shadow: 0 0 22px rgba(255, 61, 200, .25);
  transition: opacity 400ms var(--ease),
              visibility 400ms var(--ease),
              transform 500ms var(--ease-out),
              box-shadow 300ms var(--ease);
}
.to-top.is-visible { opacity: 1; visibility: visible; transform: none; }
.to-top:hover { box-shadow: 0 0 30px rgba(255, 61, 200, .6); }
.to-top svg { width: 12px; height: 12px; transition: transform 300ms var(--ease-out); }
.to-top:hover svg { transform: translateY(-3px); }

@media (min-width: 1367px) {
  /* The dot navigator occupies this corner on wide screens */
  .to-top { right: 5.5rem; }
}

/* ==========================================================================
   Reduced motion
   Honour the OS setting: keep the layout and the light, drop the movement.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  html:not(.lenis) { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  .reveal,
  .reveal-group > * {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
  }
  .sw__i,
  .js .line__in { transform: none !important; }
  .js .reveal .img-frame-large .media-tile { clip-path: none !important; }

  body::after,
  .filmstrip__track,
  .ticker__row,
  .cta-band::before,
  .cta-band__pulse,
  .yt__play::after,
  .mentor__photo::after,
  .mentor__monogram,
  .eq i { animation: none !important; }
  .cta-band__pulse { display: none; }
  .eq i { transform: scaleY(.6); }
  .page-wipe { display: none; }
}

/* ==========================================================================
   No-JS fallback — nothing stays hidden if scripts fail to run
   ========================================================================== */
.no-js .reveal,
.no-js .reveal-group > * {
  opacity: 1;
  transform: none;
  filter: none;
}
.no-js .preloader,
.no-js .page-wipe { display: none; }
.no-js .stage__beam,
.no-js .stage__ring,
.no-js .stage__pool,
.no-js .stage__smoke img,
.no-js .stage__dancer img { opacity: 1; }
.no-js .stage__smoke--front img { opacity: .7; }
