/* ==========================================================================
   SSK Business Services — Animation states
   Every pre-animation "hidden" state is scoped to html.js-anim, which is only
   added by an inline script when JS is available AND the visitor has not asked
   for reduced motion. Without JS the page renders fully visible.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Reveal primitives — initial states
   -------------------------------------------------------------------------- */
html.js-anim .reveal-up { opacity: 0; transform: translateY(28px); }
html.js-anim .reveal-fade { opacity: 0; }
html.js-anim .reveal-left { opacity: 0; transform: translateX(-30px); }
html.js-anim .reveal-right { opacity: 0; transform: translateX(30px); }
html.js-anim .reveal-scale { opacity: 0; transform: scale(0.94); }
html.js-anim .reveal-blur { opacity: 0; filter: blur(9px); transform: translateY(16px); }

/* Masked line/word reveal: the wrapper clips, the inner slides */
html.js-anim .line__inner { transform: translateY(105%); }
html.js-anim .reveal-text .line__inner { transform: translateY(105%); }

/* Word-level split (built by JS) */
html.js-anim .word { display: inline-block; overflow: hidden; vertical-align: top; }
html.js-anim .word > span { display: inline-block; transform: translateY(105%); will-change: transform; }

/* Staggered children */
html.js-anim .stagger > * { opacity: 0; transform: translateY(26px); }
html.js-anim .stagger-sm > * { opacity: 0; transform: translateY(16px); }

/* Section-specific resting states.
   These are declared in CSS and animated with gsap.to() rather than gsap.from().
   A from() tween can be re-rendered back to its start state by a later
   ScrollTrigger.refresh() (fonts loading, an accordion opening, a resize),
   which would strand the element invisible. */
/* Horizontal offsets are applied to inner content, never to a full-bleed row.
   Translating the row itself pushes it past the container, which on mobile
   widens the layout viewport and gives the whole page a sideways scroll. */
html.js-anim .svc__item { opacity: 0; }
html.js-anim .svc__item > :not(.svc__go) { transform: translateY(14px); }
@media (min-width: 992px) {
  /* Only slide sideways where the container has side margin to absorb it */
  html.js-anim .svc__item > :not(.svc__go) { transform: translateX(16px); }
}
html.js-anim .proc__step { opacity: 0; transform: translateY(26px); }
html.js-anim .work-card { opacity: 0; transform: translateY(42px); }
html.js-anim .ind { opacity: 0; transform: translateY(18px); }

/* Editorial card grids: the media wipes open while the text lifts in behind it.
   Driven by initCards() in animations.js. */
html.js-anim [data-cards] .post__media { clip-path: inset(0 0 100% 0); }
html.js-anim [data-cards] .post__media img,
html.js-anim [data-cards] .post__media .artwork { transform: scale(1.14); }
html.js-anim [data-cards] .post__body > * { opacity: 0; transform: translateY(18px); }

/* Image / media clip reveal */
html.js-anim .image-reveal { clip-path: inset(0 0 100% 0); }
html.js-anim .image-reveal > img,
html.js-anim .image-reveal > picture > img { transform: scale(1.12); }

html.js-anim .media-reveal { clip-path: inset(0 0 100% 0); }
html.js-anim .media-reveal img { transform: scale(1.1); }

/* Footer wordmark starts empty and inks in as the page bottom is reached.
   Without JS (or with reduced motion) it simply renders already filled. */
html.js-anim .footer__mark-clip { --fill: 0; }

/* Animated separator lines */
html.js-anim .rule-draw { transform: scaleX(0); }
html.js-anim .line-draw { transform: scaleY(0); transform-origin: top; }

/* SVG path drawing */
html.js-anim .draw-path { stroke-dashoffset: 1; }

/* Counter start value is written by JS, but avoid a flash of the end value */
html.js-anim .counter { opacity: 0; }

/* Nodes graph */
html.js-anim .node { opacity: 0; transform: translate(-50%, -50%) scale(0.85); }

/* --------------------------------------------------------------------------
   Hero entrance — a class the JS timeline drives
   -------------------------------------------------------------------------- */
html.js-anim .hero__badges > * { opacity: 0; transform: translateY(14px); }
html.js-anim .hero__lede { opacity: 0; transform: translateY(20px); }
html.js-anim .hero__cta > * { opacity: 0; transform: translateY(18px); }
html.js-anim .hero-viz { opacity: 0; transform: translateY(46px) scale(0.975); }
/* Showreel panel starts tilted back; initShowcase() straightens it on scroll */
html.js-anim .showcase { --rx: 12; --sc: 0.95; }
html.js-anim .trust { opacity: 0; }

/* --------------------------------------------------------------------------
   Continuous decorative motion (CSS only — cheap, GPU friendly)
   -------------------------------------------------------------------------- */
.float-slow { animation: floatY 7s ease-in-out infinite; }
.float-slower { animation: floatY 10s ease-in-out infinite; animation-delay: -3s; }

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

.spin-slow { animation: spinSlow 34s linear infinite; }
@keyframes spinSlow { to { transform: rotate(360deg); } }

.breathe { animation: breathe 9s ease-in-out infinite; }
@keyframes breathe {
  0%, 100% { transform: scale(1); opacity: 0.5; }
  50% { transform: scale(1.08); opacity: 0.72; }
}

/* Drifting hero grid — travels exactly one --grid-size so it loops seamlessly */
.grid-drift { animation: gridDrift 26s linear infinite; }
@keyframes gridDrift {
  from { background-position: 0 0, 0 0; }
  to {
    background-position:
      var(--grid-size) var(--grid-size),
      var(--grid-size) var(--grid-size);
  }
}

/* Marquee fallback if GSAP is unavailable */
html:not(.js-anim) .marquee__track { animation: marqueeSlide 34s linear infinite; }
html:not(.js-anim) .ticker__track { animation: marqueeSlide 40s linear infinite; }
@keyframes marqueeSlide {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(-50%, 0, 0); }
}

/* Scroll cue */
.scrollcue {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.scrollcue__bar {
  width: 1px;
  height: 42px;
  background: linear-gradient(to bottom, var(--line-2), transparent);
  position: relative;
  overflow: hidden;
}
.scrollcue__bar::after {
  content: "";
  position: absolute;
  inset: 0 auto auto 0;
  width: 1px; height: 40%;
  background: var(--brand);
  animation: cueRun 2.1s cubic-bezier(0.65, 0, 0.35, 1) infinite;
}
@keyframes cueRun {
  0% { transform: translateY(-100%); }
  100% { transform: translateY(250%); }
}

/* --------------------------------------------------------------------------
   Hero visual composition (built from CSS, no stock photography)
   -------------------------------------------------------------------------- */
.hero-viz {
  position: relative;
  margin-top: clamp(34px, 4.5vw, 62px);
  perspective: 1900px;
  perspective-origin: 50% 24%;
}

.viz-float {
  position: absolute;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 18px;
  border-radius: var(--r-pill);
  background: var(--float-glass);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid var(--on-ink-60);
  box-shadow: 0 20px 44px -22px var(--veil-soft);
  white-space: nowrap;
}
.viz-float__k {
  font-family: var(--font-display);
  font-size: 1.125rem;
  letter-spacing: -0.03em;
  line-height: 1;
}
.viz-float__v { font-size: 0.6875rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted-2); }
.viz-float__ico { color: var(--brand); font-size: 1.15rem; }
/* Both chips straddle the panel edge rather than sitting over its content —
   the side column is three project cells now, and anything inset from the
   right lands squarely on one of them. */
.viz-float--a { top: 11%; left: -2%; }
.viz-float--b { bottom: -5%; right: 4%; }

html.js-anim .viz-float { opacity: 0; transform: translateY(16px) scale(0.9); }

@media (max-width: 767px) {
  .viz-float--a { top: 8px; left: 8px; padding: 9px 13px; }
  .viz-float--b { bottom: -14px; right: 8px; padding: 9px 13px; }
  .viz-float__k { font-size: 0.9375rem; }
  .viz-float__v { font-size: 0.5625rem; }
}

/* --------------------------------------------------------------------------
   Reduced motion — accessibility is non-negotiable
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  /* Showreel panel sits flat; the video stays on its poster */
  .showcase { --rx: 0 !important; --sc: 1 !important; --tx: 0 !important; --ty: 0 !important; }
  .showcase__glare { display: none; }

  /* Wordmark renders already inked in */
  .footer__mark-clip { --fill: 1 !important; }


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

  /* Force every animated element to its resting state */
  .reveal-up,
  .reveal-fade,
  .reveal-left,
  .reveal-right,
  .reveal-scale,
  .reveal-blur,
  .stagger > *,
  .stagger-sm > *,
  [data-cards] .post__body > *,
  .svc__item,
  .svc__item > *,
  .proc__step,
  .work-card,
  .ind,
  .hero__badges > *,
  .hero__lede,
  .hero__cta > *,
  .hero-viz,
  .viz-float,
  .trust,
  .node,
  .counter {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
  }

  .line__inner,
  .word > span { transform: none !important; }

  .image-reveal,
  .media-reveal,
  [data-cards] .post__media { clip-path: none !important; }
  .image-reveal > img,
  .media-reveal img,
  [data-cards] .post__media img,
  [data-cards] .post__media .artwork { transform: none !important; }

  .rule-draw, .line-draw { transform: none !important; }

  .cta-band__sheen,
  .scrollcue__bar::after { display: none; }

  .marquee__track,
  .ticker__track { animation: none !important; }

  .cursor, .cursor-dot, .veil, .progress { display: none !important; }

  .float-slow, .float-slower, .spin-slow, .breathe, .grid-drift { animation: none !important; }
}

/* If JS never runs, neutralise any leftover transition-based hiding */
html.no-js .reveal-up,
html.no-js .reveal-fade,
html.no-js .stagger > * { opacity: 1; transform: none; }
