/* ============================================================
   animations.css — Motion system
   THE PRIMARCH ARCHIVE

   Everything that moves. Structural position lives in layout.css;
   this file only adds transforms, opacity, filters, and timing.
   Reduced-motion users get the global override in style.css plus
   the .reveal-specific fallback below.
   ------------------------------------------------------------ */

/* ============================================================
   1. KEYFRAMES
   ============================================================ */

@keyframes star-twinkle {
  0%, 100% { opacity: 0.25; }
  50%      { opacity: 1; }
}

@keyframes nebula-drift {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(-2%, 1.5%, 0) scale(1.05); }
  100% { transform: translate3d(0, 0, 0) scale(1); }
}

@keyframes ash-rise {
  0%   { transform: translateY(0) translateX(0); opacity: 0; }
  10%  { opacity: 0.6; }
  90%  { opacity: 0.2; }
  100% { transform: translateY(-110vh) translateX(var(--drift, 20px)); opacity: 0; }
}

@keyframes light-ray-sweep {
  0%   { transform: rotate(0deg); opacity: 0.15; }
  50%  { opacity: 0.35; }
  100% { transform: rotate(360deg); opacity: 0.15; }
}

@keyframes warp-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(201, 169, 97, 0.0); }
  50%      { box-shadow: 0 0 40px 6px rgba(61, 42, 92, 0.45); }
}

@keyframes gold-glow-pulse {
  0%, 100% { filter: drop-shadow(0 0 2px rgba(201, 169, 97, 0.3)); }
  50%      { filter: drop-shadow(0 0 10px rgba(201, 169, 97, 0.75)); }
}

@keyframes border-trace {
  to { stroke-dashoffset: 0; }
}

@keyframes fog-drift {
  0%   { transform: translateX(-4%); }
  100% { transform: translateX(4%); }
}

@keyframes preloader-fill {
  from { width: 0%; }
  to   { width: 100%; }
}

/* ============================================================
   2. HERO ATMOSPHERE
   ============================================================ */

.hero__fog {
  background:
    radial-gradient(ellipse 60% 40% at 50% 110%, rgba(74, 90, 104, 0.25), transparent 70%);
  animation: fog-drift 22s ease-in-out infinite alternate;
  mix-blend-mode: screen;
}

.hero__light-rays {
  background:
    conic-gradient(from 0deg at 50% 30%,
      transparent 0deg, rgba(201, 169, 97, 0.08) 8deg, transparent 20deg,
      transparent 160deg, rgba(201, 169, 97, 0.05) 168deg, transparent 180deg);
  animation: light-ray-sweep 60s linear infinite;
  transform-origin: 50% 30%;
  mix-blend-mode: screen;
}

/* Canvas-drawn stars/nebula/ash/planet get their pixels from
   animations.js; this class only ensures a base backdrop while
   the script initializes. */
.hero__canvas { background: radial-gradient(ellipse at 50% 40%, #14141a 0%, var(--c-void) 70%); }

/* ============================================================
   3. GLASS MORPHISM
   ============================================================ */

.glass-panel,
.site-nav,
.search-overlay__panel,
.archive-toolbar__sort,
.music-toggle {
  background: rgba(16, 16, 20, 0.55);
  backdrop-filter: blur(14px) saturate(120%);
  -webkit-backdrop-filter: blur(14px) saturate(120%);
  border: 1px solid rgba(201, 169, 97, 0.16);
}

.site-nav {
  border-left: none;
  border-right: none;
  border-top: none;
}

/* ============================================================
   4. GLOW & HOVER EFFECTS
   ============================================================ */

.site-nav__link {
  position: relative;
  transition: color 0.3s var(--ease-imperial);
}
.site-nav__link::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -4px;
  height: 1px;
  background: var(--c-gold);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform 0.3s var(--ease-imperial);
}
.site-nav__link:hover,
.site-nav__link:focus-visible { color: var(--c-gold); }
.site-nav__link:hover::after,
.site-nav__link:focus-visible::after { transform: scaleX(1); }

.btn-enter {
  position: relative;
  transition: color 0.35s var(--ease-imperial), letter-spacing 0.35s var(--ease-imperial);
}
.btn-enter:hover,
.btn-enter:focus-visible {
  color: var(--c-void);
  letter-spacing: 0.28em;
}
.btn-enter::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--c-gold);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.4s var(--ease-imperial);
  z-index: -1;
}
.btn-enter:hover::before,
.btn-enter:focus-visible::before { transform: scaleX(1); }

.btn-enter__ring {
  border: 1px solid var(--c-gold-dim);
  border-radius: var(--radius-sm);
  animation: warp-pulse 4s ease-in-out infinite;
}

.music-toggle:hover .music-toggle__icon,
.music-toggle[aria-pressed="true"] .music-toggle__icon {
  animation: gold-glow-pulse 2.2s ease-in-out infinite;
}

.site-nav__link--active { color: var(--c-gold); }
.site-nav__link--active::after { transform: scaleX(1); }

/* Search overlay backdrop + panel entrance */
.search-overlay {
  background: rgba(8, 8, 11, 0);
  opacity: 0;
  transition: opacity 0.3s var(--ease-imperial), background 0.3s var(--ease-imperial);
}
.search-overlay[data-state="open"] {
  opacity: 1;
  background: rgba(8, 8, 11, 0.75);
}
.search-overlay__panel {
  transform: translateY(-12px);
  opacity: 0;
  transition: transform 0.35s var(--ease-imperial), opacity 0.35s var(--ease-imperial);
}
.search-overlay[data-state="open"] .search-overlay__panel {
  transform: translateY(0);
  opacity: 1;
}

/* Archive-opening transition doors */
.archive-transition__door {
  transition: transform 0.7s var(--ease-imperial);
}
.archive-transition__door--left { transform: translateX(0); }
.archive-transition__door--right { transform: translateX(0); }
.archive-transition[data-state="active"] .archive-transition__door--left {
  animation: door-sweep-left 1.1s var(--ease-imperial) forwards;
}
.archive-transition[data-state="active"] .archive-transition__door--right {
  animation: door-sweep-right 1.1s var(--ease-imperial) forwards;
}
.archive-transition__text {
  opacity: 0;
}
.archive-transition[data-state="active"] .archive-transition__text {
  animation: access-granted-text 1.1s var(--ease-imperial) forwards;
}

@keyframes door-sweep-left {
  0%   { transform: translateX(-100%); }
  40%  { transform: translateX(0); }
  70%  { transform: translateX(0); }
  100% { transform: translateX(-100%); }
}
@keyframes door-sweep-right {
  0%   { transform: translateX(100%); }
  40%  { transform: translateX(0); }
  70%  { transform: translateX(0); }
  100% { transform: translateX(100%); }
}
@keyframes access-granted-text {
  0%   { opacity: 0; }
  45%  { opacity: 1; }
  75%  { opacity: 1; }
  100% { opacity: 0; }
}

/* ============================================================
   5. SCROLL REVEAL
   Elements marked .reveal start hidden; animations.js flips
   .reveal--visible via IntersectionObserver as they enter view.
   ============================================================ */

.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.8s var(--ease-imperial), transform 0.8s var(--ease-imperial);
  will-change: opacity, transform;
}
.reveal--visible {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* ============================================================
   6. MOUSE-REACTIVE LIGHTING
   animations.js writes --mx / --my (percentages) onto :root as
   the pointer moves; any element opting in gets a soft light
   that follows the cursor.
   ============================================================ */

.light-reactive {
  position: relative;
  isolation: isolate;
}
.light-reactive::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0;
  background: radial-gradient(
    280px circle at var(--mx, 50%) var(--my, 50%),
    rgba(201, 169, 97, 0.14),
    transparent 70%
  );
  transition: opacity 0.4s ease;
  pointer-events: none;
}
.light-reactive:hover::before { opacity: 1; }

/* ============================================================
   7. ANIMATED / TRACED BORDERS
   Used later by cards.css (Stages 5–8) — declared here since
   it's a motion primitive, not a card-specific visual.
   ============================================================ */

.traced-border { position: relative; }
.traced-border > svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.traced-border > svg rect,
.traced-border > svg path {
  fill: none;
  stroke: var(--c-gold-dim);
  stroke-width: 1;
  stroke-dasharray: 12 8;
  stroke-dashoffset: 400;
  animation: border-trace 6s linear infinite;
}

/* ============================================================
   8. 3D CARD FLIP PRIMITIVE
   Card face styling belongs to cards.css; only the 3D mechanics
   live here so any card-like component can reuse it.
   ============================================================ */

.flip-card { perspective: 1400px; }
.flip-card__inner {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.7s var(--ease-imperial);
}
.flip-card.is-flipped .flip-card__inner { transform: rotateY(180deg); }
.flip-card__face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
}
.flip-card__face--back { transform: rotateY(180deg); }

/* ============================================================
   9. PARALLAX HOOK
   animations.js reads data-parallax-speed and offsets translateY
   on scroll for any element carrying it.
   ============================================================ */
[data-parallax-speed] { will-change: transform; }

/* ============================================================
   10. PRELOADER BAR FILL
   ============================================================ */
.preloader[data-state="active"] .preloader__bar span {
  animation: preloader-fill 1.6s var(--ease-imperial) forwards;
}
