/* ==========================================================================
   Tequp Publishers — Animations
   Pre-animation states (JS-guarded), keyframes, hover motion primitives.
   Anything hidden here MUST be revealed by GSAP in js/animations.js.
   ========================================================================== */

/* ==========================================================================
   1. PRE-ANIMATION STATES
   Only applied when JS is available, so no-JS users see full content.
   ========================================================================== */
.js [data-reveal] { opacity: 0; will-change: transform, opacity; }
.js [data-reveal="fade"]   { transform: translateY(26px); }
.js [data-reveal="left"]   { transform: translateX(-32px); }
.js [data-reveal="right"]  { transform: translateX(32px); }
.js [data-reveal="scale"]  { transform: scale(.965); }

/* Word-by-word text reveal (masked) */
.js [data-split-words] .word {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  padding-bottom: .1em;
  margin-bottom: -.1em;
}
.js [data-split-words] .word > span {
  display: block;
  transform: translateY(110%);
  will-change: transform;
}

/* Line-by-line text reveal (masked) */
.js [data-split-lines] .line {
  display: block;
  overflow: hidden;
  padding-bottom: .06em;   /* protects descenders from the mask */
  margin-bottom: -.06em;
}
.js [data-split-lines] .line > span {
  display: block;
  transform: translateY(105%);
  will-change: transform;
}

/* Image reveal: curtain wipes off the picture.
   GSAP animates --curtain 1 → 0; the pseudo-element just follows it. */
@property --curtain {
  syntax: "<number>";
  inherits: false;
  initial-value: 1;
}

.js .img-reveal { position: relative; overflow: hidden; --curtain: 1; }
.js .img-reveal::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--dark);
  transform: scaleX(var(--curtain));
  transform-origin: right center;
  pointer-events: none;
}
.js .img-reveal img { transform: scale(1.18); will-change: transform; }

/* Loader lock: page beneath must not flash before the loader lifts */
.js body:not(.is-ready) .hero__visual { opacity: 0; }

/* ==========================================================================
   2. KEYFRAMES
   ========================================================================== */
@keyframes cue-run {
  0%   { top: -50%; }
  100% { top: 100%; }
}

@keyframes spin-slow {
  to { transform: rotate(360deg); }
}

/* Conic border sweep for the service cards and the CTA panel */
@keyframes edge-spin {
  to { --edge: 360deg; }
}

@keyframes status-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(6, 125, 98, .5); }
  60%      { box-shadow: 0 0 0 7px rgba(6, 125, 98, 0); }
}

@keyframes shimmer {
  0%   { background-position: -180% 0; }
  100% { background-position: 180% 0; }
}

@keyframes float-soft {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-12px); }
}

@keyframes glow-breathe {
  0%, 100% { opacity: .45; transform: scale(1); }
  50%      { opacity: .7;  transform: scale(1.06); }
}

/* ==========================================================================
   3. AMBIENT MOTION
   ========================================================================== */
/* With JS, GSAP owns the glow transform (breathe + parallax share one
   transform matrix). Without JS, CSS keyframes take over. */
.no-js .hero__glow { animation: glow-breathe 9s var(--ease-soft) infinite; }
.no-js .hero__glow--sun { animation-delay: -4.5s; }

/* Shimmering skeleton for lazy images before load */
.lazy-shell {
  background: linear-gradient(100deg, var(--bg-soft) 22%, #FFFFFF 42%, var(--bg-soft) 62%);
  background-size: 220% 100%;
  animation: shimmer 1.6s linear infinite;
}
img.lazy-img { opacity: 0; transition: opacity .7s var(--ease); }
img.lazy-img.is-loaded { opacity: 1; }
img.lazy-img.is-loaded + .lazy-shell,
.lazy-shell.is-loaded { animation: none; background: none; }

/* ==========================================================================
   4. HOVER MOTION PRIMITIVES
   ========================================================================== */
/* Card lift — shared by every card component across the site */
.hover-lift {
  transition: transform .55s var(--ease), box-shadow .55s var(--ease),
              border-color .35s var(--ease);
  will-change: transform;
}
.hover-lift:hover {
  transform: translateY(-8px);
  box-shadow: var(--sh-lg);
  border-color: #C2C7CB;
}

/* Sheen that sweeps across a card on hover */
.hover-sheen { position: relative; overflow: hidden; }
.hover-sheen::before {
  content: "";
  position: absolute;
  top: 0; left: -60%;
  width: 45%; height: 100%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .55), transparent);
  transform: skewX(-18deg);
  transition: left .85s var(--ease);
  pointer-events: none;
  z-index: 1;
}
.hover-sheen:hover::before { left: 125%; }

/* Underline sweep for inline nav-style links */
.hover-underline { background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% 1px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size .45s var(--ease);
}
.hover-underline:hover { background-size: 100% 1px; }

/* ==========================================================================
   5. REDUCED MOTION
   Kill decorative motion; guarantee content is visible and readable.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }

  html { scroll-behavior: auto; }

  .js [data-reveal],
  .js [data-split-words] .word > span,
  .js [data-split-lines] .line > span,
  .js body:not(.is-ready) .hero__visual {
    opacity: 1 !important;
    transform: none !important;
  }

  .js .img-reveal::after { display: none; }
  .js .img-reveal img { transform: none; }

  .cursor { display: none !important; }

  /* Ambient field holds still */
  .services__orb,
  .services__beam,
  .services__dust i { animation: none !important; transform: none !important; }
  .svc::before { animation: none !important; }
  .svc__line i { transform: scaleX(1) !important; }

  .team__blob,
  .team__beam,
  .team__dust i { animation: none !important; transform: none !important; }
  .tm::before,
  .tm__ring { animation: none !important; }
  .scroll-cue__line::after { display: none; }
}
