/*
  FrontRow Events — Animations Stylesheet
  Version: 2.0 | FRONTROW-WEB-ZERO ELITE-MAX
  ─────────────────────────────────────────
  ALL motion lives here: the page-load sequence, the hero
  entrance choreography, the scroll-reveal system and every
  keyframe. style.css stays purely structural — removing
  this file leaves a fully readable, static site.

  TABLE OF CONTENTS:
  1.  PAGE LOADER MOTION
  2.  HERO ENTRANCE CHOREOGRAPHY
  3.  KEYFRAMES — ORB FLOAT
  4.  KEYFRAMES — SCROLL INDICATOR
  5.  SCROLL REVEAL SYSTEM
  6.  KEYFRAMES — ROTATING BORDERS / SHIMMER / SPARKLE
  7.  KEYFRAMES — MICRO-INTERACTIONS
  8.  KEYFRAMES — MAP PIN & FOOTER DIVIDER
  9.  GENERAL UTILITIES
  10. NO-JS FALLBACK
  11. PREFERS-REDUCED-MOTION
*/


/* ═══════════════════════════════════════════════════
   1. PAGE LOADER MOTION
   main.js adds .done to the loader and .loaded to <body>
   once the page is ready — that kicks off the hero.
═══════════════════════════════════════════════════ */
.loader-brand {
  opacity: 0;
  animation: loaderBrandIn 0.8s cubic-bezier(0.22, 1, 0.36, 1) 0.1s forwards;
}

.loader-tag {
  opacity: 0;
  animation: loaderBrandIn 0.8s cubic-bezier(0.22, 1, 0.36, 1) 0.3s forwards;
}

.loader-bar-fill {
  animation: loaderFill 1.2s cubic-bezier(0.22, 1, 0.36, 1) 0.25s forwards;
}

.page-loader.done .loader-inner {
  transform: scale(1.04);
  opacity: 0;
  transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1),
              opacity 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}

@keyframes loaderBrandIn {
  from {
    opacity: 0;
    transform: translateY(16px);
    letter-spacing: 0.2em;
  }
  to {
    opacity: 1;
    transform: translateY(0);
    letter-spacing: 0.08em;
  }
}

@keyframes loaderFill {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}


/* ═══════════════════════════════════════════════════
   2. HERO ENTRANCE CHOREOGRAPHY
   A movie title card, in order:
   0.05s  background fades in from black (1.4s)
   0.45s  FRONTROW reveals letter by letter
   1.15s  tagline rises  (0.3s after the name)
   1.65s  buttons fade up (0.5s after the tagline)
   2.15s  scroll indicator appears
   Everything is gated on body.loaded (added by main.js).
═══════════════════════════════════════════════════ */

/* Initial hidden states — only when JS is alive to reveal them */
html:not(.no-js) .hero-bg        { opacity: 0; }
html:not(.no-js) .watermark-text { opacity: 0; }

html:not(.no-js) .hl-letter {
  opacity: 0;
  transform: translateY(0.4em) rotateX(50deg);
  filter: blur(10px);
}

html:not(.no-js) .hero-tagline,
html:not(.no-js) .hero-actions {
  opacity: 0;
  transform: translateY(36px);
}

html:not(.no-js) .scroll-indicator { opacity: 0; }

/* 1 — Background: fade in from black + slow cinematic settle,
   then an endless, barely-perceptible drift (Ken Burns) */
body.loaded .hero-bg {
  animation: heroBgIn 1.4s cubic-bezier(0.22, 1, 0.36, 1) 0.05s forwards,
             heroBgDrift 30s ease-in-out 1.45s infinite alternate;
}

@keyframes heroBgIn {
  from { opacity: 0; transform: scale(1.14); }
  to   { opacity: 1; transform: scale(1.06); }
}

@keyframes heroBgDrift {
  from { transform: scale(1.06) translateY(0); }
  to   { transform: scale(1.1)  translateY(-1.2%); }
}

/* 2 — Watermark breathes in behind everything */
body.loaded .watermark-text {
  animation: watermarkIn 1.8s cubic-bezier(0.22, 1, 0.36, 1) 0.5s forwards,
             watermarkBreathe 24s ease-in-out 2.3s infinite alternate;
}

@keyframes watermarkIn {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}

@keyframes watermarkBreathe {
  from { transform: scale(1); }
  to   { transform: scale(1.035); }
}

/* 3 — FRONTROW, letter by letter */
body.loaded .hl-letter {
  animation: heroLetter 0.75s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

body.loaded .hl-letter:nth-child(1) { animation-delay: 0.45s; }
body.loaded .hl-letter:nth-child(2) { animation-delay: 0.505s; }
body.loaded .hl-letter:nth-child(3) { animation-delay: 0.56s; }
body.loaded .hl-letter:nth-child(4) { animation-delay: 0.615s; }
body.loaded .hl-letter:nth-child(5) { animation-delay: 0.67s; }
body.loaded .hl-letter:nth-child(6) { animation-delay: 0.725s; }
body.loaded .hl-letter:nth-child(7) { animation-delay: 0.78s; }
body.loaded .hl-letter:nth-child(8) { animation-delay: 0.835s; }

@keyframes heroLetter {
  from {
    opacity: 0;
    transform: translateY(0.4em) rotateX(50deg);
    filter: blur(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0) rotateX(0deg);
    filter: blur(0);
  }
}

/* 4 — Tagline rises 0.3s after the name */
body.loaded .hero-tagline {
  animation: fadeUpHero 0.9s cubic-bezier(0.22, 1, 0.36, 1) 1.15s forwards;
}

/* 5 — Buttons follow 0.5s later */
body.loaded .hero-actions {
  animation: fadeUpHero 0.9s cubic-bezier(0.22, 1, 0.36, 1) 1.65s forwards;
}

@keyframes fadeUpHero {
  from { opacity: 0; transform: translateY(36px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* 6 — Scroll indicator fades in last, bouncing forever */
body.loaded .scroll-indicator {
  animation: scrollFadeIn 0.9s cubic-bezier(0.22, 1, 0.36, 1) 2.15s forwards,
             scrollBounce 2.5s ease-in-out 2.15s infinite;
}

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


/* ═══════════════════════════════════════════════════
   3. KEYFRAMES — ORB FLOAT (15–25s ambient loops)
═══════════════════════════════════════════════════ */
.orb-1 { animation: orbFloat1 18s ease-in-out infinite; }
.orb-2 { animation: orbFloat2 22s ease-in-out infinite; }
.orb-3 { animation: orbFloat3 16s ease-in-out infinite; }
.orb-4 { animation: orbFloat2 25s ease-in-out infinite reverse; }
.orb-5 { animation: orbFloat1 20s ease-in-out 2s infinite; }

@keyframes orbFloat1 {
  0%, 100% { transform: translate(0, 0) scale(1); }
  33%      { transform: translate(34px, -44px) scale(1.06); }
  66%      { transform: translate(-24px, 24px) scale(0.95); }
}

@keyframes orbFloat2 {
  0%, 100% { transform: translate(0, 0) scale(1); }
  40%      { transform: translate(-44px, 34px) scale(1.08); }
  70%      { transform: translate(24px, -24px) scale(0.97); }
}

@keyframes orbFloat3 {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50%      { transform: translate(28px, -38px) scale(1.05); }
}


/* ═══════════════════════════════════════════════════
   4. KEYFRAMES — SCROLL INDICATOR
═══════════════════════════════════════════════════ */
.scroll-indicator { transform: translateX(-50%); }

.scroll-wheel { animation: scrollWheel 2.5s ease-in-out infinite; }

@keyframes scrollBounce {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50%      { transform: translateX(-50%) translateY(9px); }
}

@keyframes scrollWheel {
  0%   { opacity: 1; transform: translateY(0); }
  60%  { opacity: 0; transform: translateY(12px); }
  61%  { opacity: 0; transform: translateY(0); }
  100% { opacity: 1; transform: translateY(0); }
}


/* ═══════════════════════════════════════════════════
   5. SCROLL REVEAL SYSTEM
   animations.js adds .visible when an element enters the
   viewport (IntersectionObserver, fires once only).
   Variants: fade-up, slide-left, slide-right, scale,
   3D tilt-straighten, and clip-path curtain reveal.
   data-delay="0.2" on an element adds a transition delay.
═══════════════════════════════════════════════════ */
html:not(.no-js) .reveal {
  opacity: 0;
  transform: translateY(44px);
  transition: opacity 0.9s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.9s cubic-bezier(0.22, 1, 0.36, 1);
}

html:not(.no-js) .reveal.visible {
  opacity: 1;
  transform: translateY(0);
}

/* Slide in from the left */
html:not(.no-js) .reveal-left {
  opacity: 0;
  transform: translateX(-52px);
  transition: opacity 0.9s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.9s cubic-bezier(0.22, 1, 0.36, 1);
}

html:not(.no-js) .reveal-left.visible {
  opacity: 1;
  transform: translateX(0);
}

/* Slide in from the right */
html:not(.no-js) .reveal-right {
  opacity: 0;
  transform: translateX(52px);
  transition: opacity 0.9s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.9s cubic-bezier(0.22, 1, 0.36, 1);
}

html:not(.no-js) .reveal-right.visible {
  opacity: 1;
  transform: translateX(0);
}

/* Scale up from 0.9 */
html:not(.no-js) .reveal-scale {
  opacity: 0;
  transform: scale(0.9);
  transition: opacity 0.8s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.9s cubic-bezier(0.22, 1, 0.36, 1);
}

html:not(.no-js) .reveal-scale.visible {
  opacity: 1;
  transform: scale(1);
}

/* 3D tilt that straightens as it enters */
html:not(.no-js) .reveal-tilt {
  opacity: 0;
  transform: perspective(900px) rotateX(7deg) translateY(40px);
  transition: opacity 0.9s cubic-bezier(0.22, 1, 0.36, 1),
              transform 1s cubic-bezier(0.22, 1, 0.36, 1);
}

html:not(.no-js) .reveal-tilt.visible {
  opacity: 1;
  transform: perspective(900px) rotateX(0deg) translateY(0);
}

/* ── Slogan reveal — word-by-word cascade ──────────
   Fail-safe by design: slogans are VISIBLE by default.
   animations.js wraps the words, sets a per-word delay,
   and adds .slogan-ready — only then is anything hidden.
   A stale script or any JS failure = static visible text. */
.slogan-title.slogan-ready .slogan-word {
  opacity: 0;
  transform: translateY(0.55em) rotateX(40deg);
  filter: blur(6px);
  transition: opacity 0.65s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.65s cubic-bezier(0.22, 1, 0.36, 1),
              filter 0.65s cubic-bezier(0.22, 1, 0.36, 1);
  /* per-word transition-delay is set inline by animations.js */
}

.slogan-title.slogan-ready.visible .slogan-word {
  opacity: 1;
  transform: translateY(0) rotateX(0deg);
  filter: blur(0);
}

/* Gradient underline bar sweeps in after the words land */
.slogan-title.slogan-ready::after {
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.9s cubic-bezier(0.22, 1, 0.36, 1) 0.55s;
}

.slogan-title.slogan-ready.visible::after {
  transform: scaleX(1);
}

/* Stagger parent — direct children cascade 0.1s apart */
html:not(.no-js) .reveal-stagger > * {
  opacity: 0;
  transform: translateY(34px) scale(0.98);
  transition: opacity 0.8s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
}

html:not(.no-js) .reveal-stagger.visible > * {
  opacity: 1;
  transform: translateY(0) scale(1);
}

html:not(.no-js) .reveal-stagger.visible > *:nth-child(1) { transition-delay: 0.05s; }
html:not(.no-js) .reveal-stagger.visible > *:nth-child(2) { transition-delay: 0.15s; }
html:not(.no-js) .reveal-stagger.visible > *:nth-child(3) { transition-delay: 0.25s; }
html:not(.no-js) .reveal-stagger.visible > *:nth-child(4) { transition-delay: 0.35s; }
html:not(.no-js) .reveal-stagger.visible > *:nth-child(5) { transition-delay: 0.45s; }
html:not(.no-js) .reveal-stagger.visible > *:nth-child(6) { transition-delay: 0.55s; }
html:not(.no-js) .reveal-stagger.visible > *:nth-child(7) { transition-delay: 0.65s; }
html:not(.no-js) .reveal-stagger.visible > *:nth-child(8) { transition-delay: 0.75s; }


/* ═══════════════════════════════════════════════════
   6. KEYFRAMES — ROTATING BORDERS / SHIMMER / SPARKLE
═══════════════════════════════════════════════════ */
/* Spins the registered --angle property → rotating conic border */
@keyframes spinAngle {
  from { --angle: 0deg; }
  to   { --angle: 360deg; }
}

/* Halo pulse behind the coming-soon card */
@keyframes gradientBorderPulse {
  0%, 100% { opacity: 0.14; }
  50%      { opacity: 0.3; }
}

/* Chrome shine sliding across text (background-size: 200%) */
@keyframes shimmer {
  0%   { background-position: 200% center; }
  100% { background-position: -200% center; }
}

/* Slow rotation + scale pulse for the sparkle icon */
@keyframes sparkleSpin {
  0%   { transform: rotate(0deg) scale(1); }
  25%  { transform: rotate(90deg) scale(1.08); }
  50%  { transform: rotate(180deg) scale(1); }
  75%  { transform: rotate(270deg) scale(1.08); }
  100% { transform: rotate(360deg) scale(1); }
}


/* ═══════════════════════════════════════════════════
   7. KEYFRAMES — MICRO-INTERACTIONS
═══════════════════════════════════════════════════ */
/* Service icon glow — pulses once per hover */
@keyframes iconPulse {
  0%   { transform: scale(1);    box-shadow: 0 0 0 rgba(139, 47, 201, 0); }
  45%  { transform: scale(1.16); box-shadow: 0 0 38px rgba(139, 47, 201, 0.55); }
  100% { transform: scale(1.1);  box-shadow: 0 0 24px rgba(139, 47, 201, 0.35); }
}

/* Stat counter — elastic pop when the count lands */
.stat-number.popped {
  animation: statPop 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes statPop {
  0%   { transform: scale(1); }
  55%  { transform: scale(1.18); }
  78%  { transform: scale(0.96); }
  100% { transform: scale(1); }
}

/* SVG stroke draw (checkmark circle + tick) */
@keyframes drawStroke {
  to { stroke-dashoffset: 0; }
}

/* Little celebratory pop once the checkmark finishes drawing */
@keyframes successPop {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.12); }
  100% { transform: scale(1); }
}

/* Success message slide in */
@keyframes slideInUp {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.notify-success:not([hidden]),
.form-success:not([hidden]) {
  animation: slideInUp 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}


/* ═══════════════════════════════════════════════════
   8. KEYFRAMES — FOOTER DIVIDER
═══════════════════════════════════════════════════ */
@keyframes dividerSlide {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}


/* ═══════════════════════════════════════════════════
   9. GENERAL UTILITIES
═══════════════════════════════════════════════════ */
@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}


/* ═══════════════════════════════════════════════════
   10. NO-JS FALLBACK
   Without JavaScript nothing can add .visible/.loaded —
   force every animated element to its final, visible state.
═══════════════════════════════════════════════════ */
.no-js .hero-bg,
.no-js .watermark-text,
.no-js .hl-letter,
.no-js .hero-tagline,
.no-js .hero-actions,
.no-js .scroll-indicator {
  opacity: 1;
  transform: none;
  filter: none;
}


/* ═══════════════════════════════════════════════════
   11. PREFERS-REDUCED-MOTION
   Disables all animation for users who request it —
   content appears instantly, fully visible.
═══════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
    animation-delay: 0s !important;
    scroll-behavior: auto !important;
  }

  /* Show all content — just without motion */
  html:not(.no-js) .hero-bg,
  html:not(.no-js) .watermark-text,
  html:not(.no-js) .hl-letter,
  html:not(.no-js) .hero-tagline,
  html:not(.no-js) .hero-actions,
  html:not(.no-js) .scroll-indicator,
  html:not(.no-js) .reveal,
  html:not(.no-js) .reveal-left,
  html:not(.no-js) .reveal-right,
  html:not(.no-js) .reveal-scale,
  html:not(.no-js) .reveal-tilt,
  html:not(.no-js) .reveal-stagger > * {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    transition: none !important;
    animation: none !important;
  }

  .slogan-title.slogan-ready .slogan-word {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    transition: none !important;
  }

  .slogan-title.slogan-ready::after {
    transform: none !important;
    transition: none !important;
  }

  .orb {
    display: none;
  }

  .page-loader .loader-brand,
  .page-loader .loader-tag {
    opacity: 1;
    animation: none;
  }

  .scroll-indicator,
  .scroll-wheel,
  .sparkle-icon,
  .coming-soon-title,
  .coming-soon-card::before,
  .coming-soon-card::after,
  .service-card::before,
  .footer::before,
  .watermark-text {
    animation: none !important;
  }
}
