/* =============================================================
   animations.css
   Atmosphere overlays (grain, scanlines, CRT flicker, vignette),
   reveal-on-scroll states, floating motion, cursor styling.
   All effects respect prefers-reduced-motion.
   ============================================================= */

/* ---------- Custom cursor ---------- */
.cursor {
  position: fixed;
  top: 0; left: 0;
  z-index: 9999;
  pointer-events: none;
  mix-blend-mode: difference;
  /* positioned via transform from cursor.js */
}
.cursor__dot {
  position: absolute;
  width: 6px; height: 6px;
  margin: -3px 0 0 -3px;
  background: #fff;
  border-radius: 50%;
}
.cursor__ring {
  position: absolute;
  width: 34px; height: 34px;
  margin: -17px 0 0 -17px;
  border: 1px solid #fff;
  border-radius: 50%;
  transition: width 0.3s var(--ease), height 0.3s var(--ease),
              margin 0.3s var(--ease), opacity 0.3s var(--ease);
}
/* enlarged ring state toggled by cursor.js on [data-hover] */
.cursor.is-hover .cursor__ring {
  width: 56px; height: 56px;
  margin: -28px 0 0 -28px;
  opacity: 0.6;
}
.cursor.is-down .cursor__ring { width: 24px; height: 24px; margin: -12px 0 0 -12px; }
.cursor.is-hidden { opacity: 0; }

/* ---------- Grain / noise ---------- */
.grain {
  position: fixed;
  inset: -50%;
  z-index: 9000;
  pointer-events: none;
  opacity: 0.05;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-size: 200px 200px;
  animation: grain-shift 0.6s steps(4) infinite;
  will-change: transform;
}
@keyframes grain-shift {
  0%   { transform: translate(0,0); }
  25%  { transform: translate(-3%, 2%); }
  50%  { transform: translate(2%, -3%); }
  75%  { transform: translate(-2%, -2%); }
  100% { transform: translate(3%, 3%); }
}

/* ---------- Scanlines ---------- */
.scanlines {
  position: fixed;
  inset: 0;
  z-index: 9001;
  pointer-events: none;
  background: repeating-linear-gradient(
    0deg,
    rgba(255,255,255,0.035) 0px,
    rgba(255,255,255,0.035) 1px,
    transparent 1px,
    transparent 3px
  );
  mix-blend-mode: overlay;
  animation: crt-flicker 6s infinite steps(60);
}
@keyframes crt-flicker {
  0%, 100% { opacity: 0.85; }
  48%      { opacity: 0.9; }
  49%      { opacity: 0.6; }
  50%      { opacity: 0.95; }
  92%      { opacity: 0.8; }
}

/* ---------- Vignette ---------- */
.vignette {
  position: fixed;
  inset: 0;
  z-index: 8999;
  pointer-events: none;
  background: radial-gradient(ellipse at center,
    transparent 55%, rgba(0,0,0,0.55) 100%);
}

/* ---------- Portrait CRT noise layer ---------- */
/* Masked with the same radial as the portrait so the grain dissolves
   into the page too — it must never reveal a rectangular boundary. */
.portrait__noise {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  opacity: 0.12;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='80' height='80'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-size: 140px 140px;
  mix-blend-mode: overlay;
  -webkit-mask-image: radial-gradient(ellipse 50% 56% at 50% 36%, #000 22%, transparent 54%);
  mask-image: radial-gradient(ellipse 50% 56% at 50% 36%, #000 22%, transparent 54%);
  animation: grain-shift 0.5s steps(3) infinite, portrait-flicker 5s infinite;
}
@keyframes portrait-flicker {
  0%, 100% { opacity: 0.12; }
  47% { opacity: 0.18; }
  48% { opacity: 0.06; }
  49% { opacity: 0.16; }
}

/* ---------- Scroll-cue bar animation ---------- */
.scroll-cue__bar::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--ink);
  transform: translateX(-100%);
  animation: cue-slide 2.4s var(--ease) infinite;
}
@keyframes cue-slide {
  0%   { transform: translateX(-100%); }
  50%  { transform: translateX(0); }
  100% { transform: translateX(100%); }
}

/* ---------- Reveal on scroll ---------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.8s var(--ease), transform 0.8s var(--ease);
}
[data-reveal].is-visible {
  opacity: 1;
  transform: none;
}

[data-project] {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}
[data-project].is-visible { opacity: 1; transform: none; }

/* ---------- Floating motion (hero title lines) ---------- */
[data-float] {
  animation: float 7s ease-in-out infinite;
}
[data-float]:nth-child(2) { animation-delay: -3.5s; }
@keyframes float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-8px); }
}

/* ---------- Reduced motion: disable everything non-essential ---------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal],
  [data-project] { opacity: 1; transform: none; }
}
